git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44234 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			296 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			296 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """EditWindow class."""
 | |
| 
 | |
| __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 | |
| __cvsid__ = "$Id$"
 | |
| __revision__ = "$Revision$"[11:-2]
 | |
| 
 | |
| import wx
 | |
| from wx import stc
 | |
| 
 | |
| import keyword
 | |
| import os
 | |
| import sys
 | |
| import time
 | |
| 
 | |
| import dispatcher
 | |
| from version import VERSION
 | |
| 
 | |
| 
 | |
| if 'wxMSW' in wx.PlatformInfo:
 | |
|     FACES = { 'times'     : 'Times New Roman',
 | |
|               'mono'      : 'Courier New',
 | |
|               'helv'      : 'Arial',
 | |
|               'lucida'    : 'Lucida Console',
 | |
|               'other'     : 'Comic Sans MS',
 | |
|               'size'      : 10,
 | |
|               'lnsize'    : 8,
 | |
|               'backcol'   : '#FFFFFF',
 | |
|               'calltipbg' : '#FFFFB8',
 | |
|               'calltipfg' : '#404040',
 | |
|             }
 | |
| 
 | |
| elif 'wxGTK' in wx.PlatformInfo and 'gtk2' in wx.PlatformInfo:
 | |
|     FACES = { 'times'     : 'Serif',
 | |
|               'mono'      : 'Monospace',
 | |
|               'helv'      : 'Sans',
 | |
|               'other'     : 'new century schoolbook',
 | |
|               'size'      : 10,
 | |
|               'lnsize'    : 9,
 | |
|               'backcol'   : '#FFFFFF',
 | |
|               'calltipbg' : '#FFFFB8',
 | |
|               'calltipfg' : '#404040',
 | |
|             }
 | |
| 
 | |
| elif 'wxMac' in wx.PlatformInfo:
 | |
|     FACES = { 'times'     : 'Lucida Grande',
 | |
|               'mono'      : 'Courier New',
 | |
|               'helv'      : 'Geneva',
 | |
|               'other'     : 'new century schoolbook',
 | |
|               'size'      : 13,
 | |
|               'lnsize'    : 10,
 | |
|               'backcol'   : '#FFFFFF',
 | |
|               'calltipbg' : '#FFFFB8',
 | |
|               'calltipfg' : '#404040',
 | |
|             }
 | |
| 
 | |
| else: # GTK1, etc.
 | |
|     FACES = { 'times'     : 'Times',
 | |
|               'mono'      : 'Courier',
 | |
|               'helv'      : 'Helvetica',
 | |
|               'other'     : 'new century schoolbook',
 | |
|               'size'      : 12,
 | |
|               'lnsize'    : 10,
 | |
|               'backcol'   : '#FFFFFF',
 | |
|               'calltipbg' : '#FFFFB8',
 | |
|               'calltipfg' : '#404040',
 | |
|             }
 | |
| 
 | |
| 
 | |
| class EditWindow(stc.StyledTextCtrl):
 | |
|     """EditWindow based on StyledTextCtrl."""
 | |
| 
 | |
|     revision = __revision__
 | |
| 
 | |
|     def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
 | |
|                  size=wx.DefaultSize, style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
 | |
|         """Create EditWindow instance."""
 | |
|         stc.StyledTextCtrl.__init__(self, parent, id, pos, size, style)
 | |
|         self.__config()
 | |
|         stc.EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
 | |
|         dispatcher.connect(receiver=self._fontsizer, signal='FontIncrease')
 | |
|         dispatcher.connect(receiver=self._fontsizer, signal='FontDecrease')
 | |
|         dispatcher.connect(receiver=self._fontsizer, signal='FontDefault')
 | |
| 
 | |
|     def _fontsizer(self, signal):
 | |
|         """Receiver for Font* signals."""
 | |
|         size = self.GetZoom()
 | |
|         if signal == 'FontIncrease':
 | |
|             size += 1
 | |
|         elif signal == 'FontDecrease':
 | |
|             size -= 1
 | |
|         elif signal == 'FontDefault':
 | |
|             size = 0
 | |
|         self.SetZoom(size)
 | |
| 
 | |
| 
 | |
|     def __config(self):
 | |
|         self.setDisplayLineNumbers(False)
 | |
|         
 | |
|         self.SetLexer(stc.STC_LEX_PYTHON)
 | |
|         self.SetKeyWords(0, ' '.join(keyword.kwlist))
 | |
| 
 | |
|         self.setStyles(FACES)
 | |
|         self.SetViewWhiteSpace(False)
 | |
|         self.SetTabWidth(4)
 | |
