-
- # Chapter 10: Creating Components and Extending Functionality
- # Recipe 6: StyledTextCtrl Custom Highlighting
- #
- import wx
- import wx.stc as st
- import itertools
-
- issl_table = ';+-?.#~'
-
- if wx.Platform == '__WXMSW__':
- # for windows OS
- faces = {
- 'times': 'Times New Roman',
- 'mono' : 'Courier New',
- # try temporary switch to mono
- 'helv' : 'Courier New',
- #'helv' : 'Arial',
- 'other': 'Comic Sans MS',
- 'size' : 10,
- 'size2': 8,
- }
- else:
- faces = {
- 'times': 'Times',
- 'mono' : 'Courier',
- 'helv' : 'Helvetica',
- 'other': 'new century schoolbook',
- 'size' : 12,
- 'size2': 10,
- }
-
- class MyMiniFrame(wx.MiniFrame):
- def __init__(
- self, parent, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
- style=wx.DEFAULT_FRAME_STYLE
- ):
-
- wx.MiniFrame.__init__(self, parent, -1, title, pos, size, style)
- panel = wx.Panel(self, -1)
-
- button = wx.Button(panel, -1, "Close Me")
- button.SetPosition((15, 15))
- self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
- self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
-
- def OnCloseMe(self, event):
- self.Close(True)
-
- def OnCloseWindow(self, event):
- print "OnCloseWindow"
- self.Destroy()
-
- class VowelLexer(object):
- """Simple lexer to highlight vowels"""
- # Define some style IDs
- STC_STYLE_VOWEL_DEFAULT, \
- STC_STYLE_VOWEL_KW = range(2)
- def __init__(self, lang):
- self.lang = lang
-
-
- def StyleText(self, event):
- """Handle the EVT_STC_STYLENEEDED event"""
- stc = event.GetEventObject()
- # Last correctly styled character
- last_styled_pos = stc.GetEndStyled()
- # Get styling range for this call
- line = stc.LineFromPosition(last_styled_pos)
- start_pos = stc.PositionFromLine(line)
- end_pos = event.GetPosition()
-
- word = ''
- pos = start_pos
-
- def displaystyle(lang, stcvar, stvar):
- # set other options ...
- stcvar.SetProperty("fold", "1")
- stcvar.SetMargins(0, 0)
- stcvar.SetViewWhiteSpace(False)
- stcvar.SetEdgeMode(stvar.STC_EDGE_BACKGROUND)
- stcvar.SetEdgeColumn(78)
- stcvar.SetCaretForeground("blue")
-
- # setup a margin to hold the fold markers
- stcvar.SetMarginType(2, stvar.STC_MARGIN_SYMBOL)
- stcvar.SetMarginMask(2, stvar.STC_MASK_FOLDERS)
- stcvar.SetMarginSensitive(2, True)
- stcvar.SetMarginWidth(2, 12)
-
- stcvar.SetMarginType(1, stvar.STC_MARGIN_NUMBER)
- stcvar.SetMarginWidth(1, 30)
-
- # fold markers use square headers
- stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDEROPEN,
- st.STC_MARK_BOXMINUS, "white", "#808080")
- stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDER,
- st.STC_MARK_BOXPLUS, "white", "#808080")
- stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDERSUB,
- st.STC_MARK_VLINE, "white", "#808080")
- stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDERTAIL,
- st.STC_MARK_LCORNER, "white", "#808080")
- stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDEREND,
- st.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
- stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDEROPENMID,
- st.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
- stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDERMIDTAIL,
- st.STC_MARK_TCORNER, "white", "#808080")
-
-
- # make some general styles ...
- # global default styles for all languages
- # set default font
- stcvar.StyleSetSpec(stvar.STC_STYLE_DEFAULT,
- "face:%(helv)s,size:%(size)d" % faces)
- # set default background color
- beige = '#F5F5DC'
- stcvar.StyleSetBackground(style=stvar.STC_STYLE_DEFAULT,
- back=beige)
- # reset all to be like the default
- stcvar.StyleClearAll()
-
- # more global default styles for all languages
- stcvar.StyleSetSpec(stvar.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
- stcvar.StyleSetSpec(stvar.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
- stcvar.StyleSetSpec(stvar.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
- stcvar.StyleSetSpec(stvar.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
- stcvar.StyleSetSpec(stvar.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
-
- # make the Python styles ...
- # default
- if lang == 'python':
- # Python styles
- # Default
- stcvar.StyleSetSpec(stvar.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
- # Comments
- stcvar.StyleSetSpec(stvar.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % faces)
- # Number
- stcvar.StyleSetSpec(stvar.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
- # String
- stcvar.StyleSetSpec(stvar.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
- # Single quoted string
- stcvar.StyleSetSpec(stvar.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
- # Keyword
- stcvar.StyleSetSpec(stvar.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
- # Triple quotes
- stcvar.StyleSetSpec(stvar.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % faces)
- # Triple double quotes
- stcvar.StyleSetSpec(stvar.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % faces)
- # Class name definition
- stcvar.StyleSetSpec(stvar.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % faces)
- # Function or method name definition
- stcvar.StyleSetSpec(stvar.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % faces)
- # Operators
- stcvar.StyleSetSpec(stvar.STC_P_OPERATOR, "bold,size:%(size)d" % faces)
- # Identifiers
- stcvar.StyleSetSpec(stvar.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
- # Comment-blocks
- stcvar.StyleSetSpec(stvar.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % faces)
- # End of line where string is not closed
- stcvar.StyleSetSpec(stvar.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s, back:#E0C0E0,eol,size:%(size)d" % faces)
-
-
- if self.lang == 'python':
- pythonlist = [
- 'and',
- 'as',
- 'assert',
- 'break',
- 'class',
- 'continue',
- 'def',
- 'del',
- 'elif',
- 'else',
- 'except',
- 'exec',
- 'finally',
- 'for',
- 'from',
- 'global',
- 'if',
- 'import',
- 'in',
- 'is',
- 'lambda',
- 'not',
- 'or',
- 'pass',
- 'print',
- 'raise',
- 'return',
- 'try',
- 'while',
- 'with',
- 'yield',
- ]
-
- stc.SetLexer(st.STC_LEX_PYTHON)
- stc.SetKeyWords(0, " ".join(pythonlist))
-
- displaystyle(self.lang, stc, st)
-
-
- class MyPopupMenu(wx.Menu):
-
- def __init__(self, parent):
- super(MyPopupMenu, self).__init__()
-
- self.parent = parent
-
- mmi = wx.MenuItem(self, wx.NewId(), 'Remove')
- self.AppendItem(mmi)
- self.Bind(wx.EVT_MENU, self.OnMinimize, mmi)
-
- # cmi = wx.MenuItem(self, wx.NewId(), 'Close')
- # self.AppendItem(cmi)
- # self.Bind(wx.EVT_MENU, self.OnClose, cmi)
-
-
- def OnMinimize(self, e):
- StcFrame.panel.Autosizer.Remove(self)
-
- def OnClose(self, e):
- self.parent.Close()
-
- class STC(st.StyledTextCtrl):
- def __init__(self, *args, **kwargs):
- super(STC, self).__init__(*args, **kwargs)
- # def __init__(self, *args, **kwargs):
- # super(STC, self).__init__(*args, **kwargs)
-
- # Attributes
- self.custlex = None
-
- # Event Handlers
- self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyle)
- self.InitUI()
-
- def InitUI(self):
-
- self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
-
- self.SetSize((250, 200))
- # self.SetTitle('Context menu')
- self.Centre()
- self.Show(True)
-
- def OnRightDown(self, e):
- self.PopupMenu(MyPopupMenu(self), e.GetPosition())
-
- def OnStyle(self, event):
- # Delegate to custom lexer object if one exists
- if self.custlex:
- self.custlex.StyleText(event)
- else:
- event.Skip()
-
- def SetLexer(self, lexerid, lexer=None):
- """Overrides StyledTextCtrl.SetLexer
- Adds optional param to pass in custom container
- lexer object.
- """
- self.custlex = lexer
- super(STC, self).SetLexer(lexerid)
-
-
- class StyledTextApp(wx.App):
- def OnInit(self):
- self.frame = StcFrame(None, title="Custom Lexer")
- self.frame.Show()
- return True
-
- class TestPanel(wx.Panel):
- def __init__(self, parent):
- wx.Panel.__init__(self, parent, -1)
-
- # Attributes
- self.stc1 = STC(self)
- self.stc1.Text = """print 'this is calling python'
-
- def main():
- pass
-
- print 'man'
-
- print 'good'"""
- self.stc1.SetUseHorizontalScrollBar(False)
- self.stc1.SetUseVerticalScrollBar(False)
-
- style = VowelLexer.STC_STYLE_VOWEL_DEFAULT
- self.stc1.StyleSetSpec(style, "fore:#000000")
- style = VowelLexer.STC_STYLE_VOWEL_KW
- self.stc1.StyleSetSpec(style, "fore:#FF0000,bold")
- self.stc1.SetLexer(st.STC_LEX_CONTAINER,
- VowelLexer('python')) # python
-
-
- sizer = wx.BoxSizer(wx.VERTICAL)
- sizer.Add(self.stc1, 0, wx.EXPAND)
- self.SetSizer(sizer)
- self.SetInitialSize((300, 300))
-
- self.Autosizer = wx.FlexGridSizer(rows=1, cols=2, hgap = -190, vgap = -1)
- self.Autosizer.SetFlexibleDirection(wx.VERTICAL)
-
- labels = "P".split()
- for label in labels:
- t=wx.StaticText(self, label=label)
- if label == 'P':
- t.SetForegroundColour((255,0,255))
- e=self.stc1
- self.Autosizer.Add(t,0)
- self.Autosizer.Add(e,1, wx.EXPAND)
- self.Autosizer.AddGrowableCol(1, 1) # 2 col
- self.SetSizer(self.Autosizer)
- self.Fit()
-
-
- self.Bind(wx.EVT_SCROLLWIN, self.OnScroll1)
- self.Bind(wx.EVT_SCROLLWIN, self.OnScroll2)
- self.Bind(wx.EVT_SCROLLWIN, self.OnScroll3)
-
- def OnScroll2(self, event):
- clone = event.Clone()
- clone.SetId(wx.NewId())
- clone.SetEventObject(self.stc1)
- self.stc1.GetEventHandler().ProcessEvent(clone)
- event.Skip()
-
- def OnScroll1(self, event):
- clone = event.Clone()
- clone.SetId(wx.NewId())
- clone.SetEventObject(self.stc2)
- self.stc2.GetEventHandler().ProcessEvent(clone)
- event.Skip()
-
- def OnScroll3(self, event):
- clone = event.Clone()
- clone.SetId(wx.NewId())
- clone.SetEventObject(self.stc3)
- self.stc3.GetEventHandler().ProcessEvent(clone)
- event.Skip()
-
- class StcFrame(wx.Frame):
- """Main application window"""
- def __init__(self, parent, *args, **kwargs):
- super(StcFrame, self).__init__(parent,
- *args,
- **kwargs)
-
- self.panel = TestPanel(self)
-
-
- b = wx.Button(self, 40, "Fortran", (300,200), style=wx.NO_BORDER)
- b.SetToolTipString("This button has a style flag of wx.NO_BORDER.\nOn some platforms that will give it a flattened look.")
- self.Bind(wx.EVT_BUTTON, self.OnClick, b)
-
-
-
-
-
-
- def OnClick(self, event):
- t=wx.StaticText(self, label='F')
- e= STC(self)
- e.Text = """"""
- e.SetUseHorizontalScrollBar(False)
- e.SetUseVerticalScrollBar(False)
-
- self.SetSizer(self.panel.Autosizer)
- self.panel.Layout()
-
- if __name__ == '__main__':
- app = StyledTextApp(False)
- app.MainLoop()
-