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 SaveObject(self
, fileObject
): 
  51         view 
= self
.GetFirstView() 
  52         fileObject
.write(view
.GetValue()) 
  56     def LoadObject(self
, fileObject
): 
  57         view 
= self
.GetFirstView() 
  58         data 
= fileObject
.read() 
  64         view 
= self
.GetFirstView() 
  66             return wx
.lib
.docview
.Document
.IsModified(self
) or view
.IsModified() 
  68             return wx
.lib
.docview
.Document
.IsModified(self
) 
  71     def Modify(self
, mod
): 
  72         view 
= self
.GetFirstView() 
  73         wx
.lib
.docview
.Document
.Modify(self
, mod
) 
  78     def OnCreateCommandProcessor(self
): 
  79         # Don't create a command processor, it has its own 
  83 class TextView(wx
.lib
.docview
.View
): 
  87     #---------------------------------------------------------------------------- 
  89     #---------------------------------------------------------------------------- 
  92         wx
.lib
.docview
.View
.__init
__(self
) 
  93         self
._textEditor 
= None 
  95         self
._commandProcessor 
= None 
  99     def GetCtrlClass(self
): 
 100         """ Used in split window to instantiate new instances """ 
 105         return self
._textEditor
 
 108     def SetCtrl(self
, ctrl
): 
 109         self
._textEditor 
= ctrl
 
 112     def OnCreatePrintout(self
): 
 113         """ for Print Preview and Print """ 
 114         return TextPrintout(self
, self
.GetDocument().GetPrintableName()) 
 117     def OnCreate(self
, doc
, flags
): 
 118         frame 
= wx
.GetApp().CreateDocumentFrame(self
, doc
, flags
, style 
= wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
) 
 119         self
._dynSash 
= wx
.gizmos
.DynamicSashWindow(frame
, -1, style
=wx
.CLIP_CHILDREN
) 
 120         self
._dynSash
._view 
= self
 
 121         self
._textEditor 
= self
.GetCtrlClass()(self
._dynSash
, -1, style
=wx
.NO_BORDER
) 
 122         self
._CreateSizer
(frame
) 
 129     def _CreateSizer(self
, frame
): 
 130         sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 131         sizer
.Add(self
._dynSash
, 1, wx
.EXPAND
) 
 132         frame
.SetSizer(sizer
) 
 133         frame
.SetAutoLayout(True) 
 136     def OnUpdate(self
, sender 
= None, hint 
= None): 
 137         if hint 
== "ViewStuff": 
 138             self
.GetCtrl().SetViewDefaults() 
 140             font
, color 
= self
.GetFontAndColorFromConfig() 
 141             self
.GetCtrl().SetFont(font
) 
 142             self
.GetCtrl().SetFontColor(color
) 
 145     def OnActivateView(self
, activate
, activeView
, deactiveView
): 
 146         if activate 
and self
.GetCtrl(): 
 147             # In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop 
 148             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 151                 wx
.CallAfter(self
.SetFocus
) 
 156             self
.GetCtrl().SetFocus() 
 159     def OnClose(self
, deleteWindow 
= True): 
 160         if not wx
.lib
.docview
.View
.OnClose(self
, deleteWindow
): 
 163         if deleteWindow 
and self
.GetFrame(): 
 164             self
.GetFrame().Destroy() 
 168     def ProcessEvent(self
, event
):         
 171             self
.GetCtrl().Undo() 
 173         elif id == wx
.ID_REDO
: 
 174             self
.GetCtrl().Redo() 
 176         elif id == wx
.ID_CUT
: 
 179         elif id == wx
.ID_COPY
: 
 180             self
.GetCtrl().Copy() 
 182         elif id == wx
.ID_PASTE
: 
 183             self
.GetCtrl().OnPaste() 
 185         elif id == wx
.ID_CLEAR
: 
 186             self
.GetCtrl().OnClear() 
 188         elif id == wx
.ID_SELECTALL
: 
 189             self
.GetCtrl().SetSelection(0, -1) 
 191         elif id == VIEW_WHITESPACE_ID
: 
 192             self
.GetCtrl().SetViewWhiteSpace(not self
.GetCtrl().GetViewWhiteSpace()) 
 194         elif id == VIEW_EOL_ID
: 
 195             self
.GetCtrl().SetViewEOL(not self
.GetCtrl().GetViewEOL()) 
 197         elif id == VIEW_INDENTATION_GUIDES_ID
: 
 198             self
.GetCtrl().SetViewIndentationGuides(not self
.GetCtrl().GetViewIndentationGuides()) 
 200         elif id == VIEW_RIGHT_EDGE_ID
: 
 201             self
.GetCtrl().SetViewRightEdge(not self
.GetCtrl().GetViewRightEdge()) 
 203         elif id == VIEW_LINE_NUMBERS_ID
: 
 204             self
.GetCtrl().SetViewLineNumbers(not self
.GetCtrl().GetViewLineNumbers()) 
 206         elif id == ZOOM_NORMAL_ID
: 
 207             self
.GetCtrl().SetZoom(0) 
 209         elif id == ZOOM_IN_ID
: 
 210             self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMIN
) 
 212         elif id == ZOOM_OUT_ID
: 
 213             self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMOUT
) 
 215         elif id == CHOOSE_FONT_ID
: 
 218         elif id == WORD_WRAP_ID
: 
 219             self
.GetCtrl().SetWordWrap(not self
.GetCtrl().GetWordWrap()) 
 221         elif id == FindService
.FindService
.FIND_ID
: 
 224         elif id == FindService
.FindService
.FIND_PREVIOUS_ID
: 
 225             self
.DoFind(forceFindPrevious 
= True) 
 227         elif id == FindService
.FindService
.FIND_NEXT_ID
: 
 228             self
.DoFind(forceFindNext 
= True) 
 230         elif id == FindService
.FindService
.REPLACE_ID
: 
 231             self
.OnFind(replace 
= True) 
 233         elif id == FindService
.FindService
.FINDONE_ID
: 
 236         elif id == FindService
.FindService
.REPLACEONE_ID
: 
 237             self
.DoFind(replace 
= True) 
 239         elif id == FindService
.FindService
.REPLACEALL_ID
: 
 240             self
.DoFind(replaceAll 
= True) 
 242         elif id == FindService
.FindService
.GOTO_LINE_ID
: 
 243             self
.OnGotoLine(event
) 
 246             return wx
.lib
.docview
.View
.ProcessEvent(self
, event
) 
 249     def ProcessUpdateUIEvent(self
, event
): 
 250         if not self
.GetCtrl(): 
 255             event
.Enable(self
.GetCtrl().CanUndo()) 
 256             event
.SetText(_("&Undo\tCtrl+Z"))  # replace menu string 
 258         elif id == wx
.ID_REDO
: 
 259             event
.Enable(self
.GetCtrl().CanRedo()) 
 260             event
.SetText(_("&Redo\tCtrl+Y"))  # replace menu string 
 262         elif (id == wx
.ID_CUT
 
 264         or id == wx
.ID_CLEAR
): 
 265             hasSelection 
= self
.GetCtrl().GetSelectionStart() != self
.GetCtrl().GetSelectionEnd() 
 266             event
.Enable(hasSelection
) 
 268         elif id == wx
.ID_PASTE
: 
 269             event
.Enable(self
.GetCtrl().CanPaste()) 
 271         elif id == wx
.ID_SELECTALL
: 
 272             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 273             event
.Enable(hasText
) 
 278         elif id == VIEW_WHITESPACE_ID
: 
 279             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 280             event
