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 # Use this to override MultiClient.Select to prevent yellow background.   
  84 def MultiClientSelectBGNotYellow(a
):      
  85     a
.GetParent().multiView
.UnSelect()    
  87     #a.SetBackgroundColour(wx.Colour(255,255,0)) # Yellow         
  90 class TextView(wx
.lib
.docview
.View
): 
  94     #---------------------------------------------------------------------------- 
  96     #---------------------------------------------------------------------------- 
  99         wx
.lib
.docview
.View
.__init
__(self
) 
 100         self
._textEditor 
= None 
 101         self
._markerCount 
= 0 
 102         self
._commandProcessor 
= None 
 106     def GetCtrlClass(self
): 
 107         """ Used in split window to instantiate new instances """ 
 112         if wx
.Platform 
== "__WXMAC__": 
 113             # look for active one first   
 114             self
._textEditor 
= self
._GetActiveCtrl
(self
._dynSash
)         
 115             if self
._textEditor 
== None:  # it is possible none are active        
 116                 # look for any existing one       
 117                 self
._textEditor 
= self
._FindCtrl
(self
._dynSash
) 
 118         return self
._textEditor
 
 121     def SetCtrl(self
, ctrl
): 
 122         self
._textEditor 
= ctrl
 
 125     def OnCreatePrintout(self
): 
 126         """ for Print Preview and Print """ 
 127         return TextPrintout(self
, self
.GetDocument().GetPrintableName()) 
 130     def OnCreate(self
, doc
, flags
): 
 131         frame 
= wx
.GetApp().CreateDocumentFrame(self
, doc
, flags
, style 
= wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
) 
 132         # wxBug: DynamicSashWindow doesn't work on Mac, so revert to 
 133         # multisash implementation 
 134         if wx
.Platform 
== "__WXMAC__": 
 135             wx
.lib
.multisash
.MultiClient
.Select 
= MultiClientSelectBGNotYellow
 
 136             self
._dynSash 
= wx
.lib
.multisash
.MultiSash(frame
, -1) 
 137             self
._dynSash
.SetDefaultChildClass(self
.GetCtrlClass()) # wxBug:  MultiSash instantiates the first TextCtrl with this call 
 139             self
._textEditor 
= self
.GetCtrl()  # wxBug: grab the TextCtrl from the MultiSash datastructure 
 141             self
._dynSash 
= wx
.gizmos
.DynamicSashWindow(frame
, -1, style
=wx
.CLIP_CHILDREN
) 
 142             self
._dynSash
._view 
= self
 
 143             self
._textEditor 
= self
.GetCtrlClass()(self
._dynSash
, -1, style
=wx
.NO_BORDER
) 
 144         wx
.EVT_LEFT_DOWN(self
._textEditor
, self
.OnLeftClick
) 
 145         self
._CreateSizer
(frame
) 
 152     def _CreateSizer(self
, frame
): 
 153         sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 154         sizer
.Add(self
._dynSash
, 1, wx
.EXPAND
) 
 155         frame
.SetSizer(sizer
) 
 158     def OnLeftClick(self
, event
): 
 163     def OnUpdate(self
, sender 
= None, hint 
= None): 
 164         if hint 
== "ViewStuff": 
 165             self
.GetCtrl().SetViewDefaults() 
 167             font
, color 
= self
.GetCtrl().GetFontAndColorFromConfig() 
 168             self
.GetCtrl().SetFont(font
) 
 169             self
.GetCtrl().SetFontColor(color
) 
 172     def OnActivateView(self
, activate
, activeView
, deactiveView
): 
 173         if activate 
and self
.GetCtrl(): 
 174             # In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop 
 175             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 178                 wx
.CallAfter(self
.SetFocus
) 
 183             self
.GetCtrl().SetFocus() 
 186     def OnClose(self
, deleteWindow 
= True): 
 187         if not wx
.lib
.docview
.View
.OnClose(self
, deleteWindow
): 
 190         if deleteWindow 
and self
.GetFrame(): 
 191             self
.GetFrame().Destroy() 
 195     def ProcessEvent(self
, event
):         
 198             self
.GetCtrl().Undo() 
 200         elif id == wx
.ID_REDO
: 
 201             self
.GetCtrl().Redo() 
 203         elif id == wx
.ID_CUT
: 
 206         elif id == wx
.ID_COPY
: 
 207             self
.GetCtrl().Copy() 
 209         elif id == wx
.ID_PASTE
: 
 210             self
.GetCtrl().OnPaste() 
 212         elif id == wx
.ID_CLEAR
: 
 213             self
.GetCtrl().OnClear() 
 215         elif id == wx
.ID_SELECTALL
: 
 216             self
.GetCtrl().SetSelection(0, -1) 
 218         elif id == VIEW_WHITESPACE_ID
: 
 219             self
.GetCtrl().SetViewWhiteSpace(not self
.GetCtrl().GetViewWhiteSpace()) 
 221         elif id == VIEW_EOL_ID
: 
 222             self
.GetCtrl().SetViewEOL(not self
.GetCtrl().GetViewEOL()) 
 224         elif id == VIEW_INDENTATION_GUIDES_ID
: 
 225             self
.GetCtrl().SetIndentationGuides(not self
.GetCtrl().GetIndentationGuides()) 
 227         elif id == VIEW_RIGHT_EDGE_ID
: 
 228             self
.GetCtrl().SetViewRightEdge(not self
.GetCtrl().GetViewRightEdge()) 
 230         elif id == VIEW_LINE_NUMBERS_ID
: 
 231             self
.GetCtrl().SetViewLineNumbers(not self
.GetCtrl().GetViewLineNumbers()) 
 233         elif id == ZOOM_NORMAL_ID
: 
 234             self
.GetCtrl().SetZoom(0) 
 236         elif id == ZOOM_IN_ID
: 
 237             self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMIN
) 
 239         elif id == ZOOM_OUT_ID
: 
 240             self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMOUT
) 
 242         elif id == CHOOSE_FONT_ID
: 
 245         elif id == WORD_WRAP_ID
: 
 246             self
.GetCtrl().SetWordWrap(not self
.GetCtrl().GetWordWrap()) 
 248         elif id == FindService
.FindService
.FIND_ID
: 
 251         elif id == FindService
.FindService
.FIND_PREVIOUS_ID
: 
 252             self
.DoFind(forceFindPrevious 
= True) 
 254         elif id == FindService
.FindService
.FIND_NEXT_ID
: 
 255             self
.DoFind(forceFindNext 
= True) 
 257         elif id == FindService
.FindService
.REPLACE_ID
: 
 258             self
.OnFind(replace 
= True) 
 260         elif id == FindService
.FindService
.FINDONE_ID
: 
 263         elif id == FindService
.FindService
.REPLACEONE_ID
: 
 264             self
.DoFind(replace 
= True) 
 266         elif id == FindService
.FindService
.REPLACEALL_ID
: 
 267             self
.DoFind(replaceAll 
= True) 
 269         elif id == FindService
.FindService
.GOTO_LINE_ID
: 
 270             self
.OnGotoLine(event
) 
 273             return wx
.lib
.docview
.View
.ProcessEvent(self
, event
) 
 276     def ProcessUpdateUIEvent(self
, event
): 
 277         if not self
.GetCtrl(): 
 282             event
.Enable(self
.GetCtrl().CanUndo()) 
 283             event
.SetText(_("&Undo\tCtrl+Z"))  # replace menu string 
 285         elif id == wx
.ID_REDO
: 
 286             event
.Enable(self
.GetCtrl().CanRedo()) 
 287             event
.SetText(_("&Redo\tCtrl+Y"))  # replace menu string 
 289         elif (id == wx
.ID_CUT
 
 291         or id == wx
.ID_CLEAR
): 
 292             hasSelection 
= self
.GetCtrl().GetSelectionStart() != self
.GetCtrl().GetSelectionEnd() 
 293             event
.Enable(hasSelection
) 
 295         elif id == wx
.ID_PASTE
: 
 296             event
.Enable(self
.GetCtrl().CanPaste()) 
 298         elif id == wx
.ID_SELECTALL
: 
 299             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 300             event
.Enable(hasText
) 
 305         elif id == VIEW_WHITESPACE_ID
: 
 306             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 307             event
.Enable(hasText
) 
 308             event
.Check(self
.GetCtrl().GetViewWhiteSpace()) 
 310         elif id == VIEW_EOL_ID
: 
 311             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 312             event
.Enable(hasText
) 
 313             event
