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