.Enable(hasText
) 
 281             event
.Check(self
.GetCtrl().GetViewWhiteSpace()) 
 283         elif id == VIEW_EOL_ID
: 
 284             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 285             event
.Enable(hasText
) 
 286             event
.Check(self
.GetCtrl().GetViewEOL()) 
 288         elif id == VIEW_INDENTATION_GUIDES_ID
: 
 289             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 290             event
.Enable(hasText
) 
 291             event
.Check(self
.GetCtrl().GetIndentationGuides()) 
 293         elif id == VIEW_RIGHT_EDGE_ID
: 
 294             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 295             event
.Enable(hasText
) 
 296             event
.Check(self
.GetCtrl().GetViewRightEdge()) 
 298         elif id == VIEW_LINE_NUMBERS_ID
: 
 299             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 300             event
.Enable(hasText
) 
 301             event
.Check(self
.GetCtrl().GetViewLineNumbers()) 
 306         elif id == ZOOM_NORMAL_ID
: 
 307             event
.Enable(self
.GetCtrl().GetZoom() != 0) 
 309         elif id == ZOOM_IN_ID
: 
 310             event
.Enable(self
.GetCtrl().GetZoom() < 20) 
 312         elif id == ZOOM_OUT_ID
: 
 313             event
.Enable(self
.GetCtrl().GetZoom() > -10) 
 315         elif id == CHOOSE_FONT_ID
: 
 318         elif id == WORD_WRAP_ID
: 
 319             event
.Enable(self
.GetCtrl().CanWordWrap()) 
 320             event
.Check(self
.GetCtrl().CanWordWrap() and self
.GetCtrl().GetWordWrap()) 
 322         elif id == FindService
.FindService
.FIND_ID
: 
 323             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 324             event
.Enable(hasText
) 
 326         elif id == FindService
.FindService
.FIND_PREVIOUS_ID
: 
 327             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 328             event
.Enable(hasText 
and 
 329                          self
._FindServiceHasString
() and 
 330                          self
.GetCtrl().GetSelection()[0] > 0) 
 332         elif id == FindService
.FindService
.FIND_NEXT_ID
: 
 333             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 334             event
.Enable(hasText 
and 
 335                          self
._FindServiceHasString
() and 
 336                          self
.GetCtrl().GetSelection()[0] < self
.GetCtrl().GetLength()) 
 338         elif id == FindService
.FindService
.REPLACE_ID
: 
 339             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 340             event
.Enable(hasText
) 
 342         elif id == FindService
.FindService
.GOTO_LINE_ID
: 
 345         elif id == TEXT_STATUS_BAR_ID
: 
 346             self
.OnUpdateStatusBar(event
) 
 349             return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
) 
 352     def _GetParentFrame(self
): 
 353         return wx
.GetTopLevelParent(self
.GetFrame()) 
 356     #---------------------------------------------------------------------------- 
 357     # Methods for TextDocument to call 
 358     #---------------------------------------------------------------------------- 
 360     def IsModified(self
): 
 361         if not self
.GetCtrl(): 
 363         return self
.GetCtrl().GetModify() 
 366     def SetModifyFalse(self
): 
 367         self
.GetCtrl().SetSavePoint() 
 372             return self
.GetCtrl().GetText() 
 377     def SetValue(self
, value
): 
 378         self
.GetCtrl().SetText(value
) 
 379         self
.GetCtrl().UpdateLineNumberMarginWidth() 
 380         self
.GetCtrl().EmptyUndoBuffer() 
 383     #---------------------------------------------------------------------------- 
 385     #---------------------------------------------------------------------------- 
 387     def OnUpdateStatusBar(self
, event
): 
 388         statusBar 
= self
._GetParentFrame
().GetStatusBar() 
 389         statusBar
.SetInsertMode(self
.GetCtrl().GetOvertype() == 0) 
 390         statusBar
.SetLineNumber(self
.GetCtrl().GetCurrentLine() + 1) 
 391         statusBar
.SetColumnNumber(self
.GetCtrl().GetColumn(self
.GetCtrl().GetCurrentPos()) + 1) 
 394     #---------------------------------------------------------------------------- 
 396     #---------------------------------------------------------------------------- 
 398     def OnChooseFont(self
): 
 400         data
.EnableEffects(True) 
 401         data
.SetInitialFont(self
.GetCtrl().GetFont()) 
 402         data
.SetColour(self
.GetCtrl().GetFontColor()) 
 403         fontDialog 
= wx
.FontDialog(self
.GetFrame(), data
) 
 404         if fontDialog
.ShowModal() == wx
.ID_OK
: 
 405             data 
= fontDialog
.GetFontData() 
 406             self
.GetCtrl().SetFont(data
.GetChosenFont()) 
 407             self
.GetCtrl().SetFontColor(data
.GetColour()) 
 408             self
.GetCtrl().UpdateStyles() 
 412     #---------------------------------------------------------------------------- 
 414     #---------------------------------------------------------------------------- 
 416     def OnFind(self
, replace 
= False): 
 417         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 419             findService
.ShowFindReplaceDialog(findString 
= self
.GetCtrl().GetSelectedText(), replace 
= replace
) 
 422     def DoFind(self
, forceFindNext 
= False, forceFindPrevious 
= False, replace 
= False, replaceAll 
= False): 
 423         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 426         findString 
= findService
.GetFindString() 
 427         if len(findString
) == 0: 
 429         replaceString 
= findService
.GetReplaceString() 
 430         flags 
= findService
.GetFlags() 
 431         startLoc
, endLoc 
= self
.GetCtrl().GetSelection() 
 433         wholeWord 
= flags 
& wx
.FR_WHOLEWORD 
> 0 
 434         matchCase 
= flags 
& wx
.FR_MATCHCASE 
> 0 
 435         regExp 
= flags 
& FindService
.FindService
.FR_REGEXP 
> 0 
 436         down 
= flags 
& wx
.FR_DOWN 
> 0 
 437         wrap 
= flags 
& FindService
.FindService
.FR_WRAP 
> 0 
 439         if forceFindPrevious
:   # this is from function keys, not dialog box 
 441             wrap 
= False        # user would want to know they're at the end of file 
 444             wrap 
= False        # user would want to know they're at the end of file 
 448         # On replace dialog operations, user is allowed to replace the currently highlighted text to determine if it should be replaced or not. 
 449         # 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. 
 450         # If the text is a match, then replace it. 
 452             result
, start
, end
, replText 
= findService
.DoFind(findString
, replaceString
, self
.GetCtrl().GetSelectedText(), 0, 0, True, matchCase
, wholeWord
, regExp
, replace
) 
 454                 self
.GetCtrl().ReplaceSelection(replText
) 
 455                 self
.GetDocument().Modify(True) 
 456                 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
) 
 458                     startLoc 
+= len(replText
)  # advance start location past replacement string to new text 
 460             elif result 
== FindService
.FIND_SYNTAXERROR
: 
 462                 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
) 
 465             text 
= self
.GetCtrl().GetText() 
 467             # Find the next matching text occurance or if it is a ReplaceAll, replace all occurances 
 468             # 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 
 469             result
, start
, end
, text 
= findService
.DoFind(findString
, replaceString
, text
, startLoc
, endLoc
, down
, matchCase
, wholeWord
, regExp
, False, replaceAll
, wrap
) 
 471                 self
.GetCtrl().SetTargetStart(0) 
 472                 self
.GetCtrl().SetTargetEnd(self
.GetCtrl().GetLength()) 
 473                 self