.Check(self
.GetCtrl().GetViewEOL()) 
 315         elif id == VIEW_INDENTATION_GUIDES_ID
: 
 316             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 317             event
.Enable(hasText
) 
 318             event
.Check(self
.GetCtrl().GetIndentationGuides()) 
 320         elif id == VIEW_RIGHT_EDGE_ID
: 
 321             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 322             event
.Enable(hasText
) 
 323             event
.Check(self
.GetCtrl().GetViewRightEdge()) 
 325         elif id == VIEW_LINE_NUMBERS_ID
: 
 326             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 327             event
.Enable(hasText
) 
 328             event
.Check(self
.GetCtrl().GetViewLineNumbers()) 
 333         elif id == ZOOM_NORMAL_ID
: 
 334             event
.Enable(self
.GetCtrl().GetZoom() != 0) 
 336         elif id == ZOOM_IN_ID
: 
 337             event
.Enable(self
.GetCtrl().GetZoom() < 20) 
 339         elif id == ZOOM_OUT_ID
: 
 340             event
.Enable(self
.GetCtrl().GetZoom() > -10) 
 342         elif id == CHOOSE_FONT_ID
: 
 345         elif id == WORD_WRAP_ID
: 
 346             event
.Enable(self
.GetCtrl().CanWordWrap()) 
 347             event
.Check(self
.GetCtrl().CanWordWrap() and self
.GetCtrl().GetWordWrap()) 
 349         elif id == FindService
.FindService
.FIND_ID
: 
 350             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 351             event
.Enable(hasText
) 
 353         elif id == FindService
.FindService
.FIND_PREVIOUS_ID
: 
 354             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 355             event
.Enable(hasText 
and 
 356                          self
._FindServiceHasString
() and 
 357                          self
.GetCtrl().GetSelection()[0] > 0) 
 359         elif id == FindService
.FindService
.FIND_NEXT_ID
: 
 360             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 361             event
.Enable(hasText 
and 
 362                          self
._FindServiceHasString
() and 
 363                          self
.GetCtrl().GetSelection()[0] < self
.GetCtrl().GetLength()) 
 365         elif id == FindService
.FindService
.REPLACE_ID
: 
 366             hasText 
= self
.GetCtrl().GetTextLength() > 0 
 367             event
.Enable(hasText
) 
 369         elif id == FindService
.FindService
.GOTO_LINE_ID
: 
 372         elif id == TEXT_STATUS_BAR_ID
: 
 373             self
.OnUpdateStatusBar(event
) 
 376             return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
) 
 379     def _GetParentFrame(self
): 
 380         return wx
.GetTopLevelParent(self
.GetFrame()) 
 382     def _GetActiveCtrl(self
, parent
):     
 383         """ Walk through the MultiSash windows and find the active Control """    
 384         if isinstance(parent
, wx
.lib
.multisash
.MultiClient
) and parent
.selected
:          
 386         if hasattr(parent
, "GetChildren"):        
 387             for child 
in parent
.GetChildren():    
 388                 found 
= self
._GetActiveCtrl
(child
)        
 394     def _FindCtrl(self
, parent
):          
 395         """ Walk through the MultiSash windows and find the first TextCtrl """    
 396         if isinstance(parent
, self
.GetCtrlClass()):       
 398         if hasattr(parent
, "GetChildren"):        
 399             for child 
in parent
.GetChildren():    
 400                 found 
= self
._FindCtrl
(child
)     
 406     #---------------------------------------------------------------------------- 
 407     # Methods for TextDocument to call 
 408     #---------------------------------------------------------------------------- 
 410     def IsModified(self
): 
 411         if not self
.GetCtrl(): 
 413         return self
.GetCtrl().GetModify() 
 416     def SetModifyFalse(self
): 
 417         self
.GetCtrl().SetSavePoint() 
 422             return self
.GetCtrl().GetText() 
 427     def SetValue(self
, value
): 
 428         self
.GetCtrl().SetText(value
) 
 429         self
.GetCtrl().UpdateLineNumberMarginWidth() 
 430         self
.GetCtrl().EmptyUndoBuffer() 
 433     #---------------------------------------------------------------------------- 
 435     #---------------------------------------------------------------------------- 
 437     def OnUpdateStatusBar(self
, event
): 
 438         statusBar 
= self
._GetParentFrame
().GetStatusBar() 
 439         statusBar
.SetInsertMode(self
.GetCtrl().GetOvertype() == 0) 
 440         statusBar
.SetLineNumber(self
.GetCtrl().GetCurrentLine() + 1) 
 441         statusBar
.SetColumnNumber(self
.GetCtrl().GetColumn(self
.GetCtrl().GetCurrentPos()) + 1) 
 444     #---------------------------------------------------------------------------- 
 446     #---------------------------------------------------------------------------- 
 448     def OnChooseFont(self
): 
 450         data
.EnableEffects(True) 
 451         data
.SetInitialFont(self
.GetCtrl().GetFont()) 
 452         data
.SetColour(self
.GetCtrl().GetFontColor()) 
 453         fontDialog 
= wx
.FontDialog(self
.GetFrame(), data
) 
 454         fontDialog
.CenterOnParent() 
 455         if fontDialog
.ShowModal() == wx
.ID_OK
: 
 456             data 
= fontDialog
.GetFontData() 
 457             self
.GetCtrl().SetFont(data
.GetChosenFont()) 
 458             self
.GetCtrl().SetFontColor(data
.GetColour()) 
 459             self
.GetCtrl().UpdateStyles() 
 463     #---------------------------------------------------------------------------- 
 465     #---------------------------------------------------------------------------- 
 467     def OnFind(self
, replace 
= False): 
 468         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 470             findService
.ShowFindReplaceDialog(findString 
= self
.GetCtrl().GetSelectedText(), replace 
= replace
) 
 473     def DoFind(self
, forceFindNext 
= False, forceFindPrevious 
= False, replace 
= False, replaceAll 
= False): 
 474         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 477         findString 
= findService
.GetFindString() 
 478         if len(findString
) == 0: 
 480         replaceString 
= findService
.GetReplaceString() 
 481         flags 
= findService
.GetFlags() 
 482         startLoc
, endLoc 
= self
.GetCtrl().GetSelection() 
 484         wholeWord 
= flags 
& wx
.FR_WHOLEWORD 
> 0 
 485         matchCase 
= flags 
& wx
.FR_MATCHCASE 
> 0 
 486         regExp 
= flags 
& FindService
.FindService
.FR_REGEXP 
> 0 
 487         down 
= flags 
& wx
.FR_DOWN 
> 0 
 488         wrap 
= flags 
& FindService
.FindService
.FR_WRAP 
> 0 
 490         if forceFindPrevious
:   # this is from function keys, not dialog box 
 492             wrap 
= False        # user would want to know they're at the end of file 
 495             wrap 
= False        # user would want to know they're at the end of file 
 499         # On replace dialog operations, user is allowed to replace the currently highlighted text to determine if it should be replaced or not. 
 500         # 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. 
 501         # If the text is a match, then replace it. 
 503             result
, start
, end
, replText 
= findService
.DoFind(findString
, replaceString
, self
.GetCtrl().GetSelectedText(), 0, 0, True, matchCase
, wholeWord
, regExp
, replace
) 
 505                 self
.GetCtrl().ReplaceSelection(replText
) 
 506                 self
.GetDocument().Modify(True) 
 507                 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
) 
 509                     startLoc 
+= len(replText
)  # advance start location past replacement string to new text 
 511             elif result 
== FindService
.FIND_SYNTAXERROR
: 
 513                 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
) 
 516             text 
= self
.GetCtrl().GetText() 
 518             # Find the next matching text occurance or if it is a ReplaceAll, replace all occurances 
 519             # 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 
 520             result
, start
, end
, text 
= findService
.DoFind(findString
, replaceString
, text
, startLoc
, endLoc
, down
, matchCase
, wholeWord
, regExp
, False, replaceAll
, wrap
) 
 522                 self
.GetCtrl().SetTargetStart(0) 
 523                 self
.GetCtrl().SetTargetEnd(self
.GetCtrl().GetLength()) 
 524                 self
.GetCtrl().ReplaceTarget(text
)  # Doing a SetText causes a clear document to be shown when undoing, so using replacetarget instead 
 525                 self
.GetDocument().Modify(True) 
 527                     wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
) 
 529                     wx
.GetApp().GetTopWindow().PushStatusText(_("%i occurrences of \"%s\" replaced") % (result
, findString
)) 
 531                 self
