1 #---------------------------------------------------------------------------- 
   2 # Name:         STCTextEditor.py 
   3 # Purpose:      Text Editor for wx.lib.pydocview tbat uses the Styled Text Control 
   5 # Author:       Peter Yared, Morgan Hua 
   9 # Copyright:    (c) 2003-2005 ActiveGrid, Inc. 
  10 # License:      wxWindows License 
  11 #---------------------------------------------------------------------------- 
  16 import wx
.lib
.multisash
 
  17 import wx
.lib
.pydocview
 
  24 #---------------------------------------------------------------------------- 
  26 #---------------------------------------------------------------------------- 
  29 VIEW_WHITESPACE_ID 
= wx
.NewId() 
  30 VIEW_EOL_ID 
= wx
.NewId() 
  31 VIEW_INDENTATION_GUIDES_ID 
= wx
.NewId() 
  32 VIEW_RIGHT_EDGE_ID 
= wx
.NewId() 
  33 VIEW_LINE_NUMBERS_ID 
= wx
.NewId() 
  35 ZOOM_NORMAL_ID 
= wx
.NewId() 
  36 ZOOM_IN_ID 
= wx
.NewId() 
  37 ZOOM_OUT_ID 
= wx
.NewId() 
  38 CHOOSE_FONT_ID 
= wx
.NewId() 
  39 WORD_WRAP_ID 
= wx
.NewId() 
  40 TEXT_STATUS_BAR_ID 
= wx
.NewId() 
  43 #---------------------------------------------------------------------------- 
  45 #---------------------------------------------------------------------------- 
  47 class TextDocument(wx
.lib
.docview
.Document
): 
  50     def OnSaveDocument(self
, filename
): 
  51         view 
= self
.GetFirstView() 
  52         docFile 
= file(self
._documentFile
, "w") 
  53         docFile
.write(view
.GetValue()) 
  56         self
.SetDocumentSaved(True) 
  60     def OnOpenDocument(self
, filename
): 
  61         view 
= self
.GetFirstView() 
  62         docFile 
= file(self
._documentFile
, 'r') 
  65         self
.SetFilename(filename
, True) 
  73         view 
= self
.GetFirstView() 
  75             return wx
.lib
.docview
.Document
.IsModified(self
) or view
.IsModified() 
  77             return wx
.lib
.docview
.Document
.IsModified(self
) 
  80     def Modify(self
, mod
): 
  81         view 
= self
.GetFirstView() 
  82         wx
.lib
.docview
.Document
.Modify(self
, mod
) 
  87     def OnCreateCommandProcessor(self
): 
  88         # Don't create a command processor, it has its own 
  91 # Use this to override MultiClient.Select to prevent yellow background. 
  92 def MultiClientSelectBGNotYellow(a
): 
  93         a
.GetParent().multiView
.UnSelect() 
  95         #a.SetBackgroundColour(wx.Colour(255,255,0)) # Yellow 
  98 class TextView(wx
.lib
.docview
.View
): 
 102     #---------------------------------------------------------------------------- 
 104     #---------------------------------------------------------------------------- 
 107         wx
.lib
.docview
.View
.__init
__(self
) 
 108         self
._textEditor 
= None 
 109         self
._markerCount 
= 0 
 110         self
._commandProcessor 
= None 
 111         self
._multiSash 
= None 
 114     def GetCtrlClass(self
): 
 119         # look for active one first 
 120         self
._textEditor 
= self
._GetActiveCtrl
(self
._multiSash
) 
 121         if self
._textEditor 
== None:  # it is possible none are active 
 122             # look for any existing one 
 123             self
._textEditor 
= self
._FindCtrl
(self
._multiSash
) 
 124         return self
._textEditor
 
 127 ##    def GetCtrls(self, parent = None): 
 128 ##        """ Walk through the MultiSash windows and find all Ctrls """ 
 130 ##        if isinstance(parent, self.GetCtrlClass()): 
 132 ##        if hasattr(parent, "GetChildren"): 
 133 ##            for child in parent.GetChildren(): 
 134 ##                controls = controls + self.GetCtrls(child) 
 138     def OnCreate(self
, doc
, flags
): 
 139         frame 
= wx
.GetApp().CreateDocumentFrame(self
, doc
, flags
, style 
= wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
) 
 140         wx
.lib
.multisash
.MultiClient
.Select 
= MultiClientSelectBGNotYellow
 
 141         self
._multiSash 
= wx
.lib
.multisash
.MultiSash(frame
, -1) 
 142         self
._multiSash
.SetDefaultChildClass(self
.GetCtrlClass()) # wxBug:  MultiSash instantiates the first TextCtrl with this call 
 143         self
._textEditor 
= self
.GetCtrl()  # wxBug: grab the TextCtrl from the MultiSash datastructure 
 144         self
._CreateSizer
(frame
) 
 151     def _GetActiveCtrl(self
, parent
): 
 152         """ Walk through the MultiSash windows and find the active Control """ 
 153         if isinstance(parent
, wx
.lib
.multisash
.MultiClient
) and parent
.selected
: 
 155         if hasattr(parent
, "GetChildren"): 
 156             for child 
in parent
.GetChildren(): 
 157                 found 
= self
._GetActiveCtrl
(child
) 
 163     def _FindCtrl(self
, parent
): 
 164         """ Walk through the MultiSash windows and find the first TextCtrl """ 
 165         if isinstance(parent
, self
.GetCtrlClass()): 
 167         if hasattr(parent
, "GetChildren"): 
 168             for child 
in parent
.GetChildren(): 
 169                 found 
= self
._FindCtrl
(child
) 
 175     def _CreateSizer(self
, frame
): 
 176         sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 177         sizer
.Add(self
._multiSash
, 1, wx
.EXPAND
) 
 178         frame
.SetSizer(sizer
) 
 179         frame
.SetAutoLayout(True) 
 182     def OnUpdate(self
, sender 
= None, hint 
= None): 
 183         if hint 
== "ViewStuff": 
 184             self
.GetCtrl().SetViewDefaults() 
 186             font
, color 
= self
.GetFontAndColorFromConfig() 
 187             self
.GetCtrl().SetFont(font
) 
 188             self
.GetCtrl().SetFontColor(color
) 
 191     def OnActivateView(self
, activate
, activeView
, deactiveView
): 
 192         if activate 
and self
.GetCtrl(): 
 193             # In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop 
 194             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 195                 self
.GetCtrl().SetFocus() 
 197                 wx
.CallAfter(self
.GetCtrl().SetFocus
) 
 200     def OnClose(self
, deleteWindow 
= True): 
 201         if not wx
.lib
.docview
.View
.OnClose(self
, deleteWindow
): 
 204         if deleteWindow 
and self
.GetFrame(): 
 205             self
.GetFrame().Destroy() 
 209     def ProcessEvent(self
, event
):         
 212             self
.GetCtrl().Undo() 
 214         elif id == wx
.ID_REDO
: 
 215             self
.GetCtrl().Redo() 
 217         elif id == wx
.ID_CUT
: 
 220         elif id == wx
.ID_COPY
: 
 221             self
.GetCtrl().Copy() 
 223         elif id == wx
.ID_PASTE
: 
 224             self
