confnodes/python/PythonEditor.py
changeset 721 ecf4d203c4d4
parent 720 6be032177e2a
child 722 a94f361fc42e
equal deleted inserted replaced
720:6be032177e2a 721:ecf4d203c4d4
     1 import  wx, wx.grid
       
     2 import  wx.stc  as  stc
       
     3 import keyword
       
     4 
       
     5 from controls import EditorPanel
       
     6 
       
     7 if wx.Platform == '__WXMSW__':
       
     8     faces = { 'times': 'Times New Roman',
       
     9               'mono' : 'Courier New',
       
    10               'helv' : 'Arial',
       
    11               'other': 'Comic Sans MS',
       
    12               'size' : 10,
       
    13               'size2': 8,
       
    14              }
       
    15 elif wx.Platform == '__WXMAC__':
       
    16     faces = { 'times': 'Times New Roman',
       
    17               'mono' : 'Monaco',
       
    18               'helv' : 'Arial',
       
    19               'other': 'Comic Sans MS',
       
    20               'size' : 12,
       
    21               'size2': 10,
       
    22              }
       
    23 else:
       
    24     faces = { 'times': 'Times',
       
    25               'mono' : 'Courier',
       
    26               'helv' : 'Helvetica',
       
    27               'other': 'new century schoolbook',
       
    28               'size' : 12,
       
    29               'size2': 10,
       
    30              }
       
    31 
       
    32 [ID_PYTHONEDITOR,
       
    33 ] = [wx.NewId() for _init_ctrls in range(1)]
       
    34 
       
    35 def GetCursorPos(old, new):
       
    36     old_length = len(old)
       
    37     new_length = len(new)
       
    38     common_length = min(old_length, new_length)
       
    39     i = 0
       
    40     for i in xrange(common_length):
       
    41         if old[i] != new[i]:
       
    42             break
       
    43     if old_length < new_length:
       
    44         if common_length > 0 and old[i] != new[i]:
       
    45             return i + new_length - old_length
       
    46         else:
       
    47             return i + new_length - old_length + 1
       
    48     elif old_length > new_length or i < min(old_length, new_length) - 1:
       
    49         if common_length > 0 and old[i] != new[i]:
       
    50             return i
       
    51         else:
       
    52             return i + 1
       
    53     else:
       
    54         return None
       
    55 
       
    56 class PythonEditor(EditorPanel):
       
    57 
       
    58     fold_symbols = 3
       
    59     
       
    60     def _init_Editor(self, prnt):
       
    61         self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt,
       
    62                  name="TextViewer", pos=wx.DefaultPosition, 
       
    63                  size=wx.DefaultSize, style=0)
       
    64 
       
    65         self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
       
    66         self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
       
    67 
       
    68         self.Editor.SetLexer(stc.STC_LEX_PYTHON)
       
    69         self.Editor.SetKeyWords(0, " ".join(keyword.kwlist))
       
    70 
       
    71         self.Editor.SetProperty("fold", "1")
       
    72         self.Editor.SetProperty("tab.timmy.whinge.level", "1")
       
    73         self.Editor.SetMargins(0,0)
       
    74 
       
    75         self.Editor.SetViewWhiteSpace(False)
       
    76         
       
    77         self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
       
    78         self.Editor.SetEdgeColumn(78)
       
    79 
       
    80         # Set up the numbers in the margin for margin #1
       
    81         self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
       
    82         # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
       
    83         self.Editor.SetMarginWidth(1, 40)
       
    84 
       
    85         # Setup a margin to hold fold markers
       
    86         self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
       
    87         self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS)
       
    88         self.Editor.SetMarginSensitive(2, True)
       
    89         self.Editor.SetMarginWidth(2, 12)
       
    90 
       
    91         if self.fold_symbols == 0:
       
    92             # Arrow pointing right for contracted folders, arrow pointing down for expanded
       
    93             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
       
    94             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
       
    95             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
       
    96             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
       
    97             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
       
    98             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
       
    99             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
       
   100             
       
   101         elif self.fold_symbols == 1:
       
   102             # Plus for contracted folders, minus for expanded
       
   103             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
       
   104             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
       
   105             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
       
   106             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
       
   107             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
       
   108             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
       
   109             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
       
   110 
       
   111         elif self.fold_symbols == 2:
       
   112             # Like a flattened tree control using circular headers and curved joins
       
   113             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
       
   114             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
       
   115             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
       
   116             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
       
   117             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
       
   118             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
       
   119             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
       
   120 
       
   121         elif self.fold_symbols == 3:
       
   122             # Like a flattened tree control using square headers
       
   123             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
       
   124             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
       
   125             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
       
   126             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
       
   127             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
       
   128             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
       
   129             self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
       
   130 
       
   131 
       
   132         self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
       
   133         self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
       
   134         self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
       
   135 
       
   136         # Global default style
       
   137         if wx.Platform == '__WXMSW__':
       
   138             self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New')
       
   139         elif wx.Platform == '__WXMAC__':
       
   140             # TODO: if this looks fine on Linux too, remove the Mac-specific case 
       
   141             # and use this whenever OS != MSW.
       
   142             self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco')
       
   143         else:
       
   144             defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize()
       
   145             self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize)
       
   146 
       
   147         # Clear styles and revert to default.
       
   148         self.Editor.StyleClearAll()
       
   149 
       
   150         # Following style specs only indicate differences from default.
       
   151         # The rest remains unchanged.
       
   152 
       
   153         # Line numbers in margin
       
   154         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')    
       
   155         # Highlighted brace
       
   156         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
       
   157         # Unmatched brace
       
   158         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
       
   159         # Indentation guide
       
   160         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
       
   161 
       
   162         # Python styles
       
   163         self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
       
   164         # Comments
       
   165         self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE,  'fore:#008000,back:#F0FFF0')
       
   166         self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
       
   167         # Numbers
       
   168         self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
       
   169         # Strings and characters
       
   170         self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
       
   171         self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
       
   172         # Keywords
       
   173         self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
       
   174         # Triple quotes
       
   175         self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
       
   176         self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
       
   177         # Class names
       
   178         self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
       
   179         # Function names
       
   180         self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
       
   181         # Operators
       
   182         self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
       
   183         # Identifiers. I leave this as not bold because everything seems
       
   184         # to be an identifier if it doesn't match the above criterae
       
   185         self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
       
   186 
       
   187         # Caret color
       
   188         self.Editor.SetCaretForeground("BLUE")
       
   189         # Selection background
       
   190         self.Editor.SetSelBackground(1, '#66CCFF')
       
   191 
       
   192         self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
       
   193         self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
       
   194         
       
   195         # register some images for use in the AutoComplete box.
       
   196         #self.RegisterImage(1, images.getSmilesBitmap())
       
   197         self.Editor.RegisterImage(1, 
       
   198             wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
       
   199         self.Editor.RegisterImage(2, 
       
   200             wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
       
   201         self.Editor.RegisterImage(3, 
       
   202             wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
       
   203 
       
   204         # Indentation and tab stuff
       
   205         self.Editor.SetIndent(4)               # Proscribed indent size for wx
       
   206         self.Editor.SetIndentationGuides(True) # Show indent guides
       
   207         self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
       
   208         self.Editor.SetTabIndents(True)        # Tab key indents
       
   209         self.Editor.SetTabWidth(4)             # Proscribed tab size for wx
       
   210         self.Editor.SetUseTabs(False)          # Use spaces rather than tabs, or
       
   211                                         # TabTimmy will complain!    
       
   212         # White space
       
   213         self.Editor.SetViewWhiteSpace(False)   # Don't view white space
       
   214 
       
   215         # EOL: Since we are loading/saving ourselves, and the
       
   216         # strings will always have \n's in them, set the STC to
       
   217         # edit them that way.            
       
   218         self.Editor.SetEOLMode(wx.stc.STC_EOL_LF)
       
   219         self.Editor.SetViewEOL(False)
       
   220         
       
   221         # No right-edge mode indicator
       
   222         self.Editor.SetEdgeMode(stc.STC_EDGE_NONE)
       
   223         
       
   224         self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
       
   225 
       
   226         self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR)
       
   227         self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
       
   228         self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR)
       
   229 
       
   230 
       
   231     def __init__(self, parent, controler, window):
       
   232         EditorPanel.__init__(self, parent, "", window, controler)
       
   233         
       
   234         self.DisableEvents = False
       
   235         self.CurrentAction = None
       
   236         
       
   237         img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
       
   238         self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
       
   239     
       
   240     def __del__(self):
       
   241         self.Controler.OnCloseEditor(self)
       
   242     
       
   243     def GetTitle(self):
       
   244         fullname = self.Controler.CTNFullName()
       
   245         if not self.Controler.PythonIsSaved():
       
   246             return "~%s~" % fullname
       
   247         return fullname
       
   248     
       
   249     def GetBufferState(self):
       
   250         return self.Controler.GetBufferState()
       
   251         
       
   252     def Undo(self):
       
   253         self.Controler.LoadPrevious()
       
   254         self.RefreshView()
       
   255             
       
   256     def Redo(self):
       
   257         self.Controler.LoadNext()
       
   258         self.RefreshView()
       
   259     
       
   260     def HasNoModel(self):
       
   261         return False
       
   262     
       
   263     def OnModification(self, event):
       
   264         if not self.DisableEvents:
       
   265             mod_type = event.GetModificationType()
       
   266             if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
       
   267                 if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
       
   268                     if self.CurrentAction is None:
       
   269                         self.StartBuffering()
       
   270                     elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
       
   271                         self.Controler.EndBuffering()
       
   272                         self.StartBuffering()
       
   273                     self.CurrentAction = ("Add", event.GetPosition())
       
   274                     wx.CallAfter(self.RefreshModel)
       
   275                 elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
       
   276                     if self.CurrentAction == None:
       
   277                         self.StartBuffering()
       
   278                     elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
       
   279                         self.Controler.EndBuffering()
       
   280                         self.StartBuffering()
       
   281                     self.CurrentAction = ("Delete", event.GetPosition())
       
   282                     wx.CallAfter(self.RefreshModel)
       
   283         event.Skip()
       
   284     
       
   285     def OnDoDrop(self, event):
       
   286         self.ResetBuffer()
       
   287         wx.CallAfter(self.RefreshModel)
       
   288         event.Skip()
       
   289 
       
   290     # Buffer the last model state
       
   291     def RefreshBuffer(self):
       
   292         self.Controler.BufferPython()
       
   293         if self.ParentWindow is not None:
       
   294             self.ParentWindow.RefreshTitle()
       
   295             self.ParentWindow.RefreshFileMenu()
       
   296             self.ParentWindow.RefreshEditMenu()
       
   297             self.ParentWindow.RefreshPageTitles()
       
   298     
       
   299     def StartBuffering(self):
       
   300         self.Controler.StartBuffering()
       
   301         if self.ParentWindow is not None:
       
   302             self.ParentWindow.RefreshTitle()
       
   303             self.ParentWindow.RefreshFileMenu()
       
   304             self.ParentWindow.RefreshEditMenu()
       
   305             self.ParentWindow.RefreshPageTitles()
       
   306     
       
   307     def ResetBuffer(self):
       
   308         if self.CurrentAction != None:
       
   309             self.Controler.EndBuffering()
       
   310             self.CurrentAction = None
       
   311 
       
   312     def RefreshView(self):
       
   313         self.ResetBuffer()
       
   314         self.DisableEvents = True
       
   315         old_cursor_pos = self.Editor.GetCurrentPos()
       
   316         old_text = self.Editor.GetText()
       
   317         new_text = self.Controler.GetPythonCode()
       
   318         self.Editor.SetText(new_text)
       
   319         new_cursor_pos = GetCursorPos(old_text, new_text)
       
   320         if new_cursor_pos != None:
       
   321             self.Editor.GotoPos(new_cursor_pos)
       
   322         else:
       
   323             self.Editor.GotoPos(old_cursor_pos)
       
   324         self.Editor.ScrollToColumn(0)
       
   325         self.Editor.EmptyUndoBuffer()
       
   326         self.DisableEvents = False
       
   327         
       
   328         self.Editor.Colourise(0, -1)
       
   329 
       
   330     def RefreshModel(self):
       
   331         self.Controler.SetPythonCode(self.Editor.GetText())
       
   332 
       
   333     def OnKeyPressed(self, event):
       
   334         if self.Editor.CallTipActive():
       
   335             self.Editor.CallTipCancel()
       
   336         key = event.GetKeyCode()
       
   337 
       
   338         if key == 32 and event.ControlDown():
       
   339             pos = self.Editor.GetCurrentPos()
       
   340 
       
   341             # Tips
       
   342             if event.ShiftDown():
       
   343                 pass
       
   344 ##                self.CallTipSetBackground("yellow")
       
   345 ##                self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
       
   346 ##                                 'show some suff, maybe parameters..\n\n'
       
   347 ##                                 'fubar(param1, param2)')
       
   348             # Code completion
       
   349             else:
       
   350                 self.Editor.AutoCompSetIgnoreCase(False)  # so this needs to match
       
   351 
       
   352                 # Images are specified with a appended "?type"
       
   353                 self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
       
   354         else:
       
   355             event.Skip()
       
   356 
       
   357     def OnKillFocus(self, event):
       
   358         self.Editor.AutoCompCancel()
       
   359         event.Skip()
       
   360 
       
   361     def OnUpdateUI(self, evt):
       
   362         # check for matching braces
       
   363         braceAtCaret = -1
       
   364         braceOpposite = -1
       
   365         charBefore = None
       
   366         caretPos = self.Editor.GetCurrentPos()
       
   367 
       
   368         if caretPos > 0:
       
   369             charBefore = self.Editor.GetCharAt(caretPos - 1)
       
   370             styleBefore = self.Editor.GetStyleAt(caretPos - 1)
       
   371 
       
   372         # check before
       
   373         if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
       
   374             braceAtCaret = caretPos - 1
       
   375 
       
   376         # check after
       
   377         if braceAtCaret < 0:
       
   378             charAfter = self.Editor.GetCharAt(caretPos)
       
   379             styleAfter = self.Editor.GetStyleAt(caretPos)
       
   380 
       
   381             if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
       
   382                 braceAtCaret = caretPos
       
   383 
       
   384         if braceAtCaret >= 0:
       
   385             braceOpposite = self.Editor.BraceMatch(braceAtCaret)
       
   386 
       
   387         if braceAtCaret != -1  and braceOpposite == -1:
       
   388             self.Editor.BraceBadLight(braceAtCaret)
       
   389         else:
       
   390             self.Editor.BraceHighlight(braceAtCaret, braceOpposite)
       
   391             #pt = self.Editor.PointFromPosition(braceOpposite)
       
   392             #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5))
       
   393             #print pt
       
   394             #self.Editor.Refresh(False)
       
   395 
       
   396 
       
   397     def OnMarginClick(self, evt):
       
   398         # fold and unfold as needed
       
   399         if evt.GetMargin() == 2:
       
   400             if evt.GetShift() and evt.GetControl():
       
   401                 self.FoldAll()
       
   402             else:
       
   403                 lineClicked = self.Editor.LineFromPosition(evt.GetPosition())
       
   404 
       
   405                 if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
       
   406                     if evt.GetShift():
       
   407                         self.Editor.SetFoldExpanded(lineClicked, True)
       
   408                         self.Expand(lineClicked, True, True, 1)
       
   409                     elif evt.GetControl():
       
   410                         if self.Editor.GetFoldExpanded(lineClicked):
       
   411                             self.Editor.SetFoldExpanded(lineClicked, False)
       
   412                             self.Expand(lineClicked, False, True, 0)
       
   413                         else:
       
   414                             self.Editor.SetFoldExpanded(lineClicked, True)
       
   415                             self.Expand(lineClicked, True, True, 100)
       
   416                     else:
       
   417                         self.Editor.ToggleFold(lineClicked)
       
   418 
       
   419 
       
   420     def FoldAll(self):
       
   421         lineCount = self.Editor.GetLineCount()
       
   422         expanding = True
       
   423 
       
   424         # find out if we are folding or unfolding
       
   425         for lineNum in range(lineCount):
       
   426             if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
       
   427                 expanding = not self.Editor.GetFoldExpanded(lineNum)
       
   428                 break
       
   429 
       
   430         lineNum = 0
       
   431 
       
   432         while lineNum < lineCount:
       
   433             level = self.Editor.GetFoldLevel(lineNum)
       
   434             if level & stc.STC_FOLDLEVELHEADERFLAG and \
       
   435                (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
       
   436 
       
   437                 if expanding:
       
   438                     self.Editor.SetFoldExpanded(lineNum, True)
       
   439                     lineNum = self.Expand(lineNum, True)
       
   440                     lineNum = lineNum - 1
       
   441                 else:
       
   442                     lastChild = self.Editor.GetLastChild(lineNum, -1)
       
   443                     self.Editor.SetFoldExpanded(lineNum, False)
       
   444 
       
   445                     if lastChild > lineNum:
       
   446                         self.Editor.HideLines(lineNum+1, lastChild)
       
   447 
       
   448             lineNum = lineNum + 1
       
   449 
       
   450 
       
   451 
       
   452     def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
       
   453         lastChild = self.Editor.GetLastChild(line, level)
       
   454         line = line + 1
       
   455 
       
   456         while line <= lastChild:
       
   457             if force:
       
   458                 if visLevels > 0:
       
   459                     self.Editor.ShowLines(line, line)
       
   460                 else:
       
   461                     self.Editor.HideLines(line, line)
       
   462             else:
       
   463                 if doExpand:
       
   464                     self.Editor.ShowLines(line, line)
       
   465 
       
   466             if level == -1:
       
   467                 level = self.Editor.GetFoldLevel(line)
       
   468 
       
   469             if level & stc.STC_FOLDLEVELHEADERFLAG:
       
   470                 if force:
       
   471                     if visLevels > 1:
       
   472                         self.Editor.SetFoldExpanded(line, True)
       
   473                     else:
       
   474                         self.Editor.SetFoldExpanded(line, False)
       
   475 
       
   476                     line = self.Expand(line, doExpand, force, visLevels-1)
       
   477 
       
   478                 else:
       
   479                     if doExpand and self.Editor.GetFoldExpanded(line):
       
   480                         line = self.Expand(line, True, force, visLevels-1)
       
   481                     else:
       
   482                         line = self.Expand(line, False, force, visLevels-1)
       
   483             else:
       
   484                 line = line + 1
       
   485 
       
   486         return line
       
   487 
       
   488     def Cut(self):
       
   489         self.ResetBuffer()
       
   490         self.DisableEvents = True
       
   491         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
       
   492         self.DisableEvents = False
       
   493         self.RefreshModel()
       
   494         self.RefreshBuffer()
       
   495     
       
   496     def Copy(self):
       
   497         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
       
   498     
       
   499     def Paste(self):
       
   500         self.ResetBuffer()
       
   501         self.DisableEvents = True
       
   502         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
       
   503         self.DisableEvents = False
       
   504         self.RefreshModel()
       
   505         self.RefreshBuffer()