1 #----------------------------------------------------------------------------
2 # Name: STCTextEditor.py
3 # Purpose: Text Editor for wx.lib.pydocview tbat uses the Styled Text Control
5 # Author: Peter Yared, Morgan Hua
9 # Copyright: (c) 2003-2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
16 import wx
.lib
.multisash
17 import wx
.lib
.pydocview
24 #----------------------------------------------------------------------------
26 #----------------------------------------------------------------------------
29 VIEW_WHITESPACE_ID
= wx
.NewId()
30 VIEW_EOL_ID
= wx
.NewId()
31 VIEW_INDENTATION_GUIDES_ID
= wx
.NewId()
32 VIEW_RIGHT_EDGE_ID
= wx
.NewId()
33 VIEW_LINE_NUMBERS_ID
= wx
.NewId()
35 ZOOM_NORMAL_ID
= wx
.NewId()
36 ZOOM_IN_ID
= wx
.NewId()
37 ZOOM_OUT_ID
= wx
.NewId()
38 CHOOSE_FONT_ID
= wx
.NewId()
39 WORD_WRAP_ID
= wx
.NewId()
40 TEXT_STATUS_BAR_ID
= wx
.NewId()
43 #----------------------------------------------------------------------------
45 #----------------------------------------------------------------------------
47 class TextDocument(wx
.lib
.docview
.Document
):
50 def OnSaveDocument(self
, filename
):
51 view
= self
.GetFirstView()
52 docFile
= file(self
._documentFile
, "w")
53 docFile
.write(view
.GetValue())
56 self
.SetDocumentModificationDate()
57 self
.SetDocumentSaved(True)
61 def OnOpenDocument(self
, filename
):
62 view
= self
.GetFirstView()
63 docFile
= file(self
._documentFile
, 'r')
66 self
.SetFilename(filename
, True)
68 self
.SetDocumentModificationDate()
75 view
= self
.GetFirstView()
77 return wx
.lib
.docview
.Document
.IsModified(self
) or view
.IsModified()
79 return wx
.lib
.docview
.Document
.IsModified(self
)
82 def Modify(self
, mod
):
83 view
= self
.GetFirstView()
84 wx
.lib
.docview
.Document
.Modify(self
, mod
)
89 def OnCreateCommandProcessor(self
):
90 # Don't create a command processor, it has its own
93 # Use this to override MultiClient.Select to prevent yellow background.
94 def MultiClientSelectBGNotYellow(a
):
95 a
.GetParent().multiView
.UnSelect()
97 #a.SetBackgroundColour(wx.Colour(255,255,0)) # Yellow
100 class TextView(wx
.lib
.docview
.View
):
104 #----------------------------------------------------------------------------
106 #----------------------------------------------------------------------------
109 wx
.lib
.docview
.View
.__init
__(self
)
110 self
._textEditor
= None
111 self
._markerCount
= 0
112 self
._commandProcessor
= None
113 self
._multiSash
= None
116 def GetCtrlClass(self
):
121 # look for active one first
122 self
._textEditor
= self
._GetActiveCtrl
(self
._multiSash
)
123 if self
._textEditor
== None: # it is possible none are active
124 # look for any existing one
125 self
._textEditor
= self
._FindCtrl
(self
._multiSash
)
126 return self
._textEditor
129 ## def GetCtrls(self, parent = None):
130 ## """ Walk through the MultiSash windows and find all Ctrls """
132 ## if isinstance(parent, self.GetCtrlClass()):
134 ## if hasattr(parent, "GetChildren"):
135 ## for child in parent.GetChildren():
136 ## controls = controls + self.GetCtrls(child)
140 def OnCreate(self
, doc
, flags
):
141 frame
= wx
.GetApp().CreateDocumentFrame(self
, doc
, flags
, style
= wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
142 wx
.lib
.multisash
.MultiClient
.Select
= MultiClientSelectBGNotYellow
143 self
._multiSash
= wx
.lib
.multisash
.MultiSash(frame
, -1)
144 self
._multiSash
.SetDefaultChildClass(self
.GetCtrlClass()) # wxBug: MultiSash instantiates the first TextCtrl with this call
145 self
._textEditor
= self
.GetCtrl() # wxBug: grab the TextCtrl from the MultiSash datastructure
146 self
._CreateSizer
(frame
)
153 def _GetActiveCtrl(self
, parent
):
154 """ Walk through the MultiSash windows and find the active Control """
155 if isinstance(parent
, wx
.lib
.multisash
.MultiClient
) and parent
.selected
:
157 if hasattr(parent
, "GetChildren"):
158 for child
in parent
.GetChildren():
159 found
= self
._GetActiveCtrl
(child
)
165 def _FindCtrl(self
, parent
):
166 """ Walk through the MultiSash windows and find the first TextCtrl """
167 if isinstance(parent
, self
.GetCtrlClass()):
169 if hasattr(parent
, "GetChildren"):
170 for child
in parent
.GetChildren():
171 found
= self
._FindCtrl
(child
)
177 def _CreateSizer(self
, frame
):
178 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
179 sizer
.Add(self
._multiSash
, 1, wx
.EXPAND
)
180 frame
.SetSizer(sizer
)
181 frame
.SetAutoLayout(True)
184 def OnUpdate(self
, sender
= None, hint
= None):
185 if hint
== "ViewStuff":
186 self
.GetCtrl().SetViewDefaults()
188 font
, color
= self
.GetFontAndColorFromConfig()
189 self
.GetCtrl().SetFont(font
)
190 self
.GetCtrl().SetFontColor(color
)
193 def OnActivateView(self
, activate
, activeView
, deactiveView
):
194 if activate
and self
.GetCtrl():
195 # In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop
196 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
197 self
.GetCtrl().SetFocus()
199 wx
.CallAfter(self
.GetCtrl().SetFocus
)
202 def OnClose(self
, deleteWindow
= True):
203 if not wx
.lib
.docview
.View
.OnClose(self
, deleteWindow
):
206 if deleteWindow
and self
.GetFrame():
207 self
.GetFrame().Destroy()
211 def ProcessEvent(self
, event
):
214 self
.GetCtrl().Undo()
216 elif id == wx
.ID_REDO
:
217 self
.GetCtrl().Redo()
219 elif id == wx
.ID_CUT
:
222 elif id == wx
.ID_COPY
:
223 self
.GetCtrl().Copy()
225 elif id == wx
.ID_PASTE
:
226 self
.GetCtrl().OnPaste()
228 elif id == wx
.ID_CLEAR
:
229 self
.GetCtrl().OnClear()
231 elif id == wx
.ID_SELECTALL
:
232 self
.GetCtrl().SetSelection(0, -1)
234 elif id == VIEW_WHITESPACE_ID
:
235 self
.GetCtrl().SetViewWhiteSpace(not self
.GetCtrl().GetViewWhiteSpace())
237 elif id == VIEW_EOL_ID
:
238 self
.GetCtrl().SetViewEOL(not self
.GetCtrl().GetViewEOL())
240 elif id == VIEW_INDENTATION_GUIDES_ID
:
241 self
.GetCtrl().SetViewIndentationGuides(not self
.GetCtrl().GetViewIndentationGuides())
243 elif id == VIEW_RIGHT_EDGE_ID
:
244 self
.GetCtrl().SetViewRightEdge(not self
.GetCtrl().GetViewRightEdge())
246 elif id == VIEW_LINE_NUMBERS_ID
:
247 self
.GetCtrl().SetViewLineNumbers(not self
.GetCtrl().GetViewLineNumbers())
249 elif id == ZOOM_NORMAL_ID
:
250 self
.GetCtrl().SetZoom(0)
252 elif id == ZOOM_IN_ID
:
253 self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMIN
)
255 elif id == ZOOM_OUT_ID
:
256 self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMOUT
)
258 elif id == CHOOSE_FONT_ID
:
261 elif id == WORD_WRAP_ID
:
262 self
.GetCtrl().SetWordWrap(not self
.GetCtrl().GetWordWrap())
264 elif id == FindService
.FindService
.FIND_ID
:
267 elif id == FindService
.FindService
.FIND_PREVIOUS_ID
:
268 self
.DoFind(forceFindPrevious
= True)
270 elif id == FindService
.FindService
.FIND_NEXT_ID
:
271 self
.DoFind(forceFindNext
= True)
273 elif id == FindService
.FindService
.REPLACE_ID
:
274 self
.OnFind(replace
= True)
276 elif id == FindService
.FindService
.FINDONE_ID
:
279 elif id == FindService
.FindService
.REPLACEONE_ID
:
280 self
.DoFind(replace
= True)
282 elif id == FindService
.FindService
.REPLACEALL_ID
:
283 self
.DoFind(replaceAll
= True)
285 elif id == FindService
.FindService
.GOTO_LINE_ID
:
286 self
.OnGotoLine(event
)
289 return wx
.lib
.docview
.View
.ProcessEvent(self
, event
)
292 def ProcessUpdateUIEvent(self
, event
):
293 if not self
.GetCtrl():
298 event
.Enable(self
.GetCtrl().CanUndo())
299 event
.SetText(_("Undo") + '\t' + _('Ctrl+Z'))
301 elif id == wx
.ID_REDO
:
302 event
.Enable(self
.GetCtrl().CanRedo())
303 event
.SetText(_("Redo") + '\t' + _('Ctrl+Y'))
305 elif (id == wx
.ID_CUT
307 or id == wx
.ID_CLEAR
):
308 hasSelection
= self
.GetCtrl().GetSelectionStart() != self
.GetCtrl().GetSelectionEnd()
309 event
.Enable(hasSelection
)
311 elif id == wx
.ID_PASTE
:
312 event
.Enable(self
.GetCtrl().CanPaste())
314 elif id == wx
.ID_SELECTALL
:
315 hasText
= self
.GetCtrl().GetTextLength() > 0
316 event
.Enable(hasText
)
321 elif id == VIEW_WHITESPACE_ID
:
322 hasText
= self
.GetCtrl().GetTextLength() > 0
323 event
.Enable(hasText
)
324 event
.Check(self
.GetCtrl().GetViewWhiteSpace())
326 elif id == VIEW_EOL_ID
:
327 hasText
= self
.GetCtrl().GetTextLength() > 0
328 event
.Enable(hasText
)
329 event
.Check(self
.GetCtrl().GetViewEOL())
331 elif id == VIEW_INDENTATION_GUIDES_ID
:
332 hasText
= self
.GetCtrl().GetTextLength() > 0
333 event
.Enable(hasText
)
334 event
.Check(self
.GetCtrl().GetIndentationGuides())
336 elif id == VIEW_RIGHT_EDGE_ID
:
337 hasText
= self
.GetCtrl().GetTextLength() > 0
338 event
.Enable(hasText
)
339 event
.Check(self
.GetCtrl().GetViewRightEdge())
341 elif id == VIEW_LINE_NUMBERS_ID
:
342 hasText
= self
.GetCtrl().GetTextLength() > 0
343 event
.Enable(hasText
)
344 event
.Check(self
.GetCtrl().GetViewLineNumbers())
349 elif id == ZOOM_NORMAL_ID
:
350 event
.Enable(self
.GetCtrl().GetZoom() != 0)
352 elif id == ZOOM_IN_ID
:
353 event
.Enable(self
.GetCtrl().GetZoom() < 20)
355 elif id == ZOOM_OUT_ID
:
356 event
.Enable(self
.GetCtrl().GetZoom() > -10)
358 elif id == CHOOSE_FONT_ID
:
361 elif id == WORD_WRAP_ID
:
362 event
.Enable(self
.GetCtrl().CanWordWrap())
363 event
.Check(self
.GetCtrl().CanWordWrap() and self
.GetCtrl().GetWordWrap())
365 elif id == FindService
.FindService
.FIND_ID
:
366 hasText
= self
.GetCtrl().GetTextLength() > 0
367 event
.Enable(hasText
)
369 elif id == FindService
.FindService
.FIND_PREVIOUS_ID
:
370 hasText
= self
.GetCtrl().GetTextLength() > 0
371 event
.Enable(hasText
and
372 self
._FindServiceHasString
() and
373 self
.GetCtrl().GetSelection()[0] > 0)
375 elif id == FindService
.FindService
.FIND_NEXT_ID
:
376 hasText
= self
.GetCtrl().GetTextLength() > 0
377 event
.Enable(hasText
and
378 self
._FindServiceHasString
() and
379 self
.GetCtrl().GetSelection()[0] < self
.GetCtrl().GetLength())
381 elif id == FindService
.FindService
.REPLACE_ID
:
382 hasText
= self
.GetCtrl().GetTextLength() > 0
383 event
.Enable(hasText
)
385 elif id == FindService
.FindService
.GOTO_LINE_ID
:
388 elif id == TEXT_STATUS_BAR_ID
:
389 self
.OnUpdateStatusBar(event
)
392 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
395 def _GetParentFrame(self
):
396 return wx
.GetTopLevelParent(self
.GetFrame())
399 #----------------------------------------------------------------------------
400 # Methods for TextDocument to call
401 #----------------------------------------------------------------------------
403 def IsModified(self
):
404 if not self
.GetCtrl():
406 return self
.GetCtrl().GetModify()
409 def SetModifyFalse(self
):
410 self
.GetCtrl().SetSavePoint()
415 return self
.GetCtrl().GetText()
420 def SetValue(self
, value
):
421 self
.GetCtrl().SetText(value
)
422 self
.GetCtrl().UpdateLineNumberMarginWidth()
423 self
.GetCtrl().EmptyUndoBuffer()
426 #----------------------------------------------------------------------------
428 #----------------------------------------------------------------------------
430 def OnUpdateStatusBar(self
, event
):
431 statusBar
= self
._GetParentFrame
().GetStatusBar()
432 statusBar
.SetInsertMode(self
.GetCtrl().GetOvertype() == 0)
433 statusBar
.SetLineNumber(self
.GetCtrl().GetCurrentLine() + 1)
434 statusBar
.SetColumnNumber(self
.GetCtrl().GetColumn(self
.GetCtrl().GetCurrentPos()) + 1)
437 #----------------------------------------------------------------------------
439 #----------------------------------------------------------------------------
441 def OnChooseFont(self
):
443 data
.EnableEffects(True)
444 data
.SetInitialFont(self
.GetCtrl().GetFont())
445 data
.SetColour(self
.GetCtrl().GetFontColor())
446 fontDialog
= wx
.FontDialog(self
.GetFrame(), data
)
447 if fontDialog
.ShowModal() == wx
.ID_OK
:
448 data
= fontDialog
.GetFontData()
449 self
.GetCtrl().SetFont(data
.GetChosenFont())
450 self
.GetCtrl().SetFontColor(data
.GetColour())
451 self
.GetCtrl().UpdateStyles()
455 #----------------------------------------------------------------------------
457 #----------------------------------------------------------------------------
459 def OnFind(self
, replace
= False):
460 findService
= wx
.GetApp().GetService(FindService
.FindService
)
462 findService
.ShowFindReplaceDialog(findString
= self
.GetCtrl().GetSelectedText(), replace
= replace
)
465 def DoFind(self
, forceFindNext
= False, forceFindPrevious
= False, replace
= False, replaceAll
= False):
466 findService
= wx
.GetApp().GetService(FindService
.FindService
)
469 findString
= findService
.GetFindString()
470 if len(findString
) == 0:
472 replaceString
= findService
.GetReplaceString()
473 flags
= findService
.GetFlags()
474 startLoc
, endLoc
= self
.GetCtrl().GetSelection()
476 wholeWord
= flags
& wx
.FR_WHOLEWORD
> 0
477 matchCase
= flags
& wx
.FR_MATCHCASE
> 0
478 regExp
= flags
& FindService
.FindService
.FR_REGEXP
> 0
479 down
= flags
& wx
.FR_DOWN
> 0
480 wrap
= flags
& FindService
.FindService
.FR_WRAP
> 0
482 if forceFindPrevious
: # this is from function keys, not dialog box
484 wrap
= False # user would want to know they're at the end of file
487 wrap
= False # user would want to know they're at the end of file
491 # On replace dialog operations, user is allowed to replace the currently highlighted text to determine if it should be replaced or not.
492 # 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.
493 # If the text is a match, then replace it.
495 result
, start
, end
, replText
= findService
.DoFind(findString
, replaceString
, self
.GetCtrl().GetSelectedText(), 0, 0, True, matchCase
, wholeWord
, regExp
, replace
)
497 self
.GetCtrl().ReplaceSelection(replText
)
498 self
.GetDocument().Modify(True)
499 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
)
501 startLoc
+= len(replText
) # advance start location past replacement string to new text
503 elif result
== FindService
.FIND_SYNTAXERROR
:
505 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
)
508 text
= self
.GetCtrl().GetText()
510 # Find the next matching text occurance or if it is a ReplaceAll, replace all occurances
511 # 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
512 result
, start
, end
, text
= findService
.DoFind(findString
, replaceString
, text
, startLoc
, endLoc
, down
, matchCase
, wholeWord
, regExp
, False, replaceAll
, wrap
)
514 self
.GetCtrl().SetTargetStart(0)
515 self
.GetCtrl().SetTargetEnd(self
.GetCtrl().GetLength())
516 self
.GetCtrl().ReplaceTarget(text
) # Doing a SetText causes a clear document to be shown when undoing, so using replacetarget instead
517 self
.GetDocument().Modify(True)
519 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
)
521 wx
.GetApp().GetTopWindow().PushStatusText(_("%i occurrences of \"%s\" replaced") % (result
, findString
))
523 self
.GetCtrl().SetSelection(start
, end
)
524 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(end
)) # show bottom then scroll up to top
525 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(start
)) # do this after ensuring bottom is visible
526 wx
.GetApp().GetTopWindow().PushStatusText(_("Found \"%s\".") % findString
)
527 elif result
== FindService
.FIND_SYNTAXERROR
:
528 # Dialog for this case gets popped up by the FindService.
529 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
)
531 wx
.MessageBox(_("Can't find \"%s\".") % findString
, "Find",
532 wx
.OK | wx
.ICON_INFORMATION
)
535 def _FindServiceHasString(self
):
536 findService
= wx
.GetApp().GetService(FindService
.FindService
)
537 if not findService
or not findService
.GetFindString():
542 def OnGotoLine(self
, event
):
543 findService
= wx
.GetApp().GetService(FindService
.FindService
)
545 line
= findService
.GetLineNumber(self
.GetDocumentManager().FindSuitableParent())
548 self
.GetCtrl().EnsureVisible(line
)
549 self
.GetCtrl().GotoLine(line
)
552 def GotoLine(self
, lineNum
):
554 lineNum
= lineNum
- 1 # line numbering for editor is 0 based, we are 1 based.
555 self
.GetCtrl().EnsureVisibleEnforcePolicy(lineNum
)
556 self
.GetCtrl().GotoLine(lineNum
)
559 def SetSelection(self
, start
, end
):
560 self
.GetCtrl().SetSelection(start
, end
)
563 def EnsureVisible(self
, line
):
564 self
.GetCtrl().EnsureVisible(line
-1) # line numbering for editor is 0 based, we are 1 based.
566 def EnsureVisibleEnforcePolicy(self
, line
):
567 self
.GetCtrl().EnsureVisibleEnforcePolicy(line
-1) # line numbering for editor is 0 based, we are 1 based.
569 def LineFromPosition(self
, pos
):
570 return self
.GetCtrl().LineFromPosition(pos
)+1 # line numbering for editor is 0 based, we are 1 based.
573 def PositionFromLine(self
, line
):
574 return self
.GetCtrl().PositionFromLine(line
-1) # line numbering for editor is 0 based, we are 1 based.
577 def GetLineEndPosition(self
, line
):
578 return self
.GetCtrl().GetLineEndPosition(line
-1) # line numbering for editor is 0 based, we are 1 based.
581 def GetLine(self
, lineNum
):
582 return self
.GetCtrl().GetLine(lineNum
-1) # line numbering for editor is 0 based, we are 1 based.
584 def MarkerDefine(self
):
585 """ This must be called after the texteditor is instantiated """
586 self
.GetCtrl().MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_CIRCLE
, wx
.BLACK
, wx
.BLUE
)
589 def MarkerToggle(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
591 lineNum
= self
.GetCtrl().GetCurrentLine()
592 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
593 self
.GetCtrl().MarkerDelete(lineNum
, marker_index
)
594 self
._markerCount
-= 1
596 self
.GetCtrl().MarkerAdd(lineNum
, marker_index
)
597 self
._markerCount
+= 1
599 def MarkerAdd(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
601 lineNum
= self
.GetCtrl().GetCurrentLine()
602 self
.GetCtrl().MarkerAdd(lineNum
, marker_index
)
603 self
._markerCount
+= 1
606 def MarkerDelete(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
608 lineNum
= self
.GetCtrl().GetCurrentLine()
609 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
610 self
.GetCtrl().MarkerDelete(lineNum
, marker_index
)
611 self
._markerCount
-= 1
613 def MarkerDeleteAll(self
, marker_num
=MARKER_NUM
):
614 self
.GetCtrl().MarkerDeleteAll(marker_num
)
615 if marker_num
== self
.MARKER_NUM
:
616 self
._markerCount
= 0
619 def MarkerNext(self
, lineNum
= -1):
621 lineNum
= self
.GetCtrl().GetCurrentLine() + 1 # start search below current line
622 foundLine
= self
.GetCtrl().MarkerNext(lineNum
, self
.MARKER_MASK
)
624 # wrap to top of file
625 foundLine
= self
.GetCtrl().MarkerNext(0, self
.MARKER_MASK
)
627 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers"))
630 self
.GotoLine(foundLine
+ 1)
633 def MarkerPrevious(self
, lineNum
= -1):
635 lineNum
= self
.GetCtrl().GetCurrentLine() - 1 # start search above current line
637 lineNum
= self
.GetCtrl().GetLineCount()
639 foundLine
= self
.GetCtrl().MarkerPrevious(lineNum
, self
.MARKER_MASK
)
641 # wrap to bottom of file
642 foundLine
= self
.GetCtrl().MarkerPrevious(self
.GetCtrl().GetLineCount(), self
.MARKER_MASK
)
644 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers"))
647 self
.GotoLine(foundLine
+ 1)
650 def MarkerExists(self
, lineNum
= -1, mask
=MARKER_MASK
):
652 lineNum
= self
.GetCtrl().GetCurrentLine()
653 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
659 def GetMarkerCount(self
):
660 return self
._markerCount
663 class TextService(wx
.lib
.pydocview
.DocService
):
667 wx
.lib
.pydocview
.DocService
.__init
__(self
)
670 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
671 if document
and document
.GetDocumentTemplate().GetDocumentType() != TextDocument
:
673 if not document
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
676 statusBar
= TextStatusBar(frame
, TEXT_STATUS_BAR_ID
)
677 frame
.SetStatusBar(statusBar
)
678 wx
.EVT_UPDATE_UI(frame
, TEXT_STATUS_BAR_ID
, frame
.ProcessUpdateUIEvent
)
680 viewMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View")))
682 viewMenu
.AppendSeparator()
684 textMenu
.AppendCheckItem(VIEW_WHITESPACE_ID
, _("&Whitespace"), _("Shows or hides whitespace"))
685 wx
.EVT_MENU(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessEvent
)
686 wx
.EVT_UPDATE_UI(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessUpdateUIEvent
)
687 textMenu
.AppendCheckItem(VIEW_EOL_ID
, _("&End of Line Markers"), _("Shows or hides indicators at the end of each line"))
688 wx
.EVT_MENU(frame
, VIEW_EOL_ID
, frame
.ProcessEvent
)
689 wx
.EVT_UPDATE_UI(frame
, VIEW_EOL_ID
, frame
.ProcessUpdateUIEvent
)
690 textMenu
.AppendCheckItem(VIEW_INDENTATION_GUIDES_ID
, _("&Indentation Guides"), _("Shows or hides indentations"))
691 wx
.EVT_MENU(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessEvent
)
692 wx
.EVT_UPDATE_UI(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessUpdateUIEvent
)
693 textMenu
.AppendCheckItem(VIEW_RIGHT_EDGE_ID
, _("&Right Edge"), _("Shows or hides the right edge marker"))
694 wx
.EVT_MENU(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessEvent
)
695 wx
.EVT_UPDATE_UI(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessUpdateUIEvent
)
696 textMenu
.AppendCheckItem(VIEW_LINE_NUMBERS_ID
, _("&Line Numbers"), _("Shows or hides the line numbers"))
697 wx
.EVT_MENU(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessEvent
)
698 wx
.EVT_UPDATE_UI(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessUpdateUIEvent
)
700 viewMenu
.AppendMenu(TEXT_ID
, _("&Text"), textMenu
)
701 wx
.EVT_UPDATE_UI(frame
, TEXT_ID
, frame
.ProcessUpdateUIEvent
)
703 isWindows
= (wx
.Platform
== '__WXMSW__')
706 zoomMenu
.Append(ZOOM_NORMAL_ID
, _("Normal Size"), _("Sets the document to its normal size"))
707 wx
.EVT_MENU(frame
, ZOOM_NORMAL_ID
, frame
.ProcessEvent
)
708 wx
.EVT_UPDATE_UI(frame
, ZOOM_NORMAL_ID
, frame
.ProcessUpdateUIEvent
)
710 zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In\tCtrl+Page Up"), _("Zooms the document to a larger size"))
712 zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In"), _("Zooms the document to a larger size"))
713 wx
.EVT_MENU(frame
, ZOOM_IN_ID
, frame
.ProcessEvent
)
714 wx
.EVT_UPDATE_UI(frame
, ZOOM_IN_ID
, frame
.ProcessUpdateUIEvent
)
716 zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out\tCtrl+Page Down"), _("Zooms the document to a smaller size"))
718 zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out"), _("Zooms the document to a smaller size"))
719 wx
.EVT_MENU(frame
, ZOOM_OUT_ID
, frame
.ProcessEvent
)
720 wx
.EVT_UPDATE_UI(frame
, ZOOM_OUT_ID
, frame
.ProcessUpdateUIEvent
)
722 viewMenu
.AppendMenu(ZOOM_ID
, _("&Zoom"), zoomMenu
)
723 wx
.EVT_UPDATE_UI(frame
, ZOOM_ID
, frame
.ProcessUpdateUIEvent
)
725 formatMenuIndex
= menuBar
.FindMenu(_("&Format"))
726 if formatMenuIndex
> -1:
727 formatMenu
= menuBar
.GetMenu(formatMenuIndex
)
729 formatMenu
= wx
.Menu()
730 if not menuBar
.FindItemById(CHOOSE_FONT_ID
):
731 formatMenu
.Append(CHOOSE_FONT_ID
, _("&Font..."), _("Sets the font to use"))
732 wx
.EVT_MENU(frame
, CHOOSE_FONT_ID
, frame
.ProcessEvent
)
733 wx
.EVT_UPDATE_UI(frame
, CHOOSE_FONT_ID
, frame
.ProcessUpdateUIEvent
)
734 if not menuBar
.FindItemById(WORD_WRAP_ID
):
735 formatMenu
.AppendCheckItem(WORD_WRAP_ID
, _("Word Wrap"), _("Wraps text horizontally when checked"))
736 wx
.EVT_MENU(frame
, WORD_WRAP_ID
, frame
.ProcessEvent
)
737 wx
.EVT_UPDATE_UI(frame
, WORD_WRAP_ID
, frame
.ProcessUpdateUIEvent
)
738 if formatMenuIndex
== -1:
739 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
740 menuBar
.Insert(viewMenuIndex
+ 1, formatMenu
, _("&Format"))
742 # wxBug: wxToolBar::GetToolPos doesn't exist, need it to find cut tool and then insert find in front of it.
743 toolBar
.AddSeparator()
744 toolBar
.AddTool(ZOOM_IN_ID
, getZoomInBitmap(), shortHelpString
= _("Zoom In"), longHelpString
= _("Zooms the document to a larger size"))
745 toolBar
.AddTool(ZOOM_OUT_ID
, getZoomOutBitmap(), shortHelpString
= _("Zoom Out"), longHelpString
= _("Zooms the document to a smaller size"))
749 def ProcessUpdateUIEvent(self
, event
):
752 or id == VIEW_WHITESPACE_ID
754 or id == VIEW_INDENTATION_GUIDES_ID
755 or id == VIEW_RIGHT_EDGE_ID
756 or id == VIEW_LINE_NUMBERS_ID
758 or id == ZOOM_NORMAL_ID
761 or id == CHOOSE_FONT_ID
762 or id == WORD_WRAP_ID
):
769 class TextStatusBar(wx
.StatusBar
):
771 # 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
773 def __init__(self
, parent
, id, style
= wx
.ST_SIZEGRIP
, name
= "statusBar"):
774 wx
.StatusBar
.__init
__(self
, parent
, id, style
, name
)
775 self
.SetFieldsCount(4)
776 self
.SetStatusWidths([-1, 50, 50, 55])
778 def SetInsertMode(self
, insert
= True):
783 if self
.GetStatusText(1) != newText
: # wxBug: Need to check if the text has changed, otherwise it flickers under win32
784 self
.SetStatusText(newText
, 1)
786 def SetLineNumber(self
, lineNumber
):
787 newText
= _("Ln %i") % lineNumber
788 if self
.GetStatusText(2) != newText
:
789 self
.SetStatusText(newText
, 2)
791 def SetColumnNumber(self
, colNumber
):
792 newText
= _("Col %i") % colNumber
793 if self
.GetStatusText(3) != newText
:
794 self
.SetStatusText(newText
, 3)
797 class TextOptionsPanel(wx
.Panel
):
800 def __init__(self
, parent
, id, configPrefix
= "Text", label
= "Text", hasWordWrap
= True, hasTabs
= False, addPage
=True):
801 wx
.Panel
.__init
__(self
, parent
, id)
802 self
._configPrefix
= configPrefix
803 self
._hasWordWrap
= hasWordWrap
804 self
._hasTabs
= hasTabs
807 config
= wx
.ConfigBase_Get()
808 self
._textFont
= wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
)
809 fontData
= config
.Read(self
._configPrefix
+ "EditorFont", "")
811 nativeFont
= wx
.NativeFontInfo()
812 nativeFont
.FromString(fontData
)
813 self
._textFont
.SetNativeFontInfo(nativeFont
)
814 self
._originalTextFont
= self
._textFont
815 self
._textColor
= wx
.BLACK
816 colorData
= config
.Read(self
._configPrefix
+ "EditorColor", "")
818 red
= int("0x" + colorData
[0:2], 16)
819 green
= int("0x" + colorData
[2:4], 16)
820 blue
= int("0x" + colorData
[4:6], 16)
821 self
._textColor
= wx
.Color(red
, green
, blue
)
822 self
._originalTextColor
= self
._textColor
823 fontLabel
= wx
.StaticText(self
, -1, _("Font:"))
824 self
._sampleTextCtrl
= wx
.TextCtrl(self
, -1, "", size
= (125, 21))
825 self
._sampleTextCtrl
.SetEditable(False)
826 chooseFontButton
= wx
.Button(self
, -1, _("Choose Font..."))
827 wx
.EVT_BUTTON(self
, chooseFontButton
.GetId(), self
.OnChooseFont
)
828 if self
._hasWordWrap
:
829 self
._wordWrapCheckBox
= wx
.CheckBox(self
, -1, _("Wrap words inside text area"))
830 self
._wordWrapCheckBox
.SetValue(wx
.ConfigBase_Get().ReadInt(self
._configPrefix
+ "EditorWordWrap", False))
831 self
._viewWhitespaceCheckBox
= wx
.CheckBox(self
, -1, _("Show whitespace"))
832 self
._viewWhitespaceCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewWhitespace", False))
833 self
._viewEOLCheckBox
= wx
.CheckBox(self
, -1, _("Show end of line markers"))
834 self
._viewEOLCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewEOL", False))
835 self
._viewIndentationGuideCheckBox
= wx
.CheckBox(self
, -1, _("Show indentation guides"))
836 self
._viewIndentationGuideCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewIndentationGuides", False))
837 self
._viewRightEdgeCheckBox
= wx
.CheckBox(self
, -1, _("Show right edge"))
838 self
._viewRightEdgeCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewRightEdge", False))
839 self
._viewLineNumbersCheckBox
= wx
.CheckBox(self
, -1, _("Show line numbers"))
840 self
._viewLineNumbersCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewLineNumbers", True))
842 self
._hasTabsCheckBox
= wx
.CheckBox(self
, -1, _("Use spaces instead of tabs"))
843 self
._hasTabsCheckBox
.SetValue(not wx
.ConfigBase_Get().ReadInt(self
._configPrefix
+ "EditorUseTabs", False))
844 indentWidthLabel
= wx
.StaticText(self
, -1, _("Indent Width:"))
845 self
._indentWidthChoice
= wx
.Choice(self
, -1, choices
= ["2", "4", "6", "8", "10"])
846 self
._indentWidthChoice
.SetStringSelection(str(config
.ReadInt(self
._configPrefix
+ "EditorIndentWidth", 4)))
847 textPanelBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
848 textPanelSizer
= wx
.BoxSizer(wx
.VERTICAL
)
849 textFontSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
850 textFontSizer
.Add(fontLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
)
851 textFontSizer
.Add(self
._sampleTextCtrl
, 0, wx
.ALIGN_LEFT | wx
.EXPAND | wx
.RIGHT
, HALF_SPACE
)
852 textFontSizer
.Add(chooseFontButton
, 0, wx
.ALIGN_RIGHT | wx
.LEFT
, HALF_SPACE
)
853 textPanelSizer
.Add(textFontSizer
, 0, wx
.ALL
, HALF_SPACE
)
854 if self
._hasWordWrap
:
855 textPanelSizer
.Add(self
._wordWrapCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
856 textPanelSizer
.Add(self
._viewWhitespaceCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
857 textPanelSizer
.Add(self
._viewEOLCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
858 textPanelSizer
.Add(self
._viewIndentationGuideCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
859 textPanelSizer
.Add(self
._viewRightEdgeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
860 textPanelSizer
.Add(self
._viewLineNumbersCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
862 textPanelSizer
.Add(self
._hasTabsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
863 textIndentWidthSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
864 textIndentWidthSizer
.Add(indentWidthLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
)
865 textIndentWidthSizer
.Add(self
._indentWidthChoice
, 0, wx
.ALIGN_LEFT | wx
.EXPAND
, HALF_SPACE
)
866 textPanelSizer
.Add(textIndentWidthSizer
, 0, wx
.ALL
, HALF_SPACE
)
867 textPanelBorderSizer
.Add(textPanelSizer
, 0, wx
.ALL
, SPACE
)
868 ## styleButton = wx.Button(self, -1, _("Choose Style..."))
869 ## wx.EVT_BUTTON(self, styleButton.GetId(), self.OnChooseStyle)
870 ## textPanelBorderSizer.Add(styleButton, 0, wx.ALL, SPACE)
871 self
.SetSizer(textPanelBorderSizer
)
872 self
.UpdateSampleFont()
874 parent
.AddPage(self
, _(label
))
876 def UpdateSampleFont(self
):
877 nativeFont
= wx
.NativeFontInfo()
878 nativeFont
.FromString(self
._textFont
.GetNativeFontInfoDesc())
880 font
.SetNativeFontInfo(nativeFont
)
881 font
.SetPointSize(self
._sampleTextCtrl
.GetFont().GetPointSize()) # Use the standard point size
882 self
._sampleTextCtrl
.SetFont(font
)
883 self
._sampleTextCtrl
.SetForegroundColour(self
._textColor
)
884 self
._sampleTextCtrl
.SetValue(str(self
._textFont
.GetPointSize()) + _(" pt. ") + self
._textFont
.GetFaceName())
885 self
._sampleTextCtrl
.Refresh()
889 ## def OnChooseStyle(self, event):
890 ## import STCStyleEditor
892 ## base = os.path.split(__file__)[0]
893 ## config = os.path.abspath(os.path.join(base, 'stc-styles.rc.cfg'))
895 ## dlg = STCStyleEditor.STCStyleEditDlg(None,
896 ## 'Python', 'python',
906 def OnChooseFont(self
, event
):
908 data
.EnableEffects(True)
909 data
.SetInitialFont(self
._textFont
)
910 data
.SetColour(self
._textColor
)
911 fontDialog
= wx
.FontDialog(self
, data
)
912 if fontDialog
.ShowModal() == wx
.ID_OK
:
913 data
= fontDialog
.GetFontData()
914 self
._textFont
= data
.GetChosenFont()
915 self
._textColor
= data
.GetColour()
916 self
.UpdateSampleFont()
920 def OnOK(self
, optionsDialog
):
921 config
= wx
.ConfigBase_Get()
922 doViewStuffUpdate
= config
.ReadInt(self
._configPrefix
+ "EditorViewWhitespace", False) != self
._viewWhitespaceCheckBox
.GetValue()
923 config
.WriteInt(self
._configPrefix
+ "EditorViewWhitespace", self
._viewWhitespaceCheckBox
.GetValue())
924 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewEOL", False) != self
._viewEOLCheckBox
.GetValue()
925 config
.WriteInt(self
._configPrefix
+ "EditorViewEOL", self
._viewEOLCheckBox
.GetValue())
926 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewIndentationGuides", False) != self
._viewIndentationGuideCheckBox
.GetValue()
927 config
.WriteInt(self
._configPrefix
+ "EditorViewIndentationGuides", self
._viewIndentationGuideCheckBox
.GetValue())
928 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewRightEdge", False) != self
._viewRightEdgeCheckBox
.GetValue()
929 config
.WriteInt(self
._configPrefix
+ "EditorViewRightEdge", self
._viewRightEdgeCheckBox
.GetValue())
930 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewLineNumbers", True) != self
._viewLineNumbersCheckBox
.GetValue()
931 config
.WriteInt(self
._configPrefix
+ "EditorViewLineNumbers", self
._viewLineNumbersCheckBox
.GetValue())
932 if self
._hasWordWrap
:
933 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorWordWrap", False) != self
._wordWrapCheckBox
.GetValue()
934 config
.WriteInt(self
._configPrefix
+ "EditorWordWrap", self
._wordWrapCheckBox
.GetValue())
936 doViewStuffUpdate
= doViewStuffUpdate
or not config
.ReadInt(self
._configPrefix
+ "EditorUseTabs", True) != self
._hasTabsCheckBox
.GetValue()
937 config
.WriteInt(self
._configPrefix
+ "EditorUseTabs", not self
._hasTabsCheckBox
.GetValue())
938 newIndentWidth
= int(self
._indentWidthChoice
.GetStringSelection())
939 oldIndentWidth
= config
.ReadInt(self
._configPrefix
+ "EditorIndentWidth", 4)
940 if newIndentWidth
!= oldIndentWidth
:
941 doViewStuffUpdate
= True
942 config
.WriteInt(self
._configPrefix
+ "EditorIndentWidth", newIndentWidth
)
943 doFontUpdate
= self
._originalTextFont
!= self
._textFont
or self
._originalTextColor
!= self
._textColor
944 config
.Write(self
._configPrefix
+ "EditorFont", self
._textFont
.GetNativeFontInfoDesc())
945 config
.Write(self
._configPrefix
+ "EditorColor", "%02x%02x%02x" % (self
._textColor
.Red(), self
._textColor
.Green(), self
._textColor
.Blue()))
946 if doViewStuffUpdate
or doFontUpdate
:
947 for document
in optionsDialog
.GetDocManager().GetDocuments():
948 if issubclass(document
.GetDocumentTemplate().GetDocumentType(), TextDocument
):
949 if doViewStuffUpdate
:
950 document
.UpdateAllViews(hint
= "ViewStuff")
952 document
.UpdateAllViews(hint
= "Font")
955 class TextCtrl(wx
.stc
.StyledTextCtrl
):
957 def __init__(self
, parent
, ID
= -1, style
= wx
.NO_FULL_REPAINT_ON_RESIZE
):
960 wx
.stc
.StyledTextCtrl
.__init
__(self
, parent
, ID
, style
= style
)
963 self
._fontColor
= None
965 self
.SetVisiblePolicy(wx
.stc
.STC_VISIBLE_STRICT
,1)
967 self
.CmdKeyClear(wx
.stc
.STC_KEY_ADD
, wx
.stc
.STC_SCMOD_CTRL
)
968 self
.CmdKeyClear(wx
.stc
.STC_KEY_SUBTRACT
, wx
.stc
.STC_SCMOD_CTRL
)
969 self
.CmdKeyAssign(wx
.stc
.STC_KEY_PRIOR
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMIN
)
970 self
.CmdKeyAssign(wx
.stc
.STC_KEY_NEXT
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMOUT
)
971 self
.Bind(wx
.stc
.EVT_STC_ZOOM
, self
.OnUpdateLineNumberMarginWidth
) # auto update line num width on zoom
972 wx
.EVT_KEY_DOWN(self
, self
.OnKeyPressed
)
979 self
.SetViewWhiteSpace(False)
980 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
981 self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
)
982 self
.SetEdgeColumn(78)
984 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
985 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
988 self
.SetCaretForeground("BLACK")
990 self
.SetViewDefaults()
991 font
, color
= self
.GetFontAndColorFromConfig()
993 self
.SetFontColor(color
)
994 self
.MarkerDefineDefault()
996 # for multisash initialization
997 if isinstance(parent
, wx
.lib
.multisash
.MultiClient
):
998 while parent
.GetParent():
999 parent
= parent
.GetParent()
1000 if hasattr(parent
, "GetView"):
1002 if hasattr(parent
, "GetView"):
1003 textEditor
= parent
.GetView()._textEditor
1005 doc
= textEditor
.GetDocPointer()
1007 self
.SetDocPointer(doc
)
1011 def SetViewDefaults(self
, configPrefix
= "Text", hasWordWrap
= True, hasTabs
= False):
1012 config
= wx
.ConfigBase_Get()
1013 self
.SetViewWhiteSpace(config
.ReadInt(configPrefix
+ "EditorViewWhitespace", False))
1014 self
.SetViewEOL(config
.ReadInt(configPrefix
+ "EditorViewEOL", False))
1015 self
.SetIndentationGuides(config
.ReadInt(configPrefix
+ "EditorViewIndentationGuides", False))
1016 self
.SetViewRightEdge(config
.ReadInt(configPrefix
+ "EditorViewRightEdge", False))
1017 self
.SetViewLineNumbers(config
.ReadInt(configPrefix
+ "EditorViewLineNumbers", True))
1019 self
.SetWordWrap(config
.ReadInt(configPrefix
+ "EditorWordWrap", False))
1020 if hasTabs
: # These methods do not exist in STCTextEditor and are meant for subclasses
1021 self
.SetUseTabs(config
.ReadInt(configPrefix
+ "EditorUseTabs", False))
1022 self
.SetIndent(config
.ReadInt(configPrefix
+ "EditorIndentWidth", 4))
1023 self
.SetTabWidth(config
.ReadInt(configPrefix
+ "EditorIndentWidth", 4))
1025 self
.SetUseTabs(True)
1031 def GetDefaultFont(self
):
1032 """ Subclasses should override this """
1033 return wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
)
1036 def GetDefaultColor(self
):
1037 """ Subclasses should override this """
1041 def GetFontAndColorFromConfig(self
, configPrefix
= "Text"):
1042 font
= self
.GetDefaultFont()
1043 config
= wx
.ConfigBase_Get()
1044 fontData
= config
.Read(configPrefix
+ "EditorFont", "")
1046 nativeFont
= wx
.NativeFontInfo()
1047 nativeFont
.FromString(fontData
)
1048 font
.SetNativeFontInfo(nativeFont
)
1049 color
= self
.GetDefaultColor()
1050 colorData
= config
.Read(configPrefix
+ "EditorColor", "")
1052 red
= int("0x" + colorData
[0:2], 16)
1053 green
= int("0x" + colorData
[2:4], 16)
1054 blue
= int("0x" + colorData
[4:6], 16)
1055 color
= wx
.Color(red
, green
, blue
)
1062 def SetFont(self
, font
):
1064 self
.StyleSetFont(wx
.stc
.STC_STYLE_DEFAULT
, self
._font
)
1067 def GetFontColor(self
):
1068 return self
._fontColor
1071 def SetFontColor(self
, fontColor
= wx
.BLACK
):
1072 self
._fontColor
= fontColor
1073 self
.StyleSetForeground(wx
.stc
.STC_STYLE_DEFAULT
, "#%02x%02x%02x" % (self
._fontColor
.Red(), self
._fontColor
.Green(), self
._fontColor
.Blue()))
1076 def UpdateStyles(self
):
1077 self
.StyleClearAll()
1081 def EstimatedLineNumberMarginWidth(self
):
1084 lineNum
= self
.GetLineCount()
1085 lineNum
= lineNum
/100
1086 while lineNum
>= 10:
1087 lineNum
= lineNum
/10
1088 baseNumbers
= baseNumbers
+ "0"
1090 return self
.TextWidth(wx
.stc
.STC_STYLE_LINENUMBER
, baseNumbers
) + MARGIN
1093 def OnUpdateLineNumberMarginWidth(self
, event
):
1094 self
.UpdateLineNumberMarginWidth()
1097 def UpdateLineNumberMarginWidth(self
):
1098 if self
.GetViewLineNumbers():
1099 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
1101 def MarkerDefineDefault(self
):
1102 """ This must be called after the textcontrol is instantiated """
1103 self
.MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_ROUNDRECT
, wx
.BLACK
, wx
.BLUE
)
1107 # Used when Delete key is hit.
1108 sel
= self
.GetSelection()
1110 # Delete the selection or if no selection, the character after the caret.
1111 if sel
[0] == sel
[1]:
1112 self
.SetSelection(sel
[0], sel
[0] + 1)
1114 # remove any folded lines also.
1115 startLine
= self
.LineFromPosition(sel
[0])
1116 endLine
= self
.LineFromPosition(sel
[1])
1117 endLineStart
= self
.PositionFromLine(endLine
)
1118 if startLine
!= endLine
and sel
[1] - endLineStart
== 0:
1119 while not self
.GetLineVisible(endLine
):
1121 self
.SetSelectionEnd(self
.PositionFromLine(endLine
))
1127 # replace any folded lines also.
1128 sel
= self
.GetSelection()
1129 startLine
= self
.LineFromPosition(sel
[0])
1130 endLine
= self
.LineFromPosition(sel
[1])
1131 endLineStart
= self
.PositionFromLine(endLine
)
1132 if startLine
!= endLine
and sel
[1] - endLineStart
== 0:
1133 while not self
.GetLineVisible(endLine
):
1135 self
.SetSelectionEnd(self
.PositionFromLine(endLine
))
1140 def OnKeyPressed(self
, event
):
1141 key
= event
.GetKeyCode()
1142 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
1143 if event
.ControlDown():
1144 self
.ToggleFoldAll(expand
= True, topLevelOnly
= True)
1145 elif event
.ShiftDown():
1146 self
.ToggleFoldAll(expand
= True)
1148 self
.ToggleFold(self
.GetCurrentLine())
1149 elif key
== wx
.WXK_NUMPAD_SUBTRACT
:
1150 if event
.ControlDown():
1151 self
.ToggleFoldAll(expand
= False, topLevelOnly
= True)
1152 elif event
.ShiftDown():
1153 self
.ToggleFoldAll(expand
= False)
1155 self
.ToggleFold(self
.GetCurrentLine())
1160 #----------------------------------------------------------------------------
1162 #----------------------------------------------------------------------------
1164 def GetViewRightEdge(self
):
1165 return self
.GetEdgeMode() != wx
.stc
.STC_EDGE_NONE
1168 def SetViewRightEdge(self
, viewRightEdge
):
1170 self
.SetEdgeMode(wx
.stc
.STC_EDGE_LINE
)
1172 self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
)
1175 def GetViewLineNumbers(self
):
1176 return self
.GetMarginWidth(1) > 0
1179 def SetViewLineNumbers(self
, viewLineNumbers
= True):
1181 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
1183 self
.SetMarginWidth(1, 0)
1186 def CanWordWrap(self
):
1190 def GetWordWrap(self
):
1191 return self
.GetWrapMode() == wx
.stc
.STC_WRAP_WORD
1194 def SetWordWrap(self
, wordWrap
):
1196 self
.SetWrapMode(wx
.stc
.STC_WRAP_WORD
)
1198 self
.SetWrapMode(wx
.stc
.STC_WRAP_NONE
)
1201 #----------------------------------------------------------------------------
1202 # Icon Bitmaps - generated by encode_bitmaps.py
1203 #----------------------------------------------------------------------------
1204 from wx
import ImageFromStream
, BitmapFromImage
1210 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1211 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1212 \x00\x00`IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\xa7JU!$\x12\x1d\
1213 \xeb\t\t8n\x81\xb4\x86J\xfa]h\x0ee\x83\xb4\xc6\x14\x00\x00R\xcc \t\xcd\xa1\
1214 \x08\xd2\xa3\xe1\x08*\t$\x1d\xc4\x012\x0b\x00\xce\xe4\xc8\xe0\t}\xf7\x8f\rV\
1215 \xd9\x1a\xec\xe0\xbf\xc1\xd7\x06\xd9\xf5UX\xfdF+m\x03\xb8\x00\xe4\xc74B"x\
1216 \xf1\xf4\x00\x00\x00\x00IEND\xaeB`\x82'
1219 def getTextBitmap():
1220 return BitmapFromImage(getTextImage())
1223 stream
= cStringIO
.StringIO(getTextData())
1224 return ImageFromStream(stream
)
1227 return wx
.IconFromBitmap(getTextBitmap())
1230 #----------------------------------------------------------------------------
1231 # Menu Bitmaps - generated by encode_bitmaps.py
1232 #----------------------------------------------------------------------------
1233 #----------------------------------------------------------------------
1234 def getZoomInData():
1236 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1237 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1238 \x00\x00wIDAT8\x8d\xa5\x93Q\x12\x80 \x08D\xb5\xe9X\xee\xe9\xb7{\xd5Gc\xa9\
1239 \xacX\xca\x1f\xa0\x8fE0\x92<\xc3\x82\xed*\x08\xa0\xf2I~\x07\x000\x17T,\xdb\
1240 \xd6;\x08\xa4\x00\xa4GA\xab\xca\x00\xbc*\x1eD\xb4\x90\xa4O\x1e\xe3\x16f\xcc(\
1241 \xc8\x95F\x95\x8d\x02\xef\xa1n\xa0\xce\xc5v\x91zc\xacU\xbey\x03\xf0.\xa8\xb8\
1242 \x04\x8c\xac\x04MM\xa1lA\xfe\x85?\x90\xe5=X\x06\\\xebCA\xb3Q\xf34\x14\x00\
1243 \x00\x00\x00IEND\xaeB`\x82'
1245 def getZoomInBitmap():
1246 return BitmapFromImage(getZoomInImage())
1248 def getZoomInImage():
1249 stream
= cStringIO
.StringIO(getZoomInData())
1250 return ImageFromStream(stream
)
1252 #----------------------------------------------------------------------
1253 def getZoomOutData():
1255 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1256 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1257 \x00\x00qIDAT8\x8d\xa5\x92Q\x0e\xc0 \x08C-z\xff\x13O\xd9\xd7\x16"\x05\x8d\
1258 \xf6O\xa2\x8f"\x05\xa4\x96\x1b5V\xd4\xd1\xd5\x9e!\x15\xdb\x00\x1d]\xe7\x07\
1259 \xac\xf6Iv.B*fW\x0e\x90u\xc9 d\x84\x87v\x82\xb4\xf5\x08\'r\x0e\xa2N\x91~\x07\
1260 \xd9G\x95\xe2W\xeb\x00\x19\xc4\xd6\\FX\x12\xa3 \xb1:\x05\xacdAG[\xb0y9r`u\
1261 \x9d\x83k\xc0\x0b#3@0A\x0c"\x93\x00\x00\x00\x00IEND\xaeB`\x82'
1264 def getZoomOutBitmap():
1265 return BitmapFromImage(getZoomOutImage())
1267 def getZoomOutImage():
1268 stream
= cStringIO
.StringIO(getZoomOutData())
1269 return ImageFromStream(stream
)