.GetCtrl().OnPaste() 
 226         elif id == wx
.ID_CLEAR
: 
 227             self
.GetCtrl().OnClear() 
 229         elif id == wx
.ID_SELECTALL
: 
 230             self
.GetCtrl().SetSelection(0, -1) 
 232         elif id == VIEW_WHITESPACE_ID
: 
 233             self
.GetCtrl().SetViewWhiteSpace(not self
.GetCtrl().GetViewWhiteSpace()) 
 235         elif id == VIEW_EOL_ID
: 
 236             self
.GetCtrl().SetViewEOL(not self
.GetCtrl().GetViewEOL()) 
 238         elif id == VIEW_INDENTATION_GUIDES_ID
: 
 239             self
.GetCtrl().SetViewIndentationGuides(not self
.GetCtrl().GetViewIndentationGuides()) 
 241         elif id == VIEW_RIGHT_EDGE_ID
: 
 242             self
.GetCtrl().SetViewRightEdge(not self
.GetCtrl().GetViewRightEdge()) 
 244         elif id == VIEW_LINE_NUMBERS_ID
: 
 245             self
.GetCtrl().SetViewLineNumbers(not self
.GetCtrl().GetViewLineNumbers()) 
 247         elif id == ZOOM_NORMAL_ID
: 
 248             self
.GetCtrl().SetZoom(0) 
 250         elif id == ZOOM_IN_ID
: 
 251             self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMIN
) 
 253         elif id == ZOOM_OUT_ID
: 
 254             self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMOUT
) 
 256         elif id == CHOOSE_FONT_ID
: 
 259         elif id == WORD_WRAP_ID
: 
 260             self
.GetCtrl().SetWordWrap(not self
.GetCtrl().GetWordWrap()) 
 262         elif id == FindService
.FindService
.FIND_ID
: 
 265         elif id == FindService
.FindService
.FIND_PREVIOUS_ID
: 
 266             self
.DoFind(forceFindPrevious 
= True) 
 268         elif id == FindService
.FindService
.FIND_NEXT_ID
: 
 269             self
.DoFind(forceFindNext 
= True) 
 271         elif id == FindService
.FindService
.REPLACE_ID
: 
 272             self
.OnFind(replace 
= True) 
 274         elif id == FindService
.FindService
.FINDONE_ID
: 
 277         elif id == FindService
.FindService
.REPLACEONE_ID
: 
 278             self
.DoFind(replace 
= True) 
 280         elif id == FindService
.FindService
.REPLACEALL_ID
: 
 281             self
.DoFind(replaceAll 
= True) 
 283         elif id == FindService
.FindService
.GOTO_LINE_ID
: 
 284             self
.OnGotoLine(event
) 
 287             return wx
.lib
.docview
.View
.ProcessEvent(self
, event
) 
 290     def ProcessUpdateUIEvent(self
, event
): 
 291         if not self
.GetCtrl(): 
 294         hasSelection 
= self
.GetCtrl().GetSelectionStart() != self
.GetCtrl().GetSelectionEnd() 
 295         hasText 
= self
.GetCtrl().GetTextLength() > 0 
 296         notOnLastChar 
= self
.GetCtrl().GetSelectionStart() != self
.GetCtrl().GetTextLength() 
 300              event
.Enable(self
.GetCtrl().CanUndo()) 
 301              event
.SetText(_("Undo") + '\t' + _('Ctrl+Z')) 
 303         elif id == wx
.ID_REDO
: 
 304             event
.Enable(self
.GetCtrl().CanRedo()) 
 305             event
.SetText(_("Redo") + '\t' + _('Ctrl+Y')) 
 307         elif id == wx
.ID_CUT
: 
 308             event
.Enable(hasSelection
) 
 310         elif id == wx
.ID_COPY
: 
 311             event
.Enable(hasSelection
) 
 313         elif id == wx
.ID_PASTE
: 
 314             event
.Enable(self
.GetCtrl().CanPaste()) 
 316         elif id == wx
.ID_CLEAR
: 
 317             event
.Enable(hasSelection
) 
 319         elif id == wx
.ID_SELECTALL
: 
 320             event
.Enable(hasText
) 
 325         elif id == VIEW_WHITESPACE_ID
: 
 326             event
.Enable(hasText
) 
 327             event
.Check(self
.GetCtrl().GetViewWhiteSpace()) 
 329         elif id == VIEW_EOL_ID
: 
 330             event
.Enable(hasText
) 
 331             event
.Check(self
.GetCtrl().GetViewEOL()) 
 333         elif id == VIEW_INDENTATION_GUIDES_ID
: 
 334             event
.Enable(hasText
) 
 335             event
.Check(self
.GetCtrl().GetIndentationGuides()) 
 337         elif id == VIEW_RIGHT_EDGE_ID
: 
 338             event
.Enable(hasText
) 
 339             event
.Check(self
.GetCtrl().GetViewRightEdge()) 
 341         elif id == VIEW_LINE_NUMBERS_ID
: 
 342             event
.Enable(hasText
) 
 343             event
.Check(self
.GetCtrl().GetViewLineNumbers()) 
 348         elif id == ZOOM_NORMAL_ID
: 
 349             event
.Enable(self
.GetCtrl().GetZoom() != 0) 
 351         elif id == ZOOM_IN_ID
: 
 352             event
.Enable(self
.GetCtrl().GetZoom() < 20) 
 354         elif id == ZOOM_OUT_ID
: 
 355             event
.Enable(self
.GetCtrl().GetZoom() > -10) 
 357         elif id == CHOOSE_FONT_ID
: 
 360         elif id == WORD_WRAP_ID
: 
 361             event
.Enable(self
.GetCtrl().CanWordWrap()) 
 362             event
.Check(self
.GetCtrl().CanWordWrap() and self
.GetCtrl().GetWordWrap()) 
 364         elif id == FindService
.FindService
.FIND_ID
: 
 365             event
.Enable(hasText
) 
 367         elif id == FindService
.FindService
.FIND_PREVIOUS_ID
: 
 368             event
.Enable(hasText 
and 
 369                          self
._FindServiceHasString
() and 
 370                          self
.GetCtrl().GetSelection()[0] > 0) 
 372         elif id == FindService
.FindService
.FIND_NEXT_ID
: 
 373             event
.Enable(hasText 
and 
 374                          self
._FindServiceHasString
() and 
 375                          self
.GetCtrl().GetSelection()[0] < self
.GetCtrl().GetLength()) 
 377         elif id == FindService
.FindService
.REPLACE_ID
: 
 378             event
.Enable(hasText
) 
 380         elif id == FindService
.FindService
.GOTO_LINE_ID
: 
 383         elif id == TEXT_STATUS_BAR_ID
: 
 384             self
.OnUpdateStatusBar(event
) 
 387             return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
) 
 390     def _GetParentFrame(self
): 
 391         return wx
.GetTopLevelParent(self
.GetFrame()) 
 394     #---------------------------------------------------------------------------- 
 395     # Methods for TextDocument to call 
 396     #---------------------------------------------------------------------------- 
 398     def IsModified(self
): 
 399         if not self
.GetCtrl(): 
 401         return self
.GetCtrl().GetModify() 
 404     def SetModifyFalse(self
): 
 405         self
