# -*- coding: utf-8 -*-
#@+leo-ver=4
#@+node:@file __wx_gui.py
#@@first

"""A plugin to use wxPython as Leo's gui."""

from leoPlugins import *
from leoGlobals import *

#@<< imports for wx plugin >>
#@+node:<< imports for wx plugin >>
import leoColor,leoCommands,leoFind,leoFrame,leoGui,leoMenu,leoNodes,leoTree
import os,sys,traceback

try:    from wxPython import wx
except: wx = None
#@nonl
#@-node:<< imports for wx plugin >>
#@nl
#@<< constants for wx plugin >>
#@+node:<< constants for wx plugin >>
cSplitterWidth = 600

const_dict = {}
const_lastVal = 100 # Starting wx id.

def const(name):
	
	"""Return the wx id associated with name"""
	
	# Should this canonicalize the label?  Just remove '&' ??
	
	id = const_dict.get(name)
	if id != None:
		return id
	else:
		global const_lastVal
		const_lastVal += 1
		const_dict[name] = const_lastVal
		# trace(name,const_lastVal)
		return const_lastVal
#@nonl
#@-node:<< constants for wx plugin >>
#@nl

if wx and 0: # Enable the plugin (only if wxPython has been imported)...

	#@	@+others
	#@+node:wxGui class
	class wxGui(leoGui.leoGui):
		
		#@	@+others
		#@+node: wxGui.__init__
		def __init__ (self):
			
			# trace("wxGui")
			
			# Initialize the base class.
			if 1: # in plugin
				leoGui.leoGui.__init__(self,"wxPython")
			else:
				leoGui.__init__(self,"wxPython")
				
			self.bitmap_name = None
			self.bitmap = None
		#@nonl
		#@-node: wxGui.__init__
		#@+node:createRootWindow & allies
		def createRootWindow(self):
		
			self.wxApp = wxLeoApp(None) # This redirects stdout & stderr to stupid console.
			self.wxFrame = None
			
			if 0: # Not ready yet.
				self.setDefaultIcon()
				self.getDefaultConfigFont(app.config)
				self.setEncoding()
				self.createGlobalWindows()
		
			return self.wxFrame
		#@nonl
		#@-node:createRootWindow & allies
		#@+node:setDefaultIcon
		def setDefaultIcon(self):
			
			"""Set the icon to be used in all Leo windows.
			
			This code does nothing for Tk versions before 8.4.3."""
			
			gui = self
		
			try:
				version = gui.root.getvar("tk_patchLevel")
				if CheckVersion(version,"8.4.3"):
					# tk 8.4.3 or greater: load a 16 by 16 icon.
					path = os.path.join(app.loadDir,"..","Icons")
					if os.path.exists(path):
						file = os.path.join(path,"LeoApp16.ico")
						if os.path.exists(path):
							self.bitmap = Tkinter.BitmapImage(file)
						else:
							es("LeoApp16.ico not in Icons directory", color="red")
					else:
						es("Icons directory not found: "+path, color="red")
			except:
				print "exception setting bitmap"
				traceback.print_exc()
		#@nonl
		#@-node:setDefaultIcon
		#@+node:setEncoding
		#@+at 
		#@nonl
		# According to Martin v. Löwis, getdefaultlocale() is broken, and 
		# cannot be fixed. The workaround is to copy the 
		# getpreferredencoding() function from locale.py in Python 2.3a2.  
		# This function is now in leoGlobals.py.
		#@-at
		#@@c
		
		def setEncoding (self):
		
			for (encoding,src) in (
				(app.config.tkEncoding,"config"),
				#(locale.getdefaultlocale()[1],"locale"),
				(getpreferredencoding(),"locale"),
				(sys.getdefaultencoding(),"sys"),
				("utf-8","default")):
			
				if isValidEncoding (encoding): # 3/22/03
					app.tkEncoding = encoding
					# trace(app.tkEncoding,src)
					break
				elif encoding and len(encoding) > 0:
					trace("ignoring invalid " + src + " encoding: " + `encoding`)
					
			# trace(app.tkEncoding)
		#@nonl
		#@-node:setEncoding
		#@+node:getDefaultConfigFont
		def getDefaultConfigFont(self,config):
			
			"""Get the default font from a new text widget."""
		
			t = Tkinter.Text()
			fn = t.cget("font")
			font = tkFont.Font(font=fn)
			config.defaultFont = font
			config.defaultFontFamily = font.cget("family")
		#@nonl
		#@-node:getDefaultConfigFont
		#@+node:createGlobalWindows
		def createGlobalWindows (self):
			
			"""Create the global windows for the application."""
			
			app.findFrame = wxFindFrame()
			app.findFrame.top.withdraw()
			app.globalWindows.append(app.findFrame)
		#@nonl
		#@-node:createGlobalWindows
		#@+node:destroySelf
		def destroySelf(self):
			
			pass # Nothing more needs to be done once all windows have been destroyed.
		#@nonl
		#@-node:destroySelf
		#@+node:runMainLoop
		def runMainLoop(self):
		
			"""Run tkinter's main loop."""
			
			# trace("wxGui")
			self.wxApp.MainLoop()
			# trace("done")
		#@nonl
		#@-node:runMainLoop
		#@+node:finishCreate
		def finishCreate (self):
		
			pass
			
		#@-node:finishCreate
		#@+node:killGui
		def killGui(self,exitFlag=true):
			
			"""Destroy a gui and terminate Leo if exitFlag is true."""
		
			pass # Not ready yet.
		
		#@-node:killGui
		#@+node:recreateRootWindow
		def recreateRootWindow(self):
			"""A do-nothing base class to create the hidden root window of a gui
		
			after a previous gui has terminated with killGui(false)."""
			pass
		
		#@-node:recreateRootWindow
		#@+node:runAboutLeoDialog
		def runAboutLeoDialog(self,version,copyright,url,email):
			
			"""Create and run a wxPython About Leo dialog."""
		
			message = "%s\n\n%s\n\n%s\n\n%s" % (
				version.strip(),copyright.strip(),url.strip(),email.strip())
			
			wx.wxMessageBox(message,"About Leo",wx.wxCenter,self.root)
		#@nonl
		#@-node:runAboutLeoDialog
		#@+node:runAskOkDialog
		def runAskOkDialog(self,title,message=None,text="Ok"):
			
			"""Create and run a wxPython askOK dialog ."""
			
			d = wx.wxMessageDialog(self.root,message,"Leo",wx.wxOK)
			d.ShowModal()
			return "ok"
		#@nonl
		#@-node:runAskOkDialog
		#@+node:runAskOkCancelNumberDialog TODO
		def runAskOkCancelNumberDialog(self,title,message):
		
			"""Create and run a wxPython askOkCancelNumber dialog ."""
		
			trace()
			return 666
		#@nonl
		#@-node:runAskOkCancelNumberDialog TODO
		#@+node:runAskYesNoDialog
		def runAskYesNoDialog(selftitle,message=None):
		
			"""Create and run a wxPython askYesNo dialog."""
			
			d = wx.wxMessageDialog(self.root,message,"Leo",wx.wxYES_NO)
			answer = d.ShowModal()
		
			return choose(answer==wx.wxYES,"yes","no")
		#@nonl
		#@-node:runAskYesNoDialog
		#@+node:runAskYesNoCancelDialog
		def runAskYesNoCancelDialog(self,title,
			message=None,yesMessage="Yes",noMessage="No",defaultButton="Yes"):
		
			"""Create and run a wxPython askYesNoCancel dialog ."""
			
			d = wx.wxMessageDialog(self.root,message,"Leo",wx.wxYES_NO | wx.wxCANCEL)
			answer = d.ShowModal()
			
			if answer == wx.wxID_YES:
				return "yes"
			elif answer == wx.wxID_NO:
				return "no"
			else:
				assert(answer == wx.wxID_CANCEL)
				return "cancel"
		#@nonl
		#@-node:runAskYesNoCancelDialog
		#@+node:runOpenFileDialog
		def runOpenFileDialog(self,title,filetypes,defaultextension):
		
			"""Create and run a wxPython open file dialog ."""
			
			wildcard = self.getWildcardList(filetypes)
		
			d = wx.wxFileDialog(
				parent=None, message=title,
				defaultDir="", defaultFile="",
				wildcard=wildcard,
				style= wx.wxOPEN | wx.wxCHANGE_DIR | wx.wxHIDE_READONLY)
		
			val = d.ShowModal()
			if val == wx.wxID_OK:
				file = d.GetFilename()
				return file
			else:
				return None 
		#@-node:runOpenFileDialog
		#@+node:runSaveFileDialog
		def runSaveFileDialog(self,initialfile,title,filetypes,defaultextension):
		
			"""Create and run a wxPython save file dialog ."""
		
			wildcard = self.getWildcardList(filetypes)
		
			d = wx.wxFileDialog(
				parent=None, message=title,
				defaultDir="", defaultFile="",
				wildcard=wildcard,
				style= wx.wxSAVE | wx.wxCHANGE_DIR | wx.wxOVERWRITE_PROMPT)
		
			val = d.ShowModal()
			if val == wx.wxID_OK:
				file = d.GetFilename()
				return file
			else:
				return None
		#@nonl
		#@-node:runSaveFileDialog
		#@+node:getWildcardList
		def getWildcardList (self,filetypes):
			
			"""Create a wxWindows wildcard string for open/save dialogs."""
		
			if not filetypes:
				return "*.leo"
		
			if 1: # Too bad: this is sooo wimpy.
					a,b = filetypes[0] 
					return b
		
			else: # This _sometimes_ works: wxWindows is driving me crazy!
		
				# wildcards = ["%s (%s)" % (a,b) for a,b in filetypes]
				wildcards = ["%s" % (b) for a,b in filetypes]
				wildcard = "|".join(wildcards)
				trace(wildcard)
				return wildcard
		#@nonl
		#@-node:getWildcardList
		#@+node:createColorPanel
		def createColorPanel(self,c):
		
			"""Create Color panel."""
		
			trace("not ready yet")
		#@nonl
		#@-node:createColorPanel
		#@+node:createComparePanel
		def createComparePanel(self,c):
		
			"""Create Compare panel."""
		
			trace("not ready yet")
		#@nonl
		#@-node:createComparePanel
		#@+node:createFindPanel
		def createFindPanel(self):
		
			"""Create a hidden Find panel."""
		
			return wxFindFrame()
		#@nonl
		#@-node:createFindPanel
		#@+node:createFontPanel
		def createFontPanel(self,c):
		
			"""Create a Font panel."""
		
			trace("not ready yet")
		#@nonl
		#@-node:createFontPanel
		#@+node:createLeoFrame
		def createLeoFrame(self,title):
			
			"""Create a new Leo frame."""
		
			return wxLeoFrame(title)
		#@nonl
		#@-node:createLeoFrame
		#@+node:createPrefsPanel
		def createPrefsPanel(self,c):
		
			"""Create a Prefs panel."""
		
			return wxLeoPrefs(c)
		#@nonl
		#@-node:createPrefsPanel
		#@+node:destroyLeoFrame (used??)
		def destroyLeoFrame (self,frame):
		
			trace(frame.title)
			frame.Close()
		#@nonl
		#@-node:destroyLeoFrame (used??)
		#@+node:Clipboard
		def replaceClipboardWith (self,s):
		
			cb = wx.wxTheClipboard
			if cb.Open():
				cb.Clear()
				cb.SetData(s)
				cb.Flush()
				cb.Close()
			
		def getTextFromClibboard (self):
			
			return None
			
			# This code doesn't work yet.
			
			cb = wx.wxTheClipboard ; data = None
		  	if cb.Open():
				data = wx.wxDataObject()
				cb.GetData(data)
				data = data.GetDataHere()
				cb.Close()
			return data
		#@nonl
		#@-node:Clipboard
		#@+node:bringToFront
		def bringToFront (self,window):
			
			if window.IsIconized():
				window.Maximize()
			window.Raise()
			window.Show(true)
		#@nonl
		#@-node:bringToFront
		#@+node:get_window_info
		def get_window_info(self,window):
		
			# Get the information about top and the screen.
			x,y = window.GetPosition()
			w,h = window.GetSize()
			
			return w,h,x,y
		#@nonl
		#@-node:get_window_info
		#@+node:center_dialog
		def center_dialog(window):
			
			window.Center()
		#@nonl
		#@-node:center_dialog
		#@+node:get_focus
		def get_focus(self,top):
			
			"""Returns the widget that has focus, or body if None."""
		
			pass # wx code not ready yet.
		#@nonl
		#@-node:get_focus
		#@+node:set_focus
		def set_focus(self,c,widget):
			
			"""Set the focus of the widget in the given commander if it needs to be changed."""
			
			pass # wx code not ready yet.
		#@nonl
		#@-node:set_focus
		#@+node:getFontFromParams
		def getFontFromParams(self,family,size,slant,weight):
			
			## trace(app.config.defaultFont)
			
			return app.config.defaultFont ##
			
			family_name = family
			
			try:
				font = tkFont.Font(family=family,size=size,slant=slant,weight=weight)
				#print family_name,family,size,slant,weight
				#print "actual_name:",font.cget("family")
				return font
			except:
				es("exception setting font from " + `family_name`)
				es("family,size,slant,weight:"+
					`family`+':'+`size`+':'+`slant`+':'+`weight`)
				es_exception()
				return app.config.defaultFont
		#@nonl
		#@-node:getFontFromParams
		#@+node:attachLeoIcon
		def attachLeoIcon (self,w):
			
			"""Try to attach a Leo icon to the Leo Window.
			
			Use tk's wm_iconbitmap function if available (tk 8.3.4 or greater).
			Otherwise, try to use the Python Imaging Library and the tkIcon package."""
			
			trace(w)
		
			if self.bitmap != None:
				# We don't need PIL or tkicon: this is tk 8.3.4 or greater.
				try:
					w.wm_iconbitmap(self.bitmap)
				except:
					self.bitmap = None
			
			if self.bitmap == None:
				try:
					#@			<< try to use the PIL and tkIcon packages to draw the icon >>
					#@+node:<< try to use the PIL and tkIcon packages to draw the icon >>
					#@+at 
					#@nonl
					# This code requires Fredrik Lundh's PIL and tkIcon 
					# packages:
					# 
					# Download PIL    from 
					# http://www.pythonware.com/downloads/index.htm#pil
					# Download tkIcon from 
					# http://www.effbot.org/downloads/#tkIcon
					# 
					# Many thanks to Jonathan M. Gilligan for suggesting this 
					# code.
					#@-at
					#@@c
					
					import Image,tkIcon,_tkicon
					
					# Wait until the window has been drawn once before attaching the icon in OnVisiblity.
					def visibilityCallback(event,self=self,w=w):
						try: self.leoIcon.attach(w.winfo_id())
						except: pass
					w.bind("<Visibility>",visibilityCallback)
					if not self.leoIcon:
						# Load a 16 by 16 gif.  Using .gif rather than an .ico allows us to specify transparency.
						icon_file_name = os.path.join(app.loadDir,'..','Icons','LeoWin.gif')
						icon_file_name = os.path.normpath(icon_file_name)
						icon_image = Image.open(icon_file_name)
						if 1: # Doesn't resize.
							self.leoIcon = self.createLeoIcon(icon_image)
						else: # Assumes 64x64
							self.leoIcon = tkIcon.Icon(icon_image)
					#@nonl
					#@-node:<< try to use the PIL and tkIcon packages to draw the icon >>
					#@nl
				except:
					# traceback.print_exc()
					self.leoIcon = None
		#@nonl
		#@-node:attachLeoIcon
		#@+node:createLeoIcon
		# This code is adapted from tkIcon.__init__
		# Unlike the tkIcon code, this code does _not_ resize the icon file.
		
		def createLeoIcon (self,icon):
			
			try:
				import Image,tkIcon,_tkicon
				
				i = icon ; m = None
				# create transparency mask
				if i.mode == "P":
					try:
						t = i.info["transparency"]
						m = i.point(lambda i, t=t: i==t, "1")
					except KeyError: pass
				elif i.mode == "RGBA":
					# get transparency layer
					m = i.split()[3].point(lambda i: i == 0, "1")
				if not m:
					m = Image.new("1", i.size, 0) # opaque
				# clear unused parts of the original image
				i = i.convert("RGB")
				i.paste((0, 0, 0), (0, 0), m)
				# create icon
				m = m.tostring("raw", ("1", 0, 1))
				c = i.tostring("raw", ("BGRX", 0, -1))
				return _tkicon.new(i.size, c, m)
			except:
				return None
		#@nonl
		#@-node:createLeoIcon
		#@+node:setIdleTimeHook
		def setIdleTimeHook (self,idleTimeHookHandler,*args,**keys):
			
			pass # trace(idleTimeHookHandler)
			
		#@-node:setIdleTimeHook
		#@+node:setIdleTimeHookAfterDelay
		def setIdleTimeHookAfterDelay (self,delay,idleTimeHookHandler,*args,**keys):
			
			trace(delay,idleTimeHookHandler)
		#@nonl
		#@-node:setIdleTimeHookAfterDelay
		#@+node:firstIndex
		def firstIndex (self):
		
			return 0
		#@nonl
		#@-node:firstIndex
		#@+node:lastIndex
		def lastIndex (self):
		
			return "end"
		#@nonl
		#@-node:lastIndex
		#@+node:moveIndexBackward
		def moveIndexBackward(self,index,n):
		
			return index + n
		#@-node:moveIndexBackward
		#@+node:moveIndexForward
		def moveIndexForward(self,index,n):
		
			return index -n
		#@nonl
		#@-node:moveIndexForward
		#@+node:compareIndices
		def compareIndices (self,t,n1,rel,n2):
			
			val = eval("%d $s %d" % (n1,rel,n2))
			trace(val)
			return val
		#@nonl
		#@-node:compareIndices
		#@+node:getindex
		def getindex(self,text,index):
			
			"""Convert string index of the form line.col into a tuple of two ints."""
			
			val = tuple(map(int,string.split(text.index(index), ".")))
			
			trace(val)
			
			return val
		#@nonl
		#@-node:getindex
		#@+node:getInsertPoint
		def getInsertPoint(self,t):
		
			if t:
				t.bodyCtrl.GetInsertionPoint()
			else:
				return 0
		#@nonl
		#@-node:getInsertPoint
		#@+node:setInsertPoint
		def setInsertPoint (self,t,pos):
		
			if t and pos: # s_text control doesn't exist.
				trace(pos)
				t.bodyCtrl.SetInsertionPoint(pos)
		#@nonl
		#@-node:setInsertPoint
		#@+node:getSelectionRange
		def getSelectionRange (self,t):
		
			return t.bodyCtrl.GetSelection()
		#@nonl
		#@-node:getSelectionRange
		#@+node:getTextSelection
		def getTextSelection (self,t):
			
			"""Return a tuple representing the selected range of t, a Tk.Text widget.
			
			Return a tuple giving the insertion point if no range of text is selected."""
		
			# To get the current selection
			sel = t.bodyCtrl.GetSelection()
			if len(sel) == 2:
				return sel
			else:
				# Return the insertion point if there is no selected text.
				insert = t.bodyCtrl.GetInsertionPoint()
				return insert,insert
		#@nonl
		#@-node:getTextSelection
		#@+node:setSelectionRange
		def setSelectionRange(self,t,n1,n2):
		
			if t and n1 and n2:
				trace(n1,n2)
				t.bodyCtrl.SetSelection(n1,n2)
		#@nonl
		#@-node:setSelectionRange
		#@+node:setSelectionRangeWithLength
		def setSelectionRangeWithLength(self,t,start,length):
			
			t.bodyCtrl.SetSelection(n1,start+length)
		#@nonl
		#@-node:setSelectionRangeWithLength
		#@+node:setTextSelection
		def setTextSelection (self,t,start,end):
		
			if not start or not end:
				return
				
			if start > end:
				start,end = end,start
				
			t.bodyCtrl.SetSelection(start,end)
		#@nonl
		#@-node:setTextSelection
		#@+node:getAllText
		def getAllText (self,t):
			
			"""Return all the text of Tk.Text t converted to unicode."""
			
			s = t.get("1.0","end")
			if s is None:
				return u""
			else:
				return toUnicode(s,app.tkEncoding)
		#@nonl
		#@-node:getAllText
		#@+node:getCharAfterIndex
		def getCharAfterIndex (self,t,index):
		
			ch = t.get(index + "+1c")
			return toUnicode(ch,app.tkEncoding)
		#@nonl
		#@-node:getCharAfterIndex
		#@+node:getCharAtIndex
		def getCharAtIndex (self,t,index):
			ch = t.get(index)
			return toUnicode(ch,app.tkEncoding)
		#@nonl
		#@-node:getCharAtIndex
		#@+node:getCharBeforeIndex
		def getCharBeforeIndex (self,t,index):
		
			ch = t.get(index + "-1c")
			return toUnicode(ch,app.tkEncoding)
		#@nonl
		#@-node:getCharBeforeIndex
		#@+node:getLineContainingIndex
		def getLineContainingIndex (self,t,index):
		
			line = t.get(index + " linestart", index + " lineend")
			return toUnicode(line,app.tkEncoding)
		#@nonl
		#@-node:getLineContainingIndex
		#@+node:replaceSelectionRangeWithText
		def replaceSelectionRangeWithText (self,t,start,end,text):
		
			t.delete(start,end)
			t.insert(start,text)
		#@nonl
		#@-node:replaceSelectionRangeWithText
		#@+node:makeIndexVisible
		def makeIndexVisible(self,t,index):
		
			if t and index:
				t.bodyCtrl.ShowPosition(index)
		#@-node:makeIndexVisible
		#@-others
	#@nonl
	#@-node:wxGui class
	#@+node:wxLeoApp class
	class wxLeoApp (wx.wxApp):
		
		#@	@+others
		#@+node:OnInit
		def OnInit(self):
			
			#trace("wx.wxPlatform",wx.wxPlatform)
			
			self.SetAppName("Leo")
			app.findFrame = wxFindFrame()
			app.globalWindows.append(app.findFrame)
			return true
		#@nonl
		#@-node:OnInit
		#@+node:OnExit
		def OnExit(self):
			
			# trace()
			return true
		#@-node:OnExit
		#@-others
	#@-node:wxLeoApp class
	#@+node:wxLeoBody class
	class wxLeoBody (leoFrame.leoBody):
		
		"""A class to create a wxPython body pane."""
		
		#@	@+others
		#@+node:wxLeoBody.__init__
		def __init__ (self,frame,parentFrame):
		
			# Init the base class: calls createControl.
			leoFrame.leoBody.__init__(self,frame,parentFrame)
			
			self.bodyCtrl = self.createControl(frame,parentFrame)
			self.colorizer = leoColor.colorizer(self.c)
		
			self.styles = {} # For syntax coloring.
		
			wx.EVT_TEXT(self.bodyCtrl,const("cBodyCtrl"),self.onBodyTextUpdated)
		#@nonl
		#@-node:wxLeoBody.__init__
		#@+node:wxLeoBody.createControl
		def createControl (self,frame,parentFrame):
			
			trace()
			
			ctrl = wx.wxTextCtrl(parentFrame,
				const("cBodyCtrl"), "",
				wx.wxDefaultPosition, wx.wxDefaultSize,
				wx.wxTE_RICH | wx.wxTE_RICH2 | wx.wxTE_MULTILINE)
				
			return ctrl
		#@nonl
		#@-node:wxLeoBody.createControl
		#@+node:Bounding box...
		def bbox (self,index):
			
			return self.bodyCtrl.GetClientSizeTuple()  
		#@nonl
		#@-node:Bounding box...
		#@+node:tkColorToWxColor (internal use)
		def tkColorToWxColor (self, color):
			
			d = {
				"red": wx.wxRED,
				"blue": wx.wxBLUE,
				"#00aa00": wx.wxGREEN,
				"firebrick3": wx.wxRED }
				
			return d.get(color)
		#@nonl
		#@-node:tkColorToWxColor (internal use)
		#@+node:tag_add
		def tag_add (self,tagName,index1,index2):
			
			# trace(tagName,index1,index2)
		
			style = self.styles.get(tagName)
			if style:
				self.bodyCtrl.SetStyle(index1,index2,style)
		#@nonl
		#@-node:tag_add
		#@+node:tag_bind
		def tag_bind (self,tagName,event,callback):
			
			# trace(tagName,event,callback)
			pass
		#@-node:tag_bind
		#@+node:tag_configure (hack for wxStyles)
		def tag_configure (self,colorName,**keys):
			
			foreground = keys.get("foreground")
			background = keys.get("background")
		
			if foreground:
				fcolor = self.tkColorToWxColor (foreground)
				bcolor = self.tkColorToWxColor (background)
				if fcolor and bcolor:
					# trace(colorName,foreground,keys)
					style = wx.wxTextAttr(fcolor,bcolor)
					self.styles[colorName] = style
				elif fcolor:
					style = wx.wxTextAttr(fcolor)
					self.styles[colorName] = style
		#@nonl
		#@-node:tag_configure (hack for wxStyles)
		#@+node:tag_delete
		def tag_delete(self,tagName):
		
			if tagName == "keyword": # A kludge.
		
				# trace(tagName)
				style = wx.wxTextAttr(wx.wxBLACK)
				last = self.maxWxIndex()
				
				if 1: # This may cause the screen flash.
					self.bodyCtrl.SetStyle(0,last,style)
		#@nonl
		#@-node:tag_delete
		#@+node:tag_remove
		def tag_remove (self,tagName,index1,index2):
			
			trace(tagName,index1,index2)
			pass
		#@-node:tag_remove
		#@+node:Config... TO DO
		def setBodyFontFromConfig (self):
			
			pass # trace()
		#@nonl
		#@-node:Config... TO DO
		#@+node:Focus...
		def hasFocus (self):
			
			return self.bodyCtrl == self.bodyCtrl.FindFocus()
		
		def setFocus (self):
			
			self.bodyCtrl.SetFocus()
		#@-node:Focus...
		#@+node:adjustIndex
		def adjustIndex (self,index,offset):
			
			try:
				column, row = index
				return column, row + offset
			except:
				return index + offset
		#@nonl
		#@-node:adjustIndex
		#@+node:compareIndices
		def compareIndices(self,i,rel,j):
			
			try:
				y1,x1 = i
				y2,x2 = j
				pos1 = self.bodyCtrl.XYToPosition(x1,y1)
				pos2 = self.bodyCtrl.XYToPosition(x2,y2)
			except:
				pos1 = i
				pos2 = j
			
			val = eval("%d %s %d" % (pos1,rel,pos2))
			trace(i,j,rel,val)
			return val
		#@nonl
		#@-node:compareIndices
		#@+node:convertRowColumnToIndex
		def convertRowColumnToIndex (self,row,column):
			
			index = self.bodyCtrl.XYToPosition(column,row-1)
			# trace(column,row,"->",index)
			return index
		#@nonl
		#@-node:convertRowColumnToIndex
		#@+node:convertIndexToRowColumn
		def convertIndexToRowColumn (self,index):
			
			x,y = self.bodyCtrl.PositionToXY(index)
			# trace(index,"->",y+1,x)
			return y+1,x
		#@nonl
		#@-node:convertIndexToRowColumn
		#@+node:getImageIndex
		def getImageIndex (self,image):
			
			trace(image)
		#@nonl
		#@-node:getImageIndex
		#@+node:maxWxIndex (internal use)
		def maxWxIndex (self):
			
			return self.bodyCtrl.GetLastPosition()
		#@nonl
		#@-node:maxWxIndex (internal use)
		#@+node:Idle-time callback...
		def scheduleIdleTimeRoutine (self,function,*args,**keys):
			trace()
		#@-node:Idle-time callback...
		#@+node:Height & width info...
		def getBodyPaneHeight (self):
			return self.bodyCtrl.GetCharHeight()
			
		def getBodyPaneWidth (self):
			return self.bodyCtrl.GetCharWidth()
		#@nonl
		#@-node:Height & width info...
		#@+node:Insert point
		# Returning indices...
		def getBeforeInsertionPoint (self):
			trace()
			
		def getInsertionPoint (self):
			return self.bodyCtrl.GetInsertionPoint()
			
		# Returning chars...
		def getCharAtInsertPoint (self):
			t = self.bodyCtrl
			pos = t.GetInsertionPoint()
			return t.GetRange(pos,pos+1)
		
		def getCharBeforeInsertPoint (self):
			t = self.bodyCtrl
			pos = t.GetInsertionPoint()
			return t.GetRange(pos-1,pos)
		
		# Setting the insertion point...
		def setInsertionPoint (self,index):
			self.bodyCtrl.SetInsertionPoint(index)
		
		def setInsertPointToEnd (self):
			self.bodyCtrl.SetInsertionPointEnd()
			
		def setInsertPointToStartOfLine (self,lineNumber):
			trace()
		#@nonl
		#@-node:Insert point
		#@+node:Menu
		def bind (self,bind_shortcut,callback):
			
			pass # later.
		#@nonl
		#@-node:Menu
		#@+node:Selection
		def deleteSelection (self):
			t = self.bodyCtrl
			t.Remove(t.GetSelection())
		
		def getTextSelection (self):
			return self.bodyCtrl.GetSelection()
			
		def hasTextSelection (self):
			start,end = self.bodyCtrl.GetSelection()
			return start != end
		
		def selectAllText (self):
			self.bodyCtrl.SetSelection(-1,-1)
		
		def setTextSelection (self,sel):
			self.bodyCtrl.SetSelection(sel)
		#@nonl
		#@-node:Selection
		#@+node:Text
		# These routines replace most of the former insert/delete and index routines.
		#@nonl
		#@-node:Text
		#@+node:delete... (untested)
		def deleteAllText(self):
			self.bodyCtrl.Clear()
			
		def deleteCharacter (self,index):
			self.bodyCtrl.Remove(index,index+1)
			
		def deleteLine (self,lineNumber): # zero based line number.
			t = self.bodyCtrl
			pos1 = t.XYToPosition(lineNumber)
			n = t.GetLineLength(lineNumber)
			t.Remove(pos1,pos1 + n)
		
		def deleteLines (self,lineNumber,numberOfLines): # zero based line number.
			t = self.bodyCtrl
			pos1 = t.XYToPosition(lineNumber)
			pos2 = t.XYToPosition(lineNumber+numberOfLine-1)
			n = t.GetLineLength(lineNumber+numberOfLine-1)
			t.Remove(pos1,pos2 + n)
		
		def deleteRange (self,index1,index2):
			self.bodyCtrl.Remove(index1,index2)
		#@nonl
		#@-node:delete... (untested)
		#@+node:get... TO DO
		def getAllText (self):
			return self.bodyCtrl.GetValue()
			
		def getCharAtIndex (self,index):
			return self.bodyCtrl.GetRange(index,index+1)
		
		def getInsertLines (self):
			trace()
		
		def getSelectionAreas (self):
			trace()
		
		def getSelectionLines (self):
			trace()
			
		def getTextRange(self,n1,n2):
			return self.bodyCtrl.GetRange(n1,n2)
		#@nonl
		#@-node:get... TO DO
		#@+node:insert...
		def insertAtEnd (self,s):
		
			return self.bodyCtrl.AppendText(s)
			
		def insertAtInsertPoint (self,s):
			
			self.bodyCtrl.WriteText(s)
		#@nonl
		#@-node:insert...
		#@+node:setSelectionAreas
		def setSelectionAreas (self,before,sel,after):
		
			trace()
		#@nonl
		#@-node:setSelectionAreas
		#@+node:Visibility & scrolling...
		def makeIndexVisible (self,index):
			self.bodyCtrl.ShowPosition()
			
		def setFirstVisibleIndex (self,index):
			trace()
			
		def getFirstVisibleIndex (self):
			trace()
			
		def scrollUp (self):
			trace()
			
		def scrollDown (self):
			trace()
		#@-node:Visibility & scrolling...
		#@+node:onBodyTextUpdated MORE WORK NEEDED
		def onBodyTextUpdated(self,event):
		
			frame = self.frame ; c = self.c
			if not c:  return
			v = c.currentVnode()
			if not v: return
			if self.frame.lockout > 0: return
			
			# Similar to idle_body_key
			self.frame.lockout += 1
		
			s = frame.body.bodyCtrl.GetValue()
			v.t.setTnodeText(s)
			v.t.insertSpot = c.frame.body.getInsertionPoint()
			#@	<< recolor the body >>
			#@+node:<< recolor the body >>
			### self.scanForTabWidth(v)
			
			### incremental = undoType not in ("Cut","Paste") and not self.forceFullRecolorFlag
			c.recolor()
			###self.forceFullRecolorFlag = false
			#@nonl
			#@-node:<< recolor the body >>
			#@nl
			if not c.changed:
				c.setChanged(true)
			#@	<< redraw the screen if necessary >>
			#@+node:<< redraw the screen if necessary >>
			redraw_flag = false
			
			c.beginUpdate()
			
			# Update dirty bits.
			if not v.isDirty() and v.setDirty(): # Sets all cloned and @file dirty bits
				redraw_flag = true
				
			# Update icons.
			val = v.computeIcon()
			if val != v.iconVal:
				v.iconVal = val
				redraw_flag = true
			
			c.endUpdate(redraw_flag) # redraw only if necessary
			#@nonl
			#@-node:<< redraw the screen if necessary >>
			#@nl
			if 0: # ch, etc. are not defined.
				doHook("bodykey2",c=c,v=v,ch=ch,oldSel=oldSel,undoType=undoType)
				
			self.frame.lockout -= 1
		#@nonl
		#@-node:onBodyTextUpdated MORE WORK NEEDED
		#@-others
	#@nonl
	#@-node:wxLeoBody class
	#@+node:wxLeoFrame class
	class wxLeoFrame(wx.wxFrame,leoFrame.leoFrame):
		
		"""A class to create a wxPython from for the main Leo window."""
	
		#@	@+others
		#@+node:__init__
		def __init__ (self,title):
			
			# Init the leoFrame base class.
			# We will init the wxFrame base class in finishCreate.
			leoFrame.leoFrame.__init__(self)
			
			self.c = None # set in finishCreate.
			self.bodyCtrl = None # set in finishCreate
			self.title = title
			
			# trace("wxLeoFrame",title)
			self.activeFrame = None
			self.lockout = 0 # Suppress further events
			self.quitting = false
			self.updateCount = 0
			self.treeIniting = false
			self.drawing = false # Lockout recursive draws.
			self.menuIdDict = {}
			self.menuBar = None
			self.ratio = 0.5
			self.secondary_ratio = 0.5
			self.startupWindow=false
			self.use_coloring = false # set true to enable coloring
			
			# These vars have corresponding getters/setters.
			if 0: # now defined in base tree class.
				self.mDragging = false
				self.mRootVnode = None
				self.mTopVnode = None
				self.mCurrentVnode = None
		#@nonl
		#@-node:__init__
		#@+node:__repr__
		def __repr__ (self):
			
			return "wxLeoFrame: " + self.title
		#@nonl
		#@-node:__repr__
		#@+node:finishCreate
		def finishCreate (self,c):
			
			frame = self
			frame.c = c
			c.frame = frame
			
			# Init the wxFrame base class.  The leoFrame base class has already been inited.
			wx.wxFrame.__init__(self, None, -1, self.title) # wx.wxNO_3D # hangs.
			#self.outerPanel = wx.wxPanel(self,-1)
			#self.iconPanel = wx.wxPanel(self.outerPanel, -1, "iconPanel")
		
			self.CreateStatusBar()
		
			#@	<< create the splitters >>
			#@+node:<< create the splitters >>
			self.splitter1 = wx.wxSplitterWindow(self,
				const("cSplitterWindow"),
				wx.wxDefaultPosition, wx.wxDefaultSize,
				wx.wxSP_NOBORDER)
			
			# No effect, except to create a red flash.
			if 0:
				self.splitter1.SetForegroundColour(wx.wxRED)
				self.splitter1.SetBackgroundColour(wx.wxRED)
			
			self.splitter2 = wx.wxSplitterWindow(self.splitter1, -1,
				wx.wxDefaultPosition, wx.wxDefaultSize,
				wx.wxSP_NOBORDER)
				# wx.wxSP_BORDER | wx.wxSP_3D, "splitterWindow");
			
			self.splitter1.SetMinimumPaneSize(4)
			self.splitter2.SetMinimumPaneSize(4)
			#@nonl
			#@-node:<< create the splitters >>
			#@nl
			frame.tree = wxLeoTree(frame,self.splitter2)
			frame.log = wxLeoLog(frame,self.splitter2)
			frame.body = wxLeoBody(frame,self.splitter1)
			frame.bodyCtrl = frame.body
			# Attach the controls to the splitter.
			self.splitter1.SplitHorizontally(self.splitter2,self.body.bodyCtrl,0)
			self.splitter2.SplitVertically(self.tree.treeCtrl,self.log.logCtrl,cSplitterWidth/2)
			
			self.menu = wxLeoMenu(frame)
			self.menu.createMenuBar()
			
			#@	<< set the window icon >>
			#@+node:<< set the window icon >>
			if wx.wxPlatform == "__WXMSW__":
			
				path = os.path.join(app.loadDir,"..","Icons","LeoApp16.ico")
				icon = wx.wxIcon(path,wx.wxBITMAP_TYPE_ICO,16,16)
				self.SetIcon(icon)
			#@-node:<< set the window icon >>
			#@nl
			#@	<< declare event handlers for frame >>
			#@+node:<< declare event handlers for frame >>
			if wx.wxPlatform == "__WXMSW__": # Activate events exist only on Windows.
				wx.EVT_ACTIVATE(self,self.onActivate)
			else:
				wx.EVT_SET_FOCUS(self,self.OnSetFocus)
			
			wx.EVT_CLOSE(self,self.onCloseLeoFrame)
			
			wx.EVT_MENU_OPEN(self,self.updateAllMenus) 
			
			if 0: # Causes problems at present.  The screen isn't drawn properly.
				wx.EVT_SIZE(self,self.onResize)
			#@nonl
			#@-node:<< declare event handlers for frame >>
			#@nl
			
			if 0: # Not ready yet...
				self.wxApp.SetTopWindow(self.wxFrame)
				self.wxFrame.Show(true)
				if not app.root:
					app.root = self.wxFrame
					
			self.colorizer = leoColor.colorizer(c)
					
			c.initVersion()
			self.signOnWithVersion()
			
			self.injectCallbacks()
		
			# Add the frame to the global window list.
			app.windowList.append(self)
			self.tree.redraw()
			self.Show(true) # required on some platforms: a cross-platform bug.
		#@nonl
		#@-node:finishCreate
		#@+node:initialRatios
		def initialRatios (self):
		
			config = app.config
			s = config.getWindowPref("initial_splitter_orientation")
			verticalFlag = s == None or (s != "h" and s != "horizontal")
			
			# Tweaked for tk.  Other tweaks may be best for wx.
			if verticalFlag:
				r = config.getFloatWindowPref("initial_vertical_ratio")
				if r == None or r < 0.0 or r > 1.0: r = 0.5
				r2 = config.getFloatWindowPref("initial_vertical_secondary_ratio")
				if r2 == None or r2 < 0.0 or r2 > 1.0: r2 = 0.8
			else:
				r = config.getFloatWindowPref("initial_horizontal_ratio")
				if r == None or r < 0.0 or r > 1.0: r = 0.3
				r2 = config.getFloatWindowPref("initial_horizontal_secondary_ratio")
				if r2 == None or r2 < 0.0 or r2 > 1.0: r2 = 0.8
		
			return verticalFlag,r,r2
		#@nonl
		#@-node:initialRatios
		#@+node:injectCallbacks
		def injectCallbacks(self):
			
			import leoNodes
			
			# Some callback is required.
			def doNothingCallback(*args,**keys):
				pass
		
			for name in (
				"OnBoxClick","OnDrag","OnEndDrag",
				"OnHeadlineClick","OnHeadlineRightClick","OnHeadlineKey",
				"OnHyperLinkControlClick","OnHyperLinkEnter","OnHyperLinkLeave",
				"OnIconClick","OnIconDoubleClick","OnIconRightClick"):
		
				# trace(f)
				funcToMethod(doNothingCallback,leoNodes.vnode,name=name)
		#@nonl
		#@-node:injectCallbacks
		#@+node:signOnWithVersion
		def signOnWithVersion (self):
		
			c = self.c
			color = app.config.getWindowPref("log_error_color")
			signon = c.getSignOnLine()
			n1,n2,n3,junk,junk=sys.version_info
			
			es("Leo Log Window...",color=color)
			es(signon)
			es("Python %d.%d.%d wxWindows %s" % (n1,n2,n3,wx.wxVERSION_STRING))
			enl()
		#@nonl
		#@-node:signOnWithVersion
		#@+node:destroySelf
		def destroySelf(self):
			
			self.Destroy()
		#@nonl
		#@-node:destroySelf
		#@+node:onActivate & OnSetFocus
		if wx.wxPlatform == '__WXMSW__':
			
			def onActivate(self,event):
				if event.GetActive():
					self.activeFrame = self
					if self.c:
						pass ## self.c.checkAllFileDates()
		else:
			
			def OnSetFocus(self,event):
				self.activeFrame = self
				if self.c:
					self.c.checkAllFileDates()
		#@-node:onActivate & OnSetFocus
		#@+node:onCloseLeoFrame
		def onCloseLeoFrame(self,event):
		
			frame = self
			
			# The app class does all the hard work now.
			if not app.closeLeoWindow(frame):
				if event.CanVeto():
					event.Veto()
		#@nonl
		#@-node:onCloseLeoFrame
		#@+node:onResize
		def onResize(self,event):
		
			if mIniting:
				return # Can be called during initialization.
		
			# Resize splitter1 with equal sized panes.
			size = self.splitter1.GetClientSize()
			self.splitter1.SetClientSize(size)
			w = size.GetWidth() ; h = size.GetHeight()
			if self.splitter1.GetSplitMode()== wx.wxSPLIT_VERTICAL:
				self.splitter1.SetSashPosition(w/2,true)
			else:
				self.splitter1.SetSashPosition(h/2,true)
		
			# Resize splitter2 with equal sized panes.
			size = self.splitter2.GetClientSize()
			w = size.GetWidth() ; h = size.GetHeight()
			if self.splitter2.GetSplitMode()== wx.wxSPLIT_VERTICAL:
				self.splitter2.SetSashPosition((3*w)/5,true)
			else:
				self.splitter2.SetSashPosition((3*h)/5,true)
		#@-node:onResize
		#@+node:wxFrame dummy routines: (to do: minor)
		def after_idle(*args):
			pass
		
		def get_window_info (self):
			"""Return the window information."""
			return app.gui.get_window_info(self)
		
		def resizePanesToRatio(self,ratio1,ratio2):
			pass
		
		def setInitialWindowGeometry (self):
			pass
		
		def setTopGeometry(self,geom):
			pass
		
		def lift (self):
			self.Raise()
		
		def update (self):
			pass
		#@nonl
		#@-node:wxFrame dummy routines: (to do: minor)
		#@+node:deiconify
		def deiconify (self):
		
			self.Iconize(false)
		#@nonl
		#@-node:deiconify
		#@+node:getTitle
		def getTitle (self):
			
			return self.title
		#@-node:getTitle
		#@+node:setTitle
		def setTitle (self,title):
		
			self.title = title
			self.SetTitle(title) # Call the wx code.
		#@nonl
		#@-node:setTitle
		#@+node:abortEditLabelCommand
		def abortEditLabelCommand (self):
		
			es("abortEditLabelCommand not ready yet")
			return
			
			c = self.c ; v = c.currentVnode ; tree = self.tree
			# trace(v)
			if self.revertHeadline and v.edit_text() and v == self.editVnode:
				
				# trace(`self.revertHeadline`)
				v.edit_text().delete("1.0","end")
				v.edit_text().insert("end",self.revertHeadline)
				tree.idle_head_key(v) # Must be done immediately.
				tree.revertHeadline = None
				tree.select(v)
				if v and len(v.t.joinList) > 0:
					# 3/26/03: changed redraw_now to force_redraw.
					tree.force_redraw() # force a redraw of joined headlines.
		#@nonl
		#@-node:abortEditLabelCommand
		#@+node:endEditLabelCommand
		def endEditLabelCommand (self):
			
			es("endEditLabelCommand not ready yet")
			return
		
			c = self.c ; tree = self.tree ; v = self.editVnode
		
			if v and v.edit_text():
				tree.select(v)
		
			if v: # Bug fix 10/9/02: also redraw ancestor headlines.
				# 3/26/03: changed redraw_now to force_redraw.
				tree.force_redraw() # force a redraw of joined headlines.
		
			gui.set_focus(c,c.frame.bodyCtrl) # 10/14/02
		#@nonl
		#@-node:endEditLabelCommand
		#@+node:insertHeadlineTime
		def insertHeadlineTime (self):
			
			es("insertHeadlineTime not ready yet")
			return
		
			frame = self ; c = frame.c ; v = c.currentVnode()
			h = v.headString() # Remember the old value.
		
			if v.edit_text():
				sel1,sel2 = app.gui.getTextSelection(v.edit_text())
				if sel1 and sel2 and sel1 != sel2: # 7/7/03
					v.edit_text().delete(sel1,sel2)
				v.edit_text().insert("insert",c.getTime(body=false))
				frame.idle_head_key(v)
		
			# A kludge to get around not knowing whether we are editing or not.
			if h.strip() == v.headString().strip():
				es("Edit headline to append date/time")
		#@nonl
		#@-node:insertHeadlineTime
		#@+node:cascade
		def cascade(self):
			
			es("cascade not ready yet")
			return
		
			x,y,delta = 10,10,10
			for frame in app.windowList:
				top = frame.top
				# Compute w,h
				top.update_idletasks() # Required to get proper info.
				geom = top.geometry() # geom = "WidthxHeight+XOffset+YOffset"
				dim,junkx,junky = string.split(geom,'+')
				w,h = string.split(dim,'x')
				w,h = int(w),int(h)
				# Set new x,y and old w,h
				geom = "%dx%d%+d%+d" % (w,h,x,y)
				frame.setTopGeometry(geom) # frame.top.geometry("%dx%d%+d%+d" % (w,h,x,y))
				# Compute the new offsets.
				x += 30 ; y += 30
				if x > 200:
					x = 10 + delta ; y = 40 + delta
					delta += 10
		#@-node:cascade
		#@+node:equalSizedPanes
		def equalSizedPanes(self):
			
			es("equalSizedPanes not ready yet")
			return
		
			frame = self
			frame.resizePanesToRatio(0.5,frame.secondary_ratio)
		#@-node:equalSizedPanes
		#@+node:hideLogWindow
		def hideLogWindow (self):
			
			es("hideLogWindow not ready yet")
			return
			
			frame = self
			frame.divideLeoSplitter2(0.99, not frame.splitVerticalFlag)
		#@nonl
		#@-node:hideLogWindow
		#@+node:minimizeAll
		def minimizeAll(self):
			
			es("minimizeAll not ready yet")
			return
		
			self.minimize(app.findFrame)
			self.minimize(app.pythonFrame)
			for frame in app.windowList:
				self.minimize(frame)
			
		def minimize(self, frame):
		
			if frame:
				frame.Show(false)
		#@nonl
		#@-node:minimizeAll
		#@+node:toggleActivePane
		def toggleActivePane(self):
			
			# This can't work from the menu...
			
			es("toggleActivePane not ready yet")
			return
		
			if self.FindFocus() == self.body.bodyCtrl:
				self.tree.SetFocus()
			else:
				self.body.bodyCtrl.SetFocus()
		#@nonl
		#@-node:toggleActivePane
		#@+node:toggleSplitDirection
		# The key invariant: self.splitVerticalFlag tells the alignment of the main splitter.
		def toggleSplitDirection(self):
			
			es("toggleSplitDirection not ready yet")
			return
		
			# Abbreviations.
			frame = self
			bar1 = self.bar1 ; bar2 = self.bar2
			split1Pane1,split1Pane2 = self.split1Pane1,self.split1Pane2
			split2Pane1,split2Pane2 = self.split2Pane1,self.split2Pane2
			# Switch directions.
			verticalFlag = self.splitVerticalFlag = not self.splitVerticalFlag
			orientation = choose(verticalFlag,"vertical","horizontal")
			app.config.setWindowPref("initial_splitter_orientation",orientation)
			# Reconfigure the bars.
			bar1.place_forget()
			bar2.place_forget()
			self.configureBar(bar1,verticalFlag)
			self.configureBar(bar2,not verticalFlag)
			# Make the initial placements again.
			self.placeSplitter(bar1,split1Pane1,split1Pane2,verticalFlag)
			self.placeSplitter(bar2,split2Pane1,split2Pane2,not verticalFlag)
			# Adjust the log and body panes to give more room around the bars.
			self.reconfigurePanes()
			# Redraw with an appropriate ratio.
			vflag,ratio,secondary_ratio = frame.initialRatios()
			self.resizePanesToRatio(ratio,secondary_ratio)
		#@nonl
		#@-node:toggleSplitDirection
		#@+node:leoHelp
		def leoHelp (self):
			
			es("leoHelp not ready yet")
			
			return ##
			
			file = os.path.join(app.loadDir,"..","doc","sbooks.chm")
			file = toUnicode(file,app.tkEncoding) # 10/20/03
		
			if os.path.exists(file):
				os.startfile(file)
			else:	
				answer = app.gui.runAskYesNoDialog(
					"Download Tutorial?",
					"Download tutorial (sbooks.chm) from SourceForge?")
		
				if answer == "yes":
					try:
						if 0: # Download directly.  (showProgressBar needs a lot of work)
							url = "http://umn.dl.sourceforge.net/sourceforge/leo/sbooks.chm"
							import urllib
							self.scale = None
							urllib.urlretrieve(url,file,self.showProgressBar)
							if self.scale:
								self.scale.destroy()
								self.scale = None
						else:
							url = "http://prdownloads.sourceforge.net/leo/sbooks.chm?download"
							import webbrowser
							os.chdir(app.loadDir)
							webbrowser.open_new(url)
					except:
						es("exception dowloading sbooks.chm")
						es_exception()
		#@nonl
		#@-node:leoHelp
		#@+node:showProgressBar
		def showProgressBar (self,count,size,total):
		
			# trace("count,size,total:" + `count` + "," + `size` + "," + `total`)
			if self.scale == None:
				#@		<< create the scale widget >>
				#@+node:<< create the scale widget >>
				Tk = Tkinter
				top = Tk.Toplevel()
				top.title("Download progress")
				self.scale = scale = Tk.Scale(top,state="normal",orient="horizontal",from_=0,to=total)
				scale.pack()
				top.lift()
				#@nonl
				#@-node:<< create the scale widget >>
				#@nl
			self.scale.set(count*size)
			self.scale.update_idletasks()
		#@nonl
		#@-node:showProgressBar
		#@+node:updateAllMenus (wxFrame)
		def updateAllMenus(self,event):
			
			"""Called whenever any menu is pulled down."""
			
			# We define this routine to strip off the even param.
			
			self.menu.updateAllMenus()
		#@nonl
		#@-node:updateAllMenus (wxFrame)
		#@-others
	#@nonl
	#@-node:wxLeoFrame class
	#@+node:wxLeoLog class
	class wxLeoLog (leoFrame.leoLog):
		
		"""The base class for the log pane in Leo windows."""
		
		#@	@+others
		#@+node:leoLog.__init__
		def __init__ (self,frame,parentFrame):
			
			self.frame = frame
			self.c = frame.c
			self.newlines = 0
		
			self.logCtrl = self.createControl(parentFrame)
			self.setFontFromConfig()
		#@-node:leoLog.__init__
		#@+node:leoLog.configure
		def configure (self,*args,**keys):
			
			trace(args,keys)
		#@nonl
		#@-node:leoLog.configure
		#@+node:leoLog.configureBorder
		def configureBorder(self,border):
			
			trace(border)
		#@-node:leoLog.configureBorder
		#@+node:leoLog.createControl
		def createControl (self,parentFrame):
		
			ctrl = wx.wxTextCtrl(parentFrame,
				const("cLogCtrl"), "",
				wx.wxDefaultPosition, wx.wxDefaultSize,
				wx.wxTE_MULTILINE )
				
			return ctrl
		#@nonl
		#@-node:leoLog.createControl
		#@+node:leoLog.setLogFontFromConfig
		def setFontFromConfig (self):
			
			pass # trace()
		#@nonl
		#@-node:leoLog.setLogFontFromConfig
		#@+node:wxLeoLog.put & putnl
		# All output to the log stream eventually comes here.
		
		def put (self,s,color=None):
		
			if self.logCtrl:
				self.logCtrl.AppendText(s)
		
		def putnl (self):
		
			if self.logCtrl:
				self.logCtrl.AppendText('\n')
		#@nonl
		#@-node:wxLeoLog.put & putnl
		#@-others
	#@nonl
	#@-node:wxLeoLog class
	#@+node:wxLeoMenu class
	class wxLeoMenu (leoMenu.leoMenu):
		
		"""A class that represents a wxPython Leo window."""
		
		#@	@+others
		#@+node:  wxLeoMenu.__init__
		def __init__ (self,frame):
			
			# Init the base class.
			leoMenu.leoMenu.__init__(self,frame)
			
			# Init the ivars.
			self.c = frame.c
			self.frame = frame
			
			self.menuDict = {}
		#@nonl
		#@-node:  wxLeoMenu.__init__
		#@+node:add_cascade
		def add_cascade (self,parent,label,menu,underline):
		
			"""Create a menu with the given parent menu."""
		
			if parent:
				# Create a submenu of the parent menu.
				id = const(label)
				parent.AppendMenu(id,label,menu,label)
			else:
				# Create a top-level menu.
				self.menuBar.Append(menu,label)
		#@nonl
		#@-node:add_cascade
		#@+node:add_command
		def add_command (self,menu,**keys):
			
			label    = keys.get("label")
			callback = keys.get("command")
		
			if menu:
				id = const(label)
				menu.Append(id,label,label)
				key = (menu,label),
				self.menuDict[key] = id # Remember id 
				# trace(label,callback)
				wx.EVT_MENU(self.frame,id,callback)
			else:
				trace("no menu",label)
		
		#@-node:add_command
		#@+node:add_separator
		def add_separator(self,menu):
			
			if menu:
				menu.AppendSeparator()
			else:
				trace("null menu")
		#@nonl
		#@-node:add_separator
		#@+node:bind (wx has a different key model than tk)
		def bind (self,bind_shortcut,callback):
			
			# trace(bind_shortcut,callback)
			
			pass
		#@nonl
		#@-node:bind (wx has a different key model than tk)
		#@+node:delete (not called?)
		def delete (self,menu,readItemName):
			
			trace(menu,readItemName)
			
			## return menu.delete(realItemName)
		#@-node:delete (not called?)
		#@+node:delete_range
		def delete_range (self,menu,n1,n2):
			
			if not menu:
				trace("no menu")
				return
				
			# trace(n1,n2,menu.GetTitle())
			
			items = menu.GetMenuItems()
			
			if 0: # debugging
				for item in items:
					id = item.GetId()
					item = menu.FindItemById(id)
					trace(item.GetText())
					
			## Doesn't work:  a problem with wxPython.
			
			if len(items) > n1 and len(items) > n2:
				i = n1
				while i <= n2:
					id = items[i].GetId()
					item = menu.FindItemById(id)
					trace("deleting:",item.GetText())
					menu.Delete(id)
					i += 1
		#@nonl
		#@-node:delete_range
		#@+node:destroy (not called ?)
		def destroy (self,menu):
			
			trace()
		
			## menu.destroy()
		#@nonl
		#@-node:destroy (not called ?)
		#@+node:insert_cascade
		def insert_cascade (self,parent,index,label,menu,underline):
		
			if not parent:
				self.menuBar.append(menu,label)
		#@nonl
		#@-node:insert_cascade
		#@+node:new_menu
		def new_menu(self,parent,tearoff=0):
			
			return wx.wxMenu()
		#@nonl
		#@-node:new_menu
		#@+node:createMenuBar
		def createMenuBar(self):
			
			self.menuBar = menuBar = wx.wxMenuBar()
		
			self.createMenusFromTables()
		
			self.frame.SetMenuBar(menuBar)
		#@nonl
		#@-node:createMenuBar
		#@+node:createOpenWithMenuFromTable (not ready yet)
		#@+at 
		#@nonl
		# Entries in the table passed to createOpenWithMenuFromTable are
		# tuples of the form (commandName,shortcut,data).
		# 
		# - command is one of "os.system", "os.startfile", "os.spawnl", 
		# "os.spawnv" or "exec".
		# - shortcut is a string describing a shortcut, just as for 
		# createMenuItemsFromTable.
		# - data is a tuple of the form (command,arg,ext).
		# 
		# Leo executes command(arg+path) where path is the full path to the 
		# temp file.
		# If ext is not None, the temp file has the given extension.
		# Otherwise, Leo computes an extension based on the @language 
		# directive in effect.
		#@-at
		#@@c
		
		def createOpenWithMenuFromTable (self,table):
			
			trace("Not ready yet")
			
			return ### Not ready yet
		
			app.openWithTable = table # Override any previous table.
			# Delete the previous entry.
			parent = self.getMenu("File")
			label = self.getRealMenuName("Open &With...")
			amp_index = label.find("&")
			label = label.replace("&","")
			try:
				index = parent.index(label)
				parent.delete(index)
			except:
				try:
					index = parent.index("Open With...")
					parent.delete(index)
				except: return
			# Create the "Open With..." menu.
			openWithMenu = Tkinter.Menu(parent,tearoff=0)
			self.setMenu("Open With...",openWithMenu)
			parent.insert_cascade(index,label=label,menu=openWithMenu,underline=amp_index)
			# Populate the "Open With..." menu.
			shortcut_table = []
			for triple in table:
				if len(triple) == 3: # 6/22/03
					shortcut_table.append(triple)
				else:
					es("createOpenWithMenuFromTable: invalid data",color="red")
					return
					
			# for i in shortcut_table: print i
			self.createMenuItemsFromTable("Open &With...",shortcut_table,openWith=1)
		#@-node:createOpenWithMenuFromTable (not ready yet)
		#@+node:defineMenuCallback
		def defineMenuCallback(self,command,name):
				
			# The first parameter must be event, and it must default to None.
			def callback(event=None,self=self,command=command,label=name):
				self.c.doCommand(command,label,event)
		
			return callback
		#@nonl
		#@-node:defineMenuCallback
		#@+node:defineOpenWithMenuCallback
		def defineOpenWithMenuCallback (self,command):
				
			# The first parameter must be event, and it must default to None.
			def callback(event,command=command):
				try: self.c.openWith(data=command)
				except: print traceback.print_exc()
		
			trace(`callback`)
			return callback
		#@nonl
		#@-node:defineOpenWithMenuCallback
		#@+node:disableMenu
		def disableMenu (self,menu,name):
			
			if not menu:
				trace("no menu",name)
				return
			
			realName = self.getRealMenuName(name)
			realName = realName.replace("&","")
			id = menu.FindItem(realName)
			if id:
				item = menu.FindItemById(id)
				item.Enable(0)
			else:
				trace("no item",name,val)
		#@nonl
		#@-node:disableMenu
		#@+node:enableMenu
		def enableMenu (self,menu,name,val):
			
			if not menu:
				trace("no menu",name,val)
				return
			
			realName = self.getRealMenuName(name)
			realName = realName.replace("&","")
			id = menu.FindItem(realName)
			if id:
				item = menu.FindItemById(id)
				val = choose(val,1,0)
				item.Enable(val)
			else:
				trace("no item",name,val)
		#@nonl
		#@-node:enableMenu
		#@+node:setMenuLabel
		def setMenuLabel (self,menu,name,label,underline=-1):
		
			if not menu:
				trace("no menu",name)
				return
				
			if type(name) == type(0):
				# "name" is actually an index into the menu.
				items = menu.GetMenuItems() # GetItemByPosition does not exist.
				if items and len(items) > name :
					id = items[name].GetId()
				else: id = None
			else:
				realName = self.getRealMenuName(name)
				realName = realName.replace("&","")
				id = menu.FindItem(realName)
		
			if id:
				item = menu.FindItemById(id)
				label = self.getRealMenuName(label)
				label = label.replace("&","")
				# trace(name,label)
				item.SetText(label)
			else:
				trace("no item",name,label)
		#@nonl
		#@-node:setMenuLabel
		#@-others
	#@nonl
	#@-node:wxLeoMenu class
	#@+node:wxLeoPrefs class
	class wxLeoPrefs (wx.wxFrame):
		#@	@+others
		#@+node:wxLeoPrefs.__init__
		def __init__(c):
			
			# Init the base frame.
			wxFrame.__init__(None,-1,"Leo Preferences",
				wx.wxPoint(50,50),wxDefaultSize,
				wxMINIMIZE_BOX | wxTHICK_FRAME | wxSYSTEM_MENU | wxCAPTION)
		
			self.c = c
			mPrefsPanel = PrefsPanel(self)
		
			# Resize to fit the panel.
			sizer = wxBoxSizer(wxVERTICAL)
			sizer.Add(mPrefsPanel)
			SetAutoLayout(true)# tell dialog to use sizer
			SetSizer(sizer) # actually set the sizer
			sizer.Fit(self)# set size to minimum size as calculated by the sizer
			sizer.SetSizeHints(self)# set size hints to honour mininum size
		
			# Set the window icon.
			if wx.wxPlatform == '__WXMSW__':
				self.SetIcon(wxIcon("LeoIcon"))
				
			#@	<< define event handlers for wxLeoPrefsFrame >>
			#@+node:<< define event handlers for wxLeoPrefsFrame >>
			wx.EVT_ACTIVATE(self,self.OnActivatePrefsFrame)
			wx.EVT_CLOSE(self,self.OnClosePrefsFrame)
			
			# Global options panel...
			wx.EVT_TEXT(self,cPrefsPageWidthText,self.OnPageWidthText)
			wx.EVT_CHECKBOX(self,cPrefsDoneBatCheckBox,self.OnDoneBatCheckBox)
			wx.EVT_CHECKBOX(self,cPrefsUnBatCheckBox,self.OnUnBatCheckBox)
			
			# Tangle options panel...
			wx.EVT_TEXT(self,cPrefsTangleDirectoryText,self.OnTangleDirectoryText)
			wx.EVT_CHECKBOX(self,cPrefsHeaderCheckBox,self.OnHeaderCheckBox)
			wx.EVT_CHECKBOX(self,cPrefsDocChunksCheckBox,self.OnDocChunksCheckBox)
			
			# Target language panel...
			wx.EVT_RADIOBOX(self,cPrefsTargetLanguageRadioBox,self.OnTargetLanguageRadioBox)
			#@nonl
			#@-node:<< define event handlers for wxLeoPrefsFrame >>
			#@nl
		#@nonl
		#@-node:wxLeoPrefs.__init__
		#@+node:initialize
		def initialize (self,void):
			
			# This may be called during construction.
			if not gPrefsFrame:  return
			s = ""
			if self.activeFrame:
				s += "%d" % self.activeFrame.mPageWidth
				mPrefsPanel.mPrefsPageWidthText.SetValue(s)
				mPrefsPanel.mPrefsDoneBatCheckBox.SetValue(self.activeFrame.mTangleBatchFlag)
				mPrefsPanel.mPrefsUnBatCheckBox.SetValue(self.activeFrame.mUntangleBatchFlag)
				mPrefsPanel.mPrefsTangleDirectoryText.SetValue(self.activeFrame.mDefaultDirectory)
				mPrefsPanel.mPrefsHeaderCheckBox.SetValue(self.activeFrame.mUseHeaderFlag)
				mPrefsPanel.mPrefsDocChunksCheckBox.SetValue(self.activeFrame.mOutputDocFlag)
				mPrefsPanel.mTargetLanguageRadioBox.SetSelection(languageToTarget(self.activeFrame.mTargetLanguage))
			else:
				s += "%d" % arg_page_width
				mPrefsPanel.mPrefsPageWidthText.SetValue(s)
				mPrefsPanel.mPrefsDoneBatCheckBox.SetValue(arg_tangle_batch)
				mPrefsPanel.mPrefsUnBatCheckBox.SetValue(arg_untangle_batch)
				# No global setting for director.
				mPrefsPanel.mPrefsHeaderCheckBox.SetValue(arg_use_header_flag)
				mPrefsPanel.mPrefsDocChunksCheckBox.SetValue(arg_output_doc_flag)
				mPrefsPanel.mTargetLanguageRadioBox.SetSelection(languageToTarget(arg_target_language))
		#@nonl
		#@-node:initialize
		#@+node:targetToLanguage (should be in Leo's core)
		if 0:
			def targetToLanguage(self,target):
				
				pass
		
				# switch(target)
				# case c_target: return c_language
				# case cweb_target: return cweb_language
				# case html_target: return html_language
				# case java_target: return java_language
				# case perl_target: return perl_language
				# case perlpod_target: return perlpod_language
				# case pascal_target: return pascal_language
				# case plain_text_target: return plain_text_language
				# case python_target: return python_language
				# default: return plain_text_language
		#@-node:targetToLanguage (should be in Leo's core)
		#@+node:languageToTarget (should be in Leo's core)
		def languageToTarget(self,language):
			
			pass
		
			# switch(language)
			# case c_language: return c_target
			# case cweb_language: return cweb_target
			# case html_language: return html_target
			# case java_language: return java_target
			# case pascal_language: return pascal_target
			# case perl_language: return perl_target
			# case perlpod_language: return perlpod_target
			# case plain_text_language: return plain_text_target
			# case python_language: return python_target
			# default: return plain_text_target
		#@nonl
		#@-node:languageToTarget (should be in Leo's core)
		#@+node:OnActivatePrefsFrame
		def OnActivatePrefsFrame(self,event):
		
			if gPrefsFrame and event.GetActive():
				gPrefsFrame.initialize()
		#@-node:OnActivatePrefsFrame
		#@+node:OnClosePrefsFrame
		#@+at 
		#@nonl
		# This is an event handler function called when the user has tried to 
		# close a frame or dialog box.
		# 
		# It is called via the  wxWindow::Close function, so that the 
		# application can also invoke the handler programmatically.  You 
		# should check whether the application is forcing the deletion of the 
		# window using CanVeto. If CanVeto returns FALSE, it is  not possible 
		# to skip window deletion; destroy the window using wxWindow::Destroy. 
		# If not, it is up to you whether you respond  by destroying the 
		# window.  If you don't destroy the window, you should call 
		# wxCloseEvent::Veto to let the calling code know that you did not 
		# destroy the  window. This allows the wxWindow::Close function to 
		# return TRUE or FALSE depending on whether the close instruction was  
		# honoured or not.
		#@-at
		#@@c
		
		def OnClosePrefsFrame(self,event):
		
			if event.CanVeto():
				event.Veto()# Did not destroy the window.
				self.Show(false) # Just hide the window.
			else:
				self.Destroy()
				gPrefsFrame = None
		#@-node:OnClosePrefsFrame
		#@+node:OnPageWidthText
		def OnPageWidthText(self,event):
			
			text = event.GetEventObject()
			s = text.GetValue()
		
			try:
				n = int(s)
				arg_page_width = default_page_width = n
				if self.activeFrame:
					self.activeFrame.mPageWidth = arg_page_width
			except: pass
		
		#@-node:OnPageWidthText
		#@+node:OnDoneBatCheckBox
		def OnDoneBatCheckBox(self,event):
			
			box =event.GetEventObject()
			arg_tangle_batch = default_tangle_batch = box.GetValue()
			if self.activeFrame:
				self.activeFrame.mTangleBatchFlag = arg_tangle_batch
		
		#@-node:OnDoneBatCheckBox
		#@+node:OnUnBatCheckBox
		def OnUnBatCheckBox(self,event):
			
			box = event.GetEventObject()
			arg_untangle_batch = default_untangle_batch = box.GetValue()
			if self.activeFrame:
				self.activeFrame.mUntangleBatchFlag = arg_untangle_batch
		
		#@-node:OnUnBatCheckBox
		#@+node:OnTangleDirectoryText
		def OnTangleDirectoryText(self,event):
		
			text = event.GetEventObject()
			s = text.GetValue()
			if self.activeFrame:
				self.activeFrame.mDefaultDirectory = s
				if self.activeFrame.mDefaultDirectory.Length()> 0:
					wxSetWorkingDirectory(self.activeFrame.mDefaultDirectory)
				elif self.activeFrame.mOpenDirectory.Length()> 0:
					wxSetWorkingDirectory(self.activeFrame.mOpenDirectory)
		#@nonl
		#@-node:OnTangleDirectoryText
		#@+node:OnHeaderCheckBox
		def OnHeaderCheckBox(self,event):
			
			box = event.GetEventObject()
			arg_use_header_flag = default_use_header_flag = box.GetValue()
			if self.activeFrame:
				self.activeFrame.mUseHeaderFlag = arg_use_header_flag
		
		#@-node:OnHeaderCheckBox
		#@+node:OnDocChunksCheckBox
		def OnDocChunksCheckBox(self,event):
			
			box = event.GetEventObject()
			arg_output_doc_flag = default_output_doc_flag = box.GetValue()
			if self.activeFrame:
				self.activeFrame.mOutputDocFlag = arg_output_doc_flag
		
		#@-node:OnDocChunksCheckBox
		#@+node:OnTargetLanguageRadioBox
		def OnTargetLanguageRadioBox(self,event):
			
			box = event.GetEventObject()
			targetIndex = box.GetSelection()
			default_target_language = arg_target_language = targetToLanguage(targetIndex)
		
			# Careful:  The @language or @nocolor will override this.
			if self.activeFrame:
				self.activeFrame.mTargetLanguage = arg_target_language
				c = self.activeFrame.c
				v = c.currentVnode()
				self.activeFrame.c.scanAllDirectives(v,cDontRequirePath,cDontIssueErrors)
		#@nonl
		#@-node:OnTargetLanguageRadioBox
		#@+node:PrefsPanel.__init__
		def __init__(frame):
			
			# Init the base class.
			wxPanel.__init__(frame,-1)
			
			topSizer = wxBoxSizer(wxVERTICAL)
			#@	<< Create the Global Options static box >>
			#@+node:<< Create the Global Options static box >>
			globalOptionsBox = wxStaticBox(self,-1,
				"Global Options",(10,10),(250,110),0,"")
			sizer = wxStaticBoxSizer(globalOptionsBox,wxVERTICAL)
			lineSizer = wxBoxSizer(wxHORIZONTAL)
			sizer.Add(0,5)# Extra vertical space.
			
			# Text control.
			mPrefsPageWidthText = wxTextCtrl(self,
				cPrefsPageWidthText,"132",
				wxDefaultPosition,wx.wxSize(50,25),0,wxDefaultValidator,"")
			
			lineSizer.Add(mPrefsPageWidthText)
			lineSizer.Add(20,0)# Width.
			
			# Label for text control.
			lineSizer.Add(
				wxStaticText(self,-1,"Page Width",
					(-1,10),(100,25),0,""),
				0,wxBORDER | wxTOP,5)# Vertical offset 5.
			sizer.Add(lineSizer)
			
			mPrefsDoneBatCheckBox = wxCheckBox(self,
				cPrefsDoneBatCheckBox,
				"Execute Leo_done.bat after Tangle",
				wxDefaultPosition,(235,25),0,wxDefaultValidator,"")
			sizer.Add(mPrefsDoneBatCheckBox)
			
			mPrefsUnBatCheckBox = wxCheckBox(self,
				cPrefsUnBatCheckBox,
				"Execute Leo_un.bat after Untangle",
				wxDefaultPosition,(235,25),0,wxDefaultValidator,"")
			sizer.Add(mPrefsUnBatCheckBox)
			#@nonl
			#@-node:<< Create the Global Options static box >>
			#@nl
			topSizer.Add(sizer)
			topSizer.Add(0,10)
			#@	<< Create the Default Tangle Options static box >>
			#@+node:<< Create the Default Tangle Options static box >>
			optionsBox = wxStaticBox(self,-1,
				"Default Tangle Options",
				wxDefaultPosition,wx.wxSize(250,210),
				0,"zzzz")
			
			sizer2 = wxStaticBoxSizer(optionsBox,wxVERTICAL)
			sizer2.Add(0,10)# Vertical space.
			# Label.
			sizer2.Add(
				wxStaticText(self,-1,
					"Default Tangle directory",
					wxDefaultPosition,wx.wxSize(165,25),0,""),
				0,wxBORDER | wxLEFT,30)# Indent 30.
			
			mPrefsTangleDirectoryText = wxTextCtrl(self,
				cPrefsTangleDirectoryText,"",
				wxDefaultPosition,wx.wxSize(230,25),0,
				wxDefaultValidator,"")
			sizer2.Add(mPrefsTangleDirectoryText)
			
			mPrefsHeaderCheckBox = wxCheckBox(self,
				cPrefsHeaderCheckBox,
				"Tangle outputs header line",
				wxDefaultPosition,wx.wxSize(235,25),0,
				wxDefaultValidator,"")
			sizer2.Add(mPrefsHeaderCheckBox)
			
			mPrefsDocChunksCheckBox = wxCheckBox(self,
				cPrefsDocChunksCheckBox,
				"Tangle outputs document chunks",
				wxDefaultPosition,wx.wxSize(235,25),0,
				wxDefaultValidator,"")
			sizer2.Add(mPrefsDocChunksCheckBox)
			#@nonl
			#@-node:<< Create the Default Tangle Options static box >>
			#@nl
			topSizer.Add(sizer2)
			topSizer.Add(0,10)
			#@	<< Create the Default Target Language radio buttons >>
			#@+node:<< Create the Default Target Language radio buttons >>
			targetLanguageChoices= [
				"C/C++","CWEB","HTML","Java",
				"Pascal","Perl","Perl + POD","Plain text","Python"]
				
			# We specify rows so that items will be sorted down the columns.
			mTargetLanguageRadioBox = wxRadioBox(self,
				cPrefsTargetLanguageRadioBox,
				"Default Target Language",
				wxDefaultPosition,wx.wxSize(245,145),
				WXSIZEOF(targetLanguageChoices),
				targetLanguageChoices,
				5,wxRA_SPECIFY_ROWS)
			#@nonl
			#@-node:<< Create the Default Target Language radio buttons >>
			#@nl
			topSizer.Add(mTargetLanguageRadioBox)
			SetAutoLayout(true)# tell dialog to use sizer
			SetSizer(topSizer) # actually set the sizer
			topSizer.Fit(self)# set size to minimum size as calculated by the sizer
			topSizer.SetSizeHints(self)# set size hints to honour mininum size
		#@nonl
		#@-node:PrefsPanel.__init__
		#@-others
	#@-node:wxLeoPrefs class
	#@+node:wxLeoTree class
	class wxLeoTree (leoFrame.leoTree):
		#@	@+others
		#@+node:__init__
		def __init__ (self,frame,parentFrame):
		
			# Init the base class.
			leoFrame.leoTree.__init__(self,frame)
		
			self.treeCtrl = wx.wxTreeCtrl(parentFrame,
				const("cTreeCtrl"),
				wx.wxDefaultPosition, wx.wxDefaultSize,
				wx.wxTR_HAS_BUTTONS | wx.wxTR_EDIT_LABELS, wx.wxDefaultValidator,
				"treeCtrl")
		
			self.root_id = None
			
			#@	<< declare event handlers >>
			#@+node:<< declare event handlers >>
			id = const("cTreeCtrl")
			
			wx.EVT_TREE_KEY_DOWN        (self.treeCtrl,id,self.onTreeKeyDown) # Control keys do not fire this event.
			wx.EVT_TREE_SEL_CHANGED     (self.treeCtrl,id,self.onTreeChanged)
			wx.EVT_TREE_SEL_CHANGING    (self.treeCtrl,id,self.onTreeChanging)
			wx.EVT_TREE_BEGIN_DRAG      (self.treeCtrl,id,self.onTreeBeginDrag)
			wx.EVT_TREE_END_DRAG        (self.treeCtrl,id,self.onTreeEndDrag)
			wx.EVT_TREE_BEGIN_LABEL_EDIT(self.treeCtrl,id,self.onTreeBeginLabelEdit)
			wx.EVT_TREE_END_LABEL_EDIT  (self.treeCtrl,id,self.onTreeEndLabelEdit)
			
			 
			wx.EVT_TREE_ITEM_COLLAPSED  (self.treeCtrl,id,self.onTreeCollapsed)
			wx.EVT_TREE_ITEM_EXPANDED   (self.treeCtrl,id,self.onTreeExpanded)
			
			wx.EVT_TREE_ITEM_COLLAPSING (self.treeCtrl,id,self.onTreeCollapsing)
			wx.EVT_TREE_ITEM_EXPANDING  (self.treeCtrl,id,self.onTreeExpanding)
			#@nonl
			#@-node:<< declare event handlers >>
			#@nl
		#@nonl
		#@-node:__init__
		#@+node:expandAllAncestors
		def expandAllAncestors(self,v):
			trace()
		#@nonl
		#@-node:expandAllAncestors
		#@+node:Drawing  & scrolling TO DO
		def drawIcon(self,v,x,y):
			trace(v)
		
		# Scrolling... 
		def scrollTo(self,v):
			trace()
		
		def idle_scrollTo(self,v):
			pass
		#@nonl
		#@-node:Drawing  & scrolling TO DO
		#@+node:Editing TO DO
		def editLabel(self,v):
			pass
		
		def editVnode(self):
			pass
		
		def endEditLabel(self):
			pass
			
		def setEditVnode(self,v):
			pass
		
		def setNormalLabelState(self,v):
			pass
		
		def OnActivateHeadline(self,v):
			trace()
		#@nonl
		#@-node:Editing TO DO
		#@+node:Focus
		def focus_get(self):
			
			return self.FindFocus()
		#@nonl
		#@-node:Focus
		#@+node:Fonts TO DO
		def getFont(self):
			trace()
		
		def setFont(self,font):
			trace()
		#@nonl
		#@-node:Fonts TO DO
		#@+node:beginUpdate
		def beginUpdate (self):
			
			if self.updateCount == 0:
				pass # self.Freeze() # Seems not to work...
		
			self.updateCount += 1
		#@nonl
		#@-node:beginUpdate
		#@+node:endUpdate
		def endUpdate (self,flag=true):
		
			assert(self.updateCount > 0)
		
			self.updateCount -= 1
			if flag and self.updateCount == 0:
				## self.Thaw()
				self.redraw()
		#@nonl
		#@-node:endUpdate
		#@+node:redraw & redraw_now
		def redraw (self):
		
			# trace(self.drawing)
			self.drawing = true # Tell event handlers not to call us.
		
			c = self.c ; tree = self.treeCtrl
			if c is None: return
			v = c.rootVnode()
			if v is None: return
		
			tree.DeleteAllItems()
			self.root_id = root_id = tree.AddRoot("Leo Outline Pane")
			while v:
				self.redraw_subtree(root_id,v)
				v = v.next()
			tree.Expand(root_id)
			
			self.drawing = false
				
		def redraw_now(self):
			trace()
			self.redraw()
		#@nonl
		#@-node:redraw & redraw_now
		#@+node:redraw_node
		def redraw_node(self,parent_id,v):
			
			# trace(v)
			tree = self.treeCtrl
			data = wx.wxTreeItemData(v)
			id = tree.AppendItem(parent_id,v.headString(),data=data)
			v.wxTreeId = id # Inject the ivar into the vnode.
			assert (v == tree.GetItemData(id).GetData())
			return id
			
		#@nonl
		#@-node:redraw_node
		#@+node:redraw_subtree
		def redraw_subtree(self,parent_id,v):
			
			# trace(v)
			tree = self.treeCtrl
			id = self.redraw_node(parent_id,v)
			child = v.firstChild()
			
			if v.isExpanded():
				while child:
					self.redraw_subtree(id,child)
					child = child.next()
				tree.Expand(id)
			else:
				if 1: # tree.SetItemHasChildren changes the event handler logic.  So this is good enough.
					while child:
						self.redraw_node(id,child)
						child = child.next()
				else:
					if child:
						tree.SetItemHasChildren(id)
				tree.Collapse(id)
		#@nonl
		#@-node:redraw_subtree
		#@+node:select
		# Warning: do not try to "optimize" this by returning if v==tree.currentVnode.
		
		def select (self,v,updateBeadList=true):
		
			c = self.c ; frame = c.frame ; body = frame.bodyCtrl
			old_v = c.currentVnode()
		
			if not doHook("unselect1",c=c,new_v=v,old_v=old_v):
				if 0: ## Not ready yet.
					#@			<< unselect the old node >>
					#@+node:<< unselect the old node >>
					# Remember the position of the scrollbar before making any changes.
					yview = body.yview()
					insertSpot = c.frame.body.getInsertionPoint()
					
					# Remember the old body text
					old_body = body.getAllText()
					
					if old and old != v and old.edit_text():
						old.t.scrollBarSpot = yview
						old.t.insertSpot = insertSpot
					#@-node:<< unselect the old node >>
					#@nl
			else: old_body = u""
		
			doHook("unselect2",c=c,new_v=v,old_v=old_v)
			
			if not doHook("select1",c=c,new_v=v,old_v=old_v):
				#@		<< select the new node >>
				#@+node:<< select the new node >>
				if 0: # Done in event handler??
				
					frame.setWrap(v)
				
					# Delete only if necessary: this may reduce flicker slightly.
					s = v.t.bodyString
					s = toUnicode(s,"utf-8")
					old_body = toUnicode(old_body,"utf-8")
					if old_body != s:
						body.delete("1.0","end")
						body.insert("1.0",s)
				
					# We must do a full recoloring: we may be changing context!
					self.frame.body.recolor_now(v)
				
					if v and v.t.scrollBarSpot != None:
						first,last = v.t.scrollBarSpot
						body.yview("moveto",first)
				
					if v.t.insertSpot != None: # 9/21/02: moved from c.selectVnode
						c.frame.bodyCtrl.mark_set("insert",v.t.insertSpot)
						c.frame.bodyCtrl.see(v.t.insertSpot)
					else:
						c.frame.bodyCtrl.mark_set("insert","1.0")
				#@nonl
				#@-node:<< select the new node >>
				#@nl
				if v and v != old_v: # 3/26/03: Suppress duplicate call.
					try: # may fail during initialization
						self.idle_scrollTo(v)
					except: pass
				#@		<< update c.beadList or c.beadPointer >>
				#@+node:<< update c.beadList or c.beadPointer >>
				if updateBeadList:
					
					if c.beadPointer > -1:
						present_v = c.beadList[c.beadPointer]
					else:
						present_v = None
					
					if v != present_v:
						# Replace the tail of c.beadList by c and make c the present node.
						# print "updating c.beadList"
						c.beadPointer += 1
						c.beadList[c.beadPointer:] = []
						c.beadList.append(v)
						
					# trace(c.beadPointer,v,present_v)
				#@nonl
				#@-node:<< update c.beadList or c.beadPointer >>
				#@nl
				#@		<< update c.visitedList >>
				#@+node:<< update c.visitedList >>
				# Make v the most recently visited node on the list.
				if v in c.visitedList:
					c.visitedList.remove(v)
					
				c.visitedList.insert(0,v)
				#@nonl
				#@-node:<< update c.visitedList >>
				#@nl
		
			#@	<< set the current node and redraw >>
			#@+node:<< set the current node and redraw >>
			self.setCurrentVnode(v)
			
			if 0: ## Not ready yet
				self.setSelectedLabelState(v)
				self.scanForTabWidth(v) # 9/13/02 #GS I believe this should also get into the select1 hook.
			
			app.gui.set_focus(c,c.frame.bodyCtrl)
			#@nonl
			#@-node:<< set the current node and redraw >>
			#@nl
			doHook("select2",c=c,new_v=v,old_v=old_v)
			doHook("select3",c=c,new_v=v,old_v=old_v)
		#@-node:select
		#@+node:onTreeCollapsed & onTreeExpanded
		def onTreeCollapsed(self,event):
			
			"""Prepare to collapse the tree."""
		
			pass # No need to redraw the tree.
		
		def onTreeExpanded (self,event):
			
			"""Redraw the tree when a tree collapses."""
		
			if not self.frame.lockout and not self.drawing:
		
				self.redraw()
		#@nonl
		#@-node:onTreeCollapsed & onTreeExpanded
		#@+node:onTreeCollapsing & onTreeExpanding
		def onTreeCollapsing(self,event):
			
			"""Call v.contract for a later redraw."""
		
			tree = self.treeCtrl
			id = event.GetItem()
			if id.IsOk and not self.frame.lockout:
				v = tree.GetItemData(id).GetData()
				if v:
					#trace(v)
					v.contract()
			
		def onTreeExpanding (self,event):
			
			"""Call v.expand for a later redraw."""
			
			tree = self.treeCtrl
			id = event.GetItem()
			if id.IsOk and not self.frame.lockout:
				v = tree.GetItemData(id).GetData()
				if v:
					#trace(v)
					v.expand()
		#@nonl
		#@-node:onTreeCollapsing & onTreeExpanding
		#@+node:onTreeChanged
		def onTreeChanged(self,event):
		
			frame = self ; c = self.c ; tree = self.treeCtrl
			
			if self.frame.lockout > 0: return 
		 	new_id = event.GetItem()
			if not new_id.IsOk(): return
			v = tree.GetItemData(new_id).GetData()
			if not v: return
		
			self.frame.lockout += 1 # MUST prevent further events.
			
			c.selectVnode(v)
			s = v.t.bodyString
			s = toUnicode(s,"utf-8")  # No app.tkEncoding or similar yet.
			t = self.frame.body.bodyCtrl
			t.Clear()
			t.WriteText(s)
			self.frame.body.recolor(v)
			
			self.frame.lockout -= 1
		#@nonl
		#@-node:onTreeChanged
		#@+node:onTreeChanging
		def onTreeChanging(self,event):
			
			"""Event handler gets called whenever a new node gets selected"""
		
			# trace()
			pass
		#@nonl
		#@-node:onTreeChanging
		#@+node:onTreeBeginLabelEdit
		# Editing is allowed only if this routine exists.
		
		def onTreeBeginLabelEdit(self,event):
		
			# Disallow editing of the dummy root node.
			id = event.GetItem()
			if id == self.root_id:
				event.Veto()
		#@nonl
		#@-node:onTreeBeginLabelEdit
		#@+node:onTreeEndLabelEdit
		# Editing will be allowed only if this routine exists.
		
		def onTreeEndLabelEdit(self,event):
		
			tree = self.treeCtrl
			s = event.GetLabel()
			id = event.GetItem()
			v = tree.GetItemData(id).GetData()
		
			return # Not yet: c.setChanged uses frame.top.
		
			# Set the dirty bit and the file-changed mark if the headline has changed.
			if not v.isDirty()and s != v.headString():
				v.setDirty()
				if not self.c.isChanged():
					self.c.setChanged(true)
		
			# Update all joined headlines.
			j = v.joinList()
			while j != v:
				j.setHeadString(s)
				j = j.joinList()
		#@nonl
		#@-node:onTreeEndLabelEdit
		#@+node:onTreeKeyDown
		def onTreeKeyDown(self,event):
			
			pass # Don't do anything until the end-edit event.
		#@nonl
		#@-node:onTreeKeyDown
		#@+node:onTreeBeginDrag
		def onTreeBeginDrag(self,event):
		
			trace() ; return
		
			if event.GetItem()!= self.treeCtrl.GetRootItem():
				mDraggedItem = event.GetItem()
				event.Allow()
		#@-node:onTreeBeginDrag
		#@+node:onTreeEndDrag (NOT READY YET)
		def onTreeEndDrag(self,event):
			
			trace() ; return
		
			#@	<< Define onTreeEndDrag vars >>
			#@+node:<< Define onTreeEndDrag vars >>
			assert(self.tree)
			assert(self.c)
			
			dst = event.GetItem()
			src = mDraggedItem
			mDraggedItem = 0
			
			if not dst.IsOk() or not src.IsOk():
				return
			
			src_v = self.tree.GetItemData(src)
			if src_v == None:
				return
			
			dst_v =self.tree.GetItemData(dst)
			if dst_v == None:
				return
			
			parent = self.tree.GetParent(dst)
			parent_v = None
			#@nonl
			#@-node:<< Define onTreeEndDrag vars >>
			#@nl
			if  src == 0 or dst == 0:  return
			cookie = None
			if (
				# dst is the root
				not parent.IsOk()or
				# dst has visible children and dst isn't the first child.
				self.tree.ItemHasChildren(dst)and self.tree.IsExpanded(dst)and
				self.tree.GetFirstChild(dst,cookie) != src or
				# back(src)== dst(would otherwise be a do-nothing)
				self.tree.GetPrevSibling(src) == dst):
				#@		<< Insert src as the first child of dst >>
				#@+node:<< Insert src as the first child of dst >>
				# Make sure the drag will be valid.
				parent_v = self.tree.GetItemData(dst)
				
				if not self.c.checkMoveWithParentWithWarning(src_v,parent_v,true):
					return
				
				src_v.moveToNthChildOf(dst_v,0)
				#@nonl
				#@-node:<< Insert src as the first child of dst >>
				#@nl
			else:
				# Not the root and no visible children.
				#@		<< Insert src after dst >>
				#@+node:<< Insert src after dst >>
				# Do nothing if dst is a child of src.
				p = parent
				while p.IsOk():
					if p == src:
						return
					p = self.tree.GetParent(p)
				
				# Do nothing if dst is joined to src.
				if dst_v.isJoinedTo(src_v):
					return
				
				# Make sure the drag will be valid.
				parent_v = self.tree.GetItemData(parent)
				if not self.c.checkMoveWithParentWithWarning(src_v,parent_v,true):
					return
				
				src_v.moveAfter(dst_v)
				#@nonl
				#@-node:<< Insert src after dst >>
				#@nl
			self.c.selectVnode(src_v)
			self.c.setChanged(true)
		#@-node:onTreeEndDrag (NOT READY YET)
		#@-others
	#@-node:wxLeoTree class
	#@+node:wxSearchWidget
	class wxSearchWidget:
	
		"""A dummy widget class to pass to Leo's core find code."""
	
		#@	@+others
		#@+node:wxSearchWidget.__init__
		def __init__ (self):
			
			self.insertPoint = 0
			self.selection = 0,0
			self.bodyCtrl = self
			self.body = self
			self.text = None
		#@nonl
		#@-node:wxSearchWidget.__init__
		#@+node:Insert point
		# Simulating wxWindows calls (upper case)
		def GetInsertionPoint (self):
			return self.insertPoint
		
		def SetInsertionPoint (self,index):
			self.insertPoint = index
			
		def SetInsertionPointEND (self,index):
			self.insertPoint = len(self.text)+1
		
		# Returning indices...
		def getBeforeInsertionPoint (self):
			trace()
		
		# Returning chars...
		def getCharAtInsertPoint (self):
			trace()
		
		def getCharBeforeInsertPoint (self):
			trace()
		
		# Setting the insertion point...
		def setInsertPointToEnd (self):
			self.insertPoint = -1
			
		def setInsertPointToStartOfLine (self,lineNumber):
			trace()
		#@nonl
		#@-node:Insert point
		#@+node:Selection
		# Simulating wxWindows calls (upper case)
		def SetSelection(self,n1,n2):
			self.selection = n1,n2
			
		# Others...
		def deleteSelection (self):
			self.selection = 0,0
		
		def getTextSelection (self):
			return self.selection
			
		def hasTextSelection (self):
			start,end = self.selection
			return start != end
		
		def selectAllText (self):
			self.selection = 0,-1
		
		def setTextSelection (self,sel):
			try:
				start,end = sel
				self.selection = start,end
			except:
				self.selection = sel,sel
		#@nonl
		#@-node:Selection
		#@-others
	#@nonl
	#@-node:wxSearchWidget
	#@+node:wxFindFrame class
	class wxFindFrame (wx.wxFrame,leoFind.leoFind):
	
		#@	@+others
		#@+node:FindFrame.__init__
		def __init__ (self):
		
			# Init the base classes
			wx.wxFrame.__init__(self,None,-1,"Leo Find/Change",
				wx.wxPoint(50,50), wx.wxDefaultSize,
				wx.wxMINIMIZE_BOX | wx.wxTHICK_FRAME | wx.wxSYSTEM_MENU | wx.wxCAPTION)
		
			leoFind.leoFind.__init__(self)
			
			self.dict = {} # For communication between panel and frame.
			self.findPanel = wxFindPanel(self)
			
			self.s_text = wxSearchWidget() # wx.wxTextCtrl(self,-1) # Working text widget.
		
			#@	<< resize the frame to fit the panel >>
			#@+node:<< resize the frame to fit the panel >>
			sizer = wx.wxBoxSizer(wx.wxVERTICAL)
			sizer.Add(self.findPanel)
			self.SetAutoLayout(true)# tell dialog to use sizer
			self.SetSizer(sizer) # actually set the sizer
			sizer.Fit(self)# set size to minimum size as calculated by the sizer
			sizer.SetSizeHints(self)# set size hints to honour mininum size
			#@nonl
			#@-node:<< resize the frame to fit the panel >>
			#@nl
		
			# Set the window icon.
			if wx.wxPlatform == '__WXMSW__':
				pass ## self.SetIcon(wx.wxIcon("LeoIcon"))
		
			# Set the focus.
			self.findPanel.findText.SetFocus()
		
			#@	<< define event handlers >>
			#@+node:<< define event handlers >>
			wx.EVT_CLOSE(self,self.onCloseFindFrame)
			
			#@<< create event handlers for buttons >>
			#@+node:<< create event handlers for buttons >>
			for name,command in (
				("changeButton",self.changeButton),
				("changeAllButton",self.changeAllButton),
				("changeThenFindButton",self.changeThenFindButton),
				("findButton",self.findButton),
				("findAllButton",self.findAllButton)):
					
				def eventHandler(event,command=command):
					# trace(command)
					command()
			
				id = const_dict.get(name)
				assert(id)
				wx.EVT_BUTTON(self,id,eventHandler)
			#@nonl
			#@-node:<< create event handlers for buttons >>
			#@nl
			
			#@<< create event handlers for check boxes and text >>
			#@+node:<< create event handlers for check boxes and text >>
			textKeys = ["find_text","change_text"]
			keys = textKeys[:]
			for item in self.intKeys:
				keys.append(item)
			
			for name in keys:
			
				if name not in textKeys:
					name += "_flag"
			
				def eventHandler(event,self=self,name=name):
					box = event.GetEventObject()
					val = box.GetValue()
					# trace(name,val)
					setattr(self.c,name,val)
			
				id = const_dict.get(name)
				if id:
					if name in textKeys:
						wx.EVT_TEXT(self,id,eventHandler)
					else:
						wx.EVT_CHECKBOX(self,id,eventHandler)
			#@nonl
			#@-node:<< create event handlers for check boxes and text >>
			#@nl
			#@nonl
			#@-node:<< define event handlers >>
			#@nl
		#@-node:FindFrame.__init__
		#@+node:bringToFront
		def bringToFront (self):
			
			app.gui.bringToFront(self)
			self.c = top()
			self.init(self.c)
			self.findPanel.findText.SetFocus()
			self.findPanel.findText.SetSelection(-1,-1)
		#@nonl
		#@-node:bringToFront
		#@+node:destroySelf
		def destroySelf (self):
			
			self.Destroy()
		#@nonl
		#@-node:destroySelf
		#@+node:onCloseFindFrame
		def onCloseFindFrame (self,event):
		
			if event.CanVeto():
				event.Veto()
				self.Hide()
		#@nonl
		#@-node:onCloseFindFrame
		#@+node:set_ivars
		def set_ivars (self,c):
			
			"""Init the commander ivars from the find panel."""
			
			trace()
		
			# N.B.: separate c.ivars are much more convenient than a dict.
			for key in self.intKeys:
				key = key + "_flag"
				data = self.dict.get(key)
				if data:
					box,id = data
					val = box.GetValue()
					#trace(key,val)
					setattr(c,key,val)
				else:
					#trace("no data",key)
					setattr(c,key,false)
		
			fp = self.findPanel
			c.find_text = fp.findText.GetValue()
			c.change_text = fp.changeText.GetValue()
		#@nonl
		#@-node:set_ivars
		#@+node:init_s_text
		def init_s_text (self,s):
			
			c = self.c
			t = self.s_text # the dummy widget
		
			# Set the text for searching.
			t.text = s
			
			# Set the insertion point.
			if c.reverse_flag:
				t.SetInsertionPointEnd()
			else:
				t.SetInsertionPoint(0)
			return t
		#@nonl
		#@-node:init_s_text
		#@+node:gui_search
		def gui_search (self,t,find_text,index,
			stopindex,backwards,regexp,nocase):
				
			trace(index,stopindex,backwards,regexp,nocase)
			
			s = t.text # t is the dummy text widget
			
			if index is None:
				index = 0
		
			pos = s.find(find_text,index)
		
			if pos == -1:
				pos = None
			
			return pos
		#@nonl
		#@-node:gui_search
		#@+node:init
		def init (self,c):
		
			"""Init the find panel from c.
			
			(The opposite of set_ivars)."""
		
			# N.B.: separate c.ivars are much more convenient than a dict.
			for key in self.intKeys:
				key = key + "_flag"
				val = getattr(c,key)
				data = self.dict.get(key)
				if data:
					box,id = data
					box.SetValue(val)
					# trace(key,`val`)
		
			self.findPanel.findText.SetValue(c.find_text)
			self.findPanel.changeText.SetValue(c.change_text)
		#@nonl
		#@-node:init
		#@-others
	#@nonl
	#@-node:wxFindFrame class
	#@+node:wxFindPanel class
	class wxFindPanel (wx.wxPanel):
	
		#@	@+others
		#@+node:FindPanel.__init__
		def __init__(self,frame):
			 
			# Init the base class.
			wx.wxPanel.__init__(self,frame,-1)
			self.frame = frame
		
			topSizer = wx.wxBoxSizer(wx.wxVERTICAL)
			topSizer.Add(0,10)
		
			#@	<< Create the find text box >>
			#@+node:<< Create the find text box >>
			findSizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
			findSizer.Add(5,5)# Extra space.
			
			# Label.
			findSizer.Add(
				wx.wxStaticText(self,-1,"Find:",
					wx.wxPoint(-1,10), wx.wxSize(50,25),0,""),
				0, wx.wxBORDER | wx.wxTOP,15) # Vertical offset.
			
			findSizer.Add(10,0) # Width.
			
			# Text.
			id = const("find_text")
			self.findText = wx.wxTextCtrl(self,
				id,"",
				wx.wxDefaultPosition, wx.wxSize(500,60),
				wx.wxTE_PROCESS_TAB | wx.wxTE_MULTILINE,
				wx.wxDefaultValidator,"")
			
			findSizer.Add(self.findText)
			findSizer.Add(5,0)# Width.
			topSizer.Add(findSizer)
			topSizer.Add(0,10)
			
			self.frame.dict["find_text"] = self.findText,id
			#@nonl
			#@-node:<< Create the find text box >>
			#@nl
			#@	<< Create the change text box >>
			#@+node:<< Create the change text box >>
			changeSizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
			changeSizer.Add(5,5)# Extra space.
			
			# Label.
			changeSizer.Add(
				wx.wxStaticText(self,-1,"Change:",
					wx.wxPoint(-1,10),wx.wxSize(50,25),0,""),
				0, wx.wxBORDER | wx.wxTOP,15)# Vertical offset.
			
			changeSizer.Add(10,0) # Width.
			
			# Text.
			id = const("change_text")
			self.changeText = wx.wxTextCtrl(self,
				id,"",
				wx.wxDefaultPosition, wx.wxSize(500,60),
				wx.wxTE_PROCESS_TAB | wx.wxTE_MULTILINE,
				wx.wxDefaultValidator,"")
			
			changeSizer.Add(self.changeText)
			changeSizer.Add(5,0)# Width.
			topSizer.Add(changeSizer)
			topSizer.Add(0,10)
			
			self.frame.dict["change_text"] = self.findText,id
			#@nonl
			#@-node:<< Create the change text box >>
			#@nl
			#@	<< Create all the find check boxes >>
			#@+node:<< Create all the find check boxes >>
			col1Sizer = wx.wxBoxSizer(wx.wxVERTICAL)
			#@<< Create the first column of widgets >>
			#@+node:<< Create the first column of widgets >>
			# The var names must match the names in leoFind class.
			table = (
				("plain-search-flag","Plain Search",wx.wxRB_GROUP),
				("pattern_match_flag","Pattern Match",0),
				("script_search_flag","Script Search",0))
			
			for var,label,style in table:
				
				id = const(var)
				box = wx.wxRadioButton(self,id,label,
					wx.wxDefaultPosition,(100,25),
					style,wx.wxDefaultValidator,"group1")
					
				if style == wx.wxRB_GROUP:
					box.SetValue(true) # The default entry.
			
				col1Sizer.Add(box,0,wx.wxBORDER | wx.wxLEFT,60)
				self.frame.dict[var] = box,id
				
			table = (("script_change_flag","Script Change"),)
			
			for var,label in table:
				
				id = const(var)
				box = wx.wxCheckBox(self,id,label,
					wx.wxDefaultPosition,(100,25),
					0,wx.wxDefaultValidator,"")
			
				col1Sizer.Add(box,0,wx.wxBORDER | wx.wxLEFT,60)
				self.frame.dict[var] = box,id
			#@nonl
			#@-node:<< Create the first column of widgets >>
			#@nl
			
			col2Sizer = wx.wxBoxSizer(wx.wxVERTICAL)
			#@<< Create the second column of widgets >>
			#@+node:<< Create the second column of widgets >>
			# The var names must match the names in leoFind class.
			table = (
				("whole_word_flag","Whole Word"),
				("ignore_case_flag","Ignore Case"),
				("wrap_flag","Wrap Around"),
				("reverse_flag","Reverse"))
			
			for var,label in table:
			
				id = const(var)
				box = wx.wxCheckBox(self,id,label,
					wx.wxDefaultPosition,(100,25),
					0,wx.wxDefaultValidator,"")
			
				col2Sizer.Add(box,0,wx.wxBORDER | wx.wxLEFT,20)
				self.frame.dict[var] = box,id
			#@nonl
			#@-node:<< Create the second column of widgets >>
			#@nl
			
			col3Sizer = wx.wxBoxSizer(wx.wxVERTICAL)
			#@<< Create the third column of widgets >>
			#@+node:<< Create the third column of widgets >>
			# The var names must match the names in leoFind class.
			table = (
				("Entire Outline","entire-outline",wx.wxRB_GROUP),
				("Suboutline Only","suboutline_only_flag",0),  
				("Node Only","node_only_flag",0),    
				("Selection Only","selection-only",0))
				
			for label,var,group in table:
			
				if var: id = const(var)
				else:   id = const("entire-outline")
					
				box = wx.wxRadioButton(self,id,label,
					wx.wxDefaultPosition,(100,25),
					group,wx.wxDefaultValidator,"group2")
			
				col3Sizer.Add(box,0,wx.wxBORDER | wx.wxLEFT,20)
				
				self.frame.dict[var] = box,id
			#@nonl
			#@-node:<< Create the third column of widgets >>
			#@nl
			
			col4Sizer = wx.wxBoxSizer(wx.wxVERTICAL)
			#@<< Create the fourth column of widgets >>
			#@+node:<< Create the fourth column of widgets >>
			# The var names must match the names in leoFind class.
			table = (
				("search_headline_flag","Search Headline Text"),
				("search_body_flag","Search Body Text"),
				("mark_finds_flag","Mark Finds"),
				("mark_changes_flag","Mark Changes"))
			
			for var,label in table:
				
				id = const(var)
				box = wx.wxCheckBox(self,id,label,
					wx.wxDefaultPosition,(100,25),
					0,wx.wxDefaultValidator,"")
			
				col4Sizer.Add(box,0,wx.wxBORDER | wx.wxLEFT,20)
				self.frame.dict[var] = box,id
			#@nonl
			#@-node:<< Create the fourth column of widgets >>
			#@nl
			
			# Pack the columns
			columnSizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
			columnSizer.Add(col1Sizer)
			columnSizer.Add(col2Sizer)
			columnSizer.Add(col3Sizer)
			columnSizer.Add(col4Sizer)
			
			topSizer.Add(columnSizer)
			topSizer.Add(0,10)
			#@nonl
			#@-node:<< Create all the find check boxes >>
			#@nl
			#@	<< Create all the find buttons >>
			#@+node:<< Create all the find buttons >>
			# The row sizers are a bit dim:  they should distribute the buttons automatically.
			
			row1Sizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
			#@<< Create the first row of buttons >>
			#@+node:<< Create the first row of buttons >>
			row1Sizer.Add(90,0)
			
			table = (
				("findButton","Find",true),
				("batch_flag","Show Context",false), # Old batch_flag now means Show Context.
				("findAllButton","Find All",true))
			
			for var,label,isButton in table:
				
				id = const(var)
				if isButton:
					widget = button = wx.wxButton(self,id,label,
						wx.wxDefaultPosition,(100,25),
						0,wx.wxDefaultValidator,"")
				else:
					widget = box = wx.wxCheckBox(self,id,label,
						wx.wxDefaultPosition,(100,25),
						0,wx.wxDefaultValidator,"")
					
					self.frame.dict[var] = box,id
			
				row1Sizer.Add(widget)
				row1Sizer.Add((25,0),)
			#@nonl
			#@-node:<< Create the first row of buttons >>
			#@nl
			
			row2Sizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
			#@<< Create the second row of buttons >>
			#@+node:<< Create the second row of buttons >>
			row2Sizer.Add(90,0)
			
			table = (
				("changeButton","Change"),
				("changeThenFindButton","Change,Then Find"),
				("changeAllButton","Change All"))
			
			for var,label in table:
			
				id = const(var)
				button = wx.wxButton(self,id,label,
					wx.wxDefaultPosition,(100,25),
					0,wx.wxDefaultValidator,"")
				
				row2Sizer.Add(button)
				row2Sizer.Add((25,0),)
			#@nonl
			#@-node:<< Create the second row of buttons >>
			#@nl
			
			# Pack the two rows
			buttonSizer = wx.wxBoxSizer(wx.wxVERTICAL)
			buttonSizer.Add(row1Sizer)
			buttonSizer.Add(0,10)
			
			buttonSizer.Add(row2Sizer)
			topSizer.Add(buttonSizer)
			topSizer.Add(0,10)
			#@nonl
			#@-node:<< Create all the find buttons >>
			#@nl
		
			self.SetAutoLayout(true) # tell dialog to use sizer
			self.SetSizer(topSizer) # actually set the sizer
			topSizer.Fit(self)# set size to minimum size as calculated by the sizer
			topSizer.SetSizeHints(self)# set size hints to honour mininum size
		#@nonl
		#@-node:FindPanel.__init__
		#@-others
	#@nonl
	#@-node:wxFindPanel class
	#@-others

	if app.gui is None:
		#@		<< Set app.gui >>
		#@+node:<< set app.gui >>
		app.gui = wxGui()
		app.root = app.gui.createRootWindow()
		app.gui.finishCreate()
		#@-node:<< set app.gui >>
		#@nl
		__version__ = "0.1" # Set version for the plugin handler.
		plugin_signon(__name__)
	else:
		s = "Can't install wxPython gui: previous gui installed"
		print s ; es(s,color="red")
#@nonl
#@-node:@file __wx_gui.py
#@-leo