.GetCtrl().ReplaceTarget(text
)  # Doing a SetText causes a clear document to be shown when undoing, so using replacetarget instead 
 474                 self
.GetDocument().Modify(True) 
 476                     wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
) 
 478                     wx
.GetApp().GetTopWindow().PushStatusText(_("%i occurrences of \"%s\" replaced") % (result
, findString
)) 
 480                 self
.GetCtrl().SetSelection(start
, end
) 
 481                 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(end
))  # show bottom then scroll up to top 
 482                 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(start
)) # do this after ensuring bottom is visible 
 483                 wx
.GetApp().GetTopWindow().PushStatusText(_("Found \"%s\".") % findString
) 
 484             elif result 
== FindService
.FIND_SYNTAXERROR
: 
 485                 # Dialog for this case gets popped up by the FindService. 
 486                 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
) 
 488                 wx
.MessageBox(_("Can't find \"%s\".") % findString
, "Find", 
 489                           wx
.OK | wx
.ICON_INFORMATION
) 
 492     def _FindServiceHasString(self
): 
 493         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 494         if not findService 
or not findService
.GetFindString(): 
 499     def OnGotoLine(self
, event
): 
 500         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 502             line 
= findService
.GetLineNumber(self
.GetDocumentManager().FindSuitableParent()) 
 505                 self
.GetCtrl().EnsureVisible(line
) 
 506                 self
.GetCtrl().GotoLine(line
) 
 509     def GotoLine(self
, lineNum
): 
 511             lineNum 
= lineNum 
- 1  # line numbering for editor is 0 based, we are 1 based. 
 512             self
.GetCtrl().EnsureVisibleEnforcePolicy(lineNum
) 
 513             self
.GetCtrl().GotoLine(lineNum
) 
 516     def SetSelection(self
, start
, end
): 
 517         self
.GetCtrl().SetSelection(start
, end
) 
 520     def EnsureVisible(self
, line
): 
 521         self
