laurent@366: import wx, wx.grid laurent@366: import wx.stc as stc laurent@366: import keyword laurent@366: laurent@657: from controls import EditorPanel laurent@657: laurent@366: if wx.Platform == '__WXMSW__': laurent@366: faces = { 'times': 'Times New Roman', laurent@366: 'mono' : 'Courier New', laurent@366: 'helv' : 'Arial', laurent@366: 'other': 'Comic Sans MS', laurent@366: 'size' : 10, laurent@366: 'size2': 8, laurent@366: } laurent@366: elif wx.Platform == '__WXMAC__': laurent@366: faces = { 'times': 'Times New Roman', laurent@366: 'mono' : 'Monaco', laurent@366: 'helv' : 'Arial', laurent@366: 'other': 'Comic Sans MS', laurent@366: 'size' : 12, laurent@366: 'size2': 10, laurent@366: } laurent@366: else: laurent@366: faces = { 'times': 'Times', laurent@366: 'mono' : 'Courier', laurent@366: 'helv' : 'Helvetica', laurent@366: 'other': 'new century schoolbook', laurent@366: 'size' : 12, laurent@366: 'size2': 10, laurent@366: } laurent@366: laurent@366: [ID_PYTHONEDITOR, laurent@366: ] = [wx.NewId() for _init_ctrls in range(1)] laurent@366: laurent@366: def GetCursorPos(old, new): laurent@366: old_length = len(old) laurent@366: new_length = len(new) laurent@366: common_length = min(old_length, new_length) laurent@366: i = 0 laurent@366: for i in xrange(common_length): laurent@366: if old[i] != new[i]: laurent@366: break laurent@366: if old_length < new_length: laurent@366: if common_length > 0 and old[i] != new[i]: laurent@366: return i + new_length - old_length laurent@366: else: laurent@366: return i + new_length - old_length + 1 laurent@366: elif old_length > new_length or i < min(old_length, new_length) - 1: laurent@366: if common_length > 0 and old[i] != new[i]: laurent@366: return i laurent@366: else: laurent@366: return i + 1 laurent@366: else: laurent@366: return None laurent@366: laurent@657: class PythonEditor(EditorPanel): laurent@366: laurent@366: fold_symbols = 3 laurent@366: laurent@657: def _init_Editor(self, prnt): laurent@657: self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt, laurent@657: name="TextViewer", pos=wx.DefaultPosition, laurent@657: size=wx.DefaultSize, style=0) laurent@657: laurent@657: self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN) laurent@657: self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT) laurent@657: laurent@657: self.Editor.SetLexer(stc.STC_LEX_PYTHON) laurent@657: self.Editor.SetKeyWords(0, " ".join(keyword.kwlist)) laurent@657: laurent@657: self.Editor.SetProperty("fold", "1") laurent@657: self.Editor.SetProperty("tab.timmy.whinge.level", "1") laurent@657: self.Editor.SetMargins(0,0) laurent@657: laurent@657: self.Editor.SetViewWhiteSpace(False) laurent@657: laurent@657: self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND) laurent@657: self.Editor.SetEdgeColumn(78) laurent@366: laurent@366: # Set up the numbers in the margin for margin #1 laurent@657: self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) laurent@366: # Reasonable value for, say, 4-5 digits using a mono font (40 pix) laurent@657: self.Editor.SetMarginWidth(1, 40) laurent@366: laurent@366: # Setup a margin to hold fold markers laurent@657: self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL) laurent@657: self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS) laurent@657: self.Editor.SetMarginSensitive(2, True) laurent@657: self.Editor.SetMarginWidth(2, 12) laurent@366: laurent@366: if self.fold_symbols == 0: laurent@366: # Arrow pointing right for contracted folders, arrow pointing down for expanded laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") laurent@366: laurent@366: elif self.fold_symbols == 1: laurent@366: # Plus for contracted folders, minus for expanded laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") laurent@366: laurent@366: elif self.fold_symbols == 2: laurent@366: # Like a flattened tree control using circular headers and curved joins laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040") laurent@366: laurent@366: elif self.fold_symbols == 3: laurent@366: # Like a flattened tree control using square headers laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080") laurent@657: self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080") laurent@657: laurent@657: laurent@657: self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) laurent@657: self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick) laurent@657: self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed) laurent@366: laurent@366: # Global default style laurent@366: if wx.Platform == '__WXMSW__': laurent@657: self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New') laurent@366: elif wx.Platform == '__WXMAC__': laurent@366: # TODO: if this looks fine on Linux too, remove the Mac-specific case laurent@366: # and use this whenever OS != MSW. laurent@657: self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco') laurent@366: else: laurent@366: defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize() laurent@657: self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize) laurent@366: laurent@366: # Clear styles and revert to default. laurent@657: self.Editor.StyleClearAll() laurent@366: laurent@366: # Following style specs only indicate differences from default. laurent@366: # The rest remains unchanged. laurent@366: laurent@366: # Line numbers in margin laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') laurent@366: # Highlighted brace laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') laurent@366: # Unmatched brace laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000') laurent@366: # Indentation guide laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD") laurent@366: laurent@366: # Python styles laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000') laurent@366: # Comments laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0') laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0') laurent@366: # Numbers laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080') laurent@366: # Strings and characters laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080') laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080') laurent@366: # Keywords laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold') laurent@366: # Triple quotes laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA') laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA') laurent@366: # Class names laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold') laurent@366: # Function names laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold') laurent@366: # Operators laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold') laurent@366: # Identifiers. I leave this as not bold because everything seems laurent@366: # to be an identifier if it doesn't match the above criterae laurent@657: self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000') laurent@366: laurent@366: # Caret color laurent@657: self.Editor.SetCaretForeground("BLUE") laurent@366: # Selection background laurent@657: self.Editor.SetSelBackground(1, '#66CCFF') laurent@657: laurent@657: self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)) laurent@657: self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)) laurent@366: laurent@366: # register some images for use in the AutoComplete box. laurent@366: #self.RegisterImage(1, images.getSmilesBitmap()) laurent@657: self.Editor.RegisterImage(1, laurent@366: wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16))) laurent@657: self.Editor.RegisterImage(2, laurent@366: wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16))) laurent@657: self.Editor.RegisterImage(3, laurent@366: wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16))) laurent@366: laurent@366: # Indentation and tab stuff laurent@657: self.Editor.SetIndent(4) # Proscribed indent size for wx laurent@657: self.Editor.SetIndentationGuides(True) # Show indent guides laurent@657: self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space laurent@657: self.Editor.SetTabIndents(True) # Tab key indents laurent@657: self.Editor.SetTabWidth(4) # Proscribed tab size for wx laurent@657: self.Editor.SetUseTabs(False) # Use spaces rather than tabs, or laurent@366: # TabTimmy will complain! laurent@366: # White space laurent@657: self.Editor.SetViewWhiteSpace(False) # Don't view white space laurent@366: laurent@366: # EOL: Since we are loading/saving ourselves, and the laurent@366: # strings will always have \n's in them, set the STC to laurent@366: # edit them that way. laurent@657: self.Editor.SetEOLMode(wx.stc.STC_EOL_LF) laurent@657: self.Editor.SetViewEOL(False) laurent@366: laurent@366: # No right-edge mode indicator laurent@657: self.Editor.SetEdgeMode(stc.STC_EDGE_NONE) laurent@657: laurent@657: self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE) laurent@657: laurent@657: self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR) laurent@657: self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) laurent@657: self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR) laurent@657: laurent@657: laurent@657: def __init__(self, parent, controler, window): laurent@657: EditorPanel.__init__(self, parent, "", window, controler) laurent@657: laurent@657: self.DisableEvents = False laurent@366: self.CurrentAction = None laurent@366: laurent@657: img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage() laurent@657: self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16))) laurent@657: laurent@657: def __del__(self): laurent@657: self.Controler.OnCloseEditor() laurent@657: laurent@657: def GetTitle(self): laurent@657: fullname = self.Controler.PlugFullName() laurent@657: if not self.Controler.PythonIsSaved(): laurent@657: return "~%s~" % fullname laurent@657: return fullname laurent@657: laurent@657: def GetBufferState(self): laurent@657: return self.Controler.GetBufferState() laurent@657: laurent@657: def Undo(self): laurent@657: self.Controler.LoadPrevious() laurent@657: self.RefreshView() laurent@657: laurent@657: def Redo(self): laurent@657: self.Controler.LoadNext() laurent@657: self.RefreshView() laurent@657: laurent@657: def HasNoModel(self): laurent@657: return False laurent@366: laurent@366: def OnModification(self, event): laurent@366: if not self.DisableEvents: laurent@366: mod_type = event.GetModificationType() laurent@366: if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO): laurent@366: if mod_type&wx.stc.STC_MOD_BEFOREINSERT: laurent@657: if self.CurrentAction is None: laurent@366: self.StartBuffering() laurent@366: elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1: laurent@366: self.Controler.EndBuffering() laurent@366: self.StartBuffering() laurent@366: self.CurrentAction = ("Add", event.GetPosition()) laurent@657: wx.CallAfter(self.RefreshModel) laurent@366: elif mod_type&wx.stc.STC_MOD_BEFOREDELETE: laurent@366: if self.CurrentAction == None: laurent@366: self.StartBuffering() laurent@366: elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1: laurent@366: self.Controler.EndBuffering() laurent@366: self.StartBuffering() laurent@366: self.CurrentAction = ("Delete", event.GetPosition()) laurent@657: wx.CallAfter(self.RefreshModel) laurent@366: event.Skip() laurent@366: laurent@366: def OnDoDrop(self, event): laurent@366: self.ResetBuffer() laurent@366: wx.CallAfter(self.RefreshModel) laurent@366: event.Skip() laurent@366: laurent@366: # Buffer the last model state laurent@366: def RefreshBuffer(self): laurent@366: self.Controler.BufferPython() laurent@657: if self.ParentWindow is not None: laurent@366: self.ParentWindow.RefreshTitle() laurent@534: self.ParentWindow.RefreshFileMenu() laurent@366: self.ParentWindow.RefreshEditMenu() laurent@657: self.ParentWindow.RefreshPageTitles() laurent@366: laurent@366: def StartBuffering(self): laurent@366: self.Controler.StartBuffering() laurent@657: if self.ParentWindow is not None: laurent@366: self.ParentWindow.RefreshTitle() laurent@534: self.ParentWindow.RefreshFileMenu() laurent@366: self.ParentWindow.RefreshEditMenu() laurent@657: self.ParentWindow.RefreshPageTitles() laurent@366: laurent@366: def ResetBuffer(self): laurent@366: if self.CurrentAction != None: laurent@366: self.Controler.EndBuffering() laurent@366: self.CurrentAction = None laurent@366: laurent@366: def RefreshView(self): laurent@366: self.ResetBuffer() laurent@366: self.DisableEvents = True laurent@657: old_cursor_pos = self.Editor.GetCurrentPos() laurent@657: old_text = self.Editor.GetText() laurent@366: new_text = self.Controler.GetPythonCode() laurent@657: self.Editor.SetText(new_text) laurent@366: new_cursor_pos = GetCursorPos(old_text, new_text) laurent@366: if new_cursor_pos != None: laurent@657: self.Editor.GotoPos(new_cursor_pos) laurent@366: else: laurent@657: self.Editor.GotoPos(old_cursor_pos) laurent@657: self.Editor.ScrollToColumn(0) laurent@657: self.Editor.EmptyUndoBuffer() laurent@366: self.DisableEvents = False laurent@366: laurent@657: self.Editor.Colourise(0, -1) laurent@366: laurent@366: def RefreshModel(self): laurent@657: self.Controler.SetPythonCode(self.Editor.GetText()) laurent@366: laurent@366: def OnKeyPressed(self, event): laurent@657: if self.Editor.CallTipActive(): laurent@657: self.Editor.CallTipCancel() laurent@366: key = event.GetKeyCode() laurent@366: laurent@366: if key == 32 and event.ControlDown(): laurent@657: pos = self.Editor.GetCurrentPos() laurent@366: laurent@366: # Tips laurent@366: if event.ShiftDown(): laurent@366: pass laurent@366: ## self.CallTipSetBackground("yellow") laurent@366: ## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n' laurent@366: ## 'show some suff, maybe parameters..\n\n' laurent@366: ## 'fubar(param1, param2)') laurent@366: # Code completion laurent@366: else: laurent@657: self.Editor.AutoCompSetIgnoreCase(False) # so this needs to match laurent@366: laurent@366: # Images are specified with a appended "?type" laurent@657: self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist])) laurent@366: else: laurent@366: event.Skip() laurent@366: laurent@366: def OnKillFocus(self, event): laurent@657: self.Editor.AutoCompCancel() laurent@366: event.Skip() laurent@366: laurent@366: def OnUpdateUI(self, evt): laurent@366: # check for matching braces laurent@366: braceAtCaret = -1 laurent@366: braceOpposite = -1 laurent@366: charBefore = None laurent@657: caretPos = self.Editor.GetCurrentPos() laurent@366: laurent@366: if caretPos > 0: laurent@657: charBefore = self.Editor.GetCharAt(caretPos - 1) laurent@657: styleBefore = self.Editor.GetStyleAt(caretPos - 1) laurent@366: laurent@366: # check before laurent@366: if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR: laurent@366: braceAtCaret = caretPos - 1 laurent@366: laurent@366: # check after laurent@366: if braceAtCaret < 0: laurent@657: charAfter = self.Editor.GetCharAt(caretPos) laurent@657: styleAfter = self.Editor.GetStyleAt(caretPos) laurent@366: laurent@366: if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR: laurent@366: braceAtCaret = caretPos laurent@366: laurent@366: if braceAtCaret >= 0: laurent@657: braceOpposite = self.Editor.BraceMatch(braceAtCaret) laurent@366: laurent@366: if braceAtCaret != -1 and braceOpposite == -1: laurent@657: self.Editor.BraceBadLight(braceAtCaret) laurent@366: else: laurent@657: self.Editor.BraceHighlight(braceAtCaret, braceOpposite) laurent@657: #pt = self.Editor.PointFromPosition(braceOpposite) laurent@657: #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5)) laurent@366: #print pt laurent@657: #self.Editor.Refresh(False) laurent@366: laurent@366: laurent@366: def OnMarginClick(self, evt): laurent@366: # fold and unfold as needed laurent@366: if evt.GetMargin() == 2: laurent@366: if evt.GetShift() and evt.GetControl(): laurent@366: self.FoldAll() laurent@366: else: laurent@657: lineClicked = self.Editor.LineFromPosition(evt.GetPosition()) laurent@657: laurent@657: if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG: laurent@366: if evt.GetShift(): laurent@657: self.Editor.SetFoldExpanded(lineClicked, True) laurent@366: self.Expand(lineClicked, True, True, 1) laurent@366: elif evt.GetControl(): laurent@657: if self.Editor.GetFoldExpanded(lineClicked): laurent@657: self.Editor.SetFoldExpanded(lineClicked, False) laurent@366: self.Expand(lineClicked, False, True, 0) laurent@366: else: laurent@657: self.Editor.SetFoldExpanded(lineClicked, True) laurent@366: self.Expand(lineClicked, True, True, 100) laurent@366: else: laurent@657: self.Editor.ToggleFold(lineClicked) laurent@366: laurent@366: laurent@366: def FoldAll(self): laurent@657: lineCount = self.Editor.GetLineCount() laurent@366: expanding = True laurent@366: laurent@366: # find out if we are folding or unfolding laurent@366: for lineNum in range(lineCount): laurent@657: if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: laurent@657: expanding = not self.Editor.GetFoldExpanded(lineNum) laurent@366: break laurent@366: laurent@366: lineNum = 0 laurent@366: laurent@366: while lineNum < lineCount: laurent@657: level = self.Editor.GetFoldLevel(lineNum) laurent@366: if level & stc.STC_FOLDLEVELHEADERFLAG and \ laurent@366: (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: laurent@366: laurent@366: if expanding: laurent@657: self.Editor.SetFoldExpanded(lineNum, True) laurent@366: lineNum = self.Expand(lineNum, True) laurent@366: lineNum = lineNum - 1 laurent@366: else: laurent@657: lastChild = self.Editor.GetLastChild(lineNum, -1) laurent@657: self.Editor.SetFoldExpanded(lineNum, False) laurent@366: laurent@366: if lastChild > lineNum: laurent@657: self.Editor.HideLines(lineNum+1, lastChild) laurent@366: laurent@366: lineNum = lineNum + 1 laurent@366: laurent@366: laurent@366: laurent@366: def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): laurent@657: lastChild = self.Editor.GetLastChild(line, level) laurent@366: line = line + 1 laurent@366: laurent@366: while line <= lastChild: laurent@366: if force: laurent@366: if visLevels > 0: laurent@657: self.Editor.ShowLines(line, line) laurent@366: else: laurent@657: self.Editor.HideLines(line, line) laurent@366: else: laurent@366: if doExpand: laurent@657: self.Editor.ShowLines(line, line) laurent@366: laurent@366: if level == -1: laurent@657: level = self.Editor.GetFoldLevel(line) laurent@366: laurent@366: if level & stc.STC_FOLDLEVELHEADERFLAG: laurent@366: if force: laurent@366: if visLevels > 1: laurent@657: self.Editor.SetFoldExpanded(line, True) laurent@366: else: laurent@657: self.Editor.SetFoldExpanded(line, False) laurent@366: laurent@366: line = self.Expand(line, doExpand, force, visLevels-1) laurent@366: laurent@366: else: laurent@657: if doExpand and self.Editor.GetFoldExpanded(line): laurent@366: line = self.Expand(line, True, force, visLevels-1) laurent@366: else: laurent@366: line = self.Expand(line, False, force, visLevels-1) laurent@366: else: laurent@366: line = line + 1 laurent@366: laurent@366: return line laurent@657: laurent@657: def Cut(self): laurent@657: self.ResetBuffer() laurent@657: self.DisableEvents = True laurent@657: self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT) laurent@657: self.DisableEvents = False laurent@657: self.RefreshModel() laurent@657: self.RefreshBuffer() laurent@657: laurent@657: def Copy(self): laurent@657: self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY) laurent@657: laurent@657: def Paste(self): laurent@657: self.ResetBuffer() laurent@657: self.DisableEvents = True laurent@657: self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE) laurent@657: self.DisableEvents = False laurent@657: self.RefreshModel() laurent@657: self.RefreshBuffer()