.GetCtrl().SetSelection(start
, end
) 
 532                 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(end
))  # show bottom then scroll up to top 
 533                 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(start
)) # do this after ensuring bottom is visible 
 534                 wx
.GetApp().GetTopWindow().PushStatusText(_("Found \"%s\".") % findString
) 
 535             elif result 
== FindService
.FIND_SYNTAXERROR
: 
 536                 # Dialog for this case gets popped up by the FindService. 
 537                 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
) 
 539                 wx
.MessageBox(_("Can't find \"%s\".") % findString
, "Find", 
 540                           wx
.OK | wx
.ICON_INFORMATION
) 
 543     def _FindServiceHasString(self
): 
 544         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 545         if not findService 
or not findService
.GetFindString(): 
 550     def OnGotoLine(self
, event
): 
 551         findService 
= wx
.GetApp().GetService(FindService
.FindService
) 
 553             line 
= findService
.GetLineNumber(self
.GetDocumentManager().FindSuitableParent()) 
 556                 self
.GetCtrl().EnsureVisible(line
) 
 557                 self
.GetCtrl().GotoLine(line
) 
 560     def GotoLine(self
, lineNum
): 
 562             lineNum 
= lineNum 
- 1  # line numbering for editor is 0 based, we are 1 based. 
 563             self
.GetCtrl().EnsureVisibleEnforcePolicy(lineNum
) 
 564             self
.GetCtrl().GotoLine(lineNum
) 
 567     def SetSelection(self
, start
, end
): 
 568         self
.GetCtrl().SetSelection(start
, end
) 
 571     def EnsureVisible(self
, line
): 
 572         self