|         self.SetUseTabs(False)
 | |
|         # Do we want to automatically pop up command completion options?
 | |
|         self.autoComplete = True
 | |
|         self.autoCompleteIncludeMagic = True
 | |
|         self.autoCompleteIncludeSingle = True
 | |
|         self.autoCompleteIncludeDouble = True
 | |
|         self.autoCompleteCaseInsensitive = True
 | |
|         self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
 | |
|         self.autoCompleteAutoHide = False
 | |
|         self.AutoCompSetAutoHide(self.autoCompleteAutoHide)
 | |
|         self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
 | |
|         # Do we want to automatically pop up command argument help?
 | |
|         self.autoCallTip = True
 | |
|         self.callTipInsert = True
 | |
|         self.CallTipSetBackground(FACES['calltipbg'])
 | |
|         self.CallTipSetForeground(FACES['calltipfg'])
 | |
|         self.SetWrapMode(False)
 | |
|         try:
 | |
|             self.SetEndAtLastLine(False)
 | |
|         except AttributeError:
 | |
|             pass
 | |
| 
 | |
|     def setDisplayLineNumbers(self, state):
 | |
|         self.lineNumbers = state
 | |
|         if state:
 | |
|             self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
 | |
|             self.SetMarginWidth(1, 40)
 | |
|         else:
 | |
|             # Leave a small margin so the feature hidden lines marker can be seen
 | |
|             self.SetMarginType(1, 0)
 | |
|             self.SetMarginWidth(1, 10)
 | |
|         
 | |
|     def setStyles(self, faces):
 | |
|         """Configure font size, typeface and color for lexer."""
 | |
| 
 | |
|         # Default style
 | |
|         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
 | |
|                           "face:%(mono)s,size:%(size)d,back:%(backcol)s" % \
 | |
|                           faces)
 | |
| 
 | |
|         self.StyleClearAll()
 | |
|         self.SetSelForeground(True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
 | |
|         self.SetSelBackground(True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT))
 | |
|         
 | |
|         # Built in styles
 | |
|         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,
 | |
|                           "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % FACES)
 | |
|         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR,
 | |
|                           "face:%(mono)s" % faces)
 | |
|         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
 | |
|                           "fore:#0000FF,back:#FFFF88")
 | |
|         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
 | |
|                           "fore:#FF0000,back:#FFFF88")
 | |
| 
 | |
|         # Python styles
 | |
|         self.StyleSetSpec(stc.STC_P_DEFAULT,
 | |
|                           "face:%(mono)s" % faces)
 | |
|         self.StyleSetSpec(stc.STC_P_COMMENTLINE,
 | |
|                           "fore:#007F00,face:%(mono)s" % faces)
 | |
|         self.StyleSetSpec(stc.STC_P_NUMBER,
 | |
|                           "")
 | |
|         self.StyleSetSpec(stc.STC_P_STRING,
 | |
|                           "fore:#7F007F,face:%(mono)s" % faces)
 | |
|         self.StyleSetSpec(stc.STC_P_CHARACTER,
 | |
|                           "fore:#7F007F,face:%(mono)s" % faces)
 | |
|         self.StyleSetSpec(stc.STC_P_WORD,
 | |
|                           "fore:#00007F,bold")
 | |
|         self.StyleSetSpec(stc.STC_P_TRIPLE,
 | |
|                           "fore:#7F0000")
 | |
|         self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE,
 | |
|                           "fore:#000033,back:#FFFFE8")
 | |
|         self.StyleSetSpec(stc.STC_P_CLASSNAME,
 | |
|                           "fore:#0000FF,bold")
 | |
|         self.StyleSetSpec(stc.STC_P_DEFNAME,
 | |
|                           "fore:#007F7F,bold")
 | |
|         self.StyleSetSpec(stc.STC_P_OPERATOR,
 | |
|                           "")
 | |
|         self.StyleSetSpec(stc.STC_P_IDENTIFIER,
 | |
|                           "")
 | |
|         self.StyleSetSpec(stc.STC_P_COMMENTBLOCK,
 | |
|                           "fore:#7F7F7F")
 | |
