spacepaste

  1.  
  2. # Chapter 10: Creating Components and Extending Functionality
  3. # Recipe 6: StyledTextCtrl Custom Highlighting
  4. #
  5. import wx
  6. import wx.stc as st
  7. import itertools
  8. issl_table = ';+-?.#~'
  9. if wx.Platform == '__WXMSW__':
  10. # for windows OS
  11. faces = {
  12. 'times': 'Times New Roman',
  13. 'mono' : 'Courier New',
  14. # try temporary switch to mono
  15. 'helv' : 'Courier New',
  16. #'helv' : 'Arial',
  17. 'other': 'Comic Sans MS',
  18. 'size' : 10,
  19. 'size2': 8,
  20. }
  21. else:
  22. faces = {
  23. 'times': 'Times',
  24. 'mono' : 'Courier',
  25. 'helv' : 'Helvetica',
  26. 'other': 'new century schoolbook',
  27. 'size' : 12,
  28. 'size2': 10,
  29. }
  30. class MyMiniFrame(wx.MiniFrame):
  31. def __init__(
  32. self, parent, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  33. style=wx.DEFAULT_FRAME_STYLE
  34. ):
  35. wx.MiniFrame.__init__(self, parent, -1, title, pos, size, style)
  36. panel = wx.Panel(self, -1)
  37. button = wx.Button(panel, -1, "Close Me")
  38. button.SetPosition((15, 15))
  39. self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
  40. self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
  41. def OnCloseMe(self, event):
  42. self.Close(True)
  43. def OnCloseWindow(self, event):
  44. print "OnCloseWindow"
  45. self.Destroy()
  46. class VowelLexer(object):
  47. """Simple lexer to highlight vowels"""
  48. # Define some style IDs
  49. STC_STYLE_VOWEL_DEFAULT, \
  50. STC_STYLE_VOWEL_KW = range(2)
  51. def __init__(self, lang):
  52. self.lang = lang
  53. def StyleText(self, event):
  54. """Handle the EVT_STC_STYLENEEDED event"""
  55. stc = event.GetEventObject()
  56. # Last correctly styled character
  57. last_styled_pos = stc.GetEndStyled()
  58. # Get styling range for this call
  59. line = stc.LineFromPosition(last_styled_pos)
  60. start_pos = stc.PositionFromLine(line)
  61. end_pos = event.GetPosition()
  62. word = ''
  63. pos = start_pos
  64. def displaystyle(lang, stcvar, stvar):
  65. # set other options ...
  66. stcvar.SetProperty("fold", "1")
  67. stcvar.SetMargins(0, 0)
  68. stcvar.SetViewWhiteSpace(False)
  69. stcvar.SetEdgeMode(stvar.STC_EDGE_BACKGROUND)
  70. stcvar.SetEdgeColumn(78)
  71. stcvar.SetCaretForeground("blue")
  72. # setup a margin to hold the fold markers
  73. stcvar.SetMarginType(2, stvar.STC_MARGIN_SYMBOL)
  74. stcvar.SetMarginMask(2, stvar.STC_MASK_FOLDERS)
  75. stcvar.SetMarginSensitive(2, True)
  76. stcvar.SetMarginWidth(2, 12)
  77. stcvar.SetMarginType(1, stvar.STC_MARGIN_NUMBER)
  78. stcvar.SetMarginWidth(1, 30)
  79. # fold markers use square headers
  80. stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDEROPEN,
  81. st.STC_MARK_BOXMINUS, "white", "#808080")
  82. stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDER,
  83. st.STC_MARK_BOXPLUS, "white", "#808080")
  84. stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDERSUB,
  85. st.STC_MARK_VLINE, "white", "#808080")
  86. stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDERTAIL,
  87. st.STC_MARK_LCORNER, "white", "#808080")
  88. stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDEREND,
  89. st.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
  90. stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDEROPENMID,
  91. st.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
  92. stcvar.MarkerDefine(stvar.STC_MARKNUM_FOLDERMIDTAIL,
  93. st.STC_MARK_TCORNER, "white", "#808080")
  94. # make some general styles ...
  95. # global default styles for all languages
  96. # set default font
  97. stcvar.StyleSetSpec(stvar.STC_STYLE_DEFAULT,
  98. "face:%(helv)s,size:%(size)d" % faces)
  99. # set default background color
  100. beige = '#F5F5DC'
  101. stcvar.StyleSetBackground(style=stvar.STC_STYLE_DEFAULT,
  102. back=beige)
  103. # reset all to be like the default
  104. stcvar.StyleClearAll()
  105. # more global default styles for all languages
  106. stcvar.StyleSetSpec(stvar.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
  107. stcvar.StyleSetSpec(stvar.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
  108. stcvar.StyleSetSpec(stvar.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
  109. stcvar.StyleSetSpec(stvar.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
  110. stcvar.StyleSetSpec(stvar.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
  111. # make the Python styles ...
  112. # default
  113. if lang == 'python':
  114. # Python styles
  115. # Default
  116. stcvar.StyleSetSpec(stvar.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
  117. # Comments
  118. stcvar.StyleSetSpec(stvar.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % faces)
  119. # Number
  120. stcvar.StyleSetSpec(stvar.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
  121. # String
  122. stcvar.StyleSetSpec(stvar.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
  123. # Single quoted string
  124. stcvar.StyleSetSpec(stvar.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
  125. # Keyword
  126. stcvar.StyleSetSpec(stvar.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
  127. # Triple quotes
  128. stcvar.StyleSetSpec(stvar.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % faces)
  129. # Triple double quotes
  130. stcvar.StyleSetSpec(stvar.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % faces)
  131. # Class name definition
  132. stcvar.StyleSetSpec(stvar.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % faces)
  133. # Function or method name definition
  134. stcvar.StyleSetSpec(stvar.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % faces)
  135. # Operators
  136. stcvar.StyleSetSpec(stvar.STC_P_OPERATOR, "bold,size:%(size)d" % faces)
  137. # Identifiers
  138. stcvar.StyleSetSpec(stvar.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
  139. # Comment-blocks
  140. stcvar.StyleSetSpec(stvar.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % faces)
  141. # End of line where string is not closed
  142. stcvar.StyleSetSpec(stvar.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s, back:#E0C0E0,eol,size:%(size)d" % faces)
  143. if self.lang == 'python':
  144. pythonlist = [
  145. 'and',
  146. 'as',
  147. 'assert',
  148. 'break',
  149. 'class',
  150. 'continue',
  151. 'def',
  152. 'del',
  153. 'elif',
  154. 'else',
  155. 'except',
  156. 'exec',
  157. 'finally',
  158. 'for',
  159. 'from',
  160. 'global',
  161. 'if',
  162. 'import',
  163. 'in',
  164. 'is',
  165. 'lambda',
  166. 'not',
  167. 'or',
  168. 'pass',
  169. 'print',
  170. 'raise',
  171. 'return',
  172. 'try',
  173. 'while',
  174. 'with',
  175. 'yield',
  176. ]
  177. stc.SetLexer(st.STC_LEX_PYTHON)
  178. stc.SetKeyWords(0, " ".join(pythonlist))
  179. displaystyle(self.lang, stc, st)
  180. class MyPopupMenu(wx.Menu):
  181. def __init__(self, parent):
  182. super(MyPopupMenu, self).__init__()
  183. self.parent = parent
  184. mmi = wx.MenuItem(self, wx.NewId(), 'Remove')
  185. self.AppendItem(mmi)
  186. self.Bind(wx.EVT_MENU, self.OnMinimize, mmi)
  187. # cmi = wx.MenuItem(self, wx.NewId(), 'Close')
  188. # self.AppendItem(cmi)
  189. # self.Bind(wx.EVT_MENU, self.OnClose, cmi)
  190. def OnMinimize(self, e):
  191. StcFrame.panel.Autosizer.Remove(self)
  192. def OnClose(self, e):
  193. self.parent.Close()
  194. class STC(st.StyledTextCtrl):
  195. def __init__(self, *args, **kwargs):
  196. super(STC, self).__init__(*args, **kwargs)
  197. # def __init__(self, *args, **kwargs):
  198. # super(STC, self).__init__(*args, **kwargs)
  199. # Attributes
  200. self.custlex = None
  201. # Event Handlers
  202. self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyle)
  203. self.InitUI()
  204. def InitUI(self):
  205. self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
  206. self.SetSize((250, 200))
  207. # self.SetTitle('Context menu')
  208. self.Centre()
  209. self.Show(True)
  210. def OnRightDown(self, e):
  211. self.PopupMenu(MyPopupMenu(self), e.GetPosition())
  212. def OnStyle(self, event):
  213. # Delegate to custom lexer object if one exists
  214. if self.custlex:
  215. self.custlex.StyleText(event)
  216. else:
  217. event.Skip()
  218. def SetLexer(self, lexerid, lexer=None):
  219. """Overrides StyledTextCtrl.SetLexer
  220. Adds optional param to pass in custom container
  221. lexer object.
  222. """
  223. self.custlex = lexer
  224. super(STC, self).SetLexer(lexerid)
  225. class StyledTextApp(wx.App):
  226. def OnInit(self):
  227. self.frame = StcFrame(None, title="Custom Lexer")
  228. self.frame.Show()
  229. return True
  230. class TestPanel(wx.Panel):
  231. def __init__(self, parent):
  232. wx.Panel.__init__(self, parent, -1)
  233. # Attributes
  234. self.stc1 = STC(self)
  235. self.stc1.Text = """print 'this is calling python'
  236. def main():
  237. pass
  238. print 'man'
  239. print 'good'"""
  240. self.stc1.SetUseHorizontalScrollBar(False)
  241. self.stc1.SetUseVerticalScrollBar(False)
  242. style = VowelLexer.STC_STYLE_VOWEL_DEFAULT
  243. self.stc1.StyleSetSpec(style, "fore:#000000")
  244. style = VowelLexer.STC_STYLE_VOWEL_KW
  245. self.stc1.StyleSetSpec(style, "fore:#FF0000,bold")
  246. self.stc1.SetLexer(st.STC_LEX_CONTAINER,
  247. VowelLexer('python')) # python
  248. sizer = wx.BoxSizer(wx.VERTICAL)
  249. sizer.Add(self.stc1, 0, wx.EXPAND)
  250. self.SetSizer(sizer)
  251. self.SetInitialSize((300, 300))
  252. self.Autosizer = wx.FlexGridSizer(rows=1, cols=2, hgap = -190, vgap = -1)
  253. self.Autosizer.SetFlexibleDirection(wx.VERTICAL)
  254. labels = "P".split()
  255. for label in labels:
  256. t=wx.StaticText(self, label=label)
  257. if label == 'P':
  258. t.SetForegroundColour((255,0,255))
  259. e=self.stc1
  260. self.Autosizer.Add(t,0)
  261. self.Autosizer.Add(e,1, wx.EXPAND)
  262. self.Autosizer.AddGrowableCol(1, 1) # 2 col
  263. self.SetSizer(self.Autosizer)
  264. self.Fit()
  265. self.Bind(wx.EVT_SCROLLWIN, self.OnScroll1)
  266. self.Bind(wx.EVT_SCROLLWIN, self.OnScroll2)
  267. self.Bind(wx.EVT_SCROLLWIN, self.OnScroll3)
  268. def OnScroll2(self, event):
  269. clone = event.Clone()
  270. clone.SetId(wx.NewId())
  271. clone.SetEventObject(self.stc1)
  272. self.stc1.GetEventHandler().ProcessEvent(clone)
  273. event.Skip()
  274. def OnScroll1(self, event):
  275. clone = event.Clone()
  276. clone.SetId(wx.NewId())
  277. clone.SetEventObject(self.stc2)
  278. self.stc2.GetEventHandler().ProcessEvent(clone)
  279. event.Skip()
  280. def OnScroll3(self, event):
  281. clone = event.Clone()
  282. clone.SetId(wx.NewId())
  283. clone.SetEventObject(self.stc3)
  284. self.stc3.GetEventHandler().ProcessEvent(clone)
  285. event.Skip()
  286. class StcFrame(wx.Frame):
  287. """Main application window"""
  288. def __init__(self, parent, *args, **kwargs):
  289. super(StcFrame, self).__init__(parent,
  290. *args,
  291. **kwargs)
  292. self.panel = TestPanel(self)
  293. b = wx.Button(self, 40, "Fortran", (300,200), style=wx.NO_BORDER)
  294. b.SetToolTipString("This button has a style flag of wx.NO_BORDER.\nOn some platforms that will give it a flattened look.")
  295. self.Bind(wx.EVT_BUTTON, self.OnClick, b)
  296. def OnClick(self, event):
  297. t=wx.StaticText(self, label='F')
  298. e= STC(self)
  299. e.Text = """"""
  300. e.SetUseHorizontalScrollBar(False)
  301. e.SetUseVerticalScrollBar(False)
  302. self.SetSizer(self.panel.Autosizer)
  303. self.panel.Layout()
  304. if __name__ == '__main__':
  305. app = StyledTextApp(False)
  306. app.MainLoop()
  307.