.GetCtrl().EnsureVisible(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 574     def EnsureVisibleEnforcePolicy(self
, line
): 
 575         self
.GetCtrl().EnsureVisibleEnforcePolicy(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 577     def LineFromPosition(self
, pos
): 
 578         return self
.GetCtrl().LineFromPosition(pos
)+1  # line numbering for editor is 0 based, we are 1 based. 
 581     def PositionFromLine(self
, line
): 
 582         return self
.GetCtrl().PositionFromLine(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 585     def GetLineEndPosition(self
, line
): 
 586         return self
.GetCtrl().GetLineEndPosition(line
-1)  # line numbering for editor is 0 based, we are 1 based. 
 589     def GetLine(self
, lineNum
): 
 590         return self
.GetCtrl().GetLine(lineNum
-1)  # line numbering for editor is 0 based, we are 1 based. 
 593     def MarkerDefine(self
): 
 594         """ This must be called after the texteditor is instantiated """ 
 595         self
.GetCtrl().MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_CIRCLE
, wx
.BLACK
, wx
.BLUE
) 
 598     def MarkerToggle(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 600             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 601         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 602             self
.GetCtrl().MarkerDelete(lineNum
, marker_index
) 
 603             self
._markerCount 
-= 1 
 605             self
.GetCtrl().MarkerAdd(lineNum
, marker_index
) 
 606             self
._markerCount 
+= 1 
 609     def MarkerAdd(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 611             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 612         self
.GetCtrl().MarkerAdd(lineNum
, marker_index
) 
 613         self
._markerCount 
+= 1 
 616     def MarkerDelete(self
, lineNum 
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
): 
 618             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 619         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 620             self
.GetCtrl().MarkerDelete(lineNum
, marker_index
) 
 621             self
._markerCount 
-= 1 
 623     def MarkerDeleteAll(self
, marker_num
=MARKER_NUM
): 
 624         self
.GetCtrl().MarkerDeleteAll(marker_num
) 
 625         if marker_num 
== self
.MARKER_NUM
: 
 626             self
._markerCount 
= 0 
 629     def MarkerNext(self
, lineNum 
= -1): 
 631             lineNum 
= self
.GetCtrl().GetCurrentLine() + 1  # start search below current line 
 632         foundLine 
= self
.GetCtrl().MarkerNext(lineNum
, self
.MARKER_MASK
) 
 634             # wrap to top of file 
 635             foundLine 
= self
.GetCtrl().MarkerNext(0, self
.MARKER_MASK
) 
 637                 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers")) 
 640         self
.GotoLine(foundLine 
+ 1) 
 643     def MarkerPrevious(self
, lineNum 
= -1): 
 645             lineNum 
= self
.GetCtrl().GetCurrentLine() - 1  # start search above current line 
 647                 lineNum 
= self
.GetCtrl().GetLineCount() 
 649         foundLine 
= self
.GetCtrl().MarkerPrevious(lineNum
, self
.MARKER_MASK
) 
 651             # wrap to bottom of file 
 652             foundLine 
= self
.GetCtrl().MarkerPrevious(self
.GetCtrl().GetLineCount(), self
.MARKER_MASK
) 
 654                 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers")) 
 657         self
.GotoLine(foundLine 
+ 1) 
 660     def MarkerExists(self
, lineNum 
= -1, mask
=MARKER_MASK
): 
 662             lineNum 
= self
.GetCtrl().GetCurrentLine() 
 663         if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 668     def GetMarkerLines(self
, mask
=MARKER_MASK
): 
 670         for lineNum 
in range(self
.GetCtrl().GetLineCount()): 
 671             if self
.GetCtrl().MarkerGet(lineNum
) & mask
: 
 672                 retval
.append(lineNum
) 
 675     def GetMarkerCount(self
): 
 676         return self
._markerCount
 
 679 class TextService(wx
.lib
.pydocview
.DocService
): 
 683         wx
.lib
.pydocview
.DocService
.__init
__(self
) 
 686     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
 687         if document 
and document
.GetDocumentTemplate().GetDocumentType() != TextDocument
: 
 689         if not document 
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 692         statusBar 
= TextStatusBar(frame
, TEXT_STATUS_BAR_ID
) 
 693         frame
.SetStatusBar(statusBar
) 
 694         wx
.EVT_UPDATE_UI(frame
, TEXT_STATUS_BAR_ID
, frame
.ProcessUpdateUIEvent
) 
 696         viewMenu 
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View"))) 
 698         viewMenu
.AppendSeparator() 
 700         textMenu
.AppendCheckItem(VIEW_WHITESPACE_ID
, _("&Whitespace"), _("Shows or hides whitespace")) 
 701         wx
.EVT_MENU(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessEvent
) 
 702         wx
.EVT_UPDATE_UI(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessUpdateUIEvent
) 
 703         textMenu
.AppendCheckItem(VIEW_EOL_ID
, _("&End of Line Markers"), _("Shows or hides indicators at the end of each line")) 
 704         wx
.EVT_MENU(frame
, VIEW_EOL_ID
, frame
.ProcessEvent
) 
 705         wx
.EVT_UPDATE_UI(frame
, VIEW_EOL_ID
, frame
.ProcessUpdateUIEvent
) 
 706         textMenu
.AppendCheckItem(VIEW_INDENTATION_GUIDES_ID
, _("&Indentation Guides"), _("Shows or hides indentations")) 
 707         wx
.EVT_MENU(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessEvent
) 
 708         wx
.EVT_UPDATE_UI(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessUpdateUIEvent
) 
 709         textMenu
.AppendCheckItem(VIEW_RIGHT_EDGE_ID
, _("&Right Edge"), _("Shows or hides the right edge marker")) 
 710         wx
.EVT_MENU(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessEvent
) 
 711         wx
.EVT_UPDATE_UI(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessUpdateUIEvent
) 
 712         textMenu
.AppendCheckItem(VIEW_LINE_NUMBERS_ID
, _("&Line Numbers"), _("Shows or hides the line numbers")) 
 713         wx
.EVT_MENU(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessEvent
) 
 714         wx
.EVT_UPDATE_UI(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessUpdateUIEvent
) 
 716         viewMenu
.AppendMenu(TEXT_ID
, _("&Text"), textMenu
) 
 717         wx
.EVT_UPDATE_UI(frame
, TEXT_ID
, frame
.ProcessUpdateUIEvent
) 
 719         isWindows 
= (wx
.Platform 
== '__WXMSW__') 
 722         zoomMenu
.Append(ZOOM_NORMAL_ID
, _("Normal Size"), _("Sets the document to its normal size")) 
 723         wx
.EVT_MENU(frame
, ZOOM_NORMAL_ID
, frame
.ProcessEvent
) 
 724         wx
.EVT_UPDATE_UI(frame
, ZOOM_NORMAL_ID
, frame
.ProcessUpdateUIEvent
) 
 726             zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In\tCtrl+Page Up"), _("Zooms the document to a larger size")) 
 728             zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In"), _("Zooms the document to a larger size")) 
 729         wx
.EVT_MENU(frame
, ZOOM_IN_ID
, frame
.ProcessEvent
) 
 730         wx
.EVT_UPDATE_UI(frame
, ZOOM_IN_ID
, frame
.ProcessUpdateUIEvent
) 
 732             zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out\tCtrl+Page Down"), _("Zooms the document to a smaller size")) 
 734             zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out"), _("Zooms the document to a smaller size")) 
 735         wx
.EVT_MENU(frame
, ZOOM_OUT_ID
, frame
.ProcessEvent
) 
 736         wx
.EVT_UPDATE_UI(frame
, ZOOM_OUT_ID
, frame
.ProcessUpdateUIEvent
) 
 738         viewMenu
.AppendMenu(ZOOM_ID
, _("&Zoom"), zoomMenu
) 
 739         wx
.EVT_UPDATE_UI(frame
, ZOOM_ID
, frame
.ProcessUpdateUIEvent
) 
 741         formatMenuIndex 
= menuBar
.FindMenu(_("&Format")) 
 742         if formatMenuIndex 
> -1: 
 743             formatMenu 
= menuBar
.GetMenu(formatMenuIndex
) 
 745             formatMenu 
= wx
.Menu() 
 746         if not menuBar
.FindItemById(CHOOSE_FONT_ID
): 
 747             formatMenu
.Append(CHOOSE_FONT_ID
, _("&Font..."), _("Sets the font to use")) 
 748             wx
.EVT_MENU(frame
, CHOOSE_FONT_ID
, frame
.ProcessEvent
) 
 749             wx
.EVT_UPDATE_UI(frame
, CHOOSE_FONT_ID
, frame
.ProcessUpdateUIEvent
) 
 750         if not menuBar
.FindItemById(WORD_WRAP_ID
): 
 751             formatMenu
.AppendCheckItem(WORD_WRAP_ID
, _("Word Wrap"), _("Wraps text horizontally when checked")) 
 752             wx
.EVT_MENU(frame
, WORD_WRAP_ID
, frame
.ProcessEvent
) 
 753             wx
.EVT_UPDATE_UI(frame
, WORD_WRAP_ID
, frame
.ProcessUpdateUIEvent
) 
 754         if formatMenuIndex 
== -1: 
 755             viewMenuIndex 
= menuBar
.FindMenu(_("&View")) 
 756             menuBar
.Insert(viewMenuIndex 
+ 1, formatMenu
, _("&Format")) 
 758         # wxBug: wxToolBar::GetToolPos doesn't exist, need it to find cut tool and then insert find in front of it. 
 759         toolBar
.AddSeparator() 
 760         toolBar
.AddTool(ZOOM_IN_ID
, getZoomInBitmap(), shortHelpString 
= _("Zoom In"), longHelpString 
= _("Zooms the document to a larger size")) 
 761         toolBar
.AddTool(ZOOM_OUT_ID
, getZoomOutBitmap(), shortHelpString 
= _("Zoom Out"), longHelpString 
= _("Zooms the document to a smaller size")) 
 765     def ProcessUpdateUIEvent(self
, event
): 
 768         or id == VIEW_WHITESPACE_ID
 
 770         or id == VIEW_INDENTATION_GUIDES_ID
 
 771         or id == VIEW_RIGHT_EDGE_ID
 
 772         or id == VIEW_LINE_NUMBERS_ID
 
 774         or id == ZOOM_NORMAL_ID
 
 777         or id == CHOOSE_FONT_ID
 
 778         or id == WORD_WRAP_ID
): 
 785 class TextStatusBar(wx
.StatusBar
): 
 787     # 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 
 789     def __init__(self
, parent
, id, style 
= wx
.ST_SIZEGRIP
, name 
= "statusBar"): 
 790         wx
.StatusBar
.__init
__(self
, parent
, id, style
, name
) 
 791         self
.SetFieldsCount(4) 
 792         self
.SetStatusWidths([-1, 50, 50, 55]) 
 794     def SetInsertMode(self
, insert 
= True): 
 799         if self
.GetStatusText(1) != newText
:     # wxBug: Need to check if the text has changed, otherwise it flickers under win32 
 800             self
.SetStatusText(newText
, 1) 
 802     def SetLineNumber(self
, lineNumber
): 
 803         newText 
= _("Ln %i") % lineNumber
 
 804         if self
.GetStatusText(2) != newText
: 
 805             self
.SetStatusText(newText
, 2) 
 807     def SetColumnNumber(self
, colNumber
): 
 808         newText 
= _("Col %i") % colNumber
 
 809         if self
.GetStatusText(3) != newText
: 
 810             self
.SetStatusText(newText
, 3) 
 813 class TextOptionsPanel(wx
.Panel
): 
 816     def __init__(self
, parent
, id, configPrefix 
= "Text", label 
= "Text", hasWordWrap 
= True, hasTabs 
= False, addPage
=True): 
 817         wx
.Panel
.__init
__(self
, parent
, id) 
 818         self
._configPrefix 
= configPrefix
 
 819         self
._hasWordWrap 
= hasWordWrap
 
 820         self
._hasTabs 
= hasTabs
 
 823         config 
= wx
.ConfigBase_Get() 
 824         self
._textFont 
= wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
) 
 825         fontData 
= config
.Read(self
._configPrefix 
+ "EditorFont", "") 
 827             nativeFont 
= wx
.NativeFontInfo() 
 828             nativeFont
.FromString(fontData
) 
 829             self
._textFont
.SetNativeFontInfo(nativeFont
) 
 830         self
._originalTextFont 
= self
._textFont
 
 831         self
._textColor 
= wx
.BLACK
 
 832         colorData 
= config
.Read(self
._configPrefix 
+ "EditorColor", "") 
 834             red 
= int("0x" + colorData
[0:2], 16) 
 835             green 
= int("0x" + colorData
[2:4], 16) 
 836             blue 
= int("0x" + colorData
[4:6], 16) 
 837             self
._textColor 
= wx
.Color(red
, green
, blue
) 
 838         self
._originalTextColor 
= self
._textColor
 
 839         fontLabel 
= wx
.StaticText(self
, -1, _("Font:")) 
 840         self
._sampleTextCtrl 
= wx
.TextCtrl(self
, -1, "", size 
= (125, 21)) 
 841         self
._sampleTextCtrl
.SetEditable(False) 
 842         chooseFontButton 
= wx
.Button(self
, -1, _("Choose Font...")) 
 843         wx
.EVT_BUTTON(self
, chooseFontButton
.GetId(), self
.OnChooseFont
) 
 844         if self
._hasWordWrap
: 
 845             self
._wordWrapCheckBox 
= wx
.CheckBox(self
, -1, _("Wrap words inside text area")) 
 846             self
._wordWrapCheckBox
.SetValue(wx
.ConfigBase_Get().ReadInt(self
._configPrefix 
+ "EditorWordWrap", False)) 
 847         self
._viewWhitespaceCheckBox 
= wx
.CheckBox(self
, -1, _("Show whitespace")) 
 848         self
._viewWhitespaceCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewWhitespace", False)) 
 849         self
._viewEOLCheckBox 
= wx
.CheckBox(self
, -1, _("Show end of line markers")) 
 850         self
._viewEOLCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewEOL", False)) 
 851         self
._viewIndentationGuideCheckBox 
= wx
.CheckBox(self
, -1, _("Show indentation guides")) 
 852         self
._viewIndentationGuideCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewIndentationGuides", False)) 
 853         self
._viewRightEdgeCheckBox 
= wx
.CheckBox(self
, -1, _("Show right edge")) 
 854         self
._viewRightEdgeCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewRightEdge", False)) 
 855         self
._viewLineNumbersCheckBox 
= wx
.CheckBox(self
, -1, _("Show line numbers")) 
 856         self
._viewLineNumbersCheckBox
.SetValue(config
.ReadInt(self
._configPrefix 
+ "EditorViewLineNumbers", True)) 
 858             self
._hasTabsCheckBox 
= wx
.CheckBox(self
, -1, _("Use spaces instead of tabs")) 
 859             self
._hasTabsCheckBox
.SetValue(not wx
.ConfigBase_Get().ReadInt(self
._configPrefix 
+ "EditorUseTabs", False)) 
 860             indentWidthLabel 
= wx
.StaticText(self
, -1, _("Indent Width:")) 
 861             self
._indentWidthChoice 
= wx
.Choice(self
, -1, choices 
= ["2", "4", "6", "8", "10"]) 
 862             self
._indentWidthChoice
.SetStringSelection(str(config
.ReadInt(self
._configPrefix 
+ "EditorIndentWidth", 4))) 
 863         textPanelBorderSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 864         textPanelSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 865         textFontSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 866         textFontSizer
.Add(fontLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
) 
 867         textFontSizer
.Add(self
._sampleTextCtrl
, 1, wx
.ALIGN_LEFT | wx
.EXPAND | wx
.RIGHT
, HALF_SPACE
) 
 868         textFontSizer
.Add(chooseFontButton
, 0, wx
.ALIGN_RIGHT | wx
.LEFT
, HALF_SPACE
) 
 869         textPanelSizer
.Add(textFontSizer
, 0, wx
.ALL|wx
.EXPAND
, HALF_SPACE
) 
 870         if self
._hasWordWrap
: 
 871             textPanelSizer
.Add(self
._wordWrapCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 872         textPanelSizer
.Add(self
._viewWhitespaceCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 873         textPanelSizer
.Add(self
._viewEOLCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 874         textPanelSizer
.Add(self
._viewIndentationGuideCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 875         textPanelSizer
.Add(self
._viewRightEdgeCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 876         textPanelSizer
.Add(self
._viewLineNumbersCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 878             textPanelSizer
.Add(self
._hasTabsCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
 879             textIndentWidthSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 880             textIndentWidthSizer
.Add(indentWidthLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
) 
 881             textIndentWidthSizer
.Add(self
._indentWidthChoice
, 0, wx
.ALIGN_LEFT | wx
.EXPAND
, HALF_SPACE
) 
 882             textPanelSizer
.Add(textIndentWidthSizer
, 0, wx
.ALL
, HALF_SPACE
) 
 883         textPanelBorderSizer
.Add(textPanelSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
) 
 884 ##        styleButton = wx.Button(self, -1, _("Choose Style...")) 
 885 ##        wx.EVT_BUTTON(self, styleButton.GetId(), self.OnChooseStyle) 
 886 ##        textPanelBorderSizer.Add(styleButton, 0, wx.ALL, SPACE) 
 887         self
.SetSizer(textPanelBorderSizer
) 
 888         self
.UpdateSampleFont() 
 890             parent
.AddPage(self
, _(label
)) 
 892     def UpdateSampleFont(self
): 
 893         nativeFont 
= wx
.NativeFontInfo() 
 894         nativeFont
.FromString(self
._textFont
.GetNativeFontInfoDesc()) 
 896         font
.SetNativeFontInfo(nativeFont
) 
 897         font
.SetPointSize(self
._sampleTextCtrl
.GetFont().GetPointSize())  # Use the standard point size 
 898         self
._sampleTextCtrl
.SetFont(font
) 
 899         self
._sampleTextCtrl
.SetForegroundColour(self
._textColor
) 
 900         self
._sampleTextCtrl
.SetValue(str(self
._textFont
.GetPointSize()) + _(" pt. ") + self
._textFont
.GetFaceName()) 
 901         self
._sampleTextCtrl
.Refresh() 
 905 ##    def OnChooseStyle(self, event): 
 906 ##        import STCStyleEditor 
 908 ##        base = os.path.split(__file__)[0] 
 909 ##        config = os.path.abspath(os.path.join(base, 'stc-styles.rc.cfg')) 
 911 ##        dlg = STCStyleEditor.STCStyleEditDlg(None, 
 912 ##                                'Python', 'python', 
 916 ##        dlg.CenterOnParent() 
 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         fontDialog
.CenterOnParent() 
 930         if fontDialog
.ShowModal() == wx
.ID_OK
: 
 931             data 
= fontDialog
.GetFontData() 
 932             self
._textFont 
= data
.GetChosenFont() 
 933             self
._textColor 
= data
.GetColour() 
 934             self
.UpdateSampleFont() 
 938     def OnOK(self
, optionsDialog
): 
 939         config 
= wx
.ConfigBase_Get() 
 940         doViewStuffUpdate 
= config
.ReadInt(self
._configPrefix 
+ "EditorViewWhitespace", False) != self
._viewWhitespaceCheckBox
.GetValue() 
 941         config
.WriteInt(self
._configPrefix 
+ "EditorViewWhitespace", self
._viewWhitespaceCheckBox
.GetValue()) 
 942         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewEOL", False) != self
._viewEOLCheckBox
.GetValue() 
 943         config
.WriteInt(self
._configPrefix 
+ "EditorViewEOL", self
._viewEOLCheckBox
.GetValue()) 
 944         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewIndentationGuides", False) != self
._viewIndentationGuideCheckBox
.GetValue() 
 945         config
.WriteInt(self
._configPrefix 
+ "EditorViewIndentationGuides", self
._viewIndentationGuideCheckBox
.GetValue()) 
 946         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewRightEdge", False) != self
._viewRightEdgeCheckBox
.GetValue() 
 947         config
.WriteInt(self
._configPrefix 
+ "EditorViewRightEdge", self
._viewRightEdgeCheckBox
.GetValue()) 
 948         doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorViewLineNumbers", True) != self
._viewLineNumbersCheckBox
.GetValue() 
 949         config
.WriteInt(self
._configPrefix 
+ "EditorViewLineNumbers", self
._viewLineNumbersCheckBox
.GetValue()) 
 950         if self
._hasWordWrap
: 
 951             doViewStuffUpdate 
= doViewStuffUpdate 
or config
.ReadInt(self
._configPrefix 
+ "EditorWordWrap", False) != self
._wordWrapCheckBox
.GetValue() 
 952             config
.WriteInt(self
._configPrefix 
+ "EditorWordWrap", self
._wordWrapCheckBox
.GetValue()) 
 954             doViewStuffUpdate 
= doViewStuffUpdate 
or not config
.ReadInt(self
._configPrefix 
+ "EditorUseTabs", True) != self
._hasTabsCheckBox
.GetValue() 
 955             config
.WriteInt(self
._configPrefix 
+ "EditorUseTabs", not self
._hasTabsCheckBox
.GetValue()) 
 956             newIndentWidth 
= int(self
._indentWidthChoice
.GetStringSelection()) 
 957             oldIndentWidth 
= config
.ReadInt(self
._configPrefix 
+ "EditorIndentWidth", 4) 
 958             if newIndentWidth 
!= oldIndentWidth
: 
 959                 doViewStuffUpdate 
= True 
 960                 config
.WriteInt(self
._configPrefix 
+ "EditorIndentWidth", newIndentWidth
) 
 961         doFontUpdate 
= self
._originalTextFont 
!= self
._textFont 
or self
._originalTextColor 
!= self
._textColor
 
 962         config
.Write(self
._configPrefix 
+ "EditorFont", self
._textFont
.GetNativeFontInfoDesc()) 
 963         config
.Write(self
._configPrefix 
+ "EditorColor", "%02x%02x%02x" % (self
._textColor
.Red(), self
._textColor
.Green(), self
._textColor
.Blue())) 
 964         if doViewStuffUpdate 
or doFontUpdate
: 
 965             for document 
in optionsDialog
.GetDocManager().GetDocuments(): 
 966                 if issubclass(document
.GetDocumentTemplate().GetDocumentType(), TextDocument
): 
 967                     if doViewStuffUpdate
: 
 968                         document
.UpdateAllViews(hint 
= "ViewStuff") 
 970                         document
.UpdateAllViews(hint 
= "Font") 
 977 class TextCtrl(wx
.stc
.StyledTextCtrl
): 
 979     def __init__(self
, parent
, id=-1, style
=wx
.NO_FULL_REPAINT_ON_RESIZE
): 
 980         wx
.stc
.StyledTextCtrl
.__init
__(self
, parent
, id, style
=style
) 
 982         if isinstance(parent
, wx
.gizmos
.DynamicSashWindow
): 
 983             self
._dynSash 
= parent
 
 984             self
.SetupDSScrollBars() 
 985             self
.Bind(wx
.gizmos
.EVT_DYNAMIC_SASH_SPLIT
, self
.OnDSSplit
) 
 986             self
.Bind(wx
.gizmos
.EVT_DYNAMIC_SASH_UNIFY
, self
.OnDSUnify
) 
 989         self
._fontColor 
= None 
 991         self
.SetVisiblePolicy(wx
.stc
.STC_VISIBLE_STRICT
,1) 
 993         self
.CmdKeyClear(wx
.stc
.STC_KEY_ADD
, wx
.stc
.STC_SCMOD_CTRL
) 
 994         self
.CmdKeyClear(wx
.stc
.STC_KEY_SUBTRACT
, wx
.stc
.STC_SCMOD_CTRL
) 
 995         self
.CmdKeyAssign(wx
.stc
.STC_KEY_PRIOR
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMIN
) 
 996         self
.CmdKeyAssign(wx
.stc
.STC_KEY_NEXT
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMOUT
) 
 997         self
.Bind(wx
.stc
.EVT_STC_ZOOM
, self
.OnUpdateLineNumberMarginWidth
)  # auto update line num width on zoom 
 998         wx
.EVT_KEY_DOWN(self
, self
.OnKeyPressed
) 
 999         wx
.EVT_KILL_FOCUS(self
, self
.OnKillFocus
) 
1000         wx
.EVT_SET_FOCUS(self
, self
.OnFocus
) 
1001         self
.SetMargins(0,0) 
1007         self
.SetViewWhiteSpace(False) 
1008         self
.SetEOLMode(wx
.stc
.STC_EOL_LF
) 
1009         self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
) 
1010         self
.SetEdgeColumn(78) 
1012         self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
) 
1013         self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
1016         self
.SetCaretForeground("BLACK") 
1018         self
.SetViewDefaults() 
1019         font
, color 
= self
.GetFontAndColorFromConfig() 
1021         self
.SetFontColor(color
) 
1022         self
.MarkerDefineDefault() 
1024         # for multisash initialization    
1025         if isinstance(parent
, wx
.lib
.multisash
.MultiClient
):      
1026             while parent
.GetParent():     
1027                 parent 
= parent
.GetParent()       
1028                 if hasattr(parent
, "GetView"):    
1030             if hasattr(parent
, "GetView"):        
1031                 textEditor 
= parent
.GetView()._textEditor        
 
1033                     doc 
= textEditor
.GetDocPointer()      
1035                         self
.SetDocPointer(doc
) 
1038     def OnFocus(self
, event
): 
1039         # wxBug: On Mac, the STC control may fire a focus/kill focus event 
1040         # on shutdown even if the control is in an invalid state. So check 
1041         # before handling the event. 
1042         if self
.IsBeingDeleted(): 
1045         self
.SetSelBackground(1, "BLUE") 
1046         self
.SetSelForeground(1, "WHITE") 
1047         if hasattr(self
, "_dynSash"): 
1048             self
._dynSash
._view
.SetCtrl(self
) 
1052     def OnKillFocus(self
, event
): 
1053         # wxBug: On Mac, the STC control may fire a focus/kill focus event 
1054         # on shutdown even if the control is in an invalid state. So check 
1055         # before handling the event. 
1056         if self
.IsBeingDeleted(): 
1058         self
.SetSelBackground(0, "BLUE") 
1059         self
.SetSelForeground(0, "WHITE") 
1060         self
.SetSelBackground(1, "#C0C0C0") 
1061         # Don't set foreground color, use syntax highlighted default colors. 
1065     def SetViewDefaults(self
, configPrefix 
= "Text", hasWordWrap 
= True, hasTabs 
= False): 
1066         config 
= wx
.ConfigBase_Get() 
1067         self
.SetViewWhiteSpace(config
.ReadInt(configPrefix 
+ "EditorViewWhitespace", False)) 
1068         self
.SetViewEOL(config
.ReadInt(configPrefix 
+ "EditorViewEOL", False)) 
1069         self
.SetIndentationGuides(config
.ReadInt(configPrefix 
+ "EditorViewIndentationGuides", False)) 
1070         self
.SetViewRightEdge(config
.ReadInt(configPrefix 
+ "EditorViewRightEdge", False)) 
1071         self
.SetViewLineNumbers(config
.ReadInt(configPrefix 
+ "EditorViewLineNumbers", True)) 
1073             self
.SetWordWrap(config
.ReadInt(configPrefix 
+ "EditorWordWrap", False)) 
1074         if hasTabs
:  # These methods do not exist in STCTextEditor and are meant for subclasses 
1075             self
.SetUseTabs(config
.ReadInt(configPrefix 
+ "EditorUseTabs", False)) 
1076             self
.SetIndent(config
.ReadInt(configPrefix 
+ "EditorIndentWidth", 4)) 
1077             self
.SetTabWidth(config
.ReadInt(configPrefix 
+ "EditorIndentWidth", 4)) 
1079             self
.SetUseTabs(True) 
1084     def GetDefaultFont(self
): 
1085         """ Subclasses should override this """ 
1086         return wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
) 
1089     def GetDefaultColor(self
): 
1090         """ Subclasses should override this """ 
1094     def GetFontAndColorFromConfig(self
, configPrefix 
= "Text"): 
1095         font 
= self
.GetDefaultFont() 
1096         config 
= wx
.ConfigBase_Get() 
1097         fontData 
= config
.Read(configPrefix 
+ "EditorFont", "") 
1099             nativeFont 
= wx
.NativeFontInfo() 
1100             nativeFont
.FromString(fontData
) 
1101             font
.SetNativeFontInfo(nativeFont
) 
1102         color 
= self
.GetDefaultColor() 
1103         colorData 
= config
.Read(configPrefix 
+ "EditorColor", "") 
1105             red 
= int("0x" + colorData
[0:2], 16) 
1106             green 
= int("0x" + colorData
[2:4], 16) 
1107             blue 
= int("0x" + colorData
[4:6], 16) 
1108             color 
= wx
.Color(red
, green
, blue
) 
1116     def SetFont(self
, font
): 
1118         self
.StyleSetFont(wx
.stc
.STC_STYLE_DEFAULT
, self
._font
) 
1121     def GetFontColor(self
): 
1122         return self
._fontColor
 
1125     def SetFontColor(self
, fontColor 
= wx
.BLACK
): 
1126         self
._fontColor 
= fontColor
 
1127         self
.StyleSetForeground(wx
.stc
.STC_STYLE_DEFAULT
, "#%02x%02x%02x" % (self
._fontColor
.Red(), self
._fontColor
.Green(), self
._fontColor
.Blue())) 
1130     def UpdateStyles(self
): 
1131         self
.StyleClearAll() 
1135     def EstimatedLineNumberMarginWidth(self
): 
1138         lineNum 
= self
.GetLineCount() 
1139         lineNum 
= lineNum
/100 
1140         while lineNum 
>= 10: 
1141             lineNum 
= lineNum
/10 
1142             baseNumbers 
= baseNumbers 
+ "0" 
1144         return self
.TextWidth(wx
.stc
.STC_STYLE_LINENUMBER
, baseNumbers
) + MARGIN
 
1147     def OnUpdateLineNumberMarginWidth(self
, event
): 
1148         self
.UpdateLineNumberMarginWidth() 
1151     def UpdateLineNumberMarginWidth(self
): 
1152         if self
.GetViewLineNumbers(): 
1153             self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
1155     def MarkerDefineDefault(self
): 
1156         """ This must be called after the textcontrol is instantiated """ 
1157         self
.MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_ROUNDRECT
, wx
.BLACK
, wx
.BLUE
) 
1161         # Used when Delete key is hit. 
1162         sel 
= self
.GetSelection() 
1164         # Delete the selection or if no selection, the character after the caret. 
1165         if sel
[0] == sel
[1]: 
1166             self
.SetSelection(sel
[0], sel
[0] + 1) 
1168             # remove any folded lines also. 
1169             startLine 
= self
.LineFromPosition(sel
[0]) 
1170             endLine 
= self
.LineFromPosition(sel
[1]) 
1171             endLineStart 
= self
.PositionFromLine(endLine
) 
1172             if startLine 
!= endLine 
and sel
[1] - endLineStart 
== 0: 
1173                 while not self
.GetLineVisible(endLine
): 
1175                 self
.SetSelectionEnd(self
.PositionFromLine(endLine
)) 
1181         # replace any folded lines also. 
1182         sel 
= self
.GetSelection() 
1183         startLine 
= self
.LineFromPosition(sel
[0]) 
1184         endLine 
= self
.LineFromPosition(sel
[1]) 
1185         endLineStart 
= self
.PositionFromLine(endLine
) 
1186         if startLine 
!= endLine 
and sel
[1] - endLineStart 
== 0: 
1187             while not self
.GetLineVisible(endLine
): 
1189             self
.SetSelectionEnd(self
.PositionFromLine(endLine
)) 
1194     def OnKeyPressed(self
, event
): 
1195         key 
= event
.GetKeyCode() 
1196         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 
1197             if event
.ControlDown(): 
1198                 self
.ToggleFoldAll(expand 
= True, topLevelOnly 
= True) 
1199             elif event
.ShiftDown(): 
1200                 self
.ToggleFoldAll(expand 
= True) 
1202                 self
.ToggleFold(self
.GetCurrentLine()) 
1203         elif key 
== wx
.WXK_NUMPAD_SUBTRACT
: 
1204             if event
.ControlDown(): 
1205                 self
.ToggleFoldAll(expand 
= False, topLevelOnly 
= True) 
1206             elif event
.ShiftDown(): 
1207                 self
.ToggleFoldAll(expand 
= False) 
1209                 self
.ToggleFold(self
.GetCurrentLine()) 
1214     #---------------------------------------------------------------------------- 
1216     #---------------------------------------------------------------------------- 
1218     def GetViewRightEdge(self
): 
1219         return self
.GetEdgeMode() != wx
.stc
.STC_EDGE_NONE
 
1222     def SetViewRightEdge(self
, viewRightEdge
): 
1224             self
.SetEdgeMode(wx
.stc
.STC_EDGE_LINE
) 
1226             self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
) 
1229     def GetViewLineNumbers(self
): 
1230         return self
.GetMarginWidth(1) > 0 
1233     def SetViewLineNumbers(self
, viewLineNumbers 
= True): 
1235             self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth()) 
1237             self
.SetMarginWidth(1, 0) 
1240     def CanWordWrap(self
): 
1244     def GetWordWrap(self
): 
1245         return self
.GetWrapMode() == wx
.stc
.STC_WRAP_WORD
 
1248     def SetWordWrap(self
, wordWrap
): 
1250             self
.SetWrapMode(wx
.stc
.STC_WRAP_WORD
) 
1252             self
.SetWrapMode(wx
.stc
.STC_WRAP_NONE
) 
1255     #---------------------------------------------------------------------------- 
1256     # DynamicSashWindow methods 
1257     #---------------------------------------------------------------------------- 
1259     def SetupDSScrollBars(self
): 
1260         # hook the scrollbars provided by the wxDynamicSashWindow 
1262         v_bar 
= self
._dynSash
.GetVScrollBar(self
) 
1263         h_bar 
= self
._dynSash
.GetHScrollBar(self
) 
1264         v_bar
.Bind(wx
.EVT_SCROLL
, self
.OnDSSBScroll
) 
1265         h_bar
.Bind(wx
.EVT_SCROLL
, self
.OnDSSBScroll
) 
1266         v_bar
.Bind(wx
.EVT_SET_FOCUS
, self
.OnDSSBFocus
) 
1267         h_bar
.Bind(wx
.EVT_SET_FOCUS
, self
.OnDSSBFocus
) 
1269         # And set the wxStyledText to use these scrollbars instead 
1270         # of its built-in ones. 
1271         self
.SetVScrollBar(v_bar
) 
1272         self
.SetHScrollBar(h_bar
) 
1275     def OnDSSplit(self
, evt
): 
1276         newCtrl 
= self
._dynSash
._view
.GetCtrlClass()(self
._dynSash
, -1, style
=wx
.NO_BORDER
) 
1277         newCtrl
.SetDocPointer(self
.GetDocPointer())     # use the same document 
1278         self
.SetupDSScrollBars() 
1279         if self 
== self
._dynSash
._view
.GetCtrl():  # originally had focus 
1280             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. 
1283     def OnDSUnify(self
, evt
): 
1284         self
.SetupDSScrollBars() 
1285         self
.SetFocus()  # do this to set colors correctly 
1288     def OnDSSBScroll(self
, evt
): 
1289         # redirect the scroll events from the _dynSash's scrollbars to the STC 
1290         self
.GetEventHandler().ProcessEvent(evt
) 
1293     def OnDSSBFocus(self
, evt
): 
1294         # when the scrollbar gets the focus move it back to the STC 
1298     def DSProcessEvent(self
, event
): 
1299         # wxHack: Needed for customized right mouse click menu items.         
1300         if hasattr(self
, "_dynSash"): 
1301             if event
.GetId() == wx
.ID_SELECTALL
: 
1302                 # force focus so that select all occurs in the window user right clicked on. 
1305             return self
._dynSash
._view
.ProcessEvent(event
) 
1309     def DSProcessUpdateUIEvent(self
, event
): 
1310         # wxHack: Needed for customized right mouse click menu items.         
1311         if hasattr(self
, "_dynSash"): 
1313             if (id == wx
.ID_SELECTALL  
# allow select all even in non-active window, then force focus to it, see above ProcessEvent 
1315             or id == wx
.ID_REDO
): 
1316                 pass  # allow these actions even in non-active window 
1317             else:  # disallow events in non-active windows.  Cut/Copy/Paste/Delete is too confusing user experience. 
1318                 if self
._dynSash
._view
.GetCtrl() != self
: 
1322             return self
._dynSash
._view
.ProcessUpdateUIEvent(event
) 
1326 class TextPrintout(wx
.lib
.docview
.DocPrintout
): 
1327     """ for Print Preview and Print """ 
1330     def OnPreparePrinting(self
): 
1331         """ initialization """ 
1334         ppiScreenX
, ppiScreenY 
= self
.GetPPIScreen() 
1335         ppiPrinterX
, ppiPrinterY 
= self
.GetPPIPrinter() 
1336         scaleX 
= float(ppiPrinterX
)/ppiScreenX
 
1337         scaleY 
= float(ppiPrinterY
)/ppiScreenY
 
1339         pageWidth
, pageHeight 
= self
.GetPageSizePixels() 
1340         self
._scaleFactorX 
= scaleX
/pageWidth
 
1341         self
._scaleFactorY 
= scaleY
/pageHeight
 
1344         overallScaleX 
= self
._scaleFactorX 
* w
 
1345         overallScaleY 
= self
._scaleFactorY 
* h
 
1347         txtCtrl 
= self
._printoutView
.GetCtrl() 
1348         font
, color 
= txtCtrl
.GetFontAndColorFromConfig() 
1351         self
._fontHeight 
= font
.GetPointSize() + 1 
1352         self
._pageLines 
= int((h
/overallScaleY 
- (2 * self
._margin
))/self
._fontHeight
) 
1353         self
._maxLines 
= txtCtrl
.GetLineCount() 
1354         self
._numPages
, remainder 
= divmod(self
._maxLines
, self
._pageLines
) 
1359         lineNum 
= self
._maxLines
 
1360         while lineNum 
>= 10: 
1361             lineNum 
= lineNum
/10 
1363         self
._printFormat 
= "%%0%sd: %%s" % spaces
 
1366     def OnPrintPage(self
, page
): 
1367         """ Prints the given page of the view """ 
1370         txtCtrl 
= self
._printoutView
.GetCtrl() 
1371         font
, color 
= txtCtrl
.GetFontAndColorFromConfig() 
1375         dc
.SetUserScale(self
._scaleFactorX 
* w
, self
._scaleFactorY 
* h
) 
1379         dc
.DrawText("%s - page %s" % (self
.GetTitle(), page
), self
._margin
, self
._margin
/2) 
1381         startY 
= self
._margin
 
1382         startLine 
= (page 
- 1) * self
._pageLines
 
1383         endLine 
= min((startLine 
+ self
._pageLines
), self
._maxLines
) 
1384         for i 
in range(startLine
, endLine
): 
1385             text 
= txtCtrl
.GetLine(i
).rstrip() 
1386             startY 
+= self
._fontHeight
 
1387             if txtCtrl
.GetViewLineNumbers(): 
1388                 dc
.DrawText(self
._printFormat 
% (i
+1, text
), self
._margin
, startY
) 
1390                 dc
.DrawText(text
, self
._margin
, startY
) 
1397     def HasPage(self
, pageNum
): 
1398         return pageNum 
<= self
._numPages
 
1401     def GetPageInfo(self
): 
1403         maxPage 
= self
._numPages
 
1405         selPageTo 
= self
._numPages
 
1406         return (minPage
, maxPage
, selPageFrom
, selPageTo
) 
1409 #---------------------------------------------------------------------------- 
1410 # Icon Bitmaps - generated by encode_bitmaps.py 
1411 #---------------------------------------------------------------------------- 
1412 from wx 
import ImageFromStream
, BitmapFromImage
 
1418 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1419 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1420 \x00\x015IDAT8\x8d\xad\x90\xb1N\xc2P\x14\x86\xbf\x02/\xe0\xec#\x18g\xc3\xe6T\ 
1421 \x13':1\x18H\x98\x14\x12\x17G\x177\x17\x9c4a\xc5\xc0d0\xc2\xccdLx\x02^@+\t\ 
1422 \xc1\x90\xf6r\xdb\xc6\x94\xe5:\\\xdbP)\xc5DOr\x92\x9b{\xff\xfb\xfd\xff9\xc6h\ 
1423 l+\xbek.\x02\x00\xec\x99\x03\x80\xeb\xf8\\\x9d\x1d\x1bd\xd5hl\xab\xd7O\x15\ 
1424 \xf7x\xa1\xfb\xeeq\xa4^>\x94\xba\xb8yRF.\xcf\xa6.D\xa0Nw\x18C\xad\xb2\x19\ 
1425 \x9f\x0f\xca\x165\xd1V\xed\xebZj\x92\xc2\\\x04\xec\x02\xd5\x8a\x89\xb7\xd4\ 
1426 \x97n\xa8\xe3?\x0f\x86\x08\x19dNP\x00\xf0\x96\xd0\x7f\xd0\t\x84\x0c(U-\x0eK&\ 
1427 \xd3P\x8bz\xcdV6 \x8a\xed\x86\x99f\xe9\x00{\xe6\xb0\x13\xc2\xa0\xd3\xd7\t\ 
1428 \x84\x9f\x10\xec\x9dTp\x1d\xb1=A\xa9j\x01\xc4\xb1\x01&\xfe\x9a~\x1d\xe0:Zu\ 
1429 \x7f\xdb\x05@J/!(\xd6\x1bL\xde\xec\xcd\x00!\x03\xa6!\x1c\x9dVR\x9d\xdf\xe5\ 
1430 \x96\x04\xd1au\xd3\xab3\xef\x9f_f\x03\xa2\xa5\x15\xeb\x8d\xc4\xc36\xe7\x18 \ 
1431 \xa5G\xaf\xd9J\xb8f\xcd\xfc\xb3\x0c#\x97\xff\xb58\xadr\x7f\xfa\xfd\x1f\x80/\ 
1432 \x04\x1f\x8fW\x0e^\xc3\x12\x00\x00\x00\x00IEND\xaeB`\x82"  
1435 def getTextBitmap(): 
1436     return BitmapFromImage(getTextImage()) 
1439     stream 
= cStringIO
.StringIO(getTextData()) 
1440     return ImageFromStream(stream
) 
1443     return wx
.IconFromBitmap(getTextBitmap()) 
1446 #---------------------------------------------------------------------------- 
1447 # Menu Bitmaps - generated by encode_bitmaps.py 
1448 #---------------------------------------------------------------------------- 
1449 #---------------------------------------------------------------------- 
1450 def getZoomInData(): 
1452 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1453 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1454 \x00\x01TIDAT8\x8d\x8d\x93\xbbJ\x03A\x14\x86\xbf\xd9,\xc6\xd8E%`)VF[{\xc1v\ 
1455 \xf1\x82\x8f\xb0\xb94\xda\xa5\x13\x11\x8b`\xa9h\x10F\xe3#H.\xa6\x15\xccKhg\ 
1456 \x10\xc1B\x8bTF\x90\xc0X\x8c3\xbb\xd9\xcdF\x7f\x18\xf6\xec\x9cs\xbe\xfd\xe70\ 
1457 +\x84\x93"\xacb\xc1W\xe1\xf7\xeb\xfa\x8d`\x82\xdcXcI\x8e\x02AM\x02\t\xe1\xa4\ 
1458 (\x16|uz)y\x19\xc0\xc9\xdd;\x99\xee!\x00\xd9\xbd\x00\xd6\xaf\x95\xc7B\xac\ 
1459 \x03\xd3\x1c\xd6\xc2t\x10\xf7\x13\x8e\xe0\x14\x0b\xbe\xa2$m\xf3\xca\xea\xacM\ 
1460 \xe6\xd2\xc1\xcaWdl>#\x0e\x8c\xed\xe7n\x90|\xa8\x96m\xbc~ y\x04Z\xcd\x86\xda\ 
1461 \xda\xde\xb1Gq\x00\xb2S\t\xfeB\x9aK\xa8\xb1\x0e\xf2\x15I.\xad\x0bo\x8f\xf4\ 
1462 \x97\xab\xe7z\x88\x1f\xdf\xf0\xfa9\x1e\xe0x\x9eG\xbf\x16X\xcd\xb8Ar\xc6\xd5\ 
1463 \x0b4\xd4\xf3\xbcd\x07F_\xc3 \x1e\x0c\xa3Y\x08\x9f\x1f~\xefA\xab\xd9P\x9dN\ 
1464 \x07\x80\xddcI\xc6\x85\xf9\xb4.8\xabhwK\xbd+6\x16\xf5\xdeZ=%F\x00\xa0\xa7\ 
1465 \x0b`@F\xc6\xf6\xd3\xc5&@\x0c"\xa2\xff\x82\x01\x85-\xb7\x9a\re\x00QH\x0c0N\ 
1466 \x06\x1a\x85\xbcym}\x0f\xfe\x92\x19\xdc\xf2~\xdb\xee\xdd\xf7\xf4\xf3_\x0e\ 
1467 \xa2N\xc2\xfa\x01MYp\xbc\xe4a\x0f\xa9\x00\x00\x00\x00IEND\xaeB`\x82'  
1469 def getZoomInBitmap(): 
1470     return BitmapFromImage(getZoomInImage()) 
1472 def getZoomInImage(): 
1473     stream 
= cStringIO
.StringIO(getZoomInData()) 
1474     return ImageFromStream(stream
) 
1476 #---------------------------------------------------------------------- 
1477 def getZoomOutData(): 
1479 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
1480 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
1481 \x00\x01RIDAT8\x8d\x8d\x93\xbbJ\x03A\x14\x86\xbf\xd9\x04\x93\x90J\x0cj#Dl\ 
1482 \xf4\x01\xec\x05\xdb\xc5\x0b>B\x92]\x1b+\xed,D\xb0\xb4\x08\x9afc|\x04\xc9\ 
1483 \x85\xb4>\x84\x95`\x93\x80`\x15\xd8*\x98\x84\xc0X\xcc\xce\xde7\xf8\xc30\x97=\ 
1484 \xf3\xcd\x7f\xce\xcc\na\xe4\x08\xabQ\xaf\xc9\xf0\xfc\xa5\xf3*X\xa1|b\xa3\xe5\ 
1485 D\x81 W\x81\x840r4\xea5\xf9\xf0\xe40Y@\xf3+\xf8\xb8\xbe\x16\x8c\xdd\x96\x9d\ 
1486 \n1\xf4\xc0\xdf\xdc\xb6\x01\xa8\xca\x19[\x05\xfc\x96%aY\x96\x0c\xdb\xae\xca\ 
1487 \x99\xea7\x8b\x91@w.\xf9x\xbcL\xb8\xf0k\xa0O\x1e{\xd31Q\x1d\xdd\xaaC\xfa\xbd\ 
1488 \xae<=;\xf7!F<\xd7,md\xc4\xf8\x0e\xf6\xaf\x1d\xb6\x8b*p\xa7\x0c\x95\xd0\x86\ 
1489 \xc9\x02\xbe\xa7\xe9\x00\xc34M\xdc\x96MA\xa8[,y\xc8r>h\x00ow6\xa6if;\x98K\ 
1490 \x95\xd6\xef\x12(\xc0t\x99~b8\x7f\xf0\xdeA\xbf\xd7\x95\xc3\xe1\x10\x80\x8b{\ 
1491 \x87R\x1e*\xde\xd55oTq\xf7Fm\x8ew\xd5\xdaa\'\'"\x00P\xd5\x05\xd0 -m\xfb\xf3\ 
1492 \xf9\x04 \x01\x11\xf1\x7fA\x83\xc2\x96\xfb\xbd\xae\xd4\x808$\x01H\x93\x86\ 
1493 \xc6!?\xe6 x\xca\xab\xa4\x0bwp5\xf0\xd7\xdeG\xaa\xff\x97\x83\xb8\x93\xb0\xfe\ 
1494 \x00\xc3\xa8ov\xfd\xe4\x9c\xa2\x00\x00\x00\x00IEND\xaeB`\x82'  
1497 def getZoomOutBitmap(): 
1498     return BitmapFromImage(getZoomOutImage()) 
1500 def getZoomOutImage(): 
1501     stream 
= cStringIO
.StringIO(getZoomOutData()) 
1502     return ImageFromStream(stream
)