plugins/c_ext/CppSTC.py
changeset 145 94855f7b08a9
parent 144 7818ec7b5c53
child 146 ad2d8431104e
equal deleted inserted replaced
144:7818ec7b5c53 145:94855f7b08a9
     1 import  wx
       
     2 import  wx.stc  as  stc
       
     3 
       
     4 #----------------------------------------------------------------------
       
     5 
       
     6 demoText = """\
       
     7 ## This version of the editor has been set up to edit Python source
       
     8 ## code.  Here is a copy of wxPython/demo/Main.py to play with.
       
     9 
       
    10 
       
    11 """
       
    12 
       
    13 #----------------------------------------------------------------------
       
    14 
       
    15 
       
    16 if wx.Platform == '__WXMSW__':
       
    17     faces = { 'times': 'Times New Roman',
       
    18               'mono' : 'Courier New',
       
    19               'helv' : 'Arial',
       
    20               'other': 'Comic Sans MS',
       
    21               'size' : 10,
       
    22               'size2': 8,
       
    23              }
       
    24 else:
       
    25     faces = { 'times': 'Times',
       
    26               'mono' : 'Courier',
       
    27               'helv' : 'Helvetica',
       
    28               'other': 'new century schoolbook',
       
    29               'size' : 12,
       
    30               'size2': 10,
       
    31              }
       
    32 
       
    33 
       
    34 #----------------------------------------------------------------------
       
    35 
       
    36 class CppSTC(stc.StyledTextCtrl):
       
    37 
       
    38     fold_symbols = 3
       
    39     
       
    40     def __init__(self, parent, ID,
       
    41                  pos=wx.DefaultPosition, size=wx.DefaultSize,
       
    42                  style=0):
       
    43         stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
       
    44 
       
    45         self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
       
    46         self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
       
    47 
       
    48         self.SetLexer(stc.STC_LEX_CPP)
       
    49         #self.SetKeyWords(0, " ".join(keyword.kwlist))
       
    50 
       
    51         self.SetProperty("fold", "1")
       
    52         self.SetProperty("tab.timmy.whinge.level", "1")
       
    53         self.SetMargins(0,0)
       
    54 
       
    55         self.SetViewWhiteSpace(False)
       
    56         #self.SetBufferedDraw(False)
       
    57         #self.SetViewEOL(True)
       
    58         #self.SetEOLMode(stc.STC_EOL_CRLF)
       
    59         #self.SetUseAntiAliasing(True)
       
    60         
       
    61         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
       
    62         self.SetEdgeColumn(78)
       
    63 
       
    64         # Setup a margin to hold fold markers
       
    65         #self.SetFoldFlags(16)  ###  WHAT IS THIS VALUE?  WHAT ARE THE OTHER FLAGS?  DOES IT MATTER?
       
    66         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
       
    67         self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
       
    68         self.SetMarginSensitive(2, True)
       
    69         self.SetMarginWidth(2, 12)
       
    70 
       
    71         if self.fold_symbols == 0:
       
    72             # Arrow pointing right for contracted folders, arrow pointing down for expanded
       
    73             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
       
    74             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
       
    75             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
       
    76             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
       
    77             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
       
    78             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
       
    79             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
       
    80             
       
    81         elif self.fold_symbols == 1:
       
    82             # Plus for contracted folders, minus for expanded
       
    83             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
       
    84             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
       
    85             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
       
    86             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
       
    87             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
       
    88             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
       
    89             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
       
    90 
       
    91         elif self.fold_symbols == 2:
       
    92             # Like a flattened tree control using circular headers and curved joins
       
    93             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
       
    94             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
       
    95             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
       
    96             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
       
    97             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
       
    98             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
       
    99             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
       
   100 
       
   101         elif self.fold_symbols == 3:
       
   102             # Like a flattened tree control using square headers
       
   103             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
       
   104             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
       
   105             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
       
   106             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
       
   107             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
       
   108             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
       
   109             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
       
   110 
       
   111 
       
   112         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
       
   113         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
       
   114         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
       
   115 
       
   116         # Make some styles,  The lexer defines what each style is used for, we
       
   117         # just have to define what each style looks like.  This set is adapted from
       
   118         # Scintilla sample property files.
       
   119 
       
   120         # Global default styles for all languages
       
   121         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
       
   122         self.StyleClearAll()  # Reset all to be like the default
       
   123 
       
   124         # Global default styles for all languages
       
   125         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
       
   126         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
       
   127         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
       
   128         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
       
   129         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
       
   130 
       
   131         self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#dcc000')
       
   132         self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#dcc000')
       
   133         self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#dcc000')
       
   134         self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
       
   135         self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#004080')
       
   136         self.StyleSetSpec(stc.STC_C_STRING, 'fore:#800080')
       
   137         self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'fore:#808000')
       
   138         self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
       
   139         self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
       
   140 
       
   141         """
       
   142         # Python styles
       
   143         # Default 
       
   144         self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
       
   145         # Comments
       
   146         self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % faces)
       
   147         # Number
       
   148         self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
       
   149         # String
       
   150         self.StyleSetSpec(stc.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
       
   151         # Single quoted string
       
   152         self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
       
   153         # Keyword
       
   154         self.StyleSetSpec(stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
       
   155         # Triple quotes
       
   156         self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % faces)
       
   157         # Triple double quotes
       
   158         self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % faces)
       
   159         # Class name definition
       
   160         self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % faces)
       
   161         # Function or method name definition
       
   162         self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % faces)
       
   163         # Operators
       
   164         self.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d" % faces)
       
   165         # Identifiers
       
   166         self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
       
   167         # Comment-blocks
       
   168         self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % faces)
       
   169         # End of line where string is not closed
       
   170         self.StyleSetSpec(stc.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % faces)
       
   171         """
       
   172         self.SetCaretForeground("BLUE")
       
   173 
       
   174 
       
   175         # register some images for use in the AutoComplete box.
       
   176         #self.RegisterImage(1, images.getSmilesBitmap())
       
   177         self.RegisterImage(1, 
       
   178             wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
       
   179         self.RegisterImage(2, 
       
   180             wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
       
   181         self.RegisterImage(3, 
       
   182             wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
       
   183 
       
   184 
       
   185     def OnKeyPressed(self, event):
       
   186         if self.CallTipActive():
       
   187             self.CallTipCancel()
       
   188         key = event.KeyCode()
       
   189 
       
   190         if key == 32 and event.ControlDown():
       
   191             pos = self.GetCurrentPos()
       
   192 
       
   193             # Tips
       
   194             if event.ShiftDown():
       
   195                 self.CallTipSetBackground("yellow")
       
   196                 self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
       
   197                                  'show some suff, maybe parameters..\n\n'
       
   198                                  'fubar(param1, param2)')
       
   199             # Code completion
       
   200             else:
       
   201                 #lst = []
       
   202                 #for x in range(50000):
       
   203                 #    lst.append('%05d' % x)
       
   204                 #st = " ".join(lst)
       
   205                 #print len(st)
       
   206                 #self.AutoCompShow(0, st)
       
   207 
       
   208                 #kw = keyword.kwlist[:]
       
   209                 kw = []
       
   210                 """
       
   211                 kw.append("zzzzzz?2")
       
   212                 kw.append("aaaaa?2")
       
   213                 kw.append("__init__?3")
       
   214                 kw.append("zzaaaaa?2")
       
   215                 kw.append("zzbaaaa?2")
       
   216                 kw.append("this_is_a_longer_value")
       
   217                 """
       
   218                 #kw.append("this_is_a_much_much_much_much_much_much_much_longer_value")
       
   219 
       
   220                 kw.sort()  # Python sorts are case sensitive
       
   221                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
       
   222 
       
   223                 # Images are specified with a appended "?type"
       
   224                 for i in range(len(kw)):
       
   225                     if kw[i] in keyword.kwlist:
       
   226                         kw[i] = kw[i] + "?1"
       
   227 
       
   228                 self.AutoCompShow(0, " ".join(kw))
       
   229         else:
       
   230             event.Skip()
       
   231 
       
   232 
       
   233     def OnUpdateUI(self, evt):
       
   234         # check for matching braces
       
   235         braceAtCaret = -1
       
   236         braceOpposite = -1
       
   237         charBefore = None
       
   238         caretPos = self.GetCurrentPos()
       
   239 
       
   240         if caretPos > 0:
       
   241             charBefore = self.GetCharAt(caretPos - 1)
       
   242             styleBefore = self.GetStyleAt(caretPos - 1)
       
   243 
       
   244         # check before
       
   245         if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
       
   246             braceAtCaret = caretPos - 1
       
   247 
       
   248         # check after
       
   249         if braceAtCaret < 0:
       
   250             charAfter = self.GetCharAt(caretPos)
       
   251             styleAfter = self.GetStyleAt(caretPos)
       
   252 
       
   253             if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
       
   254                 braceAtCaret = caretPos
       
   255 
       
   256         if braceAtCaret >= 0:
       
   257             braceOpposite = self.BraceMatch(braceAtCaret)
       
   258 
       
   259         if braceAtCaret != -1  and braceOpposite == -1:
       
   260             self.BraceBadLight(braceAtCaret)
       
   261         else:
       
   262             self.BraceHighlight(braceAtCaret, braceOpposite)
       
   263             #pt = self.PointFromPosition(braceOpposite)
       
   264             #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
       
   265             #print pt
       
   266             #self.Refresh(False)
       
   267 
       
   268 
       
   269     def OnMarginClick(self, evt):
       
   270         # fold and unfold as needed
       
   271         if evt.GetMargin() == 2:
       
   272             if evt.GetShift() and evt.GetControl():
       
   273                 self.FoldAll()
       
   274             else:
       
   275                 lineClicked = self.LineFromPosition(evt.GetPosition())
       
   276 
       
   277                 if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
       
   278                     if evt.GetShift():
       
   279                         self.SetFoldExpanded(lineClicked, True)
       
   280                         self.Expand(lineClicked, True, True, 1)
       
   281                     elif evt.GetControl():
       
   282                         if self.GetFoldExpanded(lineClicked):
       
   283                             self.SetFoldExpanded(lineClicked, False)
       
   284                             self.Expand(lineClicked, False, True, 0)
       
   285                         else:
       
   286                             self.SetFoldExpanded(lineClicked, True)
       
   287                             self.Expand(lineClicked, True, True, 100)
       
   288                     else:
       
   289                         self.ToggleFold(lineClicked)
       
   290 
       
   291 
       
   292     def FoldAll(self):
       
   293         lineCount = self.GetLineCount()
       
   294         expanding = True
       
   295 
       
   296         # find out if we are folding or unfolding
       
   297         for lineNum in range(lineCount):
       
   298             if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
       
   299                 expanding = not self.GetFoldExpanded(lineNum)
       
   300                 break
       
   301 
       
   302         lineNum = 0
       
   303 
       
   304         while lineNum < lineCount:
       
   305             level = self.GetFoldLevel(lineNum)
       
   306             if level & stc.STC_FOLDLEVELHEADERFLAG and \
       
   307                (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
       
   308 
       
   309                 if expanding:
       
   310                     self.SetFoldExpanded(lineNum, True)
       
   311                     lineNum = self.Expand(lineNum, True)
       
   312                     lineNum = lineNum - 1
       
   313                 else:
       
   314                     lastChild = self.GetLastChild(lineNum, -1)
       
   315                     self.SetFoldExpanded(lineNum, False)
       
   316 
       
   317                     if lastChild > lineNum:
       
   318                         self.HideLines(lineNum+1, lastChild)
       
   319 
       
   320             lineNum = lineNum + 1
       
   321 
       
   322 
       
   323 
       
   324     def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
       
   325         lastChild = self.GetLastChild(line, level)
       
   326         line = line + 1
       
   327 
       
   328         while line <= lastChild:
       
   329             if force:
       
   330                 if visLevels > 0:
       
   331                     self.ShowLines(line, line)
       
   332                 else:
       
   333                     self.HideLines(line, line)
       
   334             else:
       
   335                 if doExpand:
       
   336                     self.ShowLines(line, line)
       
   337 
       
   338             if level == -1:
       
   339                 level = self.GetFoldLevel(line)
       
   340 
       
   341             if level & stc.STC_FOLDLEVELHEADERFLAG:
       
   342                 if force:
       
   343                     if visLevels > 1:
       
   344                         self.SetFoldExpanded(line, True)
       
   345                     else:
       
   346                         self.SetFoldExpanded(line, False)
       
   347 
       
   348                     line = self.Expand(line, doExpand, force, visLevels-1)
       
   349 
       
   350                 else:
       
   351                     if doExpand and self.GetFoldExpanded(line):
       
   352                         line = self.Expand(line, True, force, visLevels-1)
       
   353                     else:
       
   354                         line = self.Expand(line, False, force, visLevels-1)
       
   355             else:
       
   356                 line = line + 1
       
   357 
       
   358         return line
       
   359