[GRASS-SVN] r51566 - in
grass/branches/releasebranch_6_4/gui/wxpython: . gmodeler gui_core
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Apr 29 06:38:19 EDT 2012
Author: martinl
Date: 2012-04-29 03:38:19 -0700 (Sun, 29 Apr 2012)
New Revision: 51566
Modified:
grass/branches/releasebranch_6_4/gui/wxpython/gmodeler/frame.py
grass/branches/releasebranch_6_4/gui/wxpython/gmodeler/model.py
grass/branches/releasebranch_6_4/gui/wxpython/gui_core/goutput.py
grass/branches/releasebranch_6_4/gui/wxpython/wxpythonlib.dox
Log:
wxGUI modeler: implement python editor
(merge r51565 from devbr6)
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gmodeler/frame.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gmodeler/frame.py 2012-04-29 10:33:22 UTC (rev 51565)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gmodeler/frame.py 2012-04-29 10:38:19 UTC (rev 51566)
@@ -9,8 +9,9 @@
- frame::ModelEvtHandler
- frame::VariablePanel
- frame::ItemPanel
+ - frame::PythonPanel
-(C) 2010-2011 by the GRASS Development Team
+(C) 2010-2012 by the GRASS Development Team
This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.
@@ -35,7 +36,7 @@
import wx.lib.flatnotebook as FN
from gui_core.widgets import GNotebook
-from gui_core.goutput import GMConsole
+from gui_core.goutput import GMConsole, PyStc
from core.debug import Debug
from core.gcmd import GMessage, GException, GWarning, GError, RunCommand
from gui_core.dialogs import GetImageHandlers
@@ -102,17 +103,21 @@
self.itemPanel = ItemPanel(parent = self)
+ self.pythonPanel = PythonPanel(parent = self)
+
self.goutput = GMConsole(parent = self, notebook = self.notebook)
self.notebook.AddPage(page = self.canvas, text=_('Model'), name = 'model')
self.notebook.AddPage(page = self.itemPanel, text=_('Items'), name = 'items')
self.notebook.AddPage(page = self.variablePanel, text=_('Variables'), name = 'variables')
+ self.notebook.AddPage(page = self.pythonPanel, text=_('Python script'), name = 'python')
self.notebook.AddPage(page = self.goutput, text=_('Command output'), name = 'output')
wx.CallAfter(self.notebook.SetSelectionByName, 'model')
wx.CallAfter(self.ModelChanged, False)
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
self._layout()
self.SetMinSize((475, 300))
@@ -162,7 +167,21 @@
self.SetTitle(self.baseTitle + " - " + os.path.basename(self.modelFile))
else:
self.SetTitle(self.baseTitle)
+
+ def OnPageChanged(self, event):
+ """!Page in notebook changed"""
+ page = event.GetSelection()
+ if page == self.notebook.GetPageIndexByName('python'):
+ if self.pythonPanel.IsEmpty():
+ self.pythonPanel.RefreshScript()
+
+ if self.pythonPanel.IsModified():
+ self.SetStatusText(_('Python script contains local modifications'), 0)
+ else:
+ self.SetStatusText(_('Python script is up-to-date'), 0)
+ event.Skip()
+
def OnVariables(self, event):
"""!Switch to variables page"""
self.notebook.SetSelectionByName('variables')
@@ -553,45 +572,9 @@
dlg.Destroy()
- def OnExportPython(self, event):
+ def OnExportPython(self, event = None, text = None):
"""!Export model to Python script"""
- filename = ''
- dlg = wx.FileDialog(parent = self,
- message = _("Choose file to save"),
- defaultDir = os.getcwd(),
- wildcard=_("Python script (*.py)|*.py"),
- style=wx.FD_SAVE)
-
- if dlg.ShowModal() == wx.ID_OK:
- filename = dlg.GetPath()
-
- if not filename:
- return
-
- # check for extension
- if filename[-3:] != ".py":
- filename += ".py"
-
- if os.path.exists(filename):
- dlg = wx.MessageDialog(self, message=_("File <%s> already exists. "
- "Do you want to overwrite this file?") % filename,
- caption=_("Save file"),
- style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
- if dlg.ShowModal() == wx.ID_NO:
- dlg.Destroy()
- return
-
- dlg.Destroy()
-
- fd = open(filename, "w")
- try:
- WritePythonFile(fd, self.model)
- finally:
- fd.close()
-
- # executable file
- os.chmod(filename, stat.S_IRWXU | stat.S_IWUSR)
-
+ filename = self.pythonPanel.SaveAs(force = True)
self.SetStatusText(_("Model exported to <%s>") % filename)
def OnDefineRelation(self, event):
@@ -1453,7 +1436,172 @@
def Update(self):
"""!Reload list of variables"""
self.list.OnReload(None)
+
+class PythonPanel(wx.Panel):
+ def __init__(self, parent, id = wx.ID_ANY,
+ **kwargs):
+ """!Model as python script
+ """
+ self.parent = parent
+ wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
+
+ self.filename = None # temp file to run
+
+ self.bodyBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
+ label = " %s " % _("Python script"))
+ self.body = PyStc(parent = self)
+
+ self.btnRun = wx.Button(parent = self, id = wx.ID_ANY, label = _("&Run"))
+ self.btnRun.SetToolTipString(_("Run python script"))
+ self.Bind(wx.EVT_BUTTON, self.OnRun, self.btnRun)
+ self.btnSaveAs = wx.Button(parent = self, id = wx.ID_SAVEAS)
+ self.btnSaveAs.SetToolTipString(_("Save python script to file"))
+ self.Bind(wx.EVT_BUTTON, self.OnSaveAs, self.btnSaveAs)
+ self.btnRefresh = wx.Button(parent = self, id = wx.ID_REFRESH)
+ self.btnRefresh.SetToolTipString(_("Refresh python script based on the model. It will discards local changes."))
+ self.Bind(wx.EVT_BUTTON, self.OnRefresh, self.btnRefresh)
+
+ self._layout()
+
+ def _layout(self):
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ bodySizer = wx.StaticBoxSizer(self.bodyBox, wx.HORIZONTAL)
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ bodySizer.Add(item = self.body, proportion = 1,
+ flag = wx.EXPAND | wx.ALL, border = 3)
+
+ btnSizer.Add(item = self.btnRefresh, proportion = 0,
+ flag = wx.LEFT | wx.RIGHT, border = 5)
+ btnSizer.AddStretchSpacer()
+ btnSizer.Add(item = self.btnSaveAs, proportion = 0,
+ flag = wx.RIGHT | wx.ALIGN_RIGHT, border = 5)
+ btnSizer.Add(item = self.btnRun, proportion = 0,
+ flag = wx.RIGHT | wx.ALIGN_RIGHT, border = 5)
+
+ sizer.Add(item = bodySizer, proportion = 1,
+ flag = wx.EXPAND | wx.ALL, border = 3)
+ sizer.Add(item = btnSizer, proportion = 0,
+ flag = wx.EXPAND | wx.ALL, border = 3)
+
+ sizer.Fit(self)
+ sizer.SetSizeHints(self)
+ self.SetSizer(sizer)
+
+ def OnRun(self, event):
+ """!Run Python script"""
+ self.filename = grass.tempfile()
+ try:
+ fd = open(self.filename, "w")
+ fd.write(self.body.GetText())
+ except IOError, e:
+ GError(_("Unable to launch Python script. %s") % e,
+ parent = self)
+ return
+ finally:
+ fd.close()
+ mode = stat.S_IMODE(os.lstat(self.filename)[stat.ST_MODE])
+ os.chmod(self.filename, mode | stat.S_IXUSR)
+
+ self.parent.goutput.RunCmd([fd.name], switchPage = True,
+ skipInterface = True, onDone = self.OnDone)
+
+ event.Skip()
+
+ def OnDone(self, cmd, returncode):
+ """!Python script finished"""
+ grass.try_remove(self.filename)
+ self.filename = None
+
+ def SaveAs(self, force = False):
+ """!Save python script to file
+
+ @return filename
+ """
+ filename = ''
+ dlg = wx.FileDialog(parent = self,
+ message = _("Choose file to save"),
+ defaultDir = os.getcwd(),
+ wildcard = _("Python script (*.py)|*.py"),
+ style = wx.FD_SAVE)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ filename = dlg.GetPath()
+
+ if not filename:
+ return ''
+
+ # check for extension
+ if filename[-3:] != ".py":
+ filename += ".py"
+
+ if os.path.exists(filename):
+ dlg = wx.MessageDialog(self, message=_("File <%s> already exists. "
+ "Do you want to overwrite this file?") % filename,
+ caption=_("Save file"),
+ style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+ if dlg.ShowModal() == wx.ID_NO:
+ dlg.Destroy()
+ return ''
+
+ dlg.Destroy()
+
+ fd = open(filename, "w")
+ try:
+ if force:
+ WritePythonFile(fd, self.parent.GetModel())
+ else:
+ fd.write(self.body.GetText())
+ finally:
+ fd.close()
+
+ # executable file
+ os.chmod(filename, stat.S_IRWXU | stat.S_IWUSR)
+
+ return filename
+
+ def OnSaveAs(self, event):
+ """!Save python script to file"""
+ self.SaveAs(force = False)
+ event.Skip()
+
+ def RefreshScript(self):
+ """!Refresh Python script"""
+ if self.body.modified:
+ dlg = wx.MessageDialog(self,
+ message = _("Python script is locally modificated. "
+ "Refresh will discard all changes. "
+ "Do you really want to continue?"),
+ caption=_("Update"),
+ style = wx.YES_NO | wx.NO_DEFAULT |
+ wx.ICON_QUESTION | wx.CENTRE)
+ ret = dlg.ShowModal()
+ dlg.Destroy()
+ if ret == wx.ID_NO:
+ return
+
+ fd = tempfile.TemporaryFile()
+ WritePythonFile(fd, self.parent.GetModel())
+ fd.seek(0)
+ self.body.SetText(fd.read())
+ fd.close()
+
+ self.body.modified = False
+
+ def OnRefresh(self, event):
+ """!Refresh Python script"""
+ self.RefreshScript()
+ event.Skip()
+
+ def IsModified(self):
+ """!Check if python script has been modified"""
+ return self.body.modified
+
+ def IsEmpty(self):
+ """!Check if python script is empty"""
+ return len(self.body.GetText()) == 0
+
def main():
import gettext
gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gmodeler/model.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gmodeler/model.py 2012-04-29 10:33:22 UTC (rev 51565)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gmodeler/model.py 2012-04-29 10:38:19 UTC (rev 51566)
@@ -17,7 +17,7 @@
- model::WritePythonFile
- model::ModelParamDialog
-(C) 2010-2011 by the GRASS Development Team
+(C) 2010-2012 by the GRASS Development Team
This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.
@@ -1994,7 +1994,7 @@
#
# MODULE: %s
#
-# AUTHOR(S): %s
+# AUTHOR(S): %s
#
# PURPOSE: %s
#
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_core/goutput.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_core/goutput.py 2012-04-29 10:33:22 UTC (rev 51565)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_core/goutput.py 2012-04-29 10:38:19 UTC (rev 51566)
@@ -9,8 +9,9 @@
- goutput::GMStdout
- goutput::GMStderr
- goutput::GMStc
+ - goutput::PyStc
-(C) 2007-2011 by the GRASS Development Team
+(C) 2007-2012 by the GRASS Development Team
This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.
@@ -28,9 +29,10 @@
import Queue
import codecs
import locale
+import keyword
import wx
-import wx.stc
+from wx import stc
from wx.lib.newevent import NewEvent
import grass.script as grass
@@ -436,7 +438,7 @@
"""!Write message in error style"""
self.WriteLog(line, style = self.cmdOutput.StyleError, switchPage = True)
- def RunCmd(self, command, compReg = True, switchPage = False,
+ def RunCmd(self, command, compReg = True, switchPage = False, skipInterface = False,
onDone = None, onPrepare = None, userData = None):
"""!Run command typed into console command prompt (GPrompt).
@@ -448,6 +450,8 @@
@param command command given as a list (produced e.g. by utils.split())
@param compReg True use computation region
@param switchPage switch to output page
+ @param skipInterface True to do not launch GRASS interface
+ parser when command has no arguments given
@param onDone function to be called when command is finished
@param onPrepare function to be called before command is launched
@param userData data defined for the command
@@ -585,7 +589,7 @@
else:
# Send any other command to the shell. Send output to
# console output window
- if len(command) == 1:
+ if len(command) == 1 and not skipInterface:
try:
task = gtask.parse_interface(command[0])
except:
@@ -659,11 +663,11 @@
@param copy True for enable, False for disable
"""
if copy:
- self.cmdPrompt.Bind(wx.stc.EVT_STC_PAINTED, self.cmdPrompt.OnTextSelectionChanged)
- self.cmdOutput.Bind(wx.stc.EVT_STC_PAINTED, self.cmdOutput.OnTextSelectionChanged)
+ self.cmdPrompt.Bind(stc.EVT_STC_PAINTED, self.cmdPrompt.OnTextSelectionChanged)
+ self.cmdOutput.Bind(stc.EVT_STC_PAINTED, self.cmdOutput.OnTextSelectionChanged)
else:
- self.cmdPrompt.Unbind(wx.stc.EVT_STC_PAINTED)
- self.cmdOutput.Unbind(wx.stc.EVT_STC_PAINTED)
+ self.cmdPrompt.Unbind(stc.EVT_STC_PAINTED)
+ self.cmdOutput.Unbind(stc.EVT_STC_PAINTED)
def OnUpdateStatusBar(self, event):
"""!Update statusbar text"""
@@ -1003,7 +1007,7 @@
evt = wxCmdProgress(value = progressValue)
wx.PostEvent(self.parent.progressbar, evt)
-class GMStc(wx.stc.StyledTextCtrl):
+class GMStc(stc.StyledTextCtrl):
"""!Styled GMConsole
Based on FrameOutErr.py
@@ -1015,7 +1019,7 @@
Licence: GPL
"""
def __init__(self, parent, id, margin = False, wrap = None):
- wx.stc.StyledTextCtrl.__init__(self, parent, id)
+ stc.StyledTextCtrl.__init__(self, parent, id)
self.parent = parent
self.SetUndoCollection(True)
self.SetReadOnly(True)
@@ -1032,7 +1036,7 @@
self.SetMarginWidth(1, 0)
self.SetMarginWidth(2, 0)
if margin:
- self.SetMarginType(0, wx.stc.STC_MARGIN_NUMBER)
+ self.SetMarginType(0, stc.STC_MARGIN_NUMBER)
self.SetMarginWidth(0, 30)
else:
self.SetMarginWidth(0, 0)
@@ -1094,7 +1098,7 @@
self.StyleUnknownSpec = "face:%s,size:%d,,fore:#000000,back:#FFFFFF" % (typeface, typesize)
# default and clear => init
- self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, self.StyleDefaultSpec)
+ self.StyleSetSpec(stc.STC_STYLE_DEFAULT, self.StyleDefaultSpec)
self.StyleClearAll()
self.StyleSetSpec(self.StyleCommand, self.StyleCommandSpec)
self.StyleSetSpec(self.StyleOutput, self.StyleOutputSpec)
@@ -1150,3 +1154,233 @@
# reset output window to read only
self.SetReadOnly(True)
+
+class PyStc(stc.StyledTextCtrl):
+ """!Styled Python output (see gmodeler::frame::PythonPanel for
+ usage)
+
+ Based on StyledTextCtrl_2 from wxPython demo
+ """
+ def __init__(self, parent, id = wx.ID_ANY):
+ stc.StyledTextCtrl.__init__(self, parent, id)
+
+ self.parent = parent
+
+ self.modified = False # content modified ?
+
+ self.faces = { 'times': 'Times New Roman',
+ 'mono' : 'Courier New',
+ 'helv' : 'Arial',
+ 'other': 'Comic Sans MS',
+ 'size' : 10,
+ 'size2': 8,
+ }
+
+ self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
+ self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
+
+ self.SetLexer(stc.STC_LEX_PYTHON)
+ self.SetKeyWords(0, " ".join(keyword.kwlist))
+
+ self.SetProperty("fold", "1")
+ self.SetProperty("tab.timmy.whinge.level", "1")
+ self.SetMargins(0, 0)
+ self.SetTabWidth(4)
+ self.SetUseTabs(False)
+
+ self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
+ self.SetEdgeColumn(78)
+
+ # setup a margin to hold fold markers
+ self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
+ self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
+ self.SetMarginSensitive(2, True)
+ self.SetMarginWidth(2, 12)
+
+ # like a flattened tree control using square headers
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
+
+ self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
+ self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
+
+ # Make some styles, the lexer defines what each style is used
+ # for, we just have to define what each style looks like.
+ # This set is adapted from Scintilla sample property files.
+
+ # global default styles for all languages
+ self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(helv)s,size:%(size)d" % self.faces)
+ self.StyleClearAll() # reset all to be like the default
+
+ # global default styles for all languages
+ self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(helv)s,size:%(size)d" % self.faces)
+ self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % self.faces)
+ self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % self.faces)
+ self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
+ self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
+
+ # Python styles
+ # Default
+ self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % self.faces)
+ # Comments
+ self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % self.faces)
+ # Number
+ self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % self.faces)
+ # String
+ self.StyleSetSpec(stc.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % self.faces)
+ # Single quoted string
+ self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % self.faces)
+ # Keyword
+ self.StyleSetSpec(stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % self.faces)
+ # Triple quotes
+ self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % self.faces)
+ # Triple double quotes
+ self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % self.faces)
+ # Class name definition
+ self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % self.faces)
+ # Function or method name definition
+ self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % self.faces)
+ # Operators
+ self.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d" % self.faces)
+ # Identifiers
+ self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % self.faces)
+ # Comment-blocks
+ self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % self.faces)
+ # End of line where string is not closed
+ self.StyleSetSpec(stc.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % self.faces)
+
+ self.SetCaretForeground("BLUE")
+
+ def OnKeyPressed(self, event):
+ """!Key pressed
+
+ @todo implement code completion (see wxPython demo)
+ """
+ if not self.modified:
+ self.modified = True
+
+ event.Skip()
+
+ def OnUpdateUI(self, evt):
+ # check for matching braces
+ braceAtCaret = -1
+ braceOpposite = -1
+ charBefore = None
+ caretPos = self.GetCurrentPos()
+
+ if caretPos > 0:
+ charBefore = self.GetCharAt(caretPos - 1)
+ styleBefore = self.GetStyleAt(caretPos - 1)
+
+ # check before
+ if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos - 1
+
+ # check after
+ if braceAtCaret < 0:
+ charAfter = self.GetCharAt(caretPos)
+ styleAfter = self.GetStyleAt(caretPos)
+
+ if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos
+
+ if braceAtCaret >= 0:
+ braceOpposite = self.BraceMatch(braceAtCaret)
+
+ if braceAtCaret != -1 and braceOpposite == -1:
+ self.BraceBadLight(braceAtCaret)
+ else:
+ self.BraceHighlight(braceAtCaret, braceOpposite)
+
+ def OnMarginClick(self, evt):
+ # fold and unfold as needed
+ if evt.GetMargin() == 2:
+ if evt.GetShift() and evt.GetControl():
+ self.FoldAll()
+ else:
+ lineClicked = self.LineFromPosition(evt.GetPosition())
+
+ if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
+ if evt.GetShift():
+ self.SetFoldExpanded(lineClicked, True)
+ self.Expand(lineClicked, True, True, 1)
+ elif evt.GetControl():
+ if self.GetFoldExpanded(lineClicked):
+ self.SetFoldExpanded(lineClicked, False)
+ self.Expand(lineClicked, False, True, 0)
+ else:
+ self.SetFoldExpanded(lineClicked, True)
+ self.Expand(lineClicked, True, True, 100)
+ else:
+ self.ToggleFold(lineClicked)
+
+ def FoldAll(self):
+ lineCount = self.GetLineCount()
+ expanding = True
+
+ # find out if we are folding or unfolding
+ for lineNum in range(lineCount):
+ if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
+ expanding = not self.GetFoldExpanded(lineNum)
+ break
+
+ lineNum = 0
+ while lineNum < lineCount:
+ level = self.GetFoldLevel(lineNum)
+ if level & stc.STC_FOLDLEVELHEADERFLAG and \
+ (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+
+ if expanding:
+ self.SetFoldExpanded(lineNum, True)
+ lineNum = self.Expand(lineNum, True)
+ lineNum = lineNum - 1
+ else:
+ lastChild = self.GetLastChild(lineNum, -1)
+ self.SetFoldExpanded(lineNum, False)
+
+ if lastChild > lineNum:
+ self.HideLines(lineNum+1, lastChild)
+
+ lineNum = lineNum + 1
+
+ def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
+ lastChild = self.GetLastChild(line, level)
+ line = line + 1
+
+ while line <= lastChild:
+ if force:
+ if visLevels > 0:
+ self.ShowLines(line, line)
+ else:
+ self.HideLines(line, line)
+ else:
+ if doExpand:
+ self.ShowLines(line, line)
+
+ if level == -1:
+ level = self.GetFoldLevel(line)
+
+ if level & stc.STC_FOLDLEVELHEADERFLAG:
+ if force:
+ if visLevels > 1:
+ self.SetFoldExpanded(line, True)
+ else:
+ self.SetFoldExpanded(line, False)
+
+ line = self.Expand(line, doExpand, force, visLevels-1)
+ else:
+ if doExpand and self.GetFoldExpanded(line):
+ line = self.Expand(line, True, force, visLevels-1)
+ else:
+ line = self.Expand(line, False, force, visLevels-1)
+ else:
+ line = line + 1
+
+ return line
+
Modified: grass/branches/releasebranch_6_4/gui/wxpython/wxpythonlib.dox
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/wxpythonlib.dox 2012-04-29 10:33:22 UTC (rev 51565)
+++ grass/branches/releasebranch_6_4/gui/wxpython/wxpythonlib.dox 2012-04-29 10:38:19 UTC (rev 51566)
@@ -122,6 +122,7 @@
- goutput::GMStc
- goutput::GMStdout
- goutput::GMStderr
+ - goutput::PyStc
- gui_core::gselect
- gselect::Select
- gselect::VectorSelect
@@ -286,6 +287,7 @@
- frame::ModelEvtHandler
- frame::VariablePanel
- frame::ItemPanel
+ - frame::PythonPanel
- gmodeler::menudata
- menudata::ModelerData
- gmodeler::model
More information about the grass-commit
mailing list