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
:
199 wx
.CallAfter(self
.SetFocus
)
204 self
.GetCtrl().SetFocus()
207 def OnClose(self
, deleteWindow
= True):
208 if not wx
.lib
.docview
.View
.OnClose(self
, deleteWindow
):
211 if deleteWindow
and self
.GetFrame():
212 self
.GetFrame().Destroy()
216 def ProcessEvent(self
, event
):
219 self
.GetCtrl().Undo()
221 elif id == wx
.ID_REDO
:
222 self
.GetCtrl().Redo()
224 elif id == wx
.ID_CUT
:
227 elif id == wx
.ID_COPY
:
228 self
.GetCtrl().Copy()
230 elif id == wx
.ID_PASTE
:
231 self
.GetCtrl().OnPaste()
233 elif id == wx
.ID_CLEAR
:
234 self
.GetCtrl().OnClear()
236 elif id == wx
.ID_SELECTALL
:
237 self
.GetCtrl().SetSelection(0, -1)
239 elif id == VIEW_WHITESPACE_ID
:
240 self
.GetCtrl().SetViewWhiteSpace(not self
.GetCtrl().GetViewWhiteSpace())
242 elif id == VIEW_EOL_ID
:
243 self
.GetCtrl().SetViewEOL(not self
.GetCtrl().GetViewEOL())
245 elif id == VIEW_INDENTATION_GUIDES_ID
:
246 self
.GetCtrl().SetViewIndentationGuides(not self
.GetCtrl().GetViewIndentationGuides())
248 elif id == VIEW_RIGHT_EDGE_ID
:
249 self
.GetCtrl().SetViewRightEdge(not self
.GetCtrl().GetViewRightEdge())
251 elif id == VIEW_LINE_NUMBERS_ID
:
252 self
.GetCtrl().SetViewLineNumbers(not self
.GetCtrl().GetViewLineNumbers())
254 elif id == ZOOM_NORMAL_ID
:
255 self
.GetCtrl().SetZoom(0)
257 elif id == ZOOM_IN_ID
:
258 self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMIN
)
260 elif id == ZOOM_OUT_ID
:
261 self
.GetCtrl().CmdKeyExecute(wx
.stc
.STC_CMD_ZOOMOUT
)
263 elif id == CHOOSE_FONT_ID
:
266 elif id == WORD_WRAP_ID
:
267 self
.GetCtrl().SetWordWrap(not self
.GetCtrl().GetWordWrap())
269 elif id == FindService
.FindService
.FIND_ID
:
272 elif id == FindService
.FindService
.FIND_PREVIOUS_ID
:
273 self
.DoFind(forceFindPrevious
= True)
275 elif id == FindService
.FindService
.FIND_NEXT_ID
:
276 self
.DoFind(forceFindNext
= True)
278 elif id == FindService
.FindService
.REPLACE_ID
:
279 self
.OnFind(replace
= True)
281 elif id == FindService
.FindService
.FINDONE_ID
:
284 elif id == FindService
.FindService
.REPLACEONE_ID
:
285 self
.DoFind(replace
= True)
287 elif id == FindService
.FindService
.REPLACEALL_ID
:
288 self
.DoFind(replaceAll
= True)
290 elif id == FindService
.FindService
.GOTO_LINE_ID
:
291 self
.OnGotoLine(event
)
294 return wx
.lib
.docview
.View
.ProcessEvent(self
, event
)
297 def ProcessUpdateUIEvent(self
, event
):
298 if not self
.GetCtrl():
303 event
.Enable(self
.GetCtrl().CanUndo())
304 event
.SetText(_("Undo") + '\t' + _('Ctrl+Z'))
306 elif id == wx
.ID_REDO
:
307 event
.Enable(self
.GetCtrl().CanRedo())
308 event
.SetText(_("Redo") + '\t' + _('Ctrl+Y'))
310 elif (id == wx
.ID_CUT
312 or id == wx
.ID_CLEAR
):
313 hasSelection
= self
.GetCtrl().GetSelectionStart() != self
.GetCtrl().GetSelectionEnd()
314 event
.Enable(hasSelection
)
316 elif id == wx
.ID_PASTE
:
317 event
.Enable(self
.GetCtrl().CanPaste())
319 elif id == wx
.ID_SELECTALL
:
320 hasText
= self
.GetCtrl().GetTextLength() > 0
321 event
.Enable(hasText
)
326 elif id == VIEW_WHITESPACE_ID
:
327 hasText
= self
.GetCtrl().GetTextLength() > 0
328 event
.Enable(hasText
)
329 event
.Check(self
.GetCtrl().GetViewWhiteSpace())
331 elif id == VIEW_EOL_ID
:
332 hasText
= self
.GetCtrl().GetTextLength() > 0
333 event
.Enable(hasText
)
334 event
.Check(self
.GetCtrl().GetViewEOL())
336 elif id == VIEW_INDENTATION_GUIDES_ID
:
337 hasText
= self
.GetCtrl().GetTextLength() > 0
338 event
.Enable(hasText
)
339 event
.Check(self
.GetCtrl().GetIndentationGuides())
341 elif id == VIEW_RIGHT_EDGE_ID
:
342 hasText
= self
.GetCtrl().GetTextLength() > 0
343 event
.Enable(hasText
)
344 event
.Check(self
.GetCtrl().GetViewRightEdge())
346 elif id == VIEW_LINE_NUMBERS_ID
:
347 hasText
= self
.GetCtrl().GetTextLength() > 0
348 event
.Enable(hasText
)
349 event
.Check(self
.GetCtrl().GetViewLineNumbers())
354 elif id == ZOOM_NORMAL_ID
:
355 event
.Enable(self
.GetCtrl().GetZoom() != 0)
357 elif id == ZOOM_IN_ID
:
358 event
.Enable(self
.GetCtrl().GetZoom() < 20)
360 elif id == ZOOM_OUT_ID
:
361 event
.Enable(self
.GetCtrl().GetZoom() > -10)
363 elif id == CHOOSE_FONT_ID
:
366 elif id == WORD_WRAP_ID
:
367 event
.Enable(self
.GetCtrl().CanWordWrap())
368 event
.Check(self
.GetCtrl().CanWordWrap() and self
.GetCtrl().GetWordWrap())
370 elif id == FindService
.FindService
.FIND_ID
:
371 hasText
= self
.GetCtrl().GetTextLength() > 0
372 event
.Enable(hasText
)
374 elif id == FindService
.FindService
.FIND_PREVIOUS_ID
:
375 hasText
= self
.GetCtrl().GetTextLength() > 0
376 event
.Enable(hasText
and
377 self
._FindServiceHasString
() and
378 self
.GetCtrl().GetSelection()[0] > 0)
380 elif id == FindService
.FindService
.FIND_NEXT_ID
:
381 hasText
= self
.GetCtrl().GetTextLength() > 0
382 event
.Enable(hasText
and
383 self
._FindServiceHasString
() and
384 self
.GetCtrl().GetSelection()[0] < self
.GetCtrl().GetLength())
386 elif id == FindService
.FindService
.REPLACE_ID
:
387 hasText
= self
.GetCtrl().GetTextLength() > 0
388 event
.Enable(hasText
)
390 elif id == FindService
.FindService
.GOTO_LINE_ID
:
393 elif id == TEXT_STATUS_BAR_ID
:
394 self
.OnUpdateStatusBar(event
)
397 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
400 def _GetParentFrame(self
):
401 return wx
.GetTopLevelParent(self
.GetFrame())
404 #----------------------------------------------------------------------------
405 # Methods for TextDocument to call
406 #----------------------------------------------------------------------------
408 def IsModified(self
):
409 if not self
.GetCtrl():
411 return self
.GetCtrl().GetModify()
414 def SetModifyFalse(self
):
415 self
.GetCtrl().SetSavePoint()
420 return self
.GetCtrl().GetText()
425 def SetValue(self
, value
):
426 self
.GetCtrl().SetText(value
)
427 self
.GetCtrl().UpdateLineNumberMarginWidth()
428 self
.GetCtrl().EmptyUndoBuffer()
431 #----------------------------------------------------------------------------
433 #----------------------------------------------------------------------------
435 def OnUpdateStatusBar(self
, event
):
436 statusBar
= self
._GetParentFrame
().GetStatusBar()
437 statusBar
.SetInsertMode(self
.GetCtrl().GetOvertype() == 0)
438 statusBar
.SetLineNumber(self
.GetCtrl().GetCurrentLine() + 1)
439 statusBar
.SetColumnNumber(self
.GetCtrl().GetColumn(self
.GetCtrl().GetCurrentPos()) + 1)
442 #----------------------------------------------------------------------------
444 #----------------------------------------------------------------------------
446 def OnChooseFont(self
):
448 data
.EnableEffects(True)
449 data
.SetInitialFont(self
.GetCtrl().GetFont())
450 data
.SetColour(self
.GetCtrl().GetFontColor())
451 fontDialog
= wx
.FontDialog(self
.GetFrame(), data
)
452 if fontDialog
.ShowModal() == wx
.ID_OK
:
453 data
= fontDialog
.GetFontData()
454 self
.GetCtrl().SetFont(data
.GetChosenFont())
455 self
.GetCtrl().SetFontColor(data
.GetColour())
456 self
.GetCtrl().UpdateStyles()
460 #----------------------------------------------------------------------------
462 #----------------------------------------------------------------------------
464 def OnFind(self
, replace
= False):
465 findService
= wx
.GetApp().GetService(FindService
.FindService
)
467 findService
.ShowFindReplaceDialog(findString
= self
.GetCtrl().GetSelectedText(), replace
= replace
)
470 def DoFind(self
, forceFindNext
= False, forceFindPrevious
= False, replace
= False, replaceAll
= False):
471 findService
= wx
.GetApp().GetService(FindService
.FindService
)
474 findString
= findService
.GetFindString()
475 if len(findString
) == 0:
477 replaceString
= findService
.GetReplaceString()
478 flags
= findService
.GetFlags()
479 startLoc
, endLoc
= self
.GetCtrl().GetSelection()
481 wholeWord
= flags
& wx
.FR_WHOLEWORD
> 0
482 matchCase
= flags
& wx
.FR_MATCHCASE
> 0
483 regExp
= flags
& FindService
.FindService
.FR_REGEXP
> 0
484 down
= flags
& wx
.FR_DOWN
> 0
485 wrap
= flags
& FindService
.FindService
.FR_WRAP
> 0
487 if forceFindPrevious
: # this is from function keys, not dialog box
489 wrap
= False # user would want to know they're at the end of file
492 wrap
= False # user would want to know they're at the end of file
496 # On replace dialog operations, user is allowed to replace the currently highlighted text to determine if it should be replaced or not.
497 # 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.
498 # If the text is a match, then replace it.
500 result
, start
, end
, replText
= findService
.DoFind(findString
, replaceString
, self
.GetCtrl().GetSelectedText(), 0, 0, True, matchCase
, wholeWord
, regExp
, replace
)
502 self
.GetCtrl().ReplaceSelection(replText
)
503 self
.GetDocument().Modify(True)
504 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
)
506 startLoc
+= len(replText
) # advance start location past replacement string to new text
508 elif result
== FindService
.FIND_SYNTAXERROR
:
510 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
)
513 text
= self
.GetCtrl().GetText()
515 # Find the next matching text occurance or if it is a ReplaceAll, replace all occurances
516 # 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
517 result
, start
, end
, text
= findService
.DoFind(findString
, replaceString
, text
, startLoc
, endLoc
, down
, matchCase
, wholeWord
, regExp
, False, replaceAll
, wrap
)
519 self
.GetCtrl().SetTargetStart(0)
520 self
.GetCtrl().SetTargetEnd(self
.GetCtrl().GetLength())
521 self
.GetCtrl().ReplaceTarget(text
) # Doing a SetText causes a clear document to be shown when undoing, so using replacetarget instead
522 self
.GetDocument().Modify(True)
524 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
)
526 wx
.GetApp().GetTopWindow().PushStatusText(_("%i occurrences of \"%s\" replaced") % (result
, findString
))
528 self
.GetCtrl().SetSelection(start
, end
)
529 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(end
)) # show bottom then scroll up to top
530 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(start
)) # do this after ensuring bottom is visible
531 wx
.GetApp().GetTopWindow().PushStatusText(_("Found \"%s\".") % findString
)
532 elif result
== FindService
.FIND_SYNTAXERROR
:
533 # Dialog for this case gets popped up by the FindService.
534 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
)
536 wx
.MessageBox(_("Can't find \"%s\".") % findString
, "Find",
537 wx
.OK | wx
.ICON_INFORMATION
)
540 def _FindServiceHasString(self
):
541 findService
= wx
.GetApp().GetService(FindService
.FindService
)
542 if not findService
or not findService
.GetFindString():
547 def OnGotoLine(self
, event
):
548 findService
= wx
.GetApp().GetService(FindService
.FindService
)
550 line
= findService
.GetLineNumber(self
.GetDocumentManager().FindSuitableParent())
553 self
.GetCtrl().EnsureVisible(line
)
554 self
.GetCtrl().GotoLine(line
)
557 def GotoLine(self
, lineNum
):
559 lineNum
= lineNum
- 1 # line numbering for editor is 0 based, we are 1 based.
560 self
.GetCtrl().EnsureVisibleEnforcePolicy(lineNum
)
561 self
.GetCtrl().GotoLine(lineNum
)
564 def SetSelection(self
, start
, end
):
565 self
.GetCtrl().SetSelection(start
, end
)
568 def EnsureVisible(self
, line
):
569 self
.GetCtrl().EnsureVisible(line
-1) # line numbering for editor is 0 based, we are 1 based.
571 def EnsureVisibleEnforcePolicy(self
, line
):
572 self
.GetCtrl().EnsureVisibleEnforcePolicy(line
-1) # line numbering for editor is 0 based, we are 1 based.
574 def LineFromPosition(self
, pos
):
575 return self
.GetCtrl().LineFromPosition(pos
)+1 # line numbering for editor is 0 based, we are 1 based.
578 def PositionFromLine(self
, line
):
579 return self
.GetCtrl().PositionFromLine(line
-1) # line numbering for editor is 0 based, we are 1 based.
582 def GetLineEndPosition(self
, line
):
583 return self
.GetCtrl().GetLineEndPosition(line
-1) # line numbering for editor is 0 based, we are 1 based.
586 def GetLine(self
, lineNum
):
587 return self
.GetCtrl().GetLine(lineNum
-1) # line numbering for editor is 0 based, we are 1 based.
589 def MarkerDefine(self
):
590 """ This must be called after the texteditor is instantiated """
591 self
.GetCtrl().MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_CIRCLE
, wx
.BLACK
, wx
.BLUE
)
594 def MarkerToggle(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
596 lineNum
= self
.GetCtrl().GetCurrentLine()
597 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
598 self
.GetCtrl().MarkerDelete(lineNum
, marker_index
)
599 self
._markerCount
-= 1
601 self
.GetCtrl().MarkerAdd(lineNum
, marker_index
)
602 self
._markerCount
+= 1
604 def MarkerAdd(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
606 lineNum
= self
.GetCtrl().GetCurrentLine()
607 self
.GetCtrl().MarkerAdd(lineNum
, marker_index
)
608 self
._markerCount
+= 1
611 def MarkerDelete(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
613 lineNum
= self
.GetCtrl().GetCurrentLine()
614 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
615 self
.GetCtrl().MarkerDelete(lineNum
, marker_index
)
616 self
._markerCount
-= 1
618 def MarkerDeleteAll(self
, marker_num
=MARKER_NUM
):
619 self
.GetCtrl().MarkerDeleteAll(marker_num
)
620 if marker_num
== self
.MARKER_NUM
:
621 self
._markerCount
= 0
624 def MarkerNext(self
, lineNum
= -1):
626 lineNum
= self
.GetCtrl().GetCurrentLine() + 1 # start search below current line
627 foundLine
= self
.GetCtrl().MarkerNext(lineNum
, self
.MARKER_MASK
)
629 # wrap to top of file
630 foundLine
= self
.GetCtrl().MarkerNext(0, self
.MARKER_MASK
)
632 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers"))
635 self
.GotoLine(foundLine
+ 1)
638 def MarkerPrevious(self
, lineNum
= -1):
640 lineNum
= self
.GetCtrl().GetCurrentLine() - 1 # start search above current line
642 lineNum
= self
.GetCtrl().GetLineCount()
644 foundLine
= self
.GetCtrl().MarkerPrevious(lineNum
, self
.MARKER_MASK
)
646 # wrap to bottom of file
647 foundLine
= self
.GetCtrl().MarkerPrevious(self
.GetCtrl().GetLineCount(), self
.MARKER_MASK
)
649 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers"))
652 self
.GotoLine(foundLine
+ 1)
655 def MarkerExists(self
, lineNum
= -1, mask
=MARKER_MASK
):
657 lineNum
= self
.GetCtrl().GetCurrentLine()
658 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
664 def GetMarkerCount(self
):
665 return self
._markerCount
668 class TextService(wx
.lib
.pydocview
.DocService
):
672 wx
.lib
.pydocview
.DocService
.__init
__(self
)
675 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
676 if document
and document
.GetDocumentTemplate().GetDocumentType() != TextDocument
:
678 if not document
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
681 statusBar
= TextStatusBar(frame
, TEXT_STATUS_BAR_ID
)
682 frame
.SetStatusBar(statusBar
)
683 wx
.EVT_UPDATE_UI(frame
, TEXT_STATUS_BAR_ID
, frame
.ProcessUpdateUIEvent
)
685 viewMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View")))
687 viewMenu
.AppendSeparator()
689 textMenu
.AppendCheckItem(VIEW_WHITESPACE_ID
, _("&Whitespace"), _("Shows or hides whitespace"))
690 wx
.EVT_MENU(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessEvent
)
691 wx
.EVT_UPDATE_UI(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessUpdateUIEvent
)
692 textMenu
.AppendCheckItem(VIEW_EOL_ID
, _("&End of Line Markers"), _("Shows or hides indicators at the end of each line"))
693 wx
.EVT_MENU(frame
, VIEW_EOL_ID
, frame
.ProcessEvent
)
694 wx
.EVT_UPDATE_UI(frame
, VIEW_EOL_ID
, frame
.ProcessUpdateUIEvent
)
695 textMenu
.AppendCheckItem(VIEW_INDENTATION_GUIDES_ID
, _("&Indentation Guides"), _("Shows or hides indentations"))
696 wx
.EVT_MENU(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessEvent
)
697 wx
.EVT_UPDATE_UI(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessUpdateUIEvent
)
698 textMenu
.AppendCheckItem(VIEW_RIGHT_EDGE_ID
, _("&Right Edge"), _("Shows or hides the right edge marker"))
699 wx
.EVT_MENU(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessEvent
)
700 wx
.EVT_UPDATE_UI(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessUpdateUIEvent
)
701 textMenu
.AppendCheckItem(VIEW_LINE_NUMBERS_ID
, _("&Line Numbers"), _("Shows or hides the line numbers"))
702 wx
.EVT_MENU(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessEvent
)
703 wx
.EVT_UPDATE_UI(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessUpdateUIEvent
)
705 viewMenu
.AppendMenu(TEXT_ID
, _("&Text"), textMenu
)
706 wx
.EVT_UPDATE_UI(frame
, TEXT_ID
, frame
.ProcessUpdateUIEvent
)
708 isWindows
= (wx
.Platform
== '__WXMSW__')
711 zoomMenu
.Append(ZOOM_NORMAL_ID
, _("Normal Size"), _("Sets the document to its normal size"))
712 wx
.EVT_MENU(frame
, ZOOM_NORMAL_ID
, frame
.ProcessEvent
)
713 wx
.EVT_UPDATE_UI(frame
, ZOOM_NORMAL_ID
, frame
.ProcessUpdateUIEvent
)
715 zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In\tCtrl+Page Up"), _("Zooms the document to a larger size"))
717 zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In"), _("Zooms the document to a larger size"))
718 wx
.EVT_MENU(frame
, ZOOM_IN_ID
, frame
.ProcessEvent
)
719 wx
.EVT_UPDATE_UI(frame
, ZOOM_IN_ID
, frame
.ProcessUpdateUIEvent
)
721 zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out\tCtrl+Page Down"), _("Zooms the document to a smaller size"))
723 zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out"), _("Zooms the document to a smaller size"))
724 wx
.EVT_MENU(frame
, ZOOM_OUT_ID
, frame
.ProcessEvent
)
725 wx
.EVT_UPDATE_UI(frame
, ZOOM_OUT_ID
, frame
.ProcessUpdateUIEvent
)
727 viewMenu
.AppendMenu(ZOOM_ID
, _("&Zoom"), zoomMenu
)
728 wx
.EVT_UPDATE_UI(frame
, ZOOM_ID
, frame
.ProcessUpdateUIEvent
)
730 formatMenuIndex
= menuBar
.FindMenu(_("&Format"))
731 if formatMenuIndex
> -1:
732 formatMenu
= menuBar
.GetMenu(formatMenuIndex
)
734 formatMenu
= wx
.Menu()
735 if not menuBar
.FindItemById(CHOOSE_FONT_ID
):
736 formatMenu
.Append(CHOOSE_FONT_ID
, _("&Font..."), _("Sets the font to use"))
737 wx
.EVT_MENU(frame
, CHOOSE_FONT_ID
, frame
.ProcessEvent
)
738 wx
.EVT_UPDATE_UI(frame
, CHOOSE_FONT_ID
, frame
.ProcessUpdateUIEvent
)
739 if not menuBar
.FindItemById(WORD_WRAP_ID
):
740 formatMenu
.AppendCheckItem(WORD_WRAP_ID
, _("Word Wrap"), _("Wraps text horizontally when checked"))
741 wx
.EVT_MENU(frame
, WORD_WRAP_ID
, frame
.ProcessEvent
)
742 wx
.EVT_UPDATE_UI(frame
, WORD_WRAP_ID
, frame
.ProcessUpdateUIEvent
)
743 if formatMenuIndex
== -1:
744 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
745 menuBar
.Insert(viewMenuIndex
+ 1, formatMenu
, _("&Format"))
747 # wxBug: wxToolBar::GetToolPos doesn't exist, need it to find cut tool and then insert find in front of it.
748 toolBar
.AddSeparator()
749 toolBar
.AddTool(ZOOM_IN_ID
, getZoomInBitmap(), shortHelpString
= _("Zoom In"), longHelpString
= _("Zooms the document to a larger size"))
750 toolBar
.AddTool(ZOOM_OUT_ID
, getZoomOutBitmap(), shortHelpString
= _("Zoom Out"), longHelpString
= _("Zooms the document to a smaller size"))
754 def ProcessUpdateUIEvent(self
, event
):
757 or id == VIEW_WHITESPACE_ID
759 or id == VIEW_INDENTATION_GUIDES_ID
760 or id == VIEW_RIGHT_EDGE_ID
761 or id == VIEW_LINE_NUMBERS_ID
763 or id == ZOOM_NORMAL_ID
766 or id == CHOOSE_FONT_ID
767 or id == WORD_WRAP_ID
):
774 class TextStatusBar(wx
.StatusBar
):
776 # 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
778 def __init__(self
, parent
, id, style
= wx
.ST_SIZEGRIP
, name
= "statusBar"):
779 wx
.StatusBar
.__init
__(self
, parent
, id, style
, name
)
780 self
.SetFieldsCount(4)
781 self
.SetStatusWidths([-1, 50, 50, 55])
783 def SetInsertMode(self
, insert
= True):
788 if self
.GetStatusText(1) != newText
: # wxBug: Need to check if the text has changed, otherwise it flickers under win32
789 self
.SetStatusText(newText
, 1)
791 def SetLineNumber(self
, lineNumber
):
792 newText
= _("Ln %i") % lineNumber
793 if self
.GetStatusText(2) != newText
:
794 self
.SetStatusText(newText
, 2)
796 def SetColumnNumber(self
, colNumber
):
797 newText
= _("Col %i") % colNumber
798 if self
.GetStatusText(3) != newText
:
799 self
.SetStatusText(newText
, 3)
802 class TextOptionsPanel(wx
.Panel
):
805 def __init__(self
, parent
, id, configPrefix
= "Text", label
= "Text", hasWordWrap
= True, hasTabs
= False, addPage
=True):
806 wx
.Panel
.__init
__(self
, parent
, id)
807 self
._configPrefix
= configPrefix
808 self
._hasWordWrap
= hasWordWrap
809 self
._hasTabs
= hasTabs
812 config
= wx
.ConfigBase_Get()
813 self
._textFont
= wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
)
814 fontData
= config
.Read(self
._configPrefix
+ "EditorFont", "")
816 nativeFont
= wx
.NativeFontInfo()
817 nativeFont
.FromString(fontData
)
818 self
._textFont
.SetNativeFontInfo(nativeFont
)
819 self
._originalTextFont
= self
._textFont
820 self
._textColor
= wx
.BLACK
821 colorData
= config
.Read(self
._configPrefix
+ "EditorColor", "")
823 red
= int("0x" + colorData
[0:2], 16)
824 green
= int("0x" + colorData
[2:4], 16)
825 blue
= int("0x" + colorData
[4:6], 16)
826 self
._textColor
= wx
.Color(red
, green
, blue
)
827 self
._originalTextColor
= self
._textColor
828 fontLabel
= wx
.StaticText(self
, -1, _("Font:"))
829 self
._sampleTextCtrl
= wx
.TextCtrl(self
, -1, "", size
= (125, 21))
830 self
._sampleTextCtrl
.SetEditable(False)
831 chooseFontButton
= wx
.Button(self
, -1, _("Choose Font..."))
832 wx
.EVT_BUTTON(self
, chooseFontButton
.GetId(), self
.OnChooseFont
)
833 if self
._hasWordWrap
:
834 self
._wordWrapCheckBox
= wx
.CheckBox(self
, -1, _("Wrap words inside text area"))
835 self
._wordWrapCheckBox
.SetValue(wx
.ConfigBase_Get().ReadInt(self
._configPrefix
+ "EditorWordWrap", False))
836 self
._viewWhitespaceCheckBox
= wx
.CheckBox(self
, -1, _("Show whitespace"))
837 self
._viewWhitespaceCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewWhitespace", False))
838 self
._viewEOLCheckBox
= wx
.CheckBox(self
, -1, _("Show end of line markers"))
839 self
._viewEOLCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewEOL", False))
840 self
._viewIndentationGuideCheckBox
= wx
.CheckBox(self
, -1, _("Show indentation guides"))
841 self
._viewIndentationGuideCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewIndentationGuides", False))
842 self
._viewRightEdgeCheckBox
= wx
.CheckBox(self
, -1, _("Show right edge"))
843 self
._viewRightEdgeCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewRightEdge", False))
844 self
._viewLineNumbersCheckBox
= wx
.CheckBox(self
, -1, _("Show line numbers"))
845 self
._viewLineNumbersCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewLineNumbers", True))
847 self
._hasTabsCheckBox
= wx
.CheckBox(self
, -1, _("Use spaces instead of tabs"))
848 self
._hasTabsCheckBox
.SetValue(not wx
.ConfigBase_Get().ReadInt(self
._configPrefix
+ "EditorUseTabs", False))
849 indentWidthLabel
= wx
.StaticText(self
, -1, _("Indent Width:"))
850 self
._indentWidthChoice
= wx
.Choice(self
, -1, choices
= ["2", "4", "6", "8", "10"])
851 self
._indentWidthChoice
.SetStringSelection(str(config
.ReadInt(self
._configPrefix
+ "EditorIndentWidth", 4)))
852 textPanelBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
853 textPanelSizer
= wx
.BoxSizer(wx
.VERTICAL
)
854 textFontSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
855 textFontSizer
.Add(fontLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
)
856 textFontSizer
.Add(self
._sampleTextCtrl
, 0, wx
.ALIGN_LEFT | wx
.EXPAND | wx
.RIGHT
, HALF_SPACE
)
857 textFontSizer
.Add(chooseFontButton
, 0, wx
.ALIGN_RIGHT | wx
.LEFT
, HALF_SPACE
)
858 textPanelSizer
.Add(textFontSizer
, 0, wx
.ALL
, HALF_SPACE
)
859 if self
._hasWordWrap
:
860 textPanelSizer
.Add(self
._wordWrapCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
861 textPanelSizer
.Add(self
._viewWhitespaceCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
862 textPanelSizer
.Add(self
._viewEOLCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
863 textPanelSizer
.Add(self
._viewIndentationGuideCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
864 textPanelSizer
.Add(self
._viewRightEdgeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
865 textPanelSizer
.Add(self
._viewLineNumbersCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
867 textPanelSizer
.Add(self
._hasTabsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
868 textIndentWidthSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
869 textIndentWidthSizer
.Add(indentWidthLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
)
870 textIndentWidthSizer
.Add(self
._indentWidthChoice
, 0, wx
.ALIGN_LEFT | wx
.EXPAND
, HALF_SPACE
)
871 textPanelSizer
.Add(textIndentWidthSizer
, 0, wx
.ALL
, HALF_SPACE
)
872 textPanelBorderSizer
.Add(textPanelSizer
, 0, wx
.ALL
, SPACE
)
873 ## styleButton = wx.Button(self, -1, _("Choose Style..."))
874 ## wx.EVT_BUTTON(self, styleButton.GetId(), self.OnChooseStyle)
875 ## textPanelBorderSizer.Add(styleButton, 0, wx.ALL, SPACE)
876 self
.SetSizer(textPanelBorderSizer
)
877 self
.UpdateSampleFont()
879 parent
.AddPage(self
, _(label
))
881 def UpdateSampleFont(self
):
882 nativeFont
= wx
.NativeFontInfo()
883 nativeFont
.FromString(self
._textFont
.GetNativeFontInfoDesc())
885 font
.SetNativeFontInfo(nativeFont
)
886 font
.SetPointSize(self
._sampleTextCtrl
.GetFont().GetPointSize()) # Use the standard point size
887 self
._sampleTextCtrl
.SetFont(font
)
888 self
._sampleTextCtrl
.SetForegroundColour(self
._textColor
)
889 self
._sampleTextCtrl
.SetValue(str(self
._textFont
.GetPointSize()) + _(" pt. ") + self
._textFont
.GetFaceName())
890 self
._sampleTextCtrl
.Refresh()
894 ## def OnChooseStyle(self, event):
895 ## import STCStyleEditor
897 ## base = os.path.split(__file__)[0]
898 ## config = os.path.abspath(os.path.join(base, 'stc-styles.rc.cfg'))
900 ## dlg = STCStyleEditor.STCStyleEditDlg(None,
901 ## 'Python', 'python',
911 def OnChooseFont(self
, event
):
913 data
.EnableEffects(True)
914 data
.SetInitialFont(self
._textFont
)
915 data
.SetColour(self
._textColor
)
916 fontDialog
= wx
.FontDialog(self
, data
)
917 if fontDialog
.ShowModal() == wx
.ID_OK
:
918 data
= fontDialog
.GetFontData()
919 self
._textFont
= data
.GetChosenFont()
920 self
._textColor
= data
.GetColour()
921 self
.UpdateSampleFont()
925 def OnOK(self
, optionsDialog
):
926 config
= wx
.ConfigBase_Get()
927 doViewStuffUpdate
= config
.ReadInt(self
._configPrefix
+ "EditorViewWhitespace", False) != self
._viewWhitespaceCheckBox
.GetValue()
928 config
.WriteInt(self
._configPrefix
+ "EditorViewWhitespace", self
._viewWhitespaceCheckBox
.GetValue())
929 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewEOL", False) != self
._viewEOLCheckBox
.GetValue()
930 config
.WriteInt(self
._configPrefix
+ "EditorViewEOL", self
._viewEOLCheckBox
.GetValue())
931 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewIndentationGuides", False) != self
._viewIndentationGuideCheckBox
.GetValue()
932 config
.WriteInt(self
._configPrefix
+ "EditorViewIndentationGuides", self
._viewIndentationGuideCheckBox
.GetValue())
933 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewRightEdge", False) != self
._viewRightEdgeCheckBox
.GetValue()
934 config
.WriteInt(self
._configPrefix
+ "EditorViewRightEdge", self
._viewRightEdgeCheckBox
.GetValue())
935 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewLineNumbers", True) != self
._viewLineNumbersCheckBox
.GetValue()
936 config
.WriteInt(self
._configPrefix
+ "EditorViewLineNumbers", self
._viewLineNumbersCheckBox
.GetValue())
937 if self
._hasWordWrap
:
938 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorWordWrap", False) != self
._wordWrapCheckBox
.GetValue()
939 config
.WriteInt(self
._configPrefix
+ "EditorWordWrap", self
._wordWrapCheckBox
.GetValue())
941 doViewStuffUpdate
= doViewStuffUpdate
or not config
.ReadInt(self
._configPrefix
+ "EditorUseTabs", True) != self
._hasTabsCheckBox
.GetValue()
942 config
.WriteInt(self
._configPrefix
+ "EditorUseTabs", not self
._hasTabsCheckBox
.GetValue())
943 newIndentWidth
= int(self
._indentWidthChoice
.GetStringSelection())
944 oldIndentWidth
= config
.ReadInt(self
._configPrefix
+ "EditorIndentWidth", 4)
945 if newIndentWidth
!= oldIndentWidth
:
946 doViewStuffUpdate
= True
947 config
.WriteInt(self
._configPrefix
+ "EditorIndentWidth", newIndentWidth
)
948 doFontUpdate
= self
._originalTextFont
!= self
._textFont
or self
._originalTextColor
!= self
._textColor
949 config
.Write(self
._configPrefix
+ "EditorFont", self
._textFont
.GetNativeFontInfoDesc())
950 config
.Write(self
._configPrefix
+ "EditorColor", "%02x%02x%02x" % (self
._textColor
.Red(), self
._textColor
.Green(), self
._textColor
.Blue()))
951 if doViewStuffUpdate
or doFontUpdate
:
952 for document
in optionsDialog
.GetDocManager().GetDocuments():
953 if issubclass(document
.GetDocumentTemplate().GetDocumentType(), TextDocument
):
954 if doViewStuffUpdate
:
955 document
.UpdateAllViews(hint
= "ViewStuff")
957 document
.UpdateAllViews(hint
= "Font")
960 class TextCtrl(wx
.stc
.StyledTextCtrl
):
962 def __init__(self
, parent
, ID
= -1, style
= wx
.NO_FULL_REPAINT_ON_RESIZE
):
965 wx
.stc
.StyledTextCtrl
.__init
__(self
, parent
, ID
, style
= style
)
968 self
._fontColor
= None
970 self
.SetVisiblePolicy(wx
.stc
.STC_VISIBLE_STRICT
,1)
972 self
.CmdKeyClear(wx
.stc
.STC_KEY_ADD
, wx
.stc
.STC_SCMOD_CTRL
)
973 self
.CmdKeyClear(wx
.stc
.STC_KEY_SUBTRACT
, wx
.stc
.STC_SCMOD_CTRL
)
974 self
.CmdKeyAssign(wx
.stc
.STC_KEY_PRIOR
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMIN
)
975 self
.CmdKeyAssign(wx
.stc
.STC_KEY_NEXT
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMOUT
)
976 self
.Bind(wx
.stc
.EVT_STC_ZOOM
, self
.OnUpdateLineNumberMarginWidth
) # auto update line num width on zoom
977 wx
.EVT_KEY_DOWN(self
, self
.OnKeyPressed
)
984 self
.SetViewWhiteSpace(False)
985 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
986 self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
)
987 self
.SetEdgeColumn(78)
989 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
990 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
993 self
.SetCaretForeground("BLACK")
995 self
.SetViewDefaults()
996 font
, color
= self
.GetFontAndColorFromConfig()
998 self
.SetFontColor(color
)
999 self
.MarkerDefineDefault()
1001 # for multisash initialization
1002 if isinstance(parent
, wx
.lib
.multisash
.MultiClient
):
1003 while parent
.GetParent():
1004 parent
= parent
.GetParent()
1005 if hasattr(parent
, "GetView"):
1007 if hasattr(parent
, "GetView"):
1008 textEditor
= parent
.GetView()._textEditor
1010 doc
= textEditor
.GetDocPointer()
1012 self
.SetDocPointer(doc
)
1016 def SetViewDefaults(self
, configPrefix
= "Text", hasWordWrap
= True, hasTabs
= False):
1017 config
= wx
.ConfigBase_Get()
1018 self
.SetViewWhiteSpace(config
.ReadInt(configPrefix
+ "EditorViewWhitespace", False))
1019 self
.SetViewEOL(config
.ReadInt(configPrefix
+ "EditorViewEOL", False))
1020 self
.SetIndentationGuides(config
.ReadInt(configPrefix
+ "EditorViewIndentationGuides", False))
1021 self
.SetViewRightEdge(config
.ReadInt(configPrefix
+ "EditorViewRightEdge", False))
1022 self
.SetViewLineNumbers(config
.ReadInt(configPrefix
+ "EditorViewLineNumbers", True))
1024 self
.SetWordWrap(config
.ReadInt(configPrefix
+ "EditorWordWrap", False))
1025 if hasTabs
: # These methods do not exist in STCTextEditor and are meant for subclasses
1026 self
.SetUseTabs(config
.ReadInt(configPrefix
+ "EditorUseTabs", False))
1027 self
.SetIndent(config
.ReadInt(configPrefix
+ "EditorIndentWidth", 4))
1028 self
.SetTabWidth(config
.ReadInt(configPrefix
+ "EditorIndentWidth", 4))
1030 self
.SetUseTabs(True)
1036 def GetDefaultFont(self
):
1037 """ Subclasses should override this """
1038 return wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
)
1041 def GetDefaultColor(self
):
1042 """ Subclasses should override this """
1046 def GetFontAndColorFromConfig(self
, configPrefix
= "Text"):
1047 font
= self
.GetDefaultFont()
1048 config
= wx
.ConfigBase_Get()
1049 fontData
= config
.Read(configPrefix
+ "EditorFont", "")
1051 nativeFont
= wx
.NativeFontInfo()
1052 nativeFont
.FromString(fontData
)
1053 font
.SetNativeFontInfo(nativeFont
)
1054 color
= self
.GetDefaultColor()
1055 colorData
= config
.Read(configPrefix
+ "EditorColor", "")
1057 red
= int("0x" + colorData
[0:2], 16)
1058 green
= int("0x" + colorData
[2:4], 16)
1059 blue
= int("0x" + colorData
[4:6], 16)
1060 color
= wx
.Color(red
, green
, blue
)
1067 def SetFont(self
, font
):
1069 self
.StyleSetFont(wx
.stc
.STC_STYLE_DEFAULT
, self
._font
)
1072 def GetFontColor(self
):
1073 return self
._fontColor
1076 def SetFontColor(self
, fontColor
= wx
.BLACK
):
1077 self
._fontColor
= fontColor
1078 self
.StyleSetForeground(wx
.stc
.STC_STYLE_DEFAULT
, "#%02x%02x%02x" % (self
._fontColor
.Red(), self
._fontColor
.Green(), self
._fontColor
.Blue()))
1081 def UpdateStyles(self
):
1082 self
.StyleClearAll()
1086 def EstimatedLineNumberMarginWidth(self
):
1089 lineNum
= self
.GetLineCount()
1090 lineNum
= lineNum
/100
1091 while lineNum
>= 10:
1092 lineNum
= lineNum
/10
1093 baseNumbers
= baseNumbers
+ "0"
1095 return self
.TextWidth(wx
.stc
.STC_STYLE_LINENUMBER
, baseNumbers
) + MARGIN
1098 def OnUpdateLineNumberMarginWidth(self
, event
):
1099 self
.UpdateLineNumberMarginWidth()
1102 def UpdateLineNumberMarginWidth(self
):
1103 if self
.GetViewLineNumbers():
1104 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
1106 def MarkerDefineDefault(self
):
1107 """ This must be called after the textcontrol is instantiated """
1108 self
.MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_ROUNDRECT
, wx
.BLACK
, wx
.BLUE
)
1112 # Used when Delete key is hit.
1113 sel
= self
.GetSelection()
1115 # Delete the selection or if no selection, the character after the caret.
1116 if sel
[0] == sel
[1]:
1117 self
.SetSelection(sel
[0], sel
[0] + 1)
1119 # remove any folded lines also.
1120 startLine
= self
.LineFromPosition(sel
[0])
1121 endLine
= self
.LineFromPosition(sel
[1])
1122 endLineStart
= self
.PositionFromLine(endLine
)
1123 if startLine
!= endLine
and sel
[1] - endLineStart
== 0:
1124 while not self
.GetLineVisible(endLine
):
1126 self
.SetSelectionEnd(self
.PositionFromLine(endLine
))
1132 # replace any folded lines also.
1133 sel
= self
.GetSelection()
1134 startLine
= self
.LineFromPosition(sel
[0])
1135 endLine
= self
.LineFromPosition(sel
[1])
1136 endLineStart
= self
.PositionFromLine(endLine
)
1137 if startLine
!= endLine
and sel
[1] - endLineStart
== 0:
1138 while not self
.GetLineVisible(endLine
):
1140 self
.SetSelectionEnd(self
.PositionFromLine(endLine
))
1145 def OnKeyPressed(self
, event
):
1146 key
= event
.GetKeyCode()
1147 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
1148 if event
.ControlDown():
1149 self
.ToggleFoldAll(expand
= True, topLevelOnly
= True)
1150 elif event
.ShiftDown():
1151 self
.ToggleFoldAll(expand
= True)
1153 self
.ToggleFold(self
.GetCurrentLine())
1154 elif key
== wx
.WXK_NUMPAD_SUBTRACT
:
1155 if event
.ControlDown():
1156 self
.ToggleFoldAll(expand
= False, topLevelOnly
= True)
1157 elif event
.ShiftDown():
1158 self
.ToggleFoldAll(expand
= False)
1160 self
.ToggleFold(self
.GetCurrentLine())
1165 #----------------------------------------------------------------------------
1167 #----------------------------------------------------------------------------
1169 def GetViewRightEdge(self
):
1170 return self
.GetEdgeMode() != wx
.stc
.STC_EDGE_NONE
1173 def SetViewRightEdge(self
, viewRightEdge
):
1175 self
.SetEdgeMode(wx
.stc
.STC_EDGE_LINE
)
1177 self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
)
1180 def GetViewLineNumbers(self
):
1181 return self
.GetMarginWidth(1) > 0
1184 def SetViewLineNumbers(self
, viewLineNumbers
= True):
1186 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
1188 self
.SetMarginWidth(1, 0)
1191 def CanWordWrap(self
):
1195 def GetWordWrap(self
):
1196 return self
.GetWrapMode() == wx
.stc
.STC_WRAP_WORD
1199 def SetWordWrap(self
, wordWrap
):
1201 self
.SetWrapMode(wx
.stc
.STC_WRAP_WORD
)
1203 self
.SetWrapMode(wx
.stc
.STC_WRAP_NONE
)
1206 #----------------------------------------------------------------------------
1207 # Icon Bitmaps - generated by encode_bitmaps.py
1208 #----------------------------------------------------------------------------
1209 from wx
import ImageFromStream
, BitmapFromImage
1215 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1216 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1217 \x00\x00`IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\xa7JU!$\x12\x1d\
1218 \xeb\t\t8n\x81\xb4\x86J\xfa]h\x0ee\x83\xb4\xc6\x14\x00\x00R\xcc \t\xcd\xa1\
1219 \x08\xd2\xa3\xe1\x08*\t$\x1d\xc4\x012\x0b\x00\xce\xe4\xc8\xe0\t}\xf7\x8f\rV\
1220 \xd9\x1a\xec\xe0\xbf\xc1\xd7\x06\xd9\xf5UX\xfdF+m\x03\xb8\x00\xe4\xc74B"x\
1221 \xf1\xf4\x00\x00\x00\x00IEND\xaeB`\x82'
1224 def getTextBitmap():
1225 return BitmapFromImage(getTextImage())
1228 stream
= cStringIO
.StringIO(getTextData())
1229 return ImageFromStream(stream
)
1232 return wx
.IconFromBitmap(getTextBitmap())
1235 #----------------------------------------------------------------------------
1236 # Menu Bitmaps - generated by encode_bitmaps.py
1237 #----------------------------------------------------------------------------
1238 #----------------------------------------------------------------------
1239 def getZoomInData():
1241 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1242 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1243 \x00\x00wIDAT8\x8d\xa5\x93Q\x12\x80 \x08D\xb5\xe9X\xee\xe9\xb7{\xd5Gc\xa9\
1244 \xacX\xca\x1f\xa0\x8fE0\x92<\xc3\x82\xed*\x08\xa0\xf2I~\x07\x000\x17T,\xdb\
1245 \xd6;\x08\xa4\x00\xa4GA\xab\xca\x00\xbc*\x1eD\xb4\x90\xa4O\x1e\xe3\x16f\xcc(\
1246 \xc8\x95F\x95\x8d\x02\xef\xa1n\xa0\xce\xc5v\x91zc\xacU\xbey\x03\xf0.\xa8\xb8\
1247 \x04\x8c\xac\x04MM\xa1lA\xfe\x85?\x90\xe5=X\x06\\\xebCA\xb3Q\xf34\x14\x00\
1248 \x00\x00\x00IEND\xaeB`\x82'
1250 def getZoomInBitmap():
1251 return BitmapFromImage(getZoomInImage())
1253 def getZoomInImage():
1254 stream
= cStringIO
.StringIO(getZoomInData())
1255 return ImageFromStream(stream
)
1257 #----------------------------------------------------------------------
1258 def getZoomOutData():
1260 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1261 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1262 \x00\x00qIDAT8\x8d\xa5\x92Q\x0e\xc0 \x08C-z\xff\x13O\xd9\xd7\x16"\x05\x8d\
1263 \xf6O\xa2\x8f"\x05\xa4\x96\x1b5V\xd4\xd1\xd5\x9e!\x15\xdb\x00\x1d]\xe7\x07\
1264 \xac\xf6Iv.B*fW\x0e\x90u\xc9 d\x84\x87v\x82\xb4\xf5\x08\'r\x0e\xa2N\x91~\x07\
1265 \xd9G\x95\xe2W\xeb\x00\x19\xc4\xd6\\FX\x12\xa3 \xb1:\x05\xacdAG[\xb0y9r`u\
1266 \x9d\x83k\xc0\x0b#3@0A\x0c"\x93\x00\x00\x00\x00IEND\xaeB`\x82'
1269 def getZoomOutBitmap():
1270 return BitmapFromImage(getZoomOutImage())
1272 def getZoomOutImage():
1273 stream
= cStringIO
.StringIO(getZoomOutData())
1274 return ImageFromStream(stream
)