.GetCtrl().SetSavePoint() 
 410             return self
.GetCtrl().GetText() 
 415     def SetValue(self
, value
): 
 416         self
.GetCtrl().SetText(value
) 
 417         self
.GetCtrl().UpdateLineNumberMarginWidth() 
 418         self
.GetCtrl().EmptyUndoBuffer() 
 421     #---------------------------------------------------------------------------- 
 423     #---------------------------------------------------------------------------- 
 425     def OnUpdateStatusBar(self
, event
): 
 426         statusBar 
= self
._GetParentFrame
().GetStatusBar() 
 427         statusBar
.SetInsertMode(self
.GetCtrl().GetOvertype() == 0) 
 428         statusBar
.SetLineNumber(self
.GetCtrl().GetCurrentLine() + 1) 
 429         statusBar
.SetColumnNumber(self
.GetCtrl().GetColumn(self
.GetCtrl().GetCurrentPos()) + 1) 
 432     #---------------------------------------------------------------------------- 
 434     #---------------------------------------------------------------------------- 
 436     def OnChooseFont(self
): 
 438         data
.EnableEffects(True) 
 439         data
.SetInitialFont(self
.GetCtrl().GetFont()) 
 440         data
.SetColour(self
.GetCtrl().GetFontColor()) 
 441         fontDialog 
= wx
.FontDialog(self
.GetFrame(), data
) 
 442         if fontDialog
.ShowModal() == wx
.ID_OK
: 
 443             data 
= fontDialog
.GetFontData() 
 444             self
.GetCtrl().SetFont(data
.GetChosenFont()) 
 445             self
.GetCtrl().SetFontColor(data
.GetColour()) 
 446             self
.GetCtrl().UpdateStyles() 
 450     #---------------------------------------------------------------------------- 
 452     #---------------------------------------------------------------------------- 
 454     def OnFind(self
, replace 
= False): 
 455         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 457             findService
.ShowFindReplaceDialog(findString 
= self
.GetCtrl().GetSelectedText(), replace 
= replace
) 
 460     def DoFind(self
, forceFindNext 
= False, forceFindPrevious 
= False, replace 
= False, replaceAll 
= False): 
 461         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 464         findString 
= findService
.GetFindString() 
 465         if len(findString
) == 0: 
 467         replaceString 
= findService
.GetReplaceString() 
 468         flags 
= findService
.GetFlags() 
 469         startLoc
, endLoc 
= self
.GetCtrl().GetSelection() 
 471         wholeWord 
= flags 
& wx
.FR_WHOLEWORD 
> 0 
 472         matchCase 
= flags 
& wx
.FR_MATCHCASE 
> 0 
 473         regExp 
= flags 
& FindService
.FindService
.FR_REGEXP 
> 0 
 474         down 
= flags 
& wx
.FR_DOWN 
> 0 
 475         wrap 
= flags 
& FindService
.FindService
.FR_WRAP 
> 0 
 477         if forceFindPrevious
:   # this is from function keys, not dialog box 
 479             wrap 
= False        # user would want to know they're at the end of file 
 482             wrap 
= False        # user would want to know they're at the end of file 
 486         # On replace dialog operations, user is allowed to replace the currently highlighted text to determine if it should be replaced or not. 
 487         # Typically, it is the text from a previous find operation, but we must check to see if it isn't, user may have moved the cursor or selected some other text accidentally. 
 488         # If the text is a match, then replace it. 
 490             result
, start
, end
, replText 
= findService
.DoFind(findString
, replaceString
, self
.GetCtrl().GetSelectedText(), 0, 0, True, matchCase
, wholeWord
, regExp
, replace
) 
 492                 self
.GetCtrl().ReplaceSelection(replText
) 
 493                 self
.GetDocument().Modify(True) 
 494                 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
) 
 496                     startLoc 
+= len(replText
)  # advance start location past replacement string to new text 
 498             elif result 
== FindService
.FIND_SYNTAXERROR
: 
 500                 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
) 
 503             text 
= self
.GetCtrl().GetText() 
 505             # Find the next matching text occurance or if it is a ReplaceAll, replace all occurances 
 506             # Even if the user is Replacing, we should replace here, but only select the text and let the user replace it with the next Replace operation 
 507             result
, start
, end
, text 
= findService
.DoFind(findString
, replaceString
, text
, startLoc
, endLoc
, down
, matchCase
, wholeWord
, regExp
, False, replaceAll
, wrap
) 
 509                 self
.GetCtrl().SetTargetStart(0) 
 510                 self
.GetCtrl().SetTargetEnd(self
.GetCtrl().GetLength()) 
 511                 self
.GetCtrl().ReplaceTarget(text
)  # Doing a SetText causes a clear document to be shown when undoing, so using replacetarget instead 
 512                 self
.GetDocument().Modify(True) 
 514                     wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
) 
 516                     wx
.GetApp().GetTopWindow().PushStatusText(_("%i occurrences of \"%s\" replaced") % (result
, findString
)) 
 518                 self
.GetCtrl().SetSelection(start
, end
) 
 519                 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(end
))  # show bottom then scroll up to top 
 520                 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(start
)) # do this after ensuring bottom is visible 
 521                 wx
.GetApp().GetTopWindow().PushStatusText(_("Found \"%s\".") % findString
) 
 522             elif result 
== FindService
.FIND_SYNTAXERROR
: 
 523                 # Dialog for this case gets popped up by the FindService. 
 524                 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
) 
 526                 wx
.MessageBox(_("Can't find \"%s\".") % findString
, "Find", 
 527                           wx
.OK | wx
.ICON_INFORMATION
) 
 530     def _FindServiceHasString(self
): 
 531         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 532         if not findService 
or not findService
.GetFindString(): 
 537     def OnGotoLine(self
, event
): 
 538         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 540             line 
= findService
.GetLineNumber(self
.GetDocumentManager().FindSuitableParent()) 
 543                 self
.GetCtrl().EnsureVisible(line
) 
 544                 self
.GetCtrl().GotoLine(line
) 
 547     def GotoLine(self
, lineNum
): 
 549             lineNum 
= lineNum 
- 1  # line numbering for editor is 0 based, we are 1 based. 
 550             self
.GetCtrl().EnsureVisibleEnforcePolicy(lineNum
) 
 551             self
.GetCtrl().GotoLine(lineNum
) 
 554     def SetSelection(self
, start
, end
): 
 555         self
.GetCtrl().SetSelection(start
, end
) 
 558     def EnsureVisible(self
, line
): 
 559         self
