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():
296 hasSelection
= self
.GetCtrl().GetSelectionStart() != self
.GetCtrl().GetSelectionEnd()
297 hasText
= self
.GetCtrl().GetTextLength() > 0
298 notOnLastChar
= self
.GetCtrl().GetSelectionStart() != self
.GetCtrl().GetTextLength()
302 event
.Enable(self
.GetCtrl().CanUndo())
303 event
.SetText(_("Undo") + '\t' + _('Ctrl+Z'))
305 elif id == wx
.ID_REDO
:
306 event
.Enable(self
.GetCtrl().CanRedo())
307 event
.SetText(_("Redo") + '\t' + _('Ctrl+Y'))
309 elif id == wx
.ID_CUT
:
310 event
.Enable(hasSelection
)
312 elif id == wx
.ID_COPY
:
313 event
.Enable(hasSelection
)
315 elif id == wx
.ID_PASTE
:
316 event
.Enable(self
.GetCtrl().CanPaste())
318 elif id == wx
.ID_CLEAR
:
319 event
.Enable(hasSelection
)
321 elif id == wx
.ID_SELECTALL
:
322 event
.Enable(hasText
)
327 elif id == VIEW_WHITESPACE_ID
:
328 event
.Enable(hasText
)
329 event
.Check(self
.GetCtrl().GetViewWhiteSpace())
331 elif id == VIEW_EOL_ID
:
332 event
.Enable(hasText
)
333 event
.Check(self
.GetCtrl().GetViewEOL())
335 elif id == VIEW_INDENTATION_GUIDES_ID
:
336 event
.Enable(hasText
)
337 event
.Check(self
.GetCtrl().GetIndentationGuides())
339 elif id == VIEW_RIGHT_EDGE_ID
:
340 event
.Enable(hasText
)
341 event
.Check(self
.GetCtrl().GetViewRightEdge())
343 elif id == VIEW_LINE_NUMBERS_ID
:
344 event
.Enable(hasText
)
345 event
.Check(self
.GetCtrl().GetViewLineNumbers())
350 elif id == ZOOM_NORMAL_ID
:
351 event
.Enable(self
.GetCtrl().GetZoom() != 0)
353 elif id == ZOOM_IN_ID
:
354 event
.Enable(self
.GetCtrl().GetZoom() < 20)
356 elif id == ZOOM_OUT_ID
:
357 event
.Enable(self
.GetCtrl().GetZoom() > -10)
359 elif id == CHOOSE_FONT_ID
:
362 elif id == WORD_WRAP_ID
:
363 event
.Enable(self
.GetCtrl().CanWordWrap())
364 event
.Check(self
.GetCtrl().CanWordWrap() and self
.GetCtrl().GetWordWrap())
366 elif id == FindService
.FindService
.FIND_ID
:
367 event
.Enable(hasText
)
369 elif id == FindService
.FindService
.FIND_PREVIOUS_ID
:
370 event
.Enable(hasText
and
371 self
._FindServiceHasString
() and
372 self
.GetCtrl().GetSelection()[0] > 0)
374 elif id == FindService
.FindService
.FIND_NEXT_ID
:
375 event
.Enable(hasText
and
376 self
._FindServiceHasString
() and
377 self
.GetCtrl().GetSelection()[0] < self
.GetCtrl().GetLength())
379 elif id == FindService
.FindService
.REPLACE_ID
:
380 event
.Enable(hasText
)
382 elif id == FindService
.FindService
.GOTO_LINE_ID
:
385 elif id == TEXT_STATUS_BAR_ID
:
386 self
.OnUpdateStatusBar(event
)
389 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
392 def _GetParentFrame(self
):
393 return wx
.GetTopLevelParent(self
.GetFrame())
396 #----------------------------------------------------------------------------
397 # Methods for TextDocument to call
398 #----------------------------------------------------------------------------
400 def IsModified(self
):
401 if not self
.GetCtrl():
403 return self
.GetCtrl().GetModify()
406 def SetModifyFalse(self
):
407 self
.GetCtrl().SetSavePoint()
412 return self
.GetCtrl().GetText()
417 def SetValue(self
, value
):
418 self
.GetCtrl().SetText(value
)
419 self
.GetCtrl().UpdateLineNumberMarginWidth()
420 self
.GetCtrl().EmptyUndoBuffer()
423 #----------------------------------------------------------------------------
425 #----------------------------------------------------------------------------
427 def OnUpdateStatusBar(self
, event
):
428 statusBar
= self
._GetParentFrame
().GetStatusBar()
429 statusBar
.SetInsertMode(self
.GetCtrl().GetOvertype() == 0)
430 statusBar
.SetLineNumber(self
.GetCtrl().GetCurrentLine() + 1)
431 statusBar
.SetColumnNumber(self
.GetCtrl().GetColumn(self
.GetCtrl().GetCurrentPos()) + 1)
434 #----------------------------------------------------------------------------
436 #----------------------------------------------------------------------------
438 def OnChooseFont(self
):
440 data
.EnableEffects(True)
441 data
.SetInitialFont(self
.GetCtrl().GetFont())
442 data
.SetColour(self
.GetCtrl().GetFontColor())
443 fontDialog
= wx
.FontDialog(self
.GetFrame(), data
)
444 if fontDialog
.ShowModal() == wx
.ID_OK
:
445 data
= fontDialog
.GetFontData()
446 self
.GetCtrl().SetFont(data
.GetChosenFont())
447 self
.GetCtrl().SetFontColor(data
.GetColour())
448 self
.GetCtrl().UpdateStyles()
452 #----------------------------------------------------------------------------
454 #----------------------------------------------------------------------------
456 def OnFind(self
, replace
= False):
457 findService
= wx
.GetApp().GetService(FindService
.FindService
)
459 findService
.ShowFindReplaceDialog(findString
= self
.GetCtrl().GetSelectedText(), replace
= replace
)
462 def DoFind(self
, forceFindNext
= False, forceFindPrevious
= False, replace
= False, replaceAll
= False):
463 findService
= wx
.GetApp().GetService(FindService
.FindService
)
466 findString
= findService
.GetFindString()
467 if len(findString
) == 0:
469 replaceString
= findService
.GetReplaceString()
470 flags
= findService
.GetFlags()
471 startLoc
, endLoc
= self
.GetCtrl().GetSelection()
473 wholeWord
= flags
& wx
.FR_WHOLEWORD
> 0
474 matchCase
= flags
& wx
.FR_MATCHCASE
> 0
475 regExp
= flags
& FindService
.FindService
.FR_REGEXP
> 0
476 down
= flags
& wx
.FR_DOWN
> 0
477 wrap
= flags
& FindService
.FindService
.FR_WRAP
> 0
479 if forceFindPrevious
: # this is from function keys, not dialog box
481 wrap
= False # user would want to know they're at the end of file
484 wrap
= False # user would want to know they're at the end of file
488 # On replace dialog operations, user is allowed to replace the currently highlighted text to determine if it should be replaced or not.
489 # 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.
490 # If the text is a match, then replace it.
492 result
, start
, end
, replText
= findService
.DoFind(findString
, replaceString
, self
.GetCtrl().GetSelectedText(), 0, 0, True, matchCase
, wholeWord
, regExp
, replace
)
494 self
.GetCtrl().ReplaceSelection(replText
)
495 self
.GetDocument().Modify(True)
496 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
)
498 startLoc
+= len(replText
) # advance start location past replacement string to new text
500 elif result
== FindService
.FIND_SYNTAXERROR
:
502 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
)
505 text
= self
.GetCtrl().GetText()
507 # Find the next matching text occurance or if it is a ReplaceAll, replace all occurances
508 # 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
509 result
, start
, end
, text
= findService
.DoFind(findString
, replaceString
, text
, startLoc
, endLoc
, down
, matchCase
, wholeWord
, regExp
, False, replaceAll
, wrap
)
511 self
.GetCtrl().SetTargetStart(0)
512 self
.GetCtrl().SetTargetEnd(self
.GetCtrl().GetLength())
513 self
.GetCtrl().ReplaceTarget(text
) # Doing a SetText causes a clear document to be shown when undoing, so using replacetarget instead
514 self
.GetDocument().Modify(True)
516 wx
.GetApp().GetTopWindow().PushStatusText(_("1 occurrence of \"%s\" replaced") % findString
)
518 wx
.GetApp().GetTopWindow().PushStatusText(_("%i occurrences of \"%s\" replaced") % (result
, findString
))
520 self
.GetCtrl().SetSelection(start
, end
)
521 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(end
)) # show bottom then scroll up to top
522 self
.GetCtrl().EnsureVisible(self
.GetCtrl().LineFromPosition(start
)) # do this after ensuring bottom is visible
523 wx
.GetApp().GetTopWindow().PushStatusText(_("Found \"%s\".") % findString
)
524 elif result
== FindService
.FIND_SYNTAXERROR
:
525 # Dialog for this case gets popped up by the FindService.
526 wx
.GetApp().GetTopWindow().PushStatusText(_("Invalid regular expression \"%s\"") % findString
)
528 wx
.MessageBox(_("Can't find \"%s\".") % findString
, "Find",
529 wx
.OK | wx
.ICON_INFORMATION
)
532 def _FindServiceHasString(self
):
533 findService
= wx
.GetApp().GetService(FindService
.FindService
)
534 if not findService
or not findService
.GetFindString():
539 def OnGotoLine(self
, event
):
540 findService
= wx
.GetApp().GetService(FindService
.FindService
)
542 line
= findService
.GetLineNumber(self
.GetDocumentManager().FindSuitableParent())
545 self
.GetCtrl().EnsureVisible(line
)
546 self
.GetCtrl().GotoLine(line
)
549 def GotoLine(self
, lineNum
):
551 lineNum
= lineNum
- 1 # line numbering for editor is 0 based, we are 1 based.
552 self
.GetCtrl().EnsureVisibleEnforcePolicy(lineNum
)
553 self
.GetCtrl().GotoLine(lineNum
)
556 def SetSelection(self
, start
, end
):
557 self
.GetCtrl().SetSelection(start
, end
)
560 def EnsureVisible(self
, line
):
561 self
.GetCtrl().EnsureVisible(line
-1) # line numbering for editor is 0 based, we are 1 based.
563 def EnsureVisibleEnforcePolicy(self
, line
):
564 self
.GetCtrl().EnsureVisibleEnforcePolicy(line
-1) # line numbering for editor is 0 based, we are 1 based.
566 def LineFromPosition(self
, pos
):
567 return self
.GetCtrl().LineFromPosition(pos
)+1 # line numbering for editor is 0 based, we are 1 based.
570 def PositionFromLine(self
, line
):
571 return self
.GetCtrl().PositionFromLine(line
-1) # line numbering for editor is 0 based, we are 1 based.
574 def GetLineEndPosition(self
, line
):
575 return self
.GetCtrl().GetLineEndPosition(line
-1) # line numbering for editor is 0 based, we are 1 based.
578 def GetLine(self
, lineNum
):
579 return self
.GetCtrl().GetLine(lineNum
-1) # line numbering for editor is 0 based, we are 1 based.
581 def MarkerDefine(self
):
582 """ This must be called after the texteditor is instantiated """
583 self
.GetCtrl().MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_CIRCLE
, wx
.BLACK
, wx
.BLUE
)
586 def MarkerToggle(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
588 lineNum
= self
.GetCtrl().GetCurrentLine()
589 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
590 self
.GetCtrl().MarkerDelete(lineNum
, marker_index
)
591 self
._markerCount
-= 1
593 self
.GetCtrl().MarkerAdd(lineNum
, marker_index
)
594 self
._markerCount
+= 1
596 def MarkerAdd(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
598 lineNum
= self
.GetCtrl().GetCurrentLine()
599 self
.GetCtrl().MarkerAdd(lineNum
, marker_index
)
600 self
._markerCount
+= 1
603 def MarkerDelete(self
, lineNum
= -1, marker_index
=MARKER_NUM
, mask
=MARKER_MASK
):
605 lineNum
= self
.GetCtrl().GetCurrentLine()
606 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
607 self
.GetCtrl().MarkerDelete(lineNum
, marker_index
)
608 self
._markerCount
-= 1
610 def MarkerDeleteAll(self
, marker_num
=MARKER_NUM
):
611 self
.GetCtrl().MarkerDeleteAll(marker_num
)
612 if marker_num
== self
.MARKER_NUM
:
613 self
._markerCount
= 0
616 def MarkerNext(self
, lineNum
= -1):
618 lineNum
= self
.GetCtrl().GetCurrentLine() + 1 # start search below current line
619 foundLine
= self
.GetCtrl().MarkerNext(lineNum
, self
.MARKER_MASK
)
621 # wrap to top of file
622 foundLine
= self
.GetCtrl().MarkerNext(0, self
.MARKER_MASK
)
624 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers"))
627 self
.GotoLine(foundLine
+ 1)
630 def MarkerPrevious(self
, lineNum
= -1):
632 lineNum
= self
.GetCtrl().GetCurrentLine() - 1 # start search above current line
634 lineNum
= self
.GetCtrl().GetLineCount()
636 foundLine
= self
.GetCtrl().MarkerPrevious(lineNum
, self
.MARKER_MASK
)
638 # wrap to bottom of file
639 foundLine
= self
.GetCtrl().MarkerPrevious(self
.GetCtrl().GetLineCount(), self
.MARKER_MASK
)
641 wx
.GetApp().GetTopWindow().PushStatusText(_("No markers"))
644 self
.GotoLine(foundLine
+ 1)
647 def MarkerExists(self
, lineNum
= -1, mask
=MARKER_MASK
):
649 lineNum
= self
.GetCtrl().GetCurrentLine()
650 if self
.GetCtrl().MarkerGet(lineNum
) & mask
:
656 def GetMarkerCount(self
):
657 return self
._markerCount
660 class TextService(wx
.lib
.pydocview
.DocService
):
664 wx
.lib
.pydocview
.DocService
.__init
__(self
)
667 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
668 if document
and document
.GetDocumentTemplate().GetDocumentType() != TextDocument
:
670 if not document
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
673 statusBar
= TextStatusBar(frame
, TEXT_STATUS_BAR_ID
)
674 frame
.SetStatusBar(statusBar
)
675 wx
.EVT_UPDATE_UI(frame
, TEXT_STATUS_BAR_ID
, frame
.ProcessUpdateUIEvent
)
677 viewMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View")))
679 viewMenu
.AppendSeparator()
681 textMenu
.AppendCheckItem(VIEW_WHITESPACE_ID
, _("&Whitespace"), _("Shows or hides whitespace"))
682 wx
.EVT_MENU(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessEvent
)
683 wx
.EVT_UPDATE_UI(frame
, VIEW_WHITESPACE_ID
, frame
.ProcessUpdateUIEvent
)
684 textMenu
.AppendCheckItem(VIEW_EOL_ID
, _("&End of Line Markers"), _("Shows or hides indicators at the end of each line"))
685 wx
.EVT_MENU(frame
, VIEW_EOL_ID
, frame
.ProcessEvent
)
686 wx
.EVT_UPDATE_UI(frame
, VIEW_EOL_ID
, frame
.ProcessUpdateUIEvent
)
687 textMenu
.AppendCheckItem(VIEW_INDENTATION_GUIDES_ID
, _("&Indentation Guides"), _("Shows or hides indentations"))
688 wx
.EVT_MENU(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessEvent
)
689 wx
.EVT_UPDATE_UI(frame
, VIEW_INDENTATION_GUIDES_ID
, frame
.ProcessUpdateUIEvent
)
690 textMenu
.AppendCheckItem(VIEW_RIGHT_EDGE_ID
, _("&Right Edge"), _("Shows or hides the right edge marker"))
691 wx
.EVT_MENU(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessEvent
)
692 wx
.EVT_UPDATE_UI(frame
, VIEW_RIGHT_EDGE_ID
, frame
.ProcessUpdateUIEvent
)
693 textMenu
.AppendCheckItem(VIEW_LINE_NUMBERS_ID
, _("&Line Numbers"), _("Shows or hides the line numbers"))
694 wx
.EVT_MENU(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessEvent
)
695 wx
.EVT_UPDATE_UI(frame
, VIEW_LINE_NUMBERS_ID
, frame
.ProcessUpdateUIEvent
)
697 viewMenu
.AppendMenu(TEXT_ID
, _("&Text"), textMenu
)
698 wx
.EVT_UPDATE_UI(frame
, TEXT_ID
, frame
.ProcessUpdateUIEvent
)
700 isWindows
= (wx
.Platform
== '__WXMSW__')
703 zoomMenu
.Append(ZOOM_NORMAL_ID
, _("Normal Size"), _("Sets the document to its normal size"))
704 wx
.EVT_MENU(frame
, ZOOM_NORMAL_ID
, frame
.ProcessEvent
)
705 wx
.EVT_UPDATE_UI(frame
, ZOOM_NORMAL_ID
, frame
.ProcessUpdateUIEvent
)
707 zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In\tCtrl+Page Up"), _("Zooms the document to a larger size"))
709 zoomMenu
.Append(ZOOM_IN_ID
, _("Zoom In"), _("Zooms the document to a larger size"))
710 wx
.EVT_MENU(frame
, ZOOM_IN_ID
, frame
.ProcessEvent
)
711 wx
.EVT_UPDATE_UI(frame
, ZOOM_IN_ID
, frame
.ProcessUpdateUIEvent
)
713 zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out\tCtrl+Page Down"), _("Zooms the document to a smaller size"))
715 zoomMenu
.Append(ZOOM_OUT_ID
, _("Zoom Out"), _("Zooms the document to a smaller size"))
716 wx
.EVT_MENU(frame
, ZOOM_OUT_ID
, frame
.ProcessEvent
)
717 wx
.EVT_UPDATE_UI(frame
, ZOOM_OUT_ID
, frame
.ProcessUpdateUIEvent
)
719 viewMenu
.AppendMenu(ZOOM_ID
, _("&Zoom"), zoomMenu
)
720 wx
.EVT_UPDATE_UI(frame
, ZOOM_ID
, frame
.ProcessUpdateUIEvent
)
722 formatMenuIndex
= menuBar
.FindMenu(_("&Format"))
723 if formatMenuIndex
> -1:
724 formatMenu
= menuBar
.GetMenu(formatMenuIndex
)
726 formatMenu
= wx
.Menu()
727 if not menuBar
.FindItemById(CHOOSE_FONT_ID
):
728 formatMenu
.Append(CHOOSE_FONT_ID
, _("&Font..."), _("Sets the font to use"))
729 wx
.EVT_MENU(frame
, CHOOSE_FONT_ID
, frame
.ProcessEvent
)
730 wx
.EVT_UPDATE_UI(frame
, CHOOSE_FONT_ID
, frame
.ProcessUpdateUIEvent
)
731 if not menuBar
.FindItemById(WORD_WRAP_ID
):
732 formatMenu
.AppendCheckItem(WORD_WRAP_ID
, _("Word Wrap"), _("Wraps text horizontally when checked"))
733 wx
.EVT_MENU(frame
, WORD_WRAP_ID
, frame
.ProcessEvent
)
734 wx
.EVT_UPDATE_UI(frame
, WORD_WRAP_ID
, frame
.ProcessUpdateUIEvent
)
735 if formatMenuIndex
== -1:
736 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
737 menuBar
.Insert(viewMenuIndex
+ 1, formatMenu
, _("&Format"))
739 # wxBug: wxToolBar::GetToolPos doesn't exist, need it to find cut tool and then insert find in front of it.
740 toolBar
.AddSeparator()
741 toolBar
.AddTool(ZOOM_IN_ID
, getZoomInBitmap(), shortHelpString
= _("Zoom In"), longHelpString
= _("Zooms the document to a larger size"))
742 toolBar
.AddTool(ZOOM_OUT_ID
, getZoomOutBitmap(), shortHelpString
= _("Zoom Out"), longHelpString
= _("Zooms the document to a smaller size"))
746 def ProcessUpdateUIEvent(self
, event
):
751 elif id == VIEW_WHITESPACE_ID
:
754 elif id == VIEW_EOL_ID
:
757 elif id == VIEW_INDENTATION_GUIDES_ID
:
760 elif id == VIEW_RIGHT_EDGE_ID
:
763 elif id == VIEW_LINE_NUMBERS_ID
:
769 elif id == ZOOM_NORMAL_ID
:
772 elif id == ZOOM_IN_ID
:
775 elif id == ZOOM_OUT_ID
:
778 elif id == CHOOSE_FONT_ID
:
781 elif id == WORD_WRAP_ID
:
788 class TextStatusBar(wx
.StatusBar
):
790 # 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
792 def __init__(self
, parent
, id, style
= wx
.ST_SIZEGRIP
, name
= "statusBar"):
793 wx
.StatusBar
.__init
__(self
, parent
, id, style
, name
)
794 self
.SetFieldsCount(4)
795 self
.SetStatusWidths([-1, 50, 50, 55])
797 def SetInsertMode(self
, insert
= True):
802 if self
.GetStatusText(1) != newText
: # wxBug: Need to check if the text has changed, otherwise it flickers under win32
803 self
.SetStatusText(newText
, 1)
805 def SetLineNumber(self
, lineNumber
):
806 newText
= _("Ln %i") % lineNumber
807 if self
.GetStatusText(2) != newText
:
808 self
.SetStatusText(newText
, 2)
810 def SetColumnNumber(self
, colNumber
):
811 newText
= _("Col %i") % colNumber
812 if self
.GetStatusText(3) != newText
:
813 self
.SetStatusText(newText
, 3)
816 class TextOptionsPanel(wx
.Panel
):
819 def __init__(self
, parent
, id, configPrefix
= "Text", label
= "Text", hasWordWrap
= True, hasTabs
= False, addPage
=True):
820 wx
.Panel
.__init
__(self
, parent
, id)
821 self
._configPrefix
= configPrefix
822 self
._hasWordWrap
= hasWordWrap
823 self
._hasTabs
= hasTabs
826 config
= wx
.ConfigBase_Get()
827 self
._textFont
= wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
)
828 fontData
= config
.Read(self
._configPrefix
+ "EditorFont", "")
830 nativeFont
= wx
.NativeFontInfo()
831 nativeFont
.FromString(fontData
)
832 self
._textFont
.SetNativeFontInfo(nativeFont
)
833 self
._originalTextFont
= self
._textFont
834 self
._textColor
= wx
.BLACK
835 colorData
= config
.Read(self
._configPrefix
+ "EditorColor", "")
837 red
= int("0x" + colorData
[0:2], 16)
838 green
= int("0x" + colorData
[2:4], 16)
839 blue
= int("0x" + colorData
[4:6], 16)
840 self
._textColor
= wx
.Color(red
, green
, blue
)
841 self
._originalTextColor
= self
._textColor
842 fontLabel
= wx
.StaticText(self
, -1, _("Font:"))
843 self
._sampleTextCtrl
= wx
.TextCtrl(self
, -1, "", size
= (125, 21))
844 self
._sampleTextCtrl
.SetEditable(False)
845 chooseFontButton
= wx
.Button(self
, -1, _("Choose Font..."))
846 wx
.EVT_BUTTON(self
, chooseFontButton
.GetId(), self
.OnChooseFont
)
847 if self
._hasWordWrap
:
848 self
._wordWrapCheckBox
= wx
.CheckBox(self
, -1, _("Wrap words inside text area"))
849 self
._wordWrapCheckBox
.SetValue(wx
.ConfigBase_Get().ReadInt(self
._configPrefix
+ "EditorWordWrap", False))
850 self
._viewWhitespaceCheckBox
= wx
.CheckBox(self
, -1, _("Show whitespace"))
851 self
._viewWhitespaceCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewWhitespace", False))
852 self
._viewEOLCheckBox
= wx
.CheckBox(self
, -1, _("Show end of line markers"))
853 self
._viewEOLCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewEOL", False))
854 self
._viewIndentationGuideCheckBox
= wx
.CheckBox(self
, -1, _("Show indentation guides"))
855 self
._viewIndentationGuideCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewIndentationGuides", False))
856 self
._viewRightEdgeCheckBox
= wx
.CheckBox(self
, -1, _("Show right edge"))
857 self
._viewRightEdgeCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewRightEdge", False))
858 self
._viewLineNumbersCheckBox
= wx
.CheckBox(self
, -1, _("Show line numbers"))
859 self
._viewLineNumbersCheckBox
.SetValue(config
.ReadInt(self
._configPrefix
+ "EditorViewLineNumbers", True))
861 self
._hasTabsCheckBox
= wx
.CheckBox(self
, -1, _("Use spaces instead of tabs"))
862 self
._hasTabsCheckBox
.SetValue(not wx
.ConfigBase_Get().ReadInt(self
._configPrefix
+ "EditorUseTabs", False))
863 indentWidthLabel
= wx
.StaticText(self
, -1, _("Indent Width:"))
864 self
._indentWidthChoice
= wx
.Choice(self
, -1, choices
= ["2", "4", "6", "8", "10"])
865 self
._indentWidthChoice
.SetStringSelection(str(config
.ReadInt(self
._configPrefix
+ "EditorIndentWidth", 4)))
866 textPanelBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
867 textPanelSizer
= wx
.BoxSizer(wx
.VERTICAL
)
868 textFontSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
869 textFontSizer
.Add(fontLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
)
870 textFontSizer
.Add(self
._sampleTextCtrl
, 0, wx
.ALIGN_LEFT | wx
.EXPAND | wx
.RIGHT
, HALF_SPACE
)
871 textFontSizer
.Add(chooseFontButton
, 0, wx
.ALIGN_RIGHT | wx
.LEFT
, HALF_SPACE
)
872 textPanelSizer
.Add(textFontSizer
, 0, wx
.ALL
, HALF_SPACE
)
873 if self
._hasWordWrap
:
874 textPanelSizer
.Add(self
._wordWrapCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
875 textPanelSizer
.Add(self
._viewWhitespaceCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
876 textPanelSizer
.Add(self
._viewEOLCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
877 textPanelSizer
.Add(self
._viewIndentationGuideCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
878 textPanelSizer
.Add(self
._viewRightEdgeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
879 textPanelSizer
.Add(self
._viewLineNumbersCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
881 textPanelSizer
.Add(self
._hasTabsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
882 textIndentWidthSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
883 textIndentWidthSizer
.Add(indentWidthLabel
, 0, wx
.ALIGN_LEFT | wx
.RIGHT | wx
.TOP
, HALF_SPACE
)
884 textIndentWidthSizer
.Add(self
._indentWidthChoice
, 0, wx
.ALIGN_LEFT | wx
.EXPAND
, HALF_SPACE
)
885 textPanelSizer
.Add(textIndentWidthSizer
, 0, wx
.ALL
, HALF_SPACE
)
886 textPanelBorderSizer
.Add(textPanelSizer
, 0, wx
.ALL
, SPACE
)
887 ## styleButton = wx.Button(self, -1, _("Choose Style..."))
888 ## wx.EVT_BUTTON(self, styleButton.GetId(), self.OnChooseStyle)
889 ## textPanelBorderSizer.Add(styleButton, 0, wx.ALL, SPACE)
890 self
.SetSizer(textPanelBorderSizer
)
891 self
.UpdateSampleFont()
893 parent
.AddPage(self
, _(label
))
895 def UpdateSampleFont(self
):
896 nativeFont
= wx
.NativeFontInfo()
897 nativeFont
.FromString(self
._textFont
.GetNativeFontInfoDesc())
899 font
.SetNativeFontInfo(nativeFont
)
900 font
.SetPointSize(self
._sampleTextCtrl
.GetFont().GetPointSize()) # Use the standard point size
901 self
._sampleTextCtrl
.SetFont(font
)
902 self
._sampleTextCtrl
.SetForegroundColour(self
._textColor
)
903 self
._sampleTextCtrl
.SetValue(str(self
._textFont
.GetPointSize()) + _(" pt. ") + self
._textFont
.GetFaceName())
904 self
._sampleTextCtrl
.Refresh()
908 ## def OnChooseStyle(self, event):
909 ## import STCStyleEditor
911 ## base = os.path.split(__file__)[0]
912 ## config = os.path.abspath(os.path.join(base, 'stc-styles.rc.cfg'))
914 ## dlg = STCStyleEditor.STCStyleEditDlg(None,
915 ## 'Python', 'python',
925 def OnChooseFont(self
, event
):
927 data
.EnableEffects(True)
928 data
.SetInitialFont(self
._textFont
)
929 data
.SetColour(self
._textColor
)
930 fontDialog
= wx
.FontDialog(self
, data
)
931 if fontDialog
.ShowModal() == wx
.ID_OK
:
932 data
= fontDialog
.GetFontData()
933 self
._textFont
= data
.GetChosenFont()
934 self
._textColor
= data
.GetColour()
935 self
.UpdateSampleFont()
939 def OnOK(self
, optionsDialog
):
940 config
= wx
.ConfigBase_Get()
941 doViewStuffUpdate
= config
.ReadInt(self
._configPrefix
+ "EditorViewWhitespace", False) != self
._viewWhitespaceCheckBox
.GetValue()
942 config
.WriteInt(self
._configPrefix
+ "EditorViewWhitespace", self
._viewWhitespaceCheckBox
.GetValue())
943 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewEOL", False) != self
._viewEOLCheckBox
.GetValue()
944 config
.WriteInt(self
._configPrefix
+ "EditorViewEOL", self
._viewEOLCheckBox
.GetValue())
945 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewIndentationGuides", False) != self
._viewIndentationGuideCheckBox
.GetValue()
946 config
.WriteInt(self
._configPrefix
+ "EditorViewIndentationGuides", self
._viewIndentationGuideCheckBox
.GetValue())
947 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewRightEdge", False) != self
._viewRightEdgeCheckBox
.GetValue()
948 config
.WriteInt(self
._configPrefix
+ "EditorViewRightEdge", self
._viewRightEdgeCheckBox
.GetValue())
949 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorViewLineNumbers", True) != self
._viewLineNumbersCheckBox
.GetValue()
950 config
.WriteInt(self
._configPrefix
+ "EditorViewLineNumbers", self
._viewLineNumbersCheckBox
.GetValue())
951 if self
._hasWordWrap
:
952 doViewStuffUpdate
= doViewStuffUpdate
or config
.ReadInt(self
._configPrefix
+ "EditorWordWrap", False) != self
._wordWrapCheckBox
.GetValue()
953 config
.WriteInt(self
._configPrefix
+ "EditorWordWrap", self
._wordWrapCheckBox
.GetValue())
955 doViewStuffUpdate
= doViewStuffUpdate
or not config
.ReadInt(self
._configPrefix
+ "EditorUseTabs", True) != self
._hasTabsCheckBox
.GetValue()
956 config
.WriteInt(self
._configPrefix
+ "EditorUseTabs", not self
._hasTabsCheckBox
.GetValue())
957 newIndentWidth
= int(self
._indentWidthChoice
.GetStringSelection())
958 oldIndentWidth
= config
.ReadInt(self
._configPrefix
+ "EditorIndentWidth", 4)
959 if newIndentWidth
!= oldIndentWidth
:
960 doViewStuffUpdate
= True
961 config
.WriteInt(self
._configPrefix
+ "EditorIndentWidth", newIndentWidth
)
962 doFontUpdate
= self
._originalTextFont
!= self
._textFont
or self
._originalTextColor
!= self
._textColor
963 config
.Write(self
._configPrefix
+ "EditorFont", self
._textFont
.GetNativeFontInfoDesc())
964 config
.Write(self
._configPrefix
+ "EditorColor", "%02x%02x%02x" % (self
._textColor
.Red(), self
._textColor
.Green(), self
._textColor
.Blue()))
965 if doViewStuffUpdate
or doFontUpdate
:
966 for document
in optionsDialog
.GetDocManager().GetDocuments():
967 if issubclass(document
.GetDocumentTemplate().GetDocumentType(), TextDocument
):
968 if doViewStuffUpdate
:
969 document
.UpdateAllViews(hint
= "ViewStuff")
971 document
.UpdateAllViews(hint
= "Font")
974 class TextCtrl(wx
.stc
.StyledTextCtrl
):
976 def __init__(self
, parent
, ID
= -1, style
= wx
.NO_FULL_REPAINT_ON_RESIZE
):
979 wx
.stc
.StyledTextCtrl
.__init
__(self
, parent
, ID
, style
= style
)
982 self
._fontColor
= None
984 self
.SetVisiblePolicy(wx
.stc
.STC_VISIBLE_STRICT
,1)
986 self
.CmdKeyClear(wx
.stc
.STC_KEY_ADD
, wx
.stc
.STC_SCMOD_CTRL
)
987 self
.CmdKeyClear(wx
.stc
.STC_KEY_SUBTRACT
, wx
.stc
.STC_SCMOD_CTRL
)
988 self
.CmdKeyAssign(wx
.stc
.STC_KEY_PRIOR
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMIN
)
989 self
.CmdKeyAssign(wx
.stc
.STC_KEY_NEXT
, wx
.stc
.STC_SCMOD_CTRL
, wx
.stc
.STC_CMD_ZOOMOUT
)
990 self
.Bind(wx
.stc
.EVT_STC_ZOOM
, self
.OnUpdateLineNumberMarginWidth
) # auto update line num width on zoom
991 wx
.EVT_KEY_DOWN(self
, self
.OnKeyPressed
)
998 self
.SetViewWhiteSpace(False)
999 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
1000 self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
)
1001 self
.SetEdgeColumn(78)
1003 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
1004 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
1007 self
.SetCaretForeground("BLACK")
1009 self
.SetViewDefaults()
1010 font
, color
= self
.GetFontAndColorFromConfig()
1012 self
.SetFontColor(color
)
1013 self
.MarkerDefineDefault()
1015 # for multisash initialization
1016 if isinstance(parent
, wx
.lib
.multisash
.MultiClient
):
1017 while parent
.GetParent():
1018 parent
= parent
.GetParent()
1019 if hasattr(parent
, "GetView"):
1021 if hasattr(parent
, "GetView"):
1022 textEditor
= parent
.GetView()._textEditor
1024 doc
= textEditor
.GetDocPointer()
1026 self
.SetDocPointer(doc
)
1030 def SetViewDefaults(self
, configPrefix
= "Text", hasWordWrap
= True, hasTabs
= False):
1031 config
= wx
.ConfigBase_Get()
1032 self
.SetViewWhiteSpace(config
.ReadInt(configPrefix
+ "EditorViewWhitespace", False))
1033 self
.SetViewEOL(config
.ReadInt(configPrefix
+ "EditorViewEOL", False))
1034 self
.SetIndentationGuides(config
.ReadInt(configPrefix
+ "EditorViewIndentationGuides", False))
1035 self
.SetViewRightEdge(config
.ReadInt(configPrefix
+ "EditorViewRightEdge", False))
1036 self
.SetViewLineNumbers(config
.ReadInt(configPrefix
+ "EditorViewLineNumbers", True))
1038 self
.SetWordWrap(config
.ReadInt(configPrefix
+ "EditorWordWrap", False))
1039 if hasTabs
: # These methods do not exist in STCTextEditor and are meant for subclasses
1040 self
.SetUseTabs(config
.ReadInt(configPrefix
+ "EditorUseTabs", False))
1041 self
.SetIndent(config
.ReadInt(configPrefix
+ "EditorIndentWidth", 4))
1042 self
.SetTabWidth(config
.ReadInt(configPrefix
+ "EditorIndentWidth", 4))
1044 self
.SetUseTabs(True)
1050 def GetDefaultFont(self
):
1051 """ Subclasses should override this """
1052 return wx
.Font(10, wx
.MODERN
, wx
.NORMAL
, wx
.NORMAL
)
1055 def GetDefaultColor(self
):
1056 """ Subclasses should override this """
1060 def GetFontAndColorFromConfig(self
, configPrefix
= "Text"):
1061 font
= self
.GetDefaultFont()
1062 config
= wx
.ConfigBase_Get()
1063 fontData
= config
.Read(configPrefix
+ "EditorFont", "")
1065 nativeFont
= wx
.NativeFontInfo()
1066 nativeFont
.FromString(fontData
)
1067 font
.SetNativeFontInfo(nativeFont
)
1068 color
= self
.GetDefaultColor()
1069 colorData
= config
.Read(configPrefix
+ "EditorColor", "")
1071 red
= int("0x" + colorData
[0:2], 16)
1072 green
= int("0x" + colorData
[2:4], 16)
1073 blue
= int("0x" + colorData
[4:6], 16)
1074 color
= wx
.Color(red
, green
, blue
)
1081 def SetFont(self
, font
):
1083 self
.StyleSetFont(wx
.stc
.STC_STYLE_DEFAULT
, self
._font
)
1086 def GetFontColor(self
):
1087 return self
._fontColor
1090 def SetFontColor(self
, fontColor
= wx
.BLACK
):
1091 self
._fontColor
= fontColor
1092 self
.StyleSetForeground(wx
.stc
.STC_STYLE_DEFAULT
, "#%02x%02x%02x" % (self
._fontColor
.Red(), self
._fontColor
.Green(), self
._fontColor
.Blue()))
1095 def UpdateStyles(self
):
1096 self
.StyleClearAll()
1100 def EstimatedLineNumberMarginWidth(self
):
1103 lineNum
= self
.GetLineCount()
1104 lineNum
= lineNum
/100
1105 while lineNum
>= 10:
1106 lineNum
= lineNum
/10
1107 baseNumbers
= baseNumbers
+ "0"
1109 return self
.TextWidth(wx
.stc
.STC_STYLE_LINENUMBER
, baseNumbers
) + MARGIN
1112 def OnUpdateLineNumberMarginWidth(self
, event
):
1113 self
.UpdateLineNumberMarginWidth()
1116 def UpdateLineNumberMarginWidth(self
):
1117 if self
.GetViewLineNumbers():
1118 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
1120 def MarkerDefineDefault(self
):
1121 """ This must be called after the textcontrol is instantiated """
1122 self
.MarkerDefine(TextView
.MARKER_NUM
, wx
.stc
.STC_MARK_ROUNDRECT
, wx
.BLACK
, wx
.BLUE
)
1126 # Used when Delete key is hit.
1127 sel
= self
.GetSelection()
1129 # Delete the selection or if no selection, the character after the caret.
1130 if sel
[0] == sel
[1]:
1131 self
.SetSelection(sel
[0], sel
[0] + 1)
1133 # remove any folded lines also.
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
))
1146 # replace any folded lines also.
1147 sel
= self
.GetSelection()
1148 startLine
= self
.LineFromPosition(sel
[0])
1149 endLine
= self
.LineFromPosition(sel
[1])
1150 endLineStart
= self
.PositionFromLine(endLine
)
1151 if startLine
!= endLine
and sel
[1] - endLineStart
== 0:
1152 while not self
.GetLineVisible(endLine
):
1154 self
.SetSelectionEnd(self
.PositionFromLine(endLine
))
1159 def OnKeyPressed(self
, event
):
1160 key
= event
.GetKeyCode()
1161 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
1162 if event
.ControlDown():
1163 self
.ToggleFoldAll(expand
= True, topLevelOnly
= True)
1164 elif event
.ShiftDown():
1165 self
.ToggleFoldAll(expand
= True)
1167 self
.ToggleFold(self
.GetCurrentLine())
1168 elif key
== wx
.WXK_NUMPAD_SUBTRACT
:
1169 if event
.ControlDown():
1170 self
.ToggleFoldAll(expand
= False, topLevelOnly
= True)
1171 elif event
.ShiftDown():
1172 self
.ToggleFoldAll(expand
= False)
1174 self
.ToggleFold(self
.GetCurrentLine())
1179 #----------------------------------------------------------------------------
1181 #----------------------------------------------------------------------------
1183 def GetViewRightEdge(self
):
1184 return self
.GetEdgeMode() != wx
.stc
.STC_EDGE_NONE
1187 def SetViewRightEdge(self
, viewRightEdge
):
1189 self
.SetEdgeMode(wx
.stc
.STC_EDGE_LINE
)
1191 self
.SetEdgeMode(wx
.stc
.STC_EDGE_NONE
)
1194 def GetViewLineNumbers(self
):
1195 return self
.GetMarginWidth(1) > 0
1198 def SetViewLineNumbers(self
, viewLineNumbers
= True):
1200 self
.SetMarginWidth(1, self
.EstimatedLineNumberMarginWidth())
1202 self
.SetMarginWidth(1, 0)
1205 def CanWordWrap(self
):
1209 def GetWordWrap(self
):
1210 return self
.GetWrapMode() == wx
.stc
.STC_WRAP_WORD
1213 def SetWordWrap(self
, wordWrap
):
1215 self
.SetWrapMode(wx
.stc
.STC_WRAP_WORD
)
1217 self
.SetWrapMode(wx
.stc
.STC_WRAP_NONE
)
1220 #----------------------------------------------------------------------------
1221 # Icon Bitmaps - generated by encode_bitmaps.py
1222 #----------------------------------------------------------------------------
1223 from wx
import ImageFromStream
, BitmapFromImage
1229 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1230 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1231 \x00\x00`IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\xa7JU!$\x12\x1d\
1232 \xeb\t\t8n\x81\xb4\x86J\xfa]h\x0ee\x83\xb4\xc6\x14\x00\x00R\xcc \t\xcd\xa1\
1233 \x08\xd2\xa3\xe1\x08*\t$\x1d\xc4\x012\x0b\x00\xce\xe4\xc8\xe0\t}\xf7\x8f\rV\
1234 \xd9\x1a\xec\xe0\xbf\xc1\xd7\x06\xd9\xf5UX\xfdF+m\x03\xb8\x00\xe4\xc74B"x\
1235 \xf1\xf4\x00\x00\x00\x00IEND\xaeB`\x82'
1238 def getTextBitmap():
1239 return BitmapFromImage(getTextImage())
1242 stream
= cStringIO
.StringIO(getTextData())
1243 return ImageFromStream(stream
)
1246 return wx
.IconFromBitmap(getTextBitmap())
1249 #----------------------------------------------------------------------------
1250 # Menu Bitmaps - generated by encode_bitmaps.py
1251 #----------------------------------------------------------------------------
1252 #----------------------------------------------------------------------
1253 def getZoomInData():
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\x00wIDAT8\x8d\xa5\x93Q\x12\x80 \x08D\xb5\xe9X\xee\xe9\xb7{\xd5Gc\xa9\
1258 \xacX\xca\x1f\xa0\x8fE0\x92<\xc3\x82\xed*\x08\xa0\xf2I~\x07\x000\x17T,\xdb\
1259 \xd6;\x08\xa4\x00\xa4GA\xab\xca\x00\xbc*\x1eD\xb4\x90\xa4O\x1e\xe3\x16f\xcc(\
1260 \xc8\x95F\x95\x8d\x02\xef\xa1n\xa0\xce\xc5v\x91zc\xacU\xbey\x03\xf0.\xa8\xb8\
1261 \x04\x8c\xac\x04MM\xa1lA\xfe\x85?\x90\xe5=X\x06\\\xebCA\xb3Q\xf34\x14\x00\
1262 \x00\x00\x00IEND\xaeB`\x82'
1264 def getZoomInBitmap():
1265 return BitmapFromImage(getZoomInImage())
1267 def getZoomInImage():
1268 stream
= cStringIO
.StringIO(getZoomInData())
1269 return ImageFromStream(stream
)
1271 #----------------------------------------------------------------------
1272 def getZoomOutData():
1274 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1275 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1276 \x00\x00qIDAT8\x8d\xa5\x92Q\x0e\xc0 \x08C-z\xff\x13O\xd9\xd7\x16"\x05\x8d\
1277 \xf6O\xa2\x8f"\x05\xa4\x96\x1b5V\xd4\xd1\xd5\x9e!\x15\xdb\x00\x1d]\xe7\x07\
1278 \xac\xf6Iv.B*fW\x0e\x90u\xc9 d\x84\x87v\x82\xb4\xf5\x08\'r\x0e\xa2N\x91~\x07\
1279 \xd9G\x95\xe2W\xeb\x00\x19\xc4\xd6\\FX\x12\xa3 \xb1:\x05\xacdAG[\xb0y9r`u\
1280 \x9d\x83k\xc0\x0b#3@0A\x0c"\x93\x00\x00\x00\x00IEND\xaeB`\x82'
1283 def getZoomOutBitmap():
1284 return BitmapFromImage(getZoomOutImage())
1286 def getZoomOutImage():
1287 stream
= cStringIO
.StringIO(getZoomOutData())
1288 return ImageFromStream(stream
)