|         self.StyleSetSpec(stc.STC_P_STRINGEOL,
 | |
|                           "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
 | |
| 
 | |
|     def OnUpdateUI(self, event):
 | |
|         """Check for matching braces."""
 | |
|         # If the auto-complete window is up let it do its thing.
 | |
|         if self.AutoCompActive() or self.CallTipActive():
 | |
|             return
 | |
|         braceAtCaret = -1
 | |
|         braceOpposite = -1
 | |
|         charBefore = None
 | |
|         caretPos = self.GetCurrentPos()
 | |
|         if caretPos > 0:
 | |
|             charBefore = self.GetCharAt(caretPos - 1)
 | |
|             styleBefore = self.GetStyleAt(caretPos - 1)
 | |
| 
 | |
|         # Check before.
 | |
|         if charBefore and chr(charBefore) in '[]{}()' \
 | |
|         and styleBefore == stc.STC_P_OPERATOR:
 | |
|             braceAtCaret = caretPos - 1
 | |
| 
 | |
|         # Check after.
 | |
|         if braceAtCaret < 0:
 | |
|             charAfter = self.GetCharAt(caretPos)
 | |
|             styleAfter = self.GetStyleAt(caretPos)
 | |
|             if charAfter and chr(charAfter) in '[]{}()' \
 | |
|             and styleAfter == stc.STC_P_OPERATOR:
 | |
|                 braceAtCaret = caretPos
 | |
| 
 | |
|         if braceAtCaret >= 0:
 | |
|             braceOpposite = self.BraceMatch(braceAtCaret)
 | |
| 
 | |
|         if braceAtCaret != -1  and braceOpposite == -1:
 | |
|             self.BraceBadLight(braceAtCaret)
 | |
|         else:
 | |
|             self.BraceHighlight(braceAtCaret, braceOpposite)
 | |
| 
 | |
|     def CanCopy(self):
 | |
|         """Return True if text is selected and can be copied."""
 | |
|         return self.GetSelectionStart() != self.GetSelectionEnd()
 | |
| 
 | |
|     def CanCut(self):
 | |
|         """Return True if text is selected and can be cut."""
 | |
|         return self.CanCopy() and self.CanEdit()
 | |
| 
 | |
|     def CanEdit(self):
 | |
|         """Return True if editing should succeed."""
 | |
|         return not self.GetReadOnly()
 | |
| 
 | |
|     def CanPaste(self):
 | |
|         """Return True if pasting should succeed."""
 | |
|         return stc.StyledTextCtrl.CanPaste(self) and self.CanEdit()
 | |
| 
 | |
| 
 | |
|     def GetLastPosition(self):
 | |
|         return self.GetLength()
 | |
| 
 | |
|     def GetRange(self, start, end):
 | |
|         return self.GetTextRange(start, end)
 | |
| 
 | |
|     def GetSelection(self):
 | |
|         return self.GetAnchor(), self.GetCurrentPos()
 | |
| 
 | |
|     def ShowPosition(self, pos):
 | |
|         line = self.LineFromPosition(pos)
 | |
|         #self.EnsureVisible(line)
 | |
|         self.GotoLine(line)
 | |
| 
 | |
|     def DoFindNext(self, findData, findDlg=None):
 | |
|         backward = not (findData.GetFlags() & wx.FR_DOWN)
 | |
|         matchcase = (findData.GetFlags() & wx.FR_MATCHCASE) != 0
 | |
|         end = self.GetLastPosition()
 | |
|         textstring = self.GetRange(0, end)
 | |
|         findstring = findData.GetFindString()
 | |
|         if not matchcase:
 | |
|             textstring = textstring.lower()
 | |
|             findstring = findstring.lower()
 | |
|         if backward:
 | |
|             start = self.GetSelection()[0]
 | |
|             loc = textstring.rfind(findstring, 0, start)
 | |
|         else:
 | |
|             start = self.GetSelection()[1]
 | |
|             loc = textstring.find(findstring, start)
 | |
| 
 | |
|         # if it wasn't found then restart at begining
 | |
|         if loc == -1 and start != 0:
 | |
|             if backward:
 | |
|                 start = end
 | |
|                 loc = textstring.rfind(findstring, 0, start)
 | |
|             else:
 | |
|                 start = 0
 | |
|                 loc = textstring.find(findstring, start)
 | |
| 
 | |
|         # was it still not found?
 | |
|         if loc == -1:
 | |
|             dlg = wx.MessageDialog(self, 'Unable to find the search text.',
 | |
|                           'Not found!',
 | |
|                           wx.OK | wx.ICON_INFORMATION)
 | |
|             dlg.ShowModal()
 | |
|             dlg.Destroy()
 | |
|         if findDlg:
 | |
|             if loc == -1:
 | |
|                 wx.CallAfter(findDlg.SetFocus)
 | |
|                 return
 | |
|             else:
 | |
|                 findDlg.Close()
 | |
| 
 | |
|         # show and select the found text
 | |
|         self.ShowPosition(loc)
 | |
|         self.SetSelection(loc, loc + len(findstring))
 |