.GetCtrl().EnsureVisible(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 523     def EnsureVisibleEnforcePolicy(self
, line
): 
 524         self
.GetCtrl().EnsureVisibleEnforcePolicy(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 526     def LineFromPosition(self
, pos
): 
 527         return self
.GetCtrl().LineFromPosition(pos
)+1  # line numbering for editor is 0 based, we are 1 based. 
 530     def PositionFromLine(self
, line
): 
 531         return self
.GetCtrl().PositionFromLine(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 534     def GetLineEndPosition(self
, line
): 
 535         return self
.GetCtrl().GetLineEndPosition(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 538     def GetLine(self
, lineNum
): 
 539         return self
.GetCtrl().GetLine(lineNum
-1)  # line numbering for editor is 0 based, we are 1 based. 
 542     def MarkerDefine(self
): 
 543         """ This must be called after the texteditor is instantiated """ 
 544         self
.GetCtrl().MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_CIRCLE
, wx
.BLACK
, wx
.BLUE
) 
 547     def MarkerToggle(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 549             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 550         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 551             self
.GetCtrl().MarkerDelete(lineNum
, marker_index
) 
 552             self
._markerCount 
-= 1 
 554             self
.GetCtrl().MarkerAdd(lineNum
, marker_index
) 
 555             self
._markerCount 
+= 1 
 558     def MarkerAdd(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 560             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 561         self
.GetCtrl().MarkerAdd(lineNum
, marker_index
) 
 562         self
._markerCount 
+= 1 
 565     def MarkerDelete(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 567             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 568         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 569             self
.GetCtrl().MarkerDelete(lineNum
, marker_index
) 
 570             self
._markerCount 
-= 1 
 572     def MarkerDeleteAll(self
, marker_num
=MARKER_NUM
): 
 573         self
.GetCtrl().MarkerDeleteAll(marker_num
) 
 574         if marker_num 
== self
.MARKER_NUM
: 
 575             self
._markerCount 
= 0 
 578     def MarkerNext(self
, lineNum 
= -1): 
 580             lineNum 
= self
.GetCtrl().GetCurrentLine() + 1  # start search below current line 
 581         foundLine 
= self
.GetCtrl().MarkerNext(lineNum
, self
.MARKER_MASK
) 
 583             # wrap to top of file 
 584             foundLine 
= self
.GetCtrl().MarkerNext(0, self
.MARKER_MASK
) 
 586                 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers")) 
 589         self
.GotoLine(foundLine 
+ 1) 
 592     def MarkerPrevious(self
, lineNum 
= -1): 
 594             lineNum 
= self
.GetCtrl().GetCurrentLine() - 1  # start search above current line 
 596                 lineNum 
= self
.GetCtrl().GetLineCount() 
 598         foundLine 
= self
.GetCtrl().MarkerPrevious(lineNum
, self
.MARKER_MASK
) 
 600             # wrap to bottom of file 
 601             foundLine 
= self
.GetCtrl().MarkerPrevious(self
.GetCtrl().GetLineCount(), self
.MARKER_MASK
) 
 603                 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers")) 
 606         self
.GotoLine(foundLine 
+ 1) 
 609     def MarkerExists(self
, lineNum 
= -1, mask
=MARKER_MASK
): 
 611             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 612         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 618     def GetMarkerCount(self
): 
 619         return self
._markerCount
 
 622 class TextService(wx
.lib
.pydocview
.DocService
): 
 626         wx
.lib
.pydocview
.DocService
.__init
__(self
) 
 629     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
 630         if document 
and document
.GetDocumentTemplate().GetDocumentType() != TextDocument
: 
 632         if not document 
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 635         statusBar 
= TextStatusBar(frame
, TEXT_STATUS_BAR_ID
) 
 636         frame
.SetStatusBar(statusBar
) 
 637         wx
.EVT_UPDATE_UI(frame
, TEXT_STATUS_BAR_ID
, frame
.ProcessUpdateUIEvent
) 
 639         viewMenu 
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View"))) 
 641         viewMenu
.AppendSeparator() 
 643         textMenu
.AppendCheckItem(VIEW_WHITESPACE_ID
, _("&Whitespace"), _("Shows or hides whitespace")) 
 644         wx
.EVT_MENU(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessEvent
) 
 645         wx
.EVT_UPDATE_UI(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessUpdateUIEvent
) 
 646         textMenu
.AppendCheckItem(VIEW_EOL_ID
, _("&End of Line Markers"), _("Shows or hides indicators at the end of each line")) 
 647         wx
.EVT_MENU(frame
, VIEW_EOL_ID
, frame
.ProcessEvent
) 
 648         wx
.EVT_UPDATE_UI(frame
, VIEW_EOL_ID
, frame
.ProcessUpdateUIEvent
) 
 649         textMenu
.AppendCheckItem(VIEW_INDENTATION_GUIDES_ID
, _("&Indentation Guides"), _("Shows or hides indentations")) 
 650         wx
.EVT_MENU(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessEvent
) 
 651         wx
.EVT_UPDATE_UI(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessUpdateUIEvent
) 
 652         textMenu
.AppendCheckItem(VIEW_RIGHT_EDGE_ID
, _("&Right Edge"), _("Shows or hides the right edge marker")) 
 653         wx
.EVT_MENU(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessEvent
) 
 654         wx
.EVT_UPDATE_UI(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessUpdateUIEvent
) 
 655         textMenu
.AppendCheckItem(VIEW_LINE_NUMBERS_ID
, _("&Line Numbers"), _("Shows or hides the line numbers")) 
 656         wx
.EVT_MENU(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessEvent
) 
 657         wx
.EVT_UPDATE_UI(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessUpdateUIEvent
) 
 659         viewMenu
.AppendMenu(TEXT_ID
, _("&Text"), textMenu
) 
 660         wx
.EVT_UPDATE_UI(frame
, TEXT_ID
, frame
.ProcessUpdateUIEvent
) 
 662         isWindows 
= (wx
.Platform 
== '__WXMSW__') 
 665         zoomMenu
.Append(ZOOM_NORMAL_ID
, _("Normal Size"), _("Sets the document to its normal size")) 
 666         wx
.EVT_MENU(frame
, ZOOM_NORMAL_ID
, frame
.ProcessEvent
) 
 667         wx
.EVT_UPDATE_UI(frame
, ZOOM_NORMAL_ID
, frame
.ProcessUpdateUIEvent
) 
 669             zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In\tCtrl+Page Up"), _("Zooms the document to a larger size")) 
 671             zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In"), _("Zooms the document to a larger size")) 
 672         wx
.EVT_MENU(frame
, ZOOM_IN_ID
, frame
.ProcessEvent
) 
 673         wx
.EVT_UPDATE_UI(frame
, ZOOM_IN_ID
, frame
.ProcessUpdateUIEvent
) 
 675             zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out\tCtrl+Page Down"), _("Zooms the document to a smaller size")) 
 677             zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out"), _("Zooms the document to a smaller size")) 
 678         wx
.EVT_MENU(frame
, ZOOM_OUT_ID
, frame
.ProcessEvent
) 
 679         wx
.EVT_UPDATE_UI(frame
, ZOOM_OUT_ID
, frame
.ProcessUpdateUIEvent
) 
 681         viewMenu
.AppendMenu(ZOOM_ID
, _("&Zoom"), zoomMenu
) 
 682         wx
.EVT_UPDATE_UI(frame
, ZOOM_ID
, frame
.ProcessUpdateUIEvent
) 
 684         formatMenuIndex 
= menuBar
.FindMenu(_("&Format")) 
 685         if formatMenuIndex 
> -1: 
 686             formatMenu 
= menuBar
.GetMenu(formatMenuIndex
) 
 688             formatMenu 
= wx
.Menu() 
 689         if not menuBar
.FindItemById(CHOOSE_FONT_ID
): 
 690             formatMenu
.Append(CHOOSE_FONT_ID
, _("&Font..."), _("Sets the font to use")) 
 691             wx
.EVT_MENU(frame
, CHOOSE_FONT_ID
, frame
.ProcessEvent
) 
 692             wx
.EVT_UPDATE_UI(frame
, CHOOSE_FONT_ID
, frame
.ProcessUpdateUIEvent
) 
 693         if not menuBar
.FindItemById(WORD_WRAP_ID
): 
 694             formatMenu
.AppendCheckItem(WORD_WRAP_ID
, _("Word Wrap"), _("Wraps text horizontally when checked")) 
 695             wx
.EVT_MENU(frame
, WORD_WRAP_ID
, frame
.ProcessEvent
) 
 696             wx
.EVT_UPDATE_UI(frame
, WORD_WRAP_ID
, frame
.ProcessUpdateUIEvent
) 
 697         if formatMenuIndex 
== -1: 
 698             viewMenuIndex 
= menuBar
.FindMenu(_("&View")) 
 699             menuBar
.Insert(viewMenuIndex 
+ 1, formatMenu
, _("&Format")) 
 701         # wxBug: wxToolBar::GetToolPos doesn't exist, need it to find cut tool and then insert find in front of it. 
 702         toolBar
.AddSeparator() 
 703         toolBar
.AddTool(ZOOM_IN_ID
, getZoomInBitmap(), shortHelpString 
= _("Zoom In"), longHelpString 
= _("Zooms the document to a larger size")) 
 704         toolBar
.AddTool(ZOOM_OUT_ID
, getZoomOutBitmap(), shortHelpString 
= _("Zoom Out"), longHelpString 
= _("Zooms the document to a smaller size")) 
 708     def ProcessUpdateUIEvent(self
, event
): 
 711         or id == VIEW_WHITESPACE_ID
 
 713         or id == VIEW_INDENTATION_GUIDES_ID
 
 714         or id == VIEW_RIGHT_EDGE_ID
 
 715         or id == VIEW_LINE_NUMBERS_ID
 
 717         or id == ZOOM_NORMAL_ID
 
 720         or id == CHOOSE_FONT_ID
 
 721         or id == WORD_WRAP_ID
): 
 728 class TextStatusBar(wx
.StatusBar
): 
 730     # 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 
 732     def __init__(self
, parent
, id, style 
= wx
.ST_SIZEGRIP
, name 
= "statusBar"): 
 733         wx
.StatusBar
.__init
__(self
, parent
, id, style
, name
) 
 734         self
.SetFieldsCount(4) 
 735         self
.SetStatusWidths([-1, 50, 50, 55]) 
 737     def SetInsertMode(self
, insert 
= True): 
 742         if self
.GetStatusText(1) != newText
:     # wxBug: Need to check if the text has changed, otherwise it flickers under win32 
 743             self
.SetStatusText(newText
, 1) 
 745     def SetLineNumber(self
, lineNumber
): 
 746         newText 
= _("Ln %i") % lineNumber
 
 747         if self
.GetStatusText(2) != newText
: 
 748             self
.SetStatusText(newText
, 2) 
 750     def SetColumnNumber(self
, colNumber
): 
 751         newText 
= _("Col %i") % colNumber
 
 752         if self
.GetStatusText(3) != newText
: 
 753             self
.SetStatusText(newText
, 3) 
 756 class TextOptionsPanel(wx
.Panel
): 
 759     def __init__(self
, parent
, id, configPrefix 
= "Text", label 
= "Text", hasWordWrap 
= True, hasTabs 
= False, addPage
=True): 
 760         wx
.Panel
.__init
__(self
, parent
, id) 
 761         self
._configPrefix 
= configPrefix
 
 762         self
._hasWordWrap 
= hasWordWrap
 
 763         self
._hasTabs 
= hasTabs
 
 766         config 
= wx
.ConfigBase_Get() 
 767         self
._textFont 
= wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
) 
 768         fontData 
= config
.Read(self
._configPrefix 
+ "EditorFont", "") 
 770             nativeFont 
= wx
.NativeFontInfo() 
 771             nativeFont
.FromString(fontData
) 
 772             self
._textFont
.SetNativeFontInfo(nativeFont
) 
 773         self
._originalTextFont 
= self
._textFont
 
 774         self
._textColor 
= wx
.BLACK
 
 775         colorData 
= config
.Read(self
._configPrefix 
+ "EditorColor", "") 
 777             red 
= int("0x" + colorData
[0:2], 16) 
 778             green 
= int("0x" + colorData
[2:4], 16) 
 779             blue 
= int("0x" + colorData
[4:6], 16) 
 780             self
._textColor 
= wx
.Color(red
, green
, blue
) 
 781         self
._originalTextColor 
= self
._textColor
 
 782         fontLabel 
= wx
.StaticText(self
, -1, _("Font:")) 
 783         self
._sampleTextCtrl 
= wx
.TextCtrl(self
, -1, "", size 
= (125, 21)) 
 784         self
._sampleTextCtrl
.SetEditable(False) 
 785         chooseFontButton 
= wx
.Button(self
, -1, _("Choose Font...")) 
 786         wx
.EVT_BUTTON(self
, chooseFontButton
.GetId(), self
.OnChooseFont
) 
 787         if self
._hasWordWrap
: 
 788             self
._wordWrapCheckBox 
= wx
.CheckBox(self
, -1, _("Wrap words inside text area")) 
 789             self
._wordWrapCheckBox
.SetValue(wx
.ConfigBase_Get().ReadInt(self
._configPrefix 
+ "EditorWordWrap", False)) 
 790         self
._viewWhitespaceCheckBox 
= wx
.CheckBox(self
, -1, _("Show whitespace")) 
 791         self
._viewWhitespaceCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewWhitespace", False)) 
 792         self
._viewEOLCheckBox 
= wx
.CheckBox(self
, -1, _("Show end of line markers")) 
 793         self
._viewEOLCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewEOL", False)) 
 794         self
._viewIndentationGuideCheckBox 
= wx
.CheckBox(self
, -1, _("Show indentation guides")) 
 795         self
._viewIndentationGuideCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewIndentationGuides", False)) 
 796         self
._viewRightEdgeCheckBox 
= wx
.CheckBox(self
, -1, _("Show right edge")) 
 797         self
._viewRightEdgeCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewRightEdge", False)) 
 798         self
._viewLineNumbersCheckBox 
= wx
.CheckBox(self
, -1, _("Show line numbers")) 
 799         self
._viewLineNumbersCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewLineNumbers", True)) 
 801             self
._hasTabsCheckBox 
= wx
.CheckBox(self
, -1, _("Use spaces instead of tabs")) 
 802             self
._hasTabsCheckBox
.SetValue(not wx
.ConfigBase_Get().ReadInt(self
._configPrefix 
+ "EditorUseTabs", False)) 
 803             indentWidthLabel 
= wx
.StaticText(self
, -1, _("Indent Width:")) 
 804             self
._indentWidthChoice 
= wx
.Choice(self
, -1, choices 
= ["2", "4", "6", "8", "10"]) 
 805             self
._indentWidthChoice
.SetStringSelection(str(config
.ReadInt(self
._configPrefix 
+ "EditorIndentWidth", 4))) 
 806         textPanelBorderSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 807         textPanelSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 808         textFontSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 809         textFontSizer
.Add(fontLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
) 
 810         textFontSizer
.Add(self
._sampleTextCtrl
, 0, wx
.ALIGN_LEFT | wx
.EXPAND | wx
.RIGHT
, HALF_SPACE
) 
 811         textFontSizer
.Add(chooseFontButton
, 0, wx
.ALIGN_RIGHT | wx
.LEFT
, HALF_SPACE
) 
 812         textPanelSizer
.Add(textFontSizer
, 0, wx
.ALL
, HALF_SPACE
) 
 813         if self
._hasWordWrap
: 
 814             textPanelSizer
.Add(self
._wordWrapCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 815         textPanelSizer
.Add(self
._viewWhitespaceCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 816         textPanelSizer
.Add(self
._viewEOLCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 817         textPanelSizer
.Add(self
._viewIndentationGuideCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 818         textPanelSizer
.Add(self
._viewRightEdgeCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 819         textPanelSizer
.Add(self
._viewLineNumbersCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 821             textPanelSizer
.Add(self
._hasTabsCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 822             textIndentWidthSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 823             textIndentWidthSizer
.Add(indentWidthLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
) 
 824             textIndentWidthSizer
.Add(self
._indentWidthChoice
, 0, wx
.ALIGN_LEFT | wx
.EXPAND
, HALF_SPACE
) 
 825             textPanelSizer
.Add(textIndentWidthSizer
, 0, wx
.ALL
, HALF_SPACE
) 
 826         textPanelBorderSizer
.Add(textPanelSizer
, 0, wx
.ALL
, SPACE
) 
 827 ##        styleButton = wx.Button(self, -1, _("Choose Style...")) 
 828 ##        wx.EVT_BUTTON(self, styleButton.GetId(), self.OnChooseStyle) 
 829 ##        textPanelBorderSizer.Add(styleButton, 0, wx.ALL, SPACE) 
 830         self
.SetSizer(textPanelBorderSizer
) 
 831         self
.UpdateSampleFont() 
 833             parent
.AddPage(self
, _(label
)) 
 835     def UpdateSampleFont(self
): 
 836         nativeFont 
= wx
.NativeFontInfo() 
 837         nativeFont
.FromString(self
._textFont
.GetNativeFontInfoDesc()) 
 839         font
.SetNativeFontInfo(nativeFont
) 
 840         font
.SetPointSize(self
._sampleTextCtrl
.GetFont().GetPointSize())  # Use the standard point size 
 841         self
._sampleTextCtrl
.SetFont(font
) 
 842         self
._sampleTextCtrl
.SetForegroundColour(self
._textColor
) 
 843         self
._sampleTextCtrl
.SetValue(str(self
._textFont
.GetPointSize()) + _(" pt. ") + self
._textFont
.GetFaceName()) 
 844         self
._sampleTextCtrl
.Refresh() 
 848 ##    def OnChooseStyle(self, event): 
 849 ##        import STCStyleEditor 
 851 ##        base = os.path.split(__file__)[0] 
 852 ##        config = os.path.abspath(os.path.join(base, 'stc-styles.rc.cfg')) 
 854 ##        dlg = STCStyleEditor.STCStyleEditDlg(None, 
 855 ##                                'Python', 'python', 
 865     def OnChooseFont(self
, event
): 
 867         data
.EnableEffects(True) 
 868         data
.SetInitialFont(self
._textFont
) 
 869         data
.SetColour(self
._textColor
) 
 870         fontDialog 
= wx
.FontDialog(self
, data
) 
 871         if fontDialog
.ShowModal() == wx
.ID_OK
: 
 872             data 
= fontDialog
.GetFontData() 
 873             self
._textFont 
= data
.GetChosenFont() 
 874             self
._textColor 
= data
.GetColour() 
 875             self
.UpdateSampleFont() 
 879     def OnOK(self
, optionsDialog
): 
 880         config 
= wx
.ConfigBase_Get() 
 881         doViewStuffUpdate 
= config
.ReadInt(self
._configPrefix 
+ "EditorViewWhitespace", False) != self
._viewWhitespaceCheckBox
.GetValue() 
 882         config
.WriteInt(self
._configPrefix 
+ "EditorViewWhitespace", self
._viewWhitespaceCheckBox
.GetValue()) 
 883         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewEOL", False) != self
._viewEOLCheckBox
.GetValue() 
 884         config
.WriteInt(self
._configPrefix 
+ "EditorViewEOL", self
._viewEOLCheckBox
.GetValue()) 
 885         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewIndentationGuides", False) != self
._viewIndentationGuideCheckBox
.GetValue() 
 886         config
.WriteInt(self
._configPrefix 
+ "EditorViewIndentationGuides", self
._viewIndentationGuideCheckBox
.GetValue()) 
 887         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewRightEdge", False) != self
._viewRightEdgeCheckBox
.GetValue() 
 888         config
.WriteInt(self
._configPrefix 
+ "EditorViewRightEdge", self
._viewRightEdgeCheckBox
.GetValue()) 
 889         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewLineNumbers", True) != self
._viewLineNumbersCheckBox
.GetValue() 
 890         config
.WriteInt(self
._configPrefix 
+ "EditorViewLineNumbers", self
._viewLineNumbersCheckBox
.GetValue()) 
 891         if self
._hasWordWrap
: 
 892             doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorWordWrap", False) != self
._wordWrapCheckBox
.GetValue() 
 893             config
.WriteInt(self
._configPrefix 
+ "EditorWordWrap", self
._wordWrapCheckBox
.GetValue()) 
 895             doViewStuffUpdate 
= doViewStuffUpdate 
or not config
.ReadInt(self
._configPrefix 
+ "EditorUseTabs", True) != self
._hasTabsCheckBox
.GetValue() 
 896             config
.WriteInt(self
._configPrefix 
+ "EditorUseTabs", not self
._hasTabsCheckBox
.GetValue()) 
 897             newIndentWidth 
= int(self
._indentWidthChoice
.GetStringSelection()) 
 898             oldIndentWidth 
= config
.ReadInt(self
._configPrefix 
+ "EditorIndentWidth", 4) 
 899             if newIndentWidth 
!= oldIndentWidth
: 
 900                 doViewStuffUpdate 
= True 
 901                 config
.WriteInt(self
._configPrefix 
+ "EditorIndentWidth", newIndentWidth
) 
 902         doFontUpdate 
= self
._originalTextFont 
!= self
._textFont 
or self
._originalTextColor 
!= self
._textColor
 
 903         config
.Write(self
._configPrefix 
+ "EditorFont", self
._textFont
.GetNativeFontInfoDesc()) 
 904         config
.Write(self
._configPrefix 
+ "EditorColor", "%02x%02x%02x" % (self
._textColor
.Red(), self
._textColor
.Green(), self
._textColor
.Blue())) 
 905         if doViewStuffUpdate 
or doFontUpdate
: 
 906             for document 
in optionsDialog
.GetDocManager().GetDocuments(): 
 907                 if issubclass(document
.GetDocumentTemplate().GetDocumentType(), TextDocument
): 
 908                     if doViewStuffUpdate
: 
 909                         document
.UpdateAllViews(hint 
= "ViewStuff") 
 911                         document
.UpdateAllViews(hint 
= "Font") 
 914 class TextCtrl(wx
.stc
.StyledTextCtrl
): 
 916     def __init__(self
, parent
, id=-1, style
=wx
.NO_FULL_REPAINT_ON_RESIZE
): 
 917         wx
.stc
.StyledTextCtrl
.__init
__(self
, parent
, id, style
=style
) 
 919         if isinstance(parent
, wx
.gizmos
.DynamicSashWindow
): 
 920             self
._dynSash 
= parent
 
 921             self
.SetupDSScrollBars() 
 922             self
.Bind(wx
.gizmos
.EVT_DYNAMIC_SASH_SPLIT
, self
.OnDSSplit
) 
 923             self
.Bind(wx
.gizmos
.EVT_DYNAMIC_SASH_UNIFY
, self
.OnDSUnify
) 
 926         self
._fontColor 
= None 
 928         self
.SetVisiblePolicy(wx
.stc
.STC_VISIBLE_STRICT
,1) 
 930         self
.CmdKeyClear(wx
.stc
.STC_KEY_ADD
, wx
.stc
.STC_SCMOD_CTRL
) 
 931         self
.CmdKeyClear(wx
.stc
.STC_KEY_SUBTRACT
, wx
.stc
.STC_SCMOD_CTRL
) 
 932         self
.CmdKeyAssign(wx
.stc
.STC_KEY_PRIOR
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMIN
) 
 933         self
.CmdKeyAssign(wx
.stc
.STC_KEY_NEXT
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMOUT
) 
 934         self
.Bind(wx
.stc
.EVT_STC_ZOOM
, self
.OnUpdateLineNumberMarginWidth
)  # auto update line num width on zoom 
 935         wx
.EVT_KEY_DOWN(self
, self
.OnKeyPressed
) 
 936         wx
.EVT_KILL_FOCUS(self
, self
.OnKillFocus
) 
 937         wx
.EVT_SET_FOCUS(self
, self
.OnFocus
) 
 944         self
.SetViewWhiteSpace(False) 
 945         self
.SetEOLMode(wx
.stc
.STC_EOL_LF
) 
 946         self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
) 
 947         self
.SetEdgeColumn(78) 
 949         self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
) 
 950         self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
 953         self
.SetCaretForeground("BLACK") 
 955         self
.SetViewDefaults() 
 956         font
, color 
= self
.GetFontAndColorFromConfig() 
 958         self
.SetFontColor(color
) 
 959         self
.MarkerDefineDefault() 
 962     def OnFocus(self
, event
): 
 963         self
.SetSelBackground(1, "BLUE") 
 964         self
.SetSelForeground(1, "WHITE") 
 965         if hasattr(self
, "_dynSash"): 
 966             self
._dynSash
._view
.SetCtrl(self
) 
 970     def OnKillFocus(self
, event
): 
 971         self
.SetSelBackground(0, "BLUE") 
 972         self
.SetSelForeground(0, "WHITE") 
 973         self
.SetSelBackground(1, "#C0C0C0") 
 974         # Don't set foreground color, use syntax highlighted default colors. 
 978     def SetViewDefaults(self
, configPrefix 
= "Text", hasWordWrap 
= True, hasTabs 
= False): 
 979         config 
= wx
.ConfigBase_Get() 
 980         self
.SetViewWhiteSpace(config
.ReadInt(configPrefix 
+ "EditorViewWhitespace", False)) 
 981         self
.SetViewEOL(config
.ReadInt(configPrefix 
+ "EditorViewEOL", False)) 
 982         self
.SetIndentationGuides(config
.ReadInt(configPrefix 
+ "EditorViewIndentationGuides", False)) 
 983         self
.SetViewRightEdge(config
.ReadInt(configPrefix 
+ "EditorViewRightEdge", False)) 
 984         self
.SetViewLineNumbers(config
.ReadInt(configPrefix 
+ "EditorViewLineNumbers", True)) 
 986             self
.SetWordWrap(config
.ReadInt(configPrefix 
+ "EditorWordWrap", False)) 
 987         if hasTabs
:  # These methods do not exist in STCTextEditor and are meant for subclasses 
 988             self
.SetUseTabs(config
.ReadInt(configPrefix 
+ "EditorUseTabs", False)) 
 989             self
.SetIndent(config
.ReadInt(configPrefix 
+ "EditorIndentWidth", 4)) 
 990             self
.SetTabWidth(config
.ReadInt(configPrefix 
+ "EditorIndentWidth", 4)) 
 992             self
.SetUseTabs(True) 
 997     def GetDefaultFont(self
): 
 998         """ Subclasses should override this """ 
 999         return wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
) 
1002     def GetDefaultColor(self
): 
1003         """ Subclasses should override this """ 
1007     def GetFontAndColorFromConfig(self
, configPrefix 
= "Text"): 
1008         font 
= self
.GetDefaultFont() 
1009         config 
= wx
.ConfigBase_Get() 
1010         fontData 
= config
.Read(configPrefix 
+ "EditorFont", "") 
1012             nativeFont 
= wx
.NativeFontInfo() 
1013             nativeFont
.FromString(fontData
) 
1014             font
.SetNativeFontInfo(nativeFont
) 
1015         color 
= self
.GetDefaultColor() 
1016         colorData 
= config
.Read(configPrefix 
+ "EditorColor", "") 
1018             red 
= int("0x" + colorData
[0:2], 16) 
1019             green 
= int("0x" + colorData
[2:4], 16) 
1020             blue 
= int("0x" + colorData
[4:6], 16) 
1021             color 
= wx
.Color(red
, green
, blue
) 
1029     def SetFont(self
, font
): 
1031         self
.StyleSetFont(wx
.stc
.STC_STYLE_DEFAULT
, self
._font
) 
1034     def GetFontColor(self
): 
1035         return self
._fontColor
 
1038     def SetFontColor(self
, fontColor 
= wx
.BLACK
): 
1039         self
._fontColor 
= fontColor
 
1040         self
.StyleSetForeground(wx
.stc
.STC_STYLE_DEFAULT
, "#%02x%02x%02x" % (self
._fontColor
.Red(), self
._fontColor
.Green(), self
._fontColor
.Blue())) 
1043     def UpdateStyles(self
): 
1044         self
.StyleClearAll() 
1048     def EstimatedLineNumberMarginWidth(self
): 
1051         lineNum 
= self
.GetLineCount() 
1052         lineNum 
= lineNum
/100 
1053         while lineNum 
>= 10: 
1054             lineNum 
= lineNum
/10 
1055             baseNumbers 
= baseNumbers 
+ "0" 
1057         return self
.TextWidth(wx
.stc
.STC_STYLE_LINENUMBER
, baseNumbers
) + MARGIN
 
1060     def OnUpdateLineNumberMarginWidth(self
, event
): 
1061         self
.UpdateLineNumberMarginWidth() 
1064     def UpdateLineNumberMarginWidth(self
): 
1065         if self
.GetViewLineNumbers(): 
1066             self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
1068     def MarkerDefineDefault(self
): 
1069         """ This must be called after the textcontrol is instantiated """ 
1070         self
.MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_ROUNDRECT
, wx
.BLACK
, wx
.BLUE
) 
1074         # Used when Delete key is hit. 
1075         sel 
= self
.GetSelection() 
1077         # Delete the selection or if no selection, the character after the caret. 
1078         if sel
[0] == sel
[1]: 
1079             self
.SetSelection(sel
[0], sel
[0] + 1) 
1081             # remove any folded lines also. 
1082             startLine 
= self
.LineFromPosition(sel
[0]) 
1083             endLine 
= self
.LineFromPosition(sel
[1]) 
1084             endLineStart 
= self
.PositionFromLine(endLine
) 
1085             if startLine 
!= endLine 
and sel
[1] - endLineStart 
== 0: 
1086                 while not self
.GetLineVisible(endLine
): 
1088                 self
.SetSelectionEnd(self
.PositionFromLine(endLine
)) 
1094         # replace any folded lines also. 
1095         sel 
= self
.GetSelection() 
1096         startLine 
= self
.LineFromPosition(sel
[0]) 
1097         endLine 
= self
.LineFromPosition(sel
[1]) 
1098         endLineStart 
= self
.PositionFromLine(endLine
) 
1099         if startLine 
!= endLine 
and sel
[1] - endLineStart 
== 0: 
1100             while not self
.GetLineVisible(endLine
): 
1102             self
.SetSelectionEnd(self
.PositionFromLine(endLine
)) 
1107     def OnKeyPressed(self
, event
): 
1108         key 
= event
.GetKeyCode() 
1109         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 
1110             if event
.ControlDown(): 
1111                 self
.ToggleFoldAll(expand 
= True, topLevelOnly 
= True) 
1112             elif event
.ShiftDown(): 
1113                 self
.ToggleFoldAll(expand 
= True) 
1115                 self
.ToggleFold(self
.GetCurrentLine()) 
1116         elif key 
== wx
.WXK_NUMPAD_SUBTRACT
: 
1117             if event
.ControlDown(): 
1118                 self
.ToggleFoldAll(expand 
= False, topLevelOnly 
= True) 
1119             elif event
.ShiftDown(): 
1120                 self
.ToggleFoldAll(expand 
= False) 
1122                 self
.ToggleFold(self
.GetCurrentLine()) 
1127     #---------------------------------------------------------------------------- 
1129     #---------------------------------------------------------------------------- 
1131     def GetViewRightEdge(self
): 
1132         return self
.GetEdgeMode() != wx
.stc
.STC_EDGE_NONE
 
1135     def SetViewRightEdge(self
, viewRightEdge
): 
1137             self
.SetEdgeMode(wx
.stc
.STC_EDGE_LINE
) 
1139             self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
) 
1142     def GetViewLineNumbers(self
): 
1143         return self
.GetMarginWidth(1) > 0 
1146     def SetViewLineNumbers(self
, viewLineNumbers 
= True): 
1148             self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
1150             self
.SetMarginWidth(1, 0) 
1153     def CanWordWrap(self
): 
1157     def GetWordWrap(self
): 
1158         return self
.GetWrapMode() == wx
.stc
.STC_WRAP_WORD
 
1161     def SetWordWrap(self
, wordWrap
): 
1163             self
.SetWrapMode(wx
.stc
.STC_WRAP_WORD
) 
1165             self
.SetWrapMode(wx
.stc
.STC_WRAP_NONE
) 
1168     #---------------------------------------------------------------------------- 
1169     # DynamicSashWindow methods 
1170     #---------------------------------------------------------------------------- 
1172     def SetupDSScrollBars(self
): 
1173         # hook the scrollbars provided by the wxDynamicSashWindow 
1175         v_bar 
= self
._dynSash
.GetVScrollBar(self
) 
1176         h_bar 
= self
._dynSash
.GetHScrollBar(self
) 
1177         v_bar
.Bind(wx
.EVT_SCROLL
, self
.OnDSSBScroll
) 
1178         h_bar
.Bind(wx
.EVT_SCROLL
, self
.OnDSSBScroll
) 
1179         v_bar
.Bind(wx
.EVT_SET_FOCUS
, self
.OnDSSBFocus
) 
1180         h_bar
.Bind(wx
.EVT_SET_FOCUS
, self
.OnDSSBFocus
) 
1182         # And set the wxStyledText to use these scrollbars instead 
1183         # of its built-in ones. 
1184         self
.SetVScrollBar(v_bar
) 
1185         self
.SetHScrollBar(h_bar
) 
1188     def OnDSSplit(self
, evt
): 
1189         newCtrl 
= self
._dynSash
._view
.GetCtrlClass()(self
._dynSash
, -1, style
=wx
.NO_BORDER
) 
1190         newCtrl
.SetDocPointer(self
.GetDocPointer())     # use the same document 
1191         self
.SetupDSScrollBars() 
1192         if self 
== self
._dynSash
._view
.GetCtrl():  # originally had focus 
1193             wx
.CallAfter(self
.SetFocus
)  # do this to set colors correctly.  wxBug:  for some reason, if we don't do a CallAfter, it immediately calls OnKillFocus right after our SetFocus. 
1196     def OnDSUnify(self
, evt
): 
1197         self
.SetupDSScrollBars() 
1198         self
.SetFocus()  # do this to set colors correctly 
1201     def OnDSSBScroll(self
, evt
): 
1202         # redirect the scroll events from the _dynSash's scrollbars to the STC 
1203         self
.GetEventHandler().ProcessEvent(evt
) 
1206     def OnDSSBFocus(self
, evt
): 
1207         # when the scrollbar gets the focus move it back to the STC 
1211     def DSProcessEvent(self
, event
): 
1212         # wxHack: Needed for customized right mouse click menu items.         
1213         if hasattr(self
, "_dynSash"): 
1214             if event
.GetId() == wx
.ID_SELECTALL
: 
1215                 # force focus so that select all occurs in the window user right clicked on. 
1218             return self
._dynSash
._view
.ProcessEvent(event
) 
1222     def DSProcessUpdateUIEvent(self
, event
): 
1223         # wxHack: Needed for customized right mouse click menu items.         
1224         if hasattr(self
, "_dynSash"): 
1226             if (id == wx
.ID_SELECTALL  
# allow select all even in non-active window, then force focus to it, see above ProcessEvent 
1228             or id == wx
.ID_REDO
): 
1229                 pass  # allow these actions even in non-active window 
1230             else:  # disallow events in non-active windows.  Cut/Copy/Paste/Delete is too confusing user experience. 
1231                 if self
._dynSash
._view
.GetCtrl() != self
: 
1235             return self
._dynSash
._view
.ProcessUpdateUIEvent(event
) 
1239 class TextPrintout(wx
.lib
.docview
.DocPrintout
): 
1240     """ for Print Preview and Print """ 
1243     def OnPreparePrinting(self
): 
1244         """ initialization """ 
1247         ppiScreenX
, ppiScreenY 
= self
.GetPPIScreen() 
1248         ppiPrinterX
, ppiPrinterY 
= self
.GetPPIPrinter() 
1249         scaleX 
= float(ppiPrinterX
)/ppiScreenX
 
1250         scaleY 
= float(ppiPrinterY
)/ppiScreenY
 
1252         pageWidth
, pageHeight 
= self
.GetPageSizePixels() 
1253         self
._scaleFactorX 
= scaleX
/pageWidth
 
1254         self
._scaleFactorY 
= scaleY
/pageHeight
 
1257         overallScaleX 
= self
._scaleFactorX 
* w
 
1258         overallScaleY 
= self
._scaleFactorY 
* h
 
1260         txtCtrl 
= self
._printoutView
.GetCtrl() 
1261         font
, color 
= txtCtrl
.GetFontAndColorFromConfig() 
1264         self
._fontHeight 
= font
.GetPointSize() + 1 
1265         self
._pageLines 
= int((h
/overallScaleY 
- (2 * self
._margin
))/self
._fontHeight
) 
1266         self
._maxLines 
= txtCtrl
.GetLineCount() 
1267         self
._numPages
, remainder 
= divmod(self
._maxLines
, self
._pageLines
) 
1272         lineNum 
= self
._maxLines
 
1273         while lineNum 
>= 10: 
1274             lineNum 
= lineNum
/10 
1276         self
._printFormat 
= "%%0%sd: %%s" % spaces
 
1279     def OnPrintPage(self
, page
): 
1280         """ Prints the given page of the view """ 
1283         txtCtrl 
= self
._printoutView
.GetCtrl() 
1284         font
, color 
= txtCtrl
.GetFontAndColorFromConfig() 
1288         dc
.SetUserScale(self
._scaleFactorX 
* w
, self
._scaleFactorY 
* h
) 
1292         dc
.DrawText("%s - page %s" % (self
.GetTitle(), page
), self
._margin
, self
._margin
/2) 
1294         startY 
= self
._margin
 
1295         startLine 
= (page 
- 1) * self
._pageLines
 
1296         endLine 
= min((startLine 
+ self
._pageLines
), self
._maxLines
) 
1297         for i 
in range(startLine
, endLine
): 
1298             text 
= txtCtrl
.GetLine(i
).rstrip() 
1299             startY 
+= self
._fontHeight
 
1300             if txtCtrl
.GetViewLineNumbers(): 
1301                 dc
.DrawText(self
._printFormat 
% (i
+1, text
), self
._margin
, startY
) 
1303                 dc
.DrawText(text
, self
._margin
, startY
) 
1310     def HasPage(self
, pageNum
): 
1311         return pageNum 
<= self
._numPages
 
1314     def GetPageInfo(self
): 
1316         maxPage 
= self
._numPages
 
1318         selPageTo 
= self
._numPages
 
1319         return (minPage
, maxPage
, selPageFrom
, selPageTo
) 
1322 #---------------------------------------------------------------------------- 
1323 # Icon Bitmaps - generated by encode_bitmaps.py 
1324 #---------------------------------------------------------------------------- 
1325 from wx 
import ImageFromStream
, BitmapFromImage
 
1331 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1332 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1333 \x00\x00`IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\xa7JU!$\x12\x1d\ 
1334 \xeb\t\t8n\x81\xb4\x86J\xfa]h\x0ee\x83\xb4\xc6\x14\x00\x00R\xcc \t\xcd\xa1\ 
1335 \x08\xd2\xa3\xe1\x08*\t$\x1d\xc4\x012\x0b\x00\xce\xe4\xc8\xe0\t}\xf7\x8f\rV\ 
1336 \xd9\x1a\xec\xe0\xbf\xc1\xd7\x06\xd9\xf5UX\xfdF+m\x03\xb8\x00\xe4\xc74B"x\ 
1337 \xf1\xf4\x00\x00\x00\x00IEND\xaeB`\x82'  
1340 def getTextBitmap(): 
1341     return BitmapFromImage(getTextImage()) 
1344     stream 
= cStringIO
.StringIO(getTextData()) 
1345     return ImageFromStream(stream
) 
1348     return wx
.IconFromBitmap(getTextBitmap()) 
1351 #---------------------------------------------------------------------------- 
1352 # Menu Bitmaps - generated by encode_bitmaps.py 
1353 #---------------------------------------------------------------------------- 
1354 #---------------------------------------------------------------------- 
1355 def getZoomInData(): 
1357 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1358 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1359 \x00\x00wIDAT8\x8d\xa5\x93Q\x12\x80 \x08D\xb5\xe9X\xee\xe9\xb7{\xd5Gc\xa9\ 
1360 \xacX\xca\x1f\xa0\x8fE0\x92<\xc3\x82\xed*\x08\xa0\xf2I~\x07\x000\x17T,\xdb\ 
1361 \xd6;\x08\xa4\x00\xa4GA\xab\xca\x00\xbc*\x1eD\xb4\x90\xa4O\x1e\xe3\x16f\xcc(\ 
1362 \xc8\x95F\x95\x8d\x02\xef\xa1n\xa0\xce\xc5v\x91zc\xacU\xbey\x03\xf0.\xa8\xb8\ 
1363 \x04\x8c\xac\x04MM\xa1lA\xfe\x85?\x90\xe5=X\x06\\\xebCA\xb3Q\xf34\x14\x00\ 
1364 \x00\x00\x00IEND\xaeB`\x82'  
1366 def getZoomInBitmap(): 
1367     return BitmapFromImage(getZoomInImage()) 
1369 def getZoomInImage(): 
1370     stream 
= cStringIO
.StringIO(getZoomInData()) 
1371     return ImageFromStream(stream
) 
1373 #---------------------------------------------------------------------- 
1374 def getZoomOutData(): 
1376 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1377 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1378 \x00\x00qIDAT8\x8d\xa5\x92Q\x0e\xc0 \x08C-z\xff\x13O\xd9\xd7\x16"\x05\x8d\ 
1379 \xf6O\xa2\x8f"\x05\xa4\x96\x1b5V\xd4\xd1\xd5\x9e!\x15\xdb\x00\x1d]\xe7\x07\ 
1380 \xac\xf6Iv.B*fW\x0e\x90u\xc9 d\x84\x87v\x82\xb4\xf5\x08\'r\x0e\xa2N\x91~\x07\ 
1381 \xd9G\x95\xe2W\xeb\x00\x19\xc4\xd6\\FX\x12\xa3 \xb1:\x05\xacdAG[\xb0y9r`u\ 
1382 \x9d\x83k\xc0\x0b#3@0A\x0c"\x93\x00\x00\x00\x00IEND\xaeB`\x82'  
1385 def getZoomOutBitmap(): 
1386     return BitmapFromImage(getZoomOutImage()) 
1388 def getZoomOutImage(): 
1389     stream 
= cStringIO
.StringIO(getZoomOutData()) 
1390     return ImageFromStream(stream
)