.GetCtrl().EnsureVisible(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 561     def EnsureVisibleEnforcePolicy(self
, line
): 
 562         self
.GetCtrl().EnsureVisibleEnforcePolicy(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 564     def LineFromPosition(self
, pos
): 
 565         return self
.GetCtrl().LineFromPosition(pos
)+1  # line numbering for editor is 0 based, we are 1 based. 
 568     def PositionFromLine(self
, line
): 
 569         return self
.GetCtrl().PositionFromLine(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 572     def GetLineEndPosition(self
, line
): 
 573         return self
.GetCtrl().GetLineEndPosition(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 576     def GetLine(self
, lineNum
): 
 577         return self
.GetCtrl().GetLine(lineNum
-1)  # line numbering for editor is 0 based, we are 1 based. 
 579     def MarkerDefine(self
): 
 580         """ This must be called after the texteditor is instantiated """ 
 581         self
.GetCtrl().MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_CIRCLE
, wx
.BLACK
, wx
.BLUE
) 
 584     def MarkerToggle(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 586             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 587         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 588             self
.GetCtrl().MarkerDelete(lineNum
, marker_index
) 
 589             self
._markerCount 
-= 1 
 591             self
.GetCtrl().MarkerAdd(lineNum
, marker_index
) 
 592             self
._markerCount 
+= 1 
 594     def MarkerAdd(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 596             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 597         self
.GetCtrl().MarkerAdd(lineNum
, marker_index
) 
 598         self
._markerCount 
+= 1 
 601     def MarkerDelete(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 603             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 604         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 605             self
.GetCtrl().MarkerDelete(lineNum
, marker_index
) 
 606             self
._markerCount 
-= 1 
 608     def MarkerDeleteAll(self
, marker_num
=MARKER_NUM
): 
 609         self
.GetCtrl().MarkerDeleteAll(marker_num
) 
 610         if marker_num 
== self
.MARKER_NUM
: 
 611             self
._markerCount 
= 0 
 614     def MarkerNext(self
, lineNum 
= -1): 
 616             lineNum 
= self
.GetCtrl().GetCurrentLine() + 1  # start search below current line 
 617         foundLine 
= self
.GetCtrl().MarkerNext(lineNum
, self
.MARKER_MASK
) 
 619             # wrap to top of file 
 620             foundLine 
= self
.GetCtrl().MarkerNext(0, self
.MARKER_MASK
) 
 622                 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers")) 
 625         self
.GotoLine(foundLine 
+ 1) 
 628     def MarkerPrevious(self
, lineNum 
= -1): 
 630             lineNum 
= self
.GetCtrl().GetCurrentLine() - 1  # start search above current line 
 632                 lineNum 
= self
.GetCtrl().GetLineCount() 
 634         foundLine 
= self
.GetCtrl().MarkerPrevious(lineNum
, self
.MARKER_MASK
) 
 636             # wrap to bottom of file 
 637             foundLine 
= self
.GetCtrl().MarkerPrevious(self
.GetCtrl().GetLineCount(), self
.MARKER_MASK
) 
 639                 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers")) 
 642         self
.GotoLine(foundLine 
+ 1) 
 645     def MarkerExists(self
, lineNum 
= -1, mask
=MARKER_MASK
): 
 647             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 648         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 654     def GetMarkerCount(self
): 
 655         return self
._markerCount
 
 658 class TextService(wx
.lib
.pydocview
.DocService
): 
 662         wx
.lib
.pydocview
.DocService
.__init
__(self
) 
 665     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
 666         if document 
and document
.GetDocumentTemplate().GetDocumentType() != TextDocument
: 
 668         if not document 
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 671         statusBar 
= TextStatusBar(frame
, TEXT_STATUS_BAR_ID
) 
 672         frame
.SetStatusBar(statusBar
) 
 673         wx
.EVT_UPDATE_UI(frame
, TEXT_STATUS_BAR_ID
, frame
.ProcessUpdateUIEvent
) 
 675         viewMenu 
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View"))) 
 677         viewMenu
.AppendSeparator() 
 679         textMenu
.AppendCheckItem(VIEW_WHITESPACE_ID
, _("&Whitespace"), _("Shows or hides whitespace")) 
 680         wx
.EVT_MENU(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessEvent
) 
 681         wx
.EVT_UPDATE_UI(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessUpdateUIEvent
) 
 682         textMenu
.AppendCheckItem(VIEW_EOL_ID
, _("&End of Line Markers"), _("Shows or hides indicators at the end of each line")) 
 683         wx
.EVT_MENU(frame
, VIEW_EOL_ID
, frame
.ProcessEvent
) 
 684         wx
.EVT_UPDATE_UI(frame
, VIEW_EOL_ID
, frame
.ProcessUpdateUIEvent
) 
 685         textMenu
.AppendCheckItem(VIEW_INDENTATION_GUIDES_ID
, _("&Indentation Guides"), _("Shows or hides indentations")) 
 686         wx
.EVT_MENU(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessEvent
) 
 687         wx
.EVT_UPDATE_UI(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessUpdateUIEvent
) 
 688         textMenu
.AppendCheckItem(VIEW_RIGHT_EDGE_ID
, _("&Right Edge"), _("Shows or hides the right edge marker")) 
 689         wx
.EVT_MENU(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessEvent
) 
 690         wx
.EVT_UPDATE_UI(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessUpdateUIEvent
) 
 691         textMenu
.AppendCheckItem(VIEW_LINE_NUMBERS_ID
, _("&Line Numbers"), _("Shows or hides the line numbers")) 
 692         wx
.EVT_MENU(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessEvent
) 
 693         wx
.EVT_UPDATE_UI(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessUpdateUIEvent
) 
 695         viewMenu
.AppendMenu(TEXT_ID
, _("&Text"), textMenu
) 
 696         wx
.EVT_UPDATE_UI(frame
, TEXT_ID
, frame
.ProcessUpdateUIEvent
) 
 698         isWindows 
= (wx
.Platform 
== '__WXMSW__') 
 701         zoomMenu
.Append(ZOOM_NORMAL_ID
, _("Normal Size"), _("Sets the document to its normal size")) 
 702         wx
.EVT_MENU(frame
, ZOOM_NORMAL_ID
, frame
.ProcessEvent
) 
 703         wx
.EVT_UPDATE_UI(frame
, ZOOM_NORMAL_ID
, frame
.ProcessUpdateUIEvent
) 
 705             zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In\tCtrl+Page Up"), _("Zooms the document to a larger size")) 
 707             zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In"), _("Zooms the document to a larger size")) 
 708         wx
.EVT_MENU(frame
, ZOOM_IN_ID
, frame
.ProcessEvent
) 
 709         wx
.EVT_UPDATE_UI(frame
, ZOOM_IN_ID
, frame
.ProcessUpdateUIEvent
) 
 711             zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out\tCtrl+Page Down"), _("Zooms the document to a smaller size")) 
 713             zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out"), _("Zooms the document to a smaller size")) 
 714         wx
.EVT_MENU(frame
, ZOOM_OUT_ID
, frame
.ProcessEvent
) 
 715         wx
.EVT_UPDATE_UI(frame
, ZOOM_OUT_ID
, frame
.ProcessUpdateUIEvent
) 
 717         viewMenu
.AppendMenu(ZOOM_ID
, _("&Zoom"), zoomMenu
) 
 718         wx
.EVT_UPDATE_UI(frame
, ZOOM_ID
, frame
.ProcessUpdateUIEvent
) 
 720         formatMenuIndex 
= menuBar
.FindMenu(_("&Format")) 
 721         if formatMenuIndex 
> -1: 
 722             formatMenu 
= menuBar
.GetMenu(formatMenuIndex
) 
 724             formatMenu 
= wx
.Menu() 
 725         if not menuBar
.FindItemById(CHOOSE_FONT_ID
): 
 726             formatMenu
.Append(CHOOSE_FONT_ID
, _("&Font..."), _("Sets the font to use")) 
 727             wx
.EVT_MENU(frame
, CHOOSE_FONT_ID
, frame
.ProcessEvent
) 
 728             wx
.EVT_UPDATE_UI(frame
, CHOOSE_FONT_ID
, frame
.ProcessUpdateUIEvent
) 
 729         if not menuBar
.FindItemById(WORD_WRAP_ID
): 
 730             formatMenu
.AppendCheckItem(WORD_WRAP_ID
, _("Word Wrap"), _("Wraps text horizontally when checked")) 
 731             wx
.EVT_MENU(frame
, WORD_WRAP_ID
, frame
.ProcessEvent
) 
 732             wx
.EVT_UPDATE_UI(frame
, WORD_WRAP_ID
, frame
.ProcessUpdateUIEvent
) 
 733         if formatMenuIndex 
== -1: 
 734             viewMenuIndex 
= menuBar
.FindMenu(_("&View")) 
 735             menuBar
.Insert(viewMenuIndex 
+ 1, formatMenu
, _("&Format")) 
 737         # wxBug: wxToolBar::GetToolPos doesn't exist, need it to find cut tool and then insert find in front of it. 
 738         toolBar
.AddSeparator() 
 739         toolBar
.AddTool(ZOOM_IN_ID
, getZoomInBitmap(), shortHelpString 
= _("Zoom In"), longHelpString 
= _("Zooms the document to a larger size")) 
 740         toolBar
.AddTool(ZOOM_OUT_ID
, getZoomOutBitmap(), shortHelpString 
= _("Zoom Out"), longHelpString 
= _("Zooms the document to a smaller size")) 
 744     def ProcessUpdateUIEvent(self
, event
): 
 749         elif id == VIEW_WHITESPACE_ID
: 
 752         elif id == VIEW_EOL_ID
: 
 755         elif id == VIEW_INDENTATION_GUIDES_ID
: 
 758         elif id == VIEW_RIGHT_EDGE_ID
: 
 761         elif id == VIEW_LINE_NUMBERS_ID
: 
 767         elif id == ZOOM_NORMAL_ID
: 
 770         elif id == ZOOM_IN_ID
: 
 773         elif id == ZOOM_OUT_ID
: 
 776         elif id == CHOOSE_FONT_ID
: 
 779         elif id == WORD_WRAP_ID
: 
 786 class TextStatusBar(wx
.StatusBar
): 
 788     # wxBug: Would be nice to show num key status in statusbar, but can't figure out how to detect if it is enabled or disabled 
 790     def __init__(self
, parent
, id, style 
= wx
.ST_SIZEGRIP
, name 
= "statusBar"): 
 791         wx
.StatusBar
.__init
__(self
, parent
, id, style
, name
) 
 792         self
.SetFieldsCount(4) 
 793         self
.SetStatusWidths([-1, 50, 50, 55]) 
 795     def SetInsertMode(self
, insert 
= True): 
 800         if self
.GetStatusText(1) != newText
:     # wxBug: Need to check if the text has changed, otherwise it flickers under win32 
 801             self
.SetStatusText(newText
, 1) 
 803     def SetLineNumber(self
, lineNumber
): 
 804         newText 
= _("Ln %i") % lineNumber
 
 805         if self
.GetStatusText(2) != newText
: 
 806             self
.SetStatusText(newText
, 2) 
 808     def SetColumnNumber(self
, colNumber
): 
 809         newText 
= _("Col %i") % colNumber
 
 810         if self
.GetStatusText(3) != newText
: 
 811             self
.SetStatusText(newText
, 3) 
 814 class TextOptionsPanel(wx
.Panel
): 
 817     def __init__(self
, parent
, id, configPrefix 
= "Text", label 
= "Text", hasWordWrap 
= True, hasTabs 
= False, addPage
=True): 
 818         wx
.Panel
.__init
__(self
, parent
, id) 
 819         self
._configPrefix 
= configPrefix
 
 820         self
._hasWordWrap 
= hasWordWrap
 
 821         self
._hasTabs 
= hasTabs
 
 824         config 
= wx
.ConfigBase_Get() 
 825         self
._textFont 
= wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
) 
 826         fontData 
= config
.Read(self
._configPrefix 
+ "EditorFont", "") 
 828             nativeFont 
= wx
.NativeFontInfo() 
 829             nativeFont
.FromString(fontData
) 
 830             self
._textFont
.SetNativeFontInfo(nativeFont
) 
 831         self
._originalTextFont 
= self
._textFont
 
 832         self
._textColor 
= wx
.BLACK
 
 833         colorData 
= config
.Read(self
._configPrefix 
+ "EditorColor", "") 
 835             red 
= int("0x" + colorData
[0:2], 16) 
 836             green 
= int("0x" + colorData
[2:4], 16) 
 837             blue 
= int("0x" + colorData
[4:6], 16) 
 838             self
._textColor 
= wx
.Color(red
, green
, blue
) 
 839         self
._originalTextColor 
= self
._textColor
 
 840         fontLabel 
= wx
.StaticText(self
, -1, _("Font:")) 
 841         self
._sampleTextCtrl 
= wx
.TextCtrl(self
, -1, "", size 
= (125, 21)) 
 842         self
._sampleTextCtrl
.SetEditable(False) 
 843         chooseFontButton 
= wx
.Button(self
, -1, _("Choose Font...")) 
 844         wx
.EVT_BUTTON(self
, chooseFontButton
.GetId(), self
.OnChooseFont
) 
 845         if self
._hasWordWrap
: 
 846             self
._wordWrapCheckBox 
= wx
.CheckBox(self
, -1, _("Wrap words inside text area")) 
 847             self
._wordWrapCheckBox
.SetValue(wx
.ConfigBase_Get().ReadInt(self
._configPrefix 
+ "EditorWordWrap", False)) 
 848         self
._viewWhitespaceCheckBox 
= wx
.CheckBox(self
, -1, _("Show whitespace")) 
 849         self
._viewWhitespaceCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewWhitespace", False)) 
 850         self
._viewEOLCheckBox 
= wx
.CheckBox(self
, -1, _("Show end of line markers")) 
 851         self
._viewEOLCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewEOL", False)) 
 852         self
._viewIndentationGuideCheckBox 
= wx
.CheckBox(self
, -1, _("Show indentation guides")) 
 853         self
._viewIndentationGuideCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewIndentationGuides", False)) 
 854         self
._viewRightEdgeCheckBox 
= wx
.CheckBox(self
, -1, _("Show right edge")) 
 855         self
._viewRightEdgeCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewRightEdge", False)) 
 856         self
._viewLineNumbersCheckBox 
= wx
.CheckBox(self
, -1, _("Show line numbers")) 
 857         self
._viewLineNumbersCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewLineNumbers", True)) 
 859             self
._hasTabsCheckBox 
= wx
.CheckBox(self
, -1, _("Use spaces instead of tabs")) 
 860             self
._hasTabsCheckBox
.SetValue(not wx
.ConfigBase_Get().ReadInt(self
._configPrefix 
+ "EditorUseTabs", False)) 
 861             indentWidthLabel 
= wx
.StaticText(self
, -1, _("Indent Width:")) 
 862             self
._indentWidthChoice 
= wx
.Choice(self
, -1, choices 
= ["2", "4", "6", "8", "10"]) 
 863             self
._indentWidthChoice
.SetStringSelection(str(config
.ReadInt(self
._configPrefix 
+ "EditorIndentWidth", 4))) 
 864         textPanelBorderSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 865         textPanelSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 866         textFontSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 867         textFontSizer
.Add(fontLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
) 
 868         textFontSizer
.Add(self
._sampleTextCtrl
, 0, wx
.ALIGN_LEFT | wx
.EXPAND | wx
.RIGHT
, HALF_SPACE
) 
 869         textFontSizer
.Add(chooseFontButton
, 0, wx
.ALIGN_RIGHT | wx
.LEFT
, HALF_SPACE
) 
 870         textPanelSizer
.Add(textFontSizer
, 0, wx
.ALL
, HALF_SPACE
) 
 871         if self
._hasWordWrap
: 
 872             textPanelSizer
.Add(self
._wordWrapCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 873         textPanelSizer
.Add(self
._viewWhitespaceCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 874         textPanelSizer
.Add(self
._viewEOLCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 875         textPanelSizer
.Add(self
._viewIndentationGuideCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 876         textPanelSizer
.Add(self
._viewRightEdgeCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 877         textPanelSizer
.Add(self
._viewLineNumbersCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 879             textPanelSizer
.Add(self
._hasTabsCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 880             textIndentWidthSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 881             textIndentWidthSizer
.Add(indentWidthLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
) 
 882             textIndentWidthSizer
.Add(self
._indentWidthChoice
, 0, wx
.ALIGN_LEFT | wx
.EXPAND
, HALF_SPACE
) 
 883             textPanelSizer
.Add(textIndentWidthSizer
, 0, wx
.ALL
, HALF_SPACE
) 
 884         textPanelBorderSizer
.Add(textPanelSizer
, 0, wx
.ALL
, SPACE
) 
 885 ##        styleButton = wx.Button(self, -1, _("Choose Style...")) 
 886 ##        wx.EVT_BUTTON(self, styleButton.GetId(), self.OnChooseStyle) 
 887 ##        textPanelBorderSizer.Add(styleButton, 0, wx.ALL, SPACE) 
 888         self
.SetSizer(textPanelBorderSizer
) 
 889         self
.UpdateSampleFont() 
 891             parent
.AddPage(self
, _(label
)) 
 893     def UpdateSampleFont(self
): 
 894         nativeFont 
= wx
.NativeFontInfo() 
 895         nativeFont
.FromString(self
._textFont
.GetNativeFontInfoDesc()) 
 897         font
.SetNativeFontInfo(nativeFont
) 
 898         font
.SetPointSize(self
._sampleTextCtrl
.GetFont().GetPointSize())  # Use the standard point size 
 899         self
._sampleTextCtrl
.SetFont(font
) 
 900         self
._sampleTextCtrl
.SetForegroundColour(self
._textColor
) 
 901         self
._sampleTextCtrl
.SetValue(str(self
._textFont
.GetPointSize()) + _(" pt. ") + self
._textFont
.GetFaceName()) 
 902         self
._sampleTextCtrl
.Refresh() 
 906 ##    def OnChooseStyle(self, event): 
 907 ##        import STCStyleEditor 
 909 ##        base = os.path.split(__file__)[0] 
 910 ##        config = os.path.abspath(os.path.join(base, 'stc-styles.rc.cfg')) 
 912 ##        dlg = STCStyleEditor.STCStyleEditDlg(None, 
 913 ##                                'Python', 'python', 
 923     def OnChooseFont(self
, event
): 
 925         data
.EnableEffects(True) 
 926         data
.SetInitialFont(self
._textFont
) 
 927         data
.SetColour(self
._textColor
) 
 928         fontDialog 
= wx
.FontDialog(self
, data
) 
 929         if fontDialog
.ShowModal() == wx
.ID_OK
: 
 930             data 
= fontDialog
.GetFontData() 
 931             self
._textFont 
= data
.GetChosenFont() 
 932             self
._textColor 
= data
.GetColour() 
 933             self
.UpdateSampleFont() 
 937     def OnOK(self
, optionsDialog
): 
 938         config 
= wx
.ConfigBase_Get() 
 939         doViewStuffUpdate 
= config
.ReadInt(self
._configPrefix 
+ "EditorViewWhitespace", False) != self
._viewWhitespaceCheckBox
.GetValue() 
 940         config
.WriteInt(self
._configPrefix 
+ "EditorViewWhitespace", self
._viewWhitespaceCheckBox
.GetValue()) 
 941         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewEOL", False) != self
._viewEOLCheckBox
.GetValue() 
 942         config
.WriteInt(self
._configPrefix 
+ "EditorViewEOL", self
._viewEOLCheckBox
.GetValue()) 
 943         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewIndentationGuides", False) != self
._viewIndentationGuideCheckBox
.GetValue() 
 944         config
.WriteInt(self
._configPrefix 
+ "EditorViewIndentationGuides", self
._viewIndentationGuideCheckBox
.GetValue()) 
 945         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewRightEdge", False) != self
._viewRightEdgeCheckBox
.GetValue() 
 946         config
.WriteInt(self
._configPrefix 
+ "EditorViewRightEdge", self
._viewRightEdgeCheckBox
.GetValue()) 
 947         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewLineNumbers", True) != self
._viewLineNumbersCheckBox
.GetValue() 
 948         config
.WriteInt(self
._configPrefix 
+ "EditorViewLineNumbers", self
._viewLineNumbersCheckBox
.GetValue()) 
 949         if self
._hasWordWrap
: 
 950             doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorWordWrap", False) != self
._wordWrapCheckBox
.GetValue() 
 951             config
.WriteInt(self
._configPrefix 
+ "EditorWordWrap", self
._wordWrapCheckBox
.GetValue()) 
 953             doViewStuffUpdate 
= doViewStuffUpdate 
or not config
.ReadInt(self
._configPrefix 
+ "EditorUseTabs", True) != self
._hasTabsCheckBox
.GetValue() 
 954             config
.WriteInt(self
._configPrefix 
+ "EditorUseTabs", not self
._hasTabsCheckBox
.GetValue()) 
 955             newIndentWidth 
= int(self
._indentWidthChoice
.GetStringSelection()) 
 956             oldIndentWidth 
= config
.ReadInt(self
._configPrefix 
+ "EditorIndentWidth", 4) 
 957             if newIndentWidth 
!= oldIndentWidth
: 
 958                 doViewStuffUpdate 
= True 
 959                 config
.WriteInt(self
._configPrefix 
+ "EditorIndentWidth", newIndentWidth
) 
 960         doFontUpdate 
= self
._originalTextFont 
!= self
._textFont 
or self
._originalTextColor 
!= self
._textColor
 
 961         config
.Write(self
._configPrefix 
+ "EditorFont", self
._textFont
.GetNativeFontInfoDesc()) 
 962         config
.Write(self
._configPrefix 
+ "EditorColor", "%02x%02x%02x" % (self
._textColor
.Red(), self
._textColor
.Green(), self
._textColor
.Blue())) 
 963         if doViewStuffUpdate 
or doFontUpdate
: 
 964             for document 
in optionsDialog
.GetDocManager().GetDocuments(): 
 965                 if issubclass(document
.GetDocumentTemplate().GetDocumentType(), TextDocument
): 
 966                     if doViewStuffUpdate
: 
 967                         document
.UpdateAllViews(hint 
= "ViewStuff") 
 969                         document
.UpdateAllViews(hint 
= "Font") 
 972 class TextCtrl(wx
.stc
.StyledTextCtrl
): 
 974     def __init__(self
, parent
, ID 
= -1, style 
= wx
.NO_FULL_REPAINT_ON_RESIZE
): 
 977         wx
.stc
.StyledTextCtrl
.__init
__(self
, parent
, ID
, style 
= style
) 
 980         self
._fontColor 
= None 
 982         self
.SetVisiblePolicy(wx
.stc
.STC_VISIBLE_STRICT
,0) 
 983         self
.SetYCaretPolicy(0, 0) 
 985         self
.CmdKeyClear(wx
.stc
.STC_KEY_ADD
, wx
.stc
.STC_SCMOD_CTRL
) 
 986         self
.CmdKeyClear(wx
.stc
.STC_KEY_SUBTRACT
, wx
.stc
.STC_SCMOD_CTRL
) 
 987         self
.CmdKeyAssign(wx
.stc
.STC_KEY_PRIOR
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMIN
) 
 988         self
.CmdKeyAssign(wx
.stc
.STC_KEY_NEXT
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMOUT
) 
 989         self
.Bind(wx
.stc
.EVT_STC_ZOOM
, self
.OnUpdateLineNumberMarginWidth
)  # auto update line num width on zoom 
 990         wx
.EVT_KEY_DOWN(self
, self
.OnKeyPressed
) 
 997         self
.SetViewWhiteSpace(False) 
 998         self
.SetEOLMode(wx
.stc
.STC_EOL_LF
) 
 999         self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
) 
1000         self
.SetEdgeColumn(78) 
1002         self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
) 
1003         self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
1006         self
.SetCaretForeground("BLACK") 
1008         self
.SetViewDefaults() 
1009         font
, color 
= self
.GetFontAndColorFromConfig() 
1011         self
.SetFontColor(color
) 
1012         self
.MarkerDefineDefault() 
1014         # for multisash initialization 
1015         if isinstance(parent
, wx
.lib
.multisash
.MultiClient
): 
1016             while parent
.GetParent(): 
1017                 parent 
= parent
.GetParent() 
1018                 if hasattr(parent
, "GetView"): 
1020             if hasattr(parent
, "GetView"): 
1021                 textEditor 
= parent
.GetView()._textEditor
 
1023                     doc 
= textEditor
.GetDocPointer() 
1025                         self
.SetDocPointer(doc
) 
1029     def SetViewDefaults(self
, configPrefix 
= "Text", hasWordWrap 
= True, hasTabs 
= False): 
1030         config 
= wx
.ConfigBase_Get() 
1031         self
.SetViewWhiteSpace(config
.ReadInt(configPrefix 
+ "EditorViewWhitespace", False)) 
1032         self
.SetViewEOL(config
.ReadInt(configPrefix 
+ "EditorViewEOL", False)) 
1033         self
.SetIndentationGuides(config
.ReadInt(configPrefix 
+ "EditorViewIndentationGuides", False)) 
1034         self
.SetViewRightEdge(config
.ReadInt(configPrefix 
+ "EditorViewRightEdge", False)) 
1035         self
.SetViewLineNumbers(config
.ReadInt(configPrefix 
+ "EditorViewLineNumbers", True)) 
1037             self
.SetWordWrap(config
.ReadInt(configPrefix 
+ "EditorWordWrap", False)) 
1038         if hasTabs
:  # These methods do not exist in STCTextEditor and are meant for subclasses 
1039             self
.SetUseTabs(config
.ReadInt(configPrefix 
+ "EditorUseTabs", False)) 
1040             self
.SetIndent(config
.ReadInt(configPrefix 
+ "EditorIndentWidth", 4)) 
1041             self
.SetTabWidth(config
.ReadInt(configPrefix 
+ "EditorIndentWidth", 4)) 
1043             self
.SetUseTabs(True) 
1049     def GetDefaultFont(self
): 
1050         """ Subclasses should override this """ 
1051         return wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
) 
1054     def GetDefaultColor(self
): 
1055         """ Subclasses should override this """ 
1059     def GetFontAndColorFromConfig(self
, configPrefix 
= "Text"): 
1060         font 
= self
.GetDefaultFont() 
1061         config 
= wx
.ConfigBase_Get() 
1062         fontData 
= config
.Read(configPrefix 
+ "EditorFont", "") 
1064             nativeFont 
= wx
.NativeFontInfo() 
1065             nativeFont
.FromString(fontData
) 
1066             font
.SetNativeFontInfo(nativeFont
) 
1067         color 
= self
.GetDefaultColor() 
1068         colorData 
= config
.Read(configPrefix 
+ "EditorColor", "") 
1070             red 
= int("0x" + colorData
[0:2], 16) 
1071             green 
= int("0x" + colorData
[2:4], 16) 
1072             blue 
= int("0x" + colorData
[4:6], 16) 
1073             color 
= wx
.Color(red
, green
, blue
) 
1080     def SetFont(self
, font
): 
1082         self
.StyleSetFont(wx
.stc
.STC_STYLE_DEFAULT
, self
._font
) 
1085     def GetFontColor(self
): 
1086         return self
._fontColor
 
1089     def SetFontColor(self
, fontColor 
= wx
.BLACK
): 
1090         self
._fontColor 
= fontColor
 
1091         self
.StyleSetForeground(wx
.stc
.STC_STYLE_DEFAULT
, "#%02x%02x%02x" % (self
._fontColor
.Red(), self
._fontColor
.Green(), self
._fontColor
.Blue())) 
1094     def UpdateStyles(self
): 
1095         self
.StyleClearAll() 
1099     def EstimatedLineNumberMarginWidth(self
): 
1102         lineNum 
= self
.GetLineCount() 
1103         lineNum 
= lineNum
/100 
1104         while lineNum 
>= 10: 
1105             lineNum 
= lineNum
/10 
1106             baseNumbers 
= baseNumbers 
+ "0" 
1108         return self
.TextWidth(wx
.stc
.STC_STYLE_LINENUMBER
, baseNumbers
) + MARGIN
 
1111     def OnUpdateLineNumberMarginWidth(self
, event
): 
1112         self
.UpdateLineNumberMarginWidth() 
1115     def UpdateLineNumberMarginWidth(self
): 
1116         if self
.GetViewLineNumbers(): 
1117             self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
1119     def MarkerDefineDefault(self
): 
1120         """ This must be called after the textcontrol is instantiated """ 
1121         self
.MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_ROUNDRECT
, wx
.BLACK
, wx
.BLUE
) 
1125         # Used when Delete key is hit. 
1126         sel 
= self
.GetSelection() 
1128         # Delete the selection or if no selection, the character after the caret. 
1129         if sel
[0] == sel
[1]: 
1130             self
.SetSelection(sel
[0], sel
[0] + 1) 
1132             # remove any folded lines also. 
1133             startLine 
= self
.LineFromPosition(sel
[0]) 
1134             endLine 
= self
.LineFromPosition(sel
[1]) 
1135             endLineStart 
= self
.PositionFromLine(endLine
) 
1136             if startLine 
!= endLine 
and sel
[1] - endLineStart 
== 0: 
1137                 while not self
.GetLineVisible(endLine
): 
1139                 self
.SetSelectionEnd(self
.PositionFromLine(endLine
)) 
1145         # replace any folded lines also. 
1146         sel 
= self
.GetSelection() 
1147         startLine 
= self
.LineFromPosition(sel
[0]) 
1148         endLine 
= self
.LineFromPosition(sel
[1]) 
1149         endLineStart 
= self
.PositionFromLine(endLine
) 
1150         if startLine 
!= endLine 
and sel
[1] - endLineStart 
== 0: 
1151             while not self
.GetLineVisible(endLine
): 
1153             self
.SetSelectionEnd(self
.PositionFromLine(endLine
)) 
1158     def OnKeyPressed(self
, event
): 
1159         key 
= event
.GetKeyCode() 
1160         if key 
== wx
.WXK_NUMPAD_ADD
:  #wxBug: For whatever reason, the key accelerators for numpad add and subtract with modifiers are not working so have to trap them here 
1161             if event
.ControlDown(): 
1162                 self
.ToggleFoldAll(expand 
= True, topLevelOnly 
= True) 
1163             elif event
.ShiftDown(): 
1164                 self
.ToggleFoldAll(expand 
= True) 
1166                 self
.ToggleFold(self
.GetCurrentLine()) 
1167         elif key 
== wx
.WXK_NUMPAD_SUBTRACT
: 
1168             if event
.ControlDown(): 
1169                 self
.ToggleFoldAll(expand 
= False, topLevelOnly 
= True) 
1170             elif event
.ShiftDown(): 
1171                 self
.ToggleFoldAll(expand 
= False) 
1173                 self
.ToggleFold(self
.GetCurrentLine()) 
1178     #---------------------------------------------------------------------------- 
1180     #---------------------------------------------------------------------------- 
1182     def GetViewRightEdge(self
): 
1183         return self
.GetEdgeMode() != wx
.stc
.STC_EDGE_NONE
 
1186     def SetViewRightEdge(self
, viewRightEdge
): 
1188             self
.SetEdgeMode(wx
.stc
.STC_EDGE_LINE
) 
1190             self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
) 
1193     def GetViewLineNumbers(self
): 
1194         return self
.GetMarginWidth(1) > 0 
1197     def SetViewLineNumbers(self
, viewLineNumbers 
= True): 
1199             self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
1201             self
.SetMarginWidth(1, 0) 
1204     def CanWordWrap(self
): 
1208     def GetWordWrap(self
): 
1209         return self
.GetWrapMode() == wx
.stc
.STC_WRAP_WORD
 
1212     def SetWordWrap(self
, wordWrap
): 
1214             self
.SetWrapMode(wx
.stc
.STC_WRAP_WORD
) 
1216             self
.SetWrapMode(wx
.stc
.STC_WRAP_NONE
) 
1219 #---------------------------------------------------------------------------- 
1220 # Icon Bitmaps - generated by encode_bitmaps.py 
1221 #---------------------------------------------------------------------------- 
1222 from wx 
import ImageFromStream
, BitmapFromImage
 
1223 from wx 
import EmptyIcon
 
1229 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1230 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1231 \x00\x00`IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\xa7JU!$\x12\x1d\ 
1232 \xeb\t\t8n\x81\xb4\x86J\xfa]h\x0ee\x83\xb4\xc6\x14\x00\x00R\xcc \t\xcd\xa1\ 
1233 \x08\xd2\xa3\xe1\x08*\t$\x1d\xc4\x012\x0b\x00\xce\xe4\xc8\xe0\t}\xf7\x8f\rV\ 
1234 \xd9\x1a\xec\xe0\xbf\xc1\xd7\x06\xd9\xf5UX\xfdF+m\x03\xb8\x00\xe4\xc74B"x\ 
1235 \xf1\xf4\x00\x00\x00\x00IEND\xaeB`\x82'  
1238 def getTextBitmap(): 
1239     return BitmapFromImage(getTextImage()) 
1242     stream 
= cStringIO
.StringIO(getTextData()) 
1243     return ImageFromStream(stream
) 
1247     icon
.CopyFromBitmap(getTextBitmap()) 
1251 #---------------------------------------------------------------------------- 
1252 # Menu Bitmaps - generated by encode_bitmaps.py 
1253 #---------------------------------------------------------------------------- 
1254 #---------------------------------------------------------------------- 
1255 def getZoomInData(): 
1257 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1258 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1259 \x00\x00wIDAT8\x8d\xa5\x93Q\x12\x80 \x08D\xb5\xe9X\xee\xe9\xb7{\xd5Gc\xa9\ 
1260 \xacX\xca\x1f\xa0\x8fE0\x92<\xc3\x82\xed*\x08\xa0\xf2I~\x07\x000\x17T,\xdb\ 
1261 \xd6;\x08\xa4\x00\xa4GA\xab\xca\x00\xbc*\x1eD\xb4\x90\xa4O\x1e\xe3\x16f\xcc(\ 
1262 \xc8\x95F\x95\x8d\x02\xef\xa1n\xa0\xce\xc5v\x91zc\xacU\xbey\x03\xf0.\xa8\xb8\ 
1263 \x04\x8c\xac\x04MM\xa1lA\xfe\x85?\x90\xe5=X\x06\\\xebCA\xb3Q\xf34\x14\x00\ 
1264 \x00\x00\x00IEND\xaeB`\x82'  
1266 def getZoomInBitmap(): 
1267     return BitmapFromImage(getZoomInImage()) 
1269 def getZoomInImage(): 
1270     stream 
= cStringIO
.StringIO(getZoomInData()) 
1271     return ImageFromStream(stream
) 
1273 #---------------------------------------------------------------------- 
1274 def getZoomOutData(): 
1276 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1277 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1278 \x00\x00qIDAT8\x8d\xa5\x92Q\x0e\xc0 \x08C-z\xff\x13O\xd9\xd7\x16"\x05\x8d\ 
1279 \xf6O\xa2\x8f"\x05\xa4\x96\x1b5V\xd4\xd1\xd5\x9e!\x15\xdb\x00\x1d]\xe7\x07\ 
1280 \xac\xf6Iv.B*fW\x0e\x90u\xc9 d\x84\x87v\x82\xb4\xf5\x08\'r\x0e\xa2N\x91~\x07\ 
1281 \xd9G\x95\xe2W\xeb\x00\x19\xc4\xd6\\FX\x12\xa3 \xb1:\x05\xacdAG[\xb0y9r`u\ 
1282 \x9d\x83k\xc0\x0b#3@0A\x0c"\x93\x00\x00\x00\x00IEND\xaeB`\x82'  
1285 def getZoomOutBitmap(): 
1286     return BitmapFromImage(getZoomOutImage()) 
1288 def getZoomOutImage(): 
1289     stream 
= cStringIO
.StringIO(getZoomOutData()) 
1290     return ImageFromStream(stream
)