etisserant@31: import wx etisserant@31: import wx.stc as stc etisserant@31: etisserant@31: #---------------------------------------------------------------------- etisserant@31: etisserant@31: demoText = """\ etisserant@31: ## This version of the editor has been set up to edit Python source etisserant@31: ## code. Here is a copy of wxPython/demo/Main.py to play with. etisserant@31: etisserant@31: etisserant@31: """ etisserant@31: etisserant@31: #---------------------------------------------------------------------- etisserant@31: etisserant@31: etisserant@31: if wx.Platform == '__WXMSW__': etisserant@31: faces = { 'times': 'Times New Roman', etisserant@31: 'mono' : 'Courier New', etisserant@31: 'helv' : 'Arial', etisserant@31: 'other': 'Comic Sans MS', etisserant@31: 'size' : 10, etisserant@31: 'size2': 8, etisserant@31: } etisserant@31: else: etisserant@31: faces = { 'times': 'Times', etisserant@31: 'mono' : 'Courier', etisserant@31: 'helv' : 'Helvetica', etisserant@31: 'other': 'new century schoolbook', etisserant@31: 'size' : 12, etisserant@31: 'size2': 10, etisserant@31: } etisserant@31: etisserant@31: etisserant@31: #---------------------------------------------------------------------- etisserant@31: etisserant@31: class CppSTC(stc.StyledTextCtrl): etisserant@31: etisserant@31: fold_symbols = 3 etisserant@31: etisserant@31: def __init__(self, parent, ID, etisserant@31: pos=wx.DefaultPosition, size=wx.DefaultSize, etisserant@31: style=0): etisserant@31: stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style) etisserant@31: etisserant@31: self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN) etisserant@31: self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT) etisserant@31: etisserant@31: self.SetLexer(stc.STC_LEX_CPP) etisserant@31: #self.SetKeyWords(0, " ".join(keyword.kwlist)) etisserant@31: etisserant@31: self.SetProperty("fold", "1") etisserant@31: self.SetProperty("tab.timmy.whinge.level", "1") etisserant@31: self.SetMargins(0,0) etisserant@31: etisserant@31: self.SetViewWhiteSpace(False) etisserant@31: #self.SetBufferedDraw(False) etisserant@31: #self.SetViewEOL(True) etisserant@31: #self.SetEOLMode(stc.STC_EOL_CRLF) etisserant@31: #self.SetUseAntiAliasing(True) etisserant@31: etisserant@31: self.SetEdgeMode(stc.STC_EDGE_BACKGROUND) etisserant@31: self.SetEdgeColumn(78) etisserant@31: etisserant@31: # Setup a margin to hold fold markers etisserant@31: #self.SetFoldFlags(16) ### WHAT IS THIS VALUE? WHAT ARE THE OTHER FLAGS? DOES IT MATTER? etisserant@31: self.SetMarginType(2, stc.STC_MARGIN_SYMBOL) etisserant@31: self.SetMarginMask(2, stc.STC_MASK_FOLDERS) etisserant@31: self.SetMarginSensitive(2, True) etisserant@31: self.SetMarginWidth(2, 12) etisserant@31: etisserant@31: if self.fold_symbols == 0: etisserant@31: # Arrow pointing right for contracted folders, arrow pointing down for expanded etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") etisserant@31: etisserant@31: elif self.fold_symbols == 1: etisserant@31: # Plus for contracted folders, minus for expanded etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") etisserant@31: etisserant@31: elif self.fold_symbols == 2: etisserant@31: # Like a flattened tree control using circular headers and curved joins etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040") etisserant@31: etisserant@31: elif self.fold_symbols == 3: etisserant@31: # Like a flattened tree control using square headers etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080") etisserant@31: self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080") etisserant@31: etisserant@31: etisserant@31: self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) etisserant@31: self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick) etisserant@31: self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed) etisserant@31: etisserant@31: # Make some styles, The lexer defines what each style is used for, we etisserant@31: # just have to define what each style looks like. This set is adapted from etisserant@31: # Scintilla sample property files. etisserant@31: etisserant@31: # Global default styles for all languages etisserant@31: self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces) etisserant@31: self.StyleClearAll() # Reset all to be like the default etisserant@31: etisserant@31: # Global default styles for all languages etisserant@31: self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces) etisserant@31: self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces) etisserant@31: self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces) etisserant@31: self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold") etisserant@31: self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold") etisserant@31: etisserant@31: self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#dcc000') etisserant@31: self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#dcc000') etisserant@31: self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#dcc000') etisserant@31: self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE') etisserant@31: self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#004080') etisserant@31: self.StyleSetSpec(stc.STC_C_STRING, 'fore:#800080') etisserant@31: self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'fore:#808000') etisserant@31: self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold') etisserant@31: self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF') etisserant@31: etisserant@31: """ etisserant@31: # Python styles etisserant@31: # Default etisserant@31: self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % faces) etisserant@31: # Comments etisserant@31: self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % faces) etisserant@31: # Number etisserant@31: self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % faces) etisserant@31: # String etisserant@31: self.StyleSetSpec(stc.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces) etisserant@31: # Single quoted string etisserant@31: self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces) etisserant@31: # Keyword etisserant@31: self.StyleSetSpec(stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % faces) etisserant@31: # Triple quotes etisserant@31: self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % faces) etisserant@31: # Triple double quotes etisserant@31: self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % faces) etisserant@31: # Class name definition etisserant@31: self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % faces) etisserant@31: # Function or method name definition etisserant@31: self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % faces) etisserant@31: # Operators etisserant@31: self.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d" % faces) etisserant@31: # Identifiers etisserant@31: self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % faces) etisserant@31: # Comment-blocks etisserant@31: self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % faces) etisserant@31: # End of line where string is not closed etisserant@31: self.StyleSetSpec(stc.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % faces) etisserant@31: """ etisserant@31: self.SetCaretForeground("BLUE") etisserant@31: etisserant@31: etisserant@31: # register some images for use in the AutoComplete box. etisserant@31: #self.RegisterImage(1, images.getSmilesBitmap()) etisserant@31: self.RegisterImage(1, etisserant@31: wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16))) etisserant@31: self.RegisterImage(2, etisserant@31: wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16))) etisserant@31: self.RegisterImage(3, etisserant@31: wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16))) etisserant@31: etisserant@31: etisserant@31: def OnKeyPressed(self, event): etisserant@31: if self.CallTipActive(): etisserant@31: self.CallTipCancel() etisserant@31: key = event.KeyCode() etisserant@31: etisserant@31: if key == 32 and event.ControlDown(): etisserant@31: pos = self.GetCurrentPos() etisserant@31: etisserant@31: # Tips etisserant@31: if event.ShiftDown(): etisserant@31: self.CallTipSetBackground("yellow") etisserant@31: self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n' etisserant@31: 'show some suff, maybe parameters..\n\n' etisserant@31: 'fubar(param1, param2)') etisserant@31: # Code completion etisserant@31: else: etisserant@31: #lst = [] etisserant@31: #for x in range(50000): etisserant@31: # lst.append('%05d' % x) etisserant@31: #st = " ".join(lst) etisserant@31: #print len(st) etisserant@31: #self.AutoCompShow(0, st) etisserant@31: etisserant@31: #kw = keyword.kwlist[:] etisserant@31: kw = [] etisserant@31: """ etisserant@31: kw.append("zzzzzz?2") etisserant@31: kw.append("aaaaa?2") etisserant@31: kw.append("__init__?3") etisserant@31: kw.append("zzaaaaa?2") etisserant@31: kw.append("zzbaaaa?2") etisserant@31: kw.append("this_is_a_longer_value") etisserant@31: """ etisserant@31: #kw.append("this_is_a_much_much_much_much_much_much_much_longer_value") etisserant@31: etisserant@31: kw.sort() # Python sorts are case sensitive etisserant@31: self.AutoCompSetIgnoreCase(False) # so this needs to match etisserant@31: etisserant@31: # Images are specified with a appended "?type" etisserant@31: for i in range(len(kw)): etisserant@31: if kw[i] in keyword.kwlist: etisserant@31: kw[i] = kw[i] + "?1" etisserant@31: etisserant@31: self.AutoCompShow(0, " ".join(kw)) etisserant@31: else: etisserant@31: event.Skip() etisserant@31: etisserant@31: etisserant@31: def OnUpdateUI(self, evt): etisserant@31: # check for matching braces etisserant@31: braceAtCaret = -1 etisserant@31: braceOpposite = -1 etisserant@31: charBefore = None etisserant@31: caretPos = self.GetCurrentPos() etisserant@31: etisserant@31: if caretPos > 0: etisserant@31: charBefore = self.GetCharAt(caretPos - 1) etisserant@31: styleBefore = self.GetStyleAt(caretPos - 1) etisserant@31: etisserant@31: # check before etisserant@31: if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR: etisserant@31: braceAtCaret = caretPos - 1 etisserant@31: etisserant@31: # check after etisserant@31: if braceAtCaret < 0: etisserant@31: charAfter = self.GetCharAt(caretPos) etisserant@31: styleAfter = self.GetStyleAt(caretPos) etisserant@31: etisserant@31: if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR: etisserant@31: braceAtCaret = caretPos etisserant@31: etisserant@31: if braceAtCaret >= 0: etisserant@31: braceOpposite = self.BraceMatch(braceAtCaret) etisserant@31: etisserant@31: if braceAtCaret != -1 and braceOpposite == -1: etisserant@31: self.BraceBadLight(braceAtCaret) etisserant@31: else: etisserant@31: self.BraceHighlight(braceAtCaret, braceOpposite) etisserant@31: #pt = self.PointFromPosition(braceOpposite) etisserant@31: #self.Refresh(True, wxRect(pt.x, pt.y, 5,5)) etisserant@31: #print pt etisserant@31: #self.Refresh(False) etisserant@31: etisserant@31: etisserant@31: def OnMarginClick(self, evt): etisserant@31: # fold and unfold as needed etisserant@31: if evt.GetMargin() == 2: etisserant@31: if evt.GetShift() and evt.GetControl(): etisserant@31: self.FoldAll() etisserant@31: else: etisserant@31: lineClicked = self.LineFromPosition(evt.GetPosition()) etisserant@31: etisserant@31: if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG: etisserant@31: if evt.GetShift(): etisserant@31: self.SetFoldExpanded(lineClicked, True) etisserant@31: self.Expand(lineClicked, True, True, 1) etisserant@31: elif evt.GetControl(): etisserant@31: if self.GetFoldExpanded(lineClicked): etisserant@31: self.SetFoldExpanded(lineClicked, False) etisserant@31: self.Expand(lineClicked, False, True, 0) etisserant@31: else: etisserant@31: self.SetFoldExpanded(lineClicked, True) etisserant@31: self.Expand(lineClicked, True, True, 100) etisserant@31: else: etisserant@31: self.ToggleFold(lineClicked) etisserant@31: etisserant@31: etisserant@31: def FoldAll(self): etisserant@31: lineCount = self.GetLineCount() etisserant@31: expanding = True etisserant@31: etisserant@31: # find out if we are folding or unfolding etisserant@31: for lineNum in range(lineCount): etisserant@31: if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: etisserant@31: expanding = not self.GetFoldExpanded(lineNum) etisserant@31: break etisserant@31: etisserant@31: lineNum = 0 etisserant@31: etisserant@31: while lineNum < lineCount: etisserant@31: level = self.GetFoldLevel(lineNum) etisserant@31: if level & stc.STC_FOLDLEVELHEADERFLAG and \ etisserant@31: (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: etisserant@31: etisserant@31: if expanding: etisserant@31: self.SetFoldExpanded(lineNum, True) etisserant@31: lineNum = self.Expand(lineNum, True) etisserant@31: lineNum = lineNum - 1 etisserant@31: else: etisserant@31: lastChild = self.GetLastChild(lineNum, -1) etisserant@31: self.SetFoldExpanded(lineNum, False) etisserant@31: etisserant@31: if lastChild > lineNum: etisserant@31: self.HideLines(lineNum+1, lastChild) etisserant@31: etisserant@31: lineNum = lineNum + 1 etisserant@31: etisserant@31: etisserant@31: etisserant@31: def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): etisserant@31: lastChild = self.GetLastChild(line, level) etisserant@31: line = line + 1 etisserant@31: etisserant@31: while line <= lastChild: etisserant@31: if force: etisserant@31: if visLevels > 0: etisserant@31: self.ShowLines(line, line) etisserant@31: else: etisserant@31: self.HideLines(line, line) etisserant@31: else: etisserant@31: if doExpand: etisserant@31: self.ShowLines(line, line) etisserant@31: etisserant@31: if level == -1: etisserant@31: level = self.GetFoldLevel(line) etisserant@31: etisserant@31: if level & stc.STC_FOLDLEVELHEADERFLAG: etisserant@31: if force: etisserant@31: if visLevels > 1: etisserant@31: self.SetFoldExpanded(line, True) etisserant@31: else: etisserant@31: self.SetFoldExpanded(line, False) etisserant@31: etisserant@31: line = self.Expand(line, doExpand, force, visLevels-1) etisserant@31: etisserant@31: else: etisserant@31: if doExpand and self.GetFoldExpanded(line): etisserant@31: line = self.Expand(line, True, force, visLevels-1) etisserant@31: else: etisserant@31: line = self.Expand(line, False, force, visLevels-1) etisserant@31: else: etisserant@31: line = line + 1 etisserant@31: etisserant@31: return line etisserant@31: