[GRASS-SVN] r40125 - in grass/branches/develbranch_6/gui/wxpython:
. gui_modules
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Dec 24 06:50:23 EST 2009
Author: martinl
Date: 2009-12-24 06:50:22 -0500 (Thu, 24 Dec 2009)
New Revision: 40125
Modified:
grass/branches/develbranch_6/gui/wxpython/gui_modules/goutput.py
grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py
grass/branches/develbranch_6/gui/wxpython/gui_modules/prompt.py
grass/branches/develbranch_6/gui/wxpython/wxgui.py
Log:
wxGUI: design GPrompt as abstract class used by GPromptPopUp and
GPromptSTC, enable search engine, general clean-up (in progress)
Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/goutput.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/goutput.py 2009-12-24 11:43:07 UTC (rev 40124)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/goutput.py 2009-12-24 11:50:22 UTC (rev 40125)
@@ -138,7 +138,8 @@
wx.SplitterWindow.__init__(self, parent, id, style = style, *kwargs)
self.SetName("GMConsole")
- self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
+ self.panelOutput = wx.Panel(parent = self, id = wx.ID_ANY)
+ self.panelPrompt = wx.Panel(parent = self, id = wx.ID_ANY)
# initialize variables
self.Map = None
@@ -162,7 +163,7 @@
#
# progress bar
#
- self.console_progressbar = wx.Gauge(parent=self.panel, id=wx.ID_ANY,
+ self.console_progressbar = wx.Gauge(parent=self.panelOutput, id=wx.ID_ANY,
range=100, pos=(110, 50), size=(-1, 25),
style=wx.GA_HORIZONTAL)
self.console_progressbar.Bind(EVT_CMD_PROGRESS, self.OnCmdProgress)
@@ -170,7 +171,7 @@
#
# text control for command output
#
- self.cmd_output = GMStc(parent=self, id=wx.ID_ANY, margin=margin,
+ self.cmd_output = GMStc(parent=self.panelOutput, id=wx.ID_ANY, margin=margin,
wrap=None)
self.cmd_output_timer = wx.Timer(self.cmd_output, id=wx.ID_ANY)
self.cmd_output.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
@@ -179,11 +180,19 @@
self.Bind(EVT_CMD_DONE, self.OnCmdDone)
#
- # command prompt
+ # search & command prompt
#
- self.cmd_prompt = prompt.GPromptSTC(parent = self.panel, id=wx.ID_ANY,
- onRun = self.RunCmd)
+ self.searchBy = wx.Choice(parent = self.panelPrompt, id = wx.ID_ANY,
+ choices = [_("description"),
+ _("keywords")])
+
+ self.search = wx.TextCtrl(parent = self.panelPrompt, id = wx.ID_ANY,
+ value = "", size = (-1, 25))
+
+ self.cmd_prompt = prompt.GPromptSTC(parent = self)
if self.parent.GetName() != 'LayerManager':
+ self.searchBy.Hide()
+ self.search.Hide()
self.cmd_prompt.Hide()
#
@@ -200,16 +209,16 @@
#
# buttons
#
- self.btn_console_clear = wx.Button(parent = self.panel, id = wx.ID_ANY,
+ self.btn_console_clear = wx.Button(parent = self.panelPrompt, id = wx.ID_ANY,
label = _("C&lear output"), size=(125,-1))
- self.btn_cmd_clear = wx.Button(parent = self.panel, id = wx.ID_ANY,
- label = _("Cl&ear command"), size=(125,-1))
+ self.btn_cmd_clear = wx.Button(parent = self.panelPrompt, id = wx.ID_ANY,
+ label = _("&Clear command"), size=(125,-1))
if self.parent.GetName() != 'LayerManager':
self.btn_cmd_clear.Hide()
- self.btn_console_save = wx.Button(parent = self.panel, id = wx.ID_ANY,
+ self.btn_console_save = wx.Button(parent = self.panelPrompt, id = wx.ID_ANY,
label = _("&Save output"), size=(125,-1))
# abort
- self.btn_abort = wx.Button(parent = self.panel, id = wx.ID_ANY, label = _("&Abort command"),
+ self.btn_abort = wx.Button(parent = self.panelPrompt, id = wx.ID_ANY, label = _("&Abort command"),
size=(125,-1))
self.btn_abort.SetToolTipString(_("Abort the running command"))
self.btn_abort.Enable(False)
@@ -220,48 +229,81 @@
self.btn_abort.Bind(wx.EVT_BUTTON, self.OnCmdAbort)
self.btn_abort.Bind(EVT_CMD_ABORT, self.OnCmdAbort)
+ self.search.Bind(wx.EVT_TEXT, self.OnSearchModule)
+
self.__layout()
def __layout(self):
"""!Do layout"""
- boxsizer = wx.BoxSizer(wx.VERTICAL)
- buttonsizer = wx.BoxSizer(wx.HORIZONTAL)
+ OutputSizer = wx.BoxSizer(wx.VERTICAL)
+ PromptSizer = wx.BoxSizer(wx.VERTICAL)
+ SearchSizer = wx.BoxSizer(wx.HORIZONTAL)
+ ButtonSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ OutputSizer.Add(item=self.cmd_output, proportion=1,
+ flag=wx.EXPAND | wx.ALL, border=1)
+ OutputSizer.Add(item=self.console_progressbar, proportion=0,
+ flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=3)
- boxsizer.Add(item=self.cmd_prompt, proportion=1,
- flag=wx.EXPAND | wx.ALL, border=1)
+ if self.searchBy.IsShown():
+ SearchSizer.Add(item = wx.StaticText(parent = self.panelPrompt, id = wx.ID_ANY,
+ label = _("Find module:")),
+ proportion = 0, flag = wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border = 3)
+ SearchSizer.Add(item = self.searchBy,
+ proportion = 0, flag = wx.LEFT, border = 3)
+ SearchSizer.Add(item = self.search,
+ proportion = 1, flag = wx.LEFT | wx.EXPAND, border = 3)
- buttonsizer.Add(item=self.btn_console_clear, proportion=0,
+ PromptSizer.Add(item=SearchSizer, proportion=0,
+ flag=wx.EXPAND | wx.ALL, border=1)
+ PromptSizer.Add(item=self.cmd_prompt, proportion=1,
+ flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border=2)
+
+ ButtonSizer.Add(item=self.btn_console_clear, proportion=0,
flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE | wx.ALL, border=5)
- buttonsizer.Add(item=self.btn_console_save, proportion=0,
+ ButtonSizer.Add(item=self.btn_console_save, proportion=0,
flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE | wx.ALL, border=5)
- buttonsizer.Add(item=self.btn_cmd_clear, proportion=0,
+ ButtonSizer.Add(item=self.btn_cmd_clear, proportion=0,
flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE | wx.ALL, border=5)
- buttonsizer.Add(item=self.btn_abort, proportion=0,
+ ButtonSizer.Add(item=self.btn_abort, proportion=0,
flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE | wx.ALL, border=5)
- boxsizer.Add(item=buttonsizer, proportion=0,
- flag=wx.ALIGN_CENTER)
+ PromptSizer.Add(item=ButtonSizer, proportion=0,
+ flag=wx.ALIGN_CENTER)
- boxsizer.Add(item=self.console_progressbar, proportion=0,
- flag=wx.EXPAND | wx.ALIGN_CENTRE_VERTICAL | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=3)
-
- boxsizer.Fit(self)
- boxsizer.SetSizeHints(self)
+ OutputSizer.Fit(self)
+ OutputSizer.SetSizeHints(self)
- self.panel.SetSizer(boxsizer)
+ PromptSizer.Fit(self)
+ PromptSizer.SetSizeHints(self)
+
+ self.panelOutput.SetSizer(OutputSizer)
+ self.panelPrompt.SetSizer(PromptSizer)
# split window
if self.parent.GetName() == 'LayerManager':
- self.SplitHorizontally(self.cmd_output, self.panel, -75)
+ self.SplitHorizontally(self.panelOutput, self.panelPrompt, -75)
self.SetMinimumPaneSize(100)
else:
- self.SplitHorizontally(self.cmd_output, self.panel, -10)
- self.SetMinimumPaneSize(65)
+ self.SplitHorizontally(self.panelOutput, self.panelPrompt, -10)
+ self.SetMinimumPaneSize(45)
self.Fit()
# layout
self.SetAutoLayout(True)
self.Layout()
+ def GetPanel(self, prompt = True):
+ """!Get panel
+
+ @param prompt get prompt / output panel
+
+ @return wx.Panel reference
+ """
+ if prompt:
+ return self.panelPrompt
+
+ return self.panelOutput
+
def Redirect(self):
"""!Redirect stderr
@@ -379,6 +421,9 @@
self.parent.cmdinput.SetHistoryItems()
except AttributeError:
pass
+
+ # allow writing to output window
+ self.cmd_output.SetReadOnly(False)
if cmdlist[0] in globalvar.grassCmd['all']:
# send GRASS command without arguments to GUI command interface
@@ -468,6 +513,9 @@
self.btn_abort.Enable()
self.cmd_output_timer.Start(50)
+ # reset output window to read only
+ self.cmd_output.SetReadOnly(True)
+
return None
def ClearHistory(self, event):
@@ -505,7 +553,39 @@
def GetCmd(self):
"""!Get running command or None"""
return self.requestQ.get()
+
+ def OnSearchModule(self, event):
+ """!Search module by keywords or description"""
+ text = event.GetString()
+ if not text:
+ self.cmd_prompt.SetFilter(None)
+ return
+ modules = dict()
+ iFound = 0
+ for module, data in self.cmd_prompt.moduleDesc.iteritems():
+ found = False
+ if self.searchBy.GetSelection() == 0: # -> description
+ if text in data['desc']:
+ found = True
+ else: # -> keywords
+ if self.__checkKey(text, data['keywords']):
+ found = True
+
+ if found:
+ iFound += 1
+ try:
+ group, name = module.split('.')
+ except ValueError:
+ continue # TODO
+
+ if not modules.has_key(group):
+ modules[group] = list()
+ modules[group].append(name)
+
+ self.parent.statusbar.SetStatusText(_("%d modules found") % iFound)
+ self.cmd_prompt.SetFilter(modules)
+
def OnCmdOutput(self, event):
"""!Print command output"""
message = event.text
@@ -779,6 +859,7 @@
wx.stc.StyledTextCtrl.__init__(self, parent, id)
self.parent = parent
self.SetUndoCollection(True)
+ self.SetReadOnly(True)
#
# styles
@@ -811,19 +892,7 @@
# bindings
#
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
- self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
-
- def OnKeyPressed(self, event):
- """!Traps key presses so that the STC behaves like read only to
- key presses, but not to logged output or errors. Exception for
- key press modified by ctrl or cmd (Mac) to allow cut, copy, paste
- through key filter"""
- if event.ControlDown() or event.CmdDown():
- event.Skip()
- else:
- return
-
def SetStyle(self):
"""!Set styles for styled text output windows with type face
and point size selected by user (Courier New 10 is default)"""
Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py 2009-12-24 11:43:07 UTC (rev 40124)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py 2009-12-24 11:50:22 UTC (rev 40125)
@@ -312,7 +312,11 @@
if grassModule is not None:
processTask(tree = etree.fromstring(getInterfaceDescription(grassModule)),
task = self)
-
+
+ def get_name(self):
+ """!Get task name"""
+ return self.name
+
def get_list_params(self, element = 'name'):
"""!Get list of parameters"""
params = []
Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/prompt.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/prompt.py 2009-12-24 11:43:07 UTC (rev 40124)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/prompt.py 2009-12-24 11:50:22 UTC (rev 40125)
@@ -1,16 +1,15 @@
"""!
@package prompt.py
- at brief wxGUI prompt
+ at brief wxGUI command prompt
Classes:
- - GPromptPopUp
- PromptListCtrl
- TextCtrlAutoComplete
+ - GPrompt
+ - GPromptPopUp
- GPromptSTC
- at todo: reduce size of STC prompt to about 3 lines
-
(C) 2009 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
@@ -23,6 +22,7 @@
import os
import sys
import shlex
+import copy
import wx
import wx.stc
@@ -32,196 +32,19 @@
import globalvar
import menudata
+import menuform
import gcmd
+import utils
-class GPromptPopUp:
- """!Interactive GRASS prompt"""
- def __init__(self, parent):
- self.parent = parent # GMFrame
-
- # dictionary of modules (description, keywords, ...)
- self.modules = self.parent.menudata.GetModules()
-
- self.panel, self.input = self.__create()
-
- def __create(self):
- """!Create widget"""
- cmdprompt = wx.Panel(self.parent)
-
- #
- # search
- #
- searchTxt = wx.StaticText(parent = cmdprompt, id = wx.ID_ANY,
- label = _("Find module:"))
-
- self.searchBy = wx.Choice(parent = cmdprompt, id = wx.ID_ANY,
- choices = [_("description"),
- _("keywords")])
- winHeight = self.searchBy.GetSize()[1]
-
- self.search = wx.TextCtrl(parent = cmdprompt, id = wx.ID_ANY,
- value = "", size = (-1, 25))
-
- label = wx.Button(parent = cmdprompt, id = wx.ID_ANY,
- label = _("&Cmd >"), size = (-1, winHeight))
- label.SetToolTipString(_("Click for erasing command prompt"))
-
- ### todo: fix TextCtrlAutoComplete to work also on Macs
- ### reason: missing wx.PopupWindow()
- try:
- cmdinput = TextCtrlAutoComplete(parent = cmdprompt, id = wx.ID_ANY,
- value = "",
- style = wx.TE_LINEWRAP | wx.TE_PROCESS_ENTER,
- size = (-1, winHeight),
- statusbar = self.parent.statusbar)
- except NotImplementedError:
- # wx.PopupWindow may be not available in wxMac
- # see http://trac.wxwidgets.org/ticket/9377
- cmdinput = wx.TextCtrl(parent = cmdprompt, id = wx.ID_ANY,
- value = "",
- style=wx.TE_LINEWRAP | wx.TE_PROCESS_ENTER,
- size = (-1, 25))
- self.searchBy.Enable(False)
- self.search.Enable(False)
-
- cmdinput.SetFont(wx.Font(10, wx.FONTFAMILY_MODERN, wx.NORMAL, wx.NORMAL, 0, ''))
-
- wx.CallAfter(cmdinput.SetInsertionPoint, 0)
-
- # bidnings
- label.Bind(wx.EVT_BUTTON, self.OnCmdErase)
- cmdinput.Bind(wx.EVT_TEXT_ENTER, self.OnRunCmd)
- cmdinput.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
- self.search.Bind(wx.EVT_TEXT, self.OnSearchModule)
-
- # layout
- sizer = wx.GridBagSizer(hgap=5, vgap=5)
- sizer.AddGrowableRow(1)
- sizer.AddGrowableCol(2)
-
- sizer.Add(item = searchTxt,
- flag = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL,
- pos = (0, 0))
-
- sizer.Add(item = self.searchBy,
- flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER,
- pos = (0, 1))
-
- sizer.Add(item = self.search,
- flag = wx.EXPAND | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER,
- border = 5,
- pos = (0, 2))
-
- sizer.Add(item = label,
- flag = wx.LEFT | wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER,
- border = 5,
- pos = (1, 0))
-
- sizer.Add(item = cmdinput,
- flag = wx.EXPAND | wx.RIGHT,
- border = 5,
- pos = (1, 1), span = (1, 2))
-
- cmdprompt.SetSizer(sizer)
- sizer.Fit(cmdprompt)
- cmdprompt.Layout()
-
- return cmdprompt, cmdinput
-
- def __checkKey(self, text, keywords):
- """!Check if text is in keywords"""
- found = 0
- keys = text.split(',')
- if len(keys) > 1: # -> multiple keys
- for k in keys[:-1]:
- k = k.strip()
- for key in keywords:
- if k == key: # full match
- found += 1
- break
- k = keys[-1].strip()
- for key in keywords:
- if k in key: # partial match
- found +=1
- break
- else:
- for key in keywords:
- if text in key: # partial match
- found +=1
- break
-
- if found == len(keys):
- return True
-
- return False
-
- def GetPanel(self):
- """!Get main widget panel"""
- return self.panel
-
- def GetInput(self):
- """!Get main prompt widget"""
- return self.input
-
- def OnCmdErase(self, event):
- """!Erase command prompt"""
- self.input.SetValue('')
-
- def OnRunCmd(self, event):
- """!Run command"""
- cmdString = event.GetString()
-
- if self.parent.GetName() != "LayerManager":
- return
-
- if cmdString[:2] == 'd.' and not self.parent.curr_page:
- self.parent.NewDisplay(show=True)
-
- cmd = shlex.split(str(cmdString))
- if len(cmd) > 1:
- self.parent.goutput.RunCmd(cmd, switchPage = True)
- else:
- self.parent.goutput.RunCmd(cmd, switchPage = False)
-
- self.OnUpdateStatusBar(None)
-
- def OnUpdateStatusBar(self, event):
- """!Update Layer Manager status bar"""
- if self.parent.GetName() != "LayerManager":
- return
-
- if event is None:
- self.parent.statusbar.SetStatusText("")
- else:
- self.parent.statusbar.SetStatusText(_("Type GRASS command and run by pressing ENTER"))
- event.Skip()
-
- def OnSearchModule(self, event):
- """!Search module by metadata"""
- text = event.GetString()
- if not text:
- self.input.SetChoices(globalvar.grassCmd['all'])
- return
-
- modules = []
- for module, data in self.modules.iteritems():
- if self.searchBy.GetSelection() == 0: # -> description
- if text in data['desc']:
- modules.append(module)
- else: # -> keywords
- if self.__checkKey(text, data['keywords']):
- modules.append(module)
-
- self.parent.statusbar.SetStatusText(_("%d modules found") % len(modules))
- self.input.SetChoices(modules)
-
class PromptListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
+ """!PopUp window used by GPromptPopUp"""
def __init__(self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition,
size = wx.DefaultSize, style = 0):
wx.ListCtrl.__init__(self, parent, id, pos, size, style)
listmix.ListCtrlAutoWidthMixin.__init__(self)
class TextCtrlAutoComplete(wx.ComboBox, listmix.ColumnSorterMixin):
+ """!Auto complete text area used by GPromptPopUp"""
def __init__ (self, parent, statusbar,
id = wx.ID_ANY, choices = [], **kwargs):
"""!Constructor works just like wx.TextCtrl except you can pass in a
@@ -666,108 +489,179 @@
event.Skip()
-class GPromptSTC(wx.stc.StyledTextCtrl):
- """!Styled GRASS prompt with autocomplete and calltips"""
- def __init__(self, parent, id, onRun, margin=False, wrap=None):
- wx.stc.StyledTextCtrl.__init__(self, parent, id)
- self.parent = parent
- self.SetUndoCollection(True)
- self.RunCmd = onRun
+class GPrompt(object):
+ """!Abstract class for interactive wxGUI prompt
+
+ See subclass GPromptPopUp and GPromptSTC.
+ """
+ def __init__(self, parent):
+ self.parent = parent # GMConsole
+ self.panel = self.parent.GetPanel()
+
+ if self.parent.parent.GetName() != "LayerManager":
+ self.standAlone = True
+ else:
+ self.standAlone = False
+ # dictionary of modules (description, keywords, ...)
+ if not self.standAlone:
+ self.moduleDesc = parent.parent.menudata.GetModules()
+ self.moduleList = self._getListOfModules()
+ self.mapList = self._getListOfMaps()
+ else:
+ self.moduleDesc = self.moduleList = self.mapList = None
+
+ # auto complete items
+ self.autoCompList = list()
+ self.autoCompFilter = None
+
+ # command description (menuform.grassTask)
+ self.cmdDesc = None
+ self.cmdbuffer = list()
+
+ def _getListOfModules(self):
+ """!Get list of modules"""
+ result = dict()
+ for module in globalvar.grassCmd['all']:
+ try:
+ group, name = module.split('.', 1)
+ except ValueError:
+ continue # TODO
+
+ if not result.has_key(group):
+ result[group] = list()
+ result[group].append(name)
+
+ # sort list of names
+ for group in result.keys():
+ result[group].sort()
+
+ return result
+
+ def _getListOfMaps(self):
+ """!Get list of maps"""
+ result = dict()
+ result['raster'] = grass.list_strings('rast')
+ result['vector'] = grass.list_strings('vect')
+
+ return result
+
+ def OnRunCmd(self, event):
+ """!Run command"""
+ cmdString = event.GetString()
+
+ if self.standAlone:
+ return
+
+ if cmdString[:2] == 'd.' and not self.parent.curr_page:
+ self.parent.NewDisplay(show=True)
+
+ cmd = shlex.split(str(cmdString))
+ if len(cmd) > 1:
+ self.parent.goutput.RunCmd(cmd, switchPage = True)
+ else:
+ self.parent.goutput.RunCmd(cmd, switchPage = False)
+
+ self.OnUpdateStatusBar(None)
+
+ def OnUpdateStatusBar(self, event):
+ """!Update Layer Manager status bar"""
+ if self.standAlone:
+ return
+
+ if event is None:
+ self.parent.statusbar.SetStatusText("")
+ else:
+ self.parent.statusbar.SetStatusText(_("Type GRASS command and run by pressing ENTER"))
+ event.Skip()
+
+ def GetPanel(self):
+ """!Get main widget panel"""
+ return self.panel
+
+ def GetInput(self):
+ """!Get main prompt widget"""
+ return self.input
+
+class GPromptPopUp(GPrompt, TextCtrlAutoComplete):
+ """!Interactive wxGUI prompt - popup version"""
+ def __init__(self, parent):
+ GPrompt.__init__(self, parent)
+
+ ### todo: fix TextCtrlAutoComplete to work also on Macs
+ ### reason: missing wx.PopupWindow()
+ try:
+ TextCtrlAutoComplete.__init__(self, parent = self.panel, id = wx.ID_ANY,
+ value = "",
+ style = wx.TE_LINEWRAP | wx.TE_PROCESS_ENTER,
+ statusbar = self.parent.parent.statusbar)
+ except NotImplementedError:
+ # wx.PopupWindow may be not available in wxMac
+ # see http://trac.wxwidgets.org/ticket/9377
+ wx.TextCtrl.__init__(parent = self.panel, id = wx.ID_ANY,
+ value = "",
+ style=wx.TE_LINEWRAP | wx.TE_PROCESS_ENTER,
+ size = (-1, 25))
+ self.searchBy.Enable(False)
+ self.search.Enable(False)
+
+ self.SetFont(wx.Font(10, wx.FONTFAMILY_MODERN, wx.NORMAL, wx.NORMAL, 0, ''))
+
+ wx.CallAfter(self.SetInsertionPoint, 0)
+
+ # bidnings
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnRunCmd)
+ self.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
+
+ def __checkKey(self, text, keywords):
+ """!Check if text is in keywords"""
+ found = 0
+ keys = text.split(',')
+ if len(keys) > 1: # -> multiple keys
+ for k in keys[:-1]:
+ k = k.strip()
+ for key in keywords:
+ if k == key: # full match
+ found += 1
+ break
+ k = keys[-1].strip()
+ for key in keywords:
+ if k in key: # partial match
+ found +=1
+ break
+ else:
+ for key in keywords:
+ if text in key: # partial match
+ found +=1
+ break
+
+ if found == len(keys):
+ return True
+
+ return False
+
+ def OnCmdErase(self, event):
+ """!Erase command prompt"""
+ self.input.SetValue('')
+
+class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
+ """!Styled wxGUI prompt with autocomplete and calltips"""
+ def __init__(self, parent, id = wx.ID_ANY, margin = False, wrap = None):
+ GPrompt.__init__(self, parent)
+ wx.stc.StyledTextCtrl.__init__(self, self.panel, id)
+
#
# styles
#
self.SetWrapMode(True)
+ self.SetUndoCollection(True)
#
# create command and map lists for autocompletion
#
self.AutoCompSetIgnoreCase(False)
- self.rastlist = []
- self.vectlist = []
- self.imglist = []
- self.r3list = []
- self.dblist = []
- self.genlist = []
- self.displist = []
-
#
- # Get available GRASS commands and parse into lists by command type for autocomplete
- #
- for item in globalvar.grassCmd['all']:
- if len(item.split('.')) > 1:
- start,end = item.split('.',1)
- if start == 'r': self.rastlist.append(end)
- elif start == 'v': self.vectlist.append(end)
- elif start == 'i': self.imglist.append(end)
- elif start == 'r3': self.r3list.append(end)
- elif start == 'db': self.dblist.append(end)
- elif start == 'g': self.genlist.append(end)
- elif start == 'd': self.displist.append(end)
-
- self.rastlist.sort()
- self.vectlist.sort()
- self.imglist.sort()
- self.r3list.sort()
- self.dblist.sort()
- self.genlist.sort()
- self.displist.sort()
-
- #
- # Create lists of element types and possible arguments for autocomplete
- #
- self.datatypes = []
- self.maplists = {}
- self.maptype = ''
- self.datatypes = ['rast',
- 'rast3d',
- 'vect',
- 'oldvect',
- 'asciivect',
- 'labels',
- 'region',
- 'region3d',
- 'group',
- '3dview']
-
- self.drastcmd = ['d.rast',
- 'd.rgb',
- 'd.his',
- 'd.rast.arrow',
- 'd.rast.num']
-
- self.dvectcmd = ['d.vect',
- 'd.vect.chart'
- 'd.thematic.area',
- 'd.vect.thematic']
-
- self.rastargs = ['map',
- 'input',
- 'rast',
- 'raster',
- 'red',
- 'green',
- 'blue',
- 'h_map',
- 'i_map',
- 's_map',
- 'hue_input',
- 'intensity_input',
- 'saturation_input',
- 'red_input',
- 'green_input',
- 'blue_input']
-
- self.__getfiles()
-
- #
- # command history buffer
- #
- self.cmdbuffer = []
- self.cmdindex = 0
-
- #
# line margins
#
# TODO print number only from cmdlog
@@ -778,71 +672,79 @@
self.SetMarginWidth(0, 30)
else:
self.SetMarginWidth(0, 0)
-
+
#
# miscellaneous
#
self.SetViewWhiteSpace(False)
-# self.SetTabWidth(4)
self.SetUseTabs(False)
self.UsePopUp(True)
self.SetSelBackground(True, "#FFFF00")
self.SetUseHorizontalScrollBar(True)
-
+
#
# bindings
#
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
-
- def __getfiles(self):
- """!Get accessible files for autocomplete"""
- for item in self.datatypes:
- mlist = grass.read_command("g.mlist", "m", type=item).splitlines()
- mlist.sort()
- self.maplists[item] = mlist
-
- def OnKeyPressed(self, event):
- """!Key press capture for autocompletion, calltips, and command history"""
+ self.Bind(wx.stc.EVT_STC_AUTOCOMP_SELECTION, self.OnItemSelected)
+
+ def SetFilter(self, items):
+ """!Sets filter
- #keycodes used: "." = 46, "=" = 61, "," = 44
+ @param choices list of items to be filtered
+ """
+ self.autoCompFilter = items
+
+ def OnItemSelected(self, event):
+ """!Item selected from the list"""
+ text = self.GetTextLeft()[:self.AutoCompPosStart()] + event.GetText() + ' '
+ self.SetText(text)
+ pos = len(text)
+ self.SetSelectionStart(pos)
+ self.SetCurrentPos(pos)
+
+ cmd = text.split()[0]
+ if not self.cmdDesc or cmd != self.cmdDesc.get_name():
+ try:
+ self.cmdDesc = menuform.GUI().ParseInterface(cmd = [cmd])
+ except IOError:
+ self.cmdDesc = None
+
+ def OnKeyPressed(self, event):
+ """!Key press capture for autocompletion, calltips, and command history
+
+ @todo event.ControlDown() for manual autocomplete
+ """
+ # keycodes used: "." = 46, "=" = 61, "," = 44
line = ''
entry = ''
usage = ''
cmdtype = ''
cmdname = ''
cmd = ''
-
- # CAN CHANGE: event.ControlDown() for manual autocomplete
if event.GetKeyCode() == 46 and not event.ShiftDown():
- #GRASS command autocomplete when "." is pressed after r,v,i,g,db, or d
- listcmds = []
+ # GRASS command autocomplete when '.' is pressed after 'r', 'v', 'i', 'g', 'db', or 'd'
+ self.autoCompList = list()
pos = self.GetCurrentPos()
- self.InsertText(pos,'.')
+ self.InsertText(pos, '.')
self.CharRight()
entry = self.GetTextLeft()
- if entry not in ['r.','v.','i.','g.','db.','d.']:
+ if entry not in ['r.', 'v.', 'i.', 'g.', 'db.', 'd.']:
return
-
- if entry == 'r.': listcmds = self.rastlist
- elif entry == 'v.': listcmds = self.vectlist
- elif entry == 'i.': listcmds = self.imglist
- elif entry == 'r3.': listcmds = self.r3list
- elif entry == 'db.': listcmds = self.dblist
- elif entry == 'g.': listcmds = self.genlist
- elif entry == 'd.': listcmds = self.displist
-
- if listcmds == []:
- return
+
+ if self.autoCompFilter:
+ self.autoCompList = self.autoCompFilter[entry[:-1]]
else:
- self.AutoCompShow(0, " ".join(listcmds))
+ self.autoCompList = self.moduleList[entry[:-1]]
+ if len(self.autoCompList) > 0:
+ self.AutoCompShow(lenEntered = 0, itemList = ' '.join(self.autoCompList))
elif event.GetKeyCode() == wx.WXK_TAB:
- #GRASS command calltips
-
- #Must be a command to the left somewhere
+ # show GRASS command calltips (to hide press 'ESC')
+
pos = self.GetCurrentPos()
entry = self.GetTextLeft()
cmd = entry.split()[0].strip()
@@ -851,76 +753,35 @@
usage, description = self.GetCommandUsage(cmd)
- self.CallTipSetBackground("PALE GREEN")
+ self.CallTipSetBackground("GREY")
self.CallTipSetForeground("BLACK")
- self.CallTipShow(pos, usage+'\n\n'+description)
+ self.CallTipShow(pos, usage + '\n\n' + description)
elif (event.GetKeyCode() == wx.WXK_SPACE and event.ControlDown()) or \
- event.GetKeyCode() == 61 or event.GetKeyCode() == 44:
- #Autocompletion for map/data file name entry after '=', ',', or manually
-
+ event.GetKeyCode() == 61 or event.GetKeyCode() == 44:
+ # Autocompletion for map/data file name entry after '=', ',', or manually
pos = self.GetCurrentPos()
entry = self.GetTextLeft()
if event.GetKeyCode() != 44:
- self.maptype = ''
- arg = ''
- cmdtype = ''
- cmdname = ''
- cmd = ''
-
- if entry.strip()[0:2] in ['r.','v.','i.','g.','db.','d.']:
- cmdtype = entry.strip()[0]
- cmd = entry.split()[0].strip()
- if cmd in globalvar.grassCmd['all']:
- cmdname = cmd.split('.')[1]
- else:
- #No complete GRASS command found
- cmd = ''
- cmdname = ''
- elif entry.strip()[0:4] == 'nviz':
- cmdtype = ''
- cmdname = cmd = 'nviz'
- else:
- #No partial or complete GRASS command found
+ self.promptType = None
+
+ if not self.cmdDesc:
+ # No partial or complete GRASS command found
return
-
- cmdargs = entry.strip('=')
+
try:
- arg = cmdargs.rsplit(' ',1)[1]
+ # find last typed option
+ arg = entry.rstrip('=').rsplit(' ', 1)[1]
except:
arg = ''
-
+
+ self.promptType = self.cmdDesc.get_param(arg)['prompt']
+
if event.GetKeyCode() == 61:
# autocompletion after '='
# insert the '=' and move to after the '=', ready for a map name
- self.InsertText(pos,'=')
+ self.InsertText(pos, '=')
self.CharRight()
-
- maplist = []
- self.maptype = ''
-
- # what kind of map/data type is desired?
- if (((cmdtype in ['r', 'i'] or cmd in self.drastcmd) and arg in self.rastargs) or
- ((cmd=='nviz' or cmdtype=='r3') and arg in ['elevation','color']) or
- arg in ['rast', 'raster']):
- self.maptype = 'rast'
- elif (((cmdtype=='v' or cmd in self.dvectcmd) and arg in ['map', 'input']) or
- (cmdtype=='r3' and arg=='input') or
- arg in ['vect', 'vector', 'points']):
- self.maptype = 'vect'
- elif ((cmdtype=='r3' and arg in ['map', 'input']) or
- (cmdtype=='nviz' and arg=='volume') or arg=='rast3d'):
- self.maptype = 'rast3d'
- elif arg=='labels':
- self.maptype ='labels'
- elif arg=='region':
- self.maptype ='region'
- elif arg=='region3d':
- self.maptype ='region3d'
- elif arg=='group':
- self.maptype ='group'
- elif arg=='3dview':
- self.maptype ='3dview'
elif event.GetKeyCode() == 44:
# autocompletion after ','
@@ -946,16 +807,16 @@
elif cmdtype=='r3':
self.maptype = 'rast3d'
- if self.maptype == '':
- return
- else:
- maplist = self.maplists[self.maptype]
- self.AutoCompShow(0, " ".join(maplist))
-
- elif event.GetKeyCode() in [wx.WXK_UP,wx.WXK_DOWN] and event.ControlDown():
+ if self.promptType and self.promptType in ('raster', 'vector'):
+ self.autoCompList = self.mapList[self.promptType]
+ self.AutoCompShow(lenEntered = 0, itemList = ' '.join(self.autoCompList))
+
+ elif event.GetKeyCode() in [wx.WXK_UP, wx.WXK_DOWN] and event.ControlDown():
# Command history using ctrl-up and ctrl-down
- if self.cmdbuffer == []: return
+ if len(self.cmdbuffer) < 1:
+ return
+
txt = ''
self.DocumentEnd()
@@ -995,19 +856,19 @@
cmd = shlex.split(str(line))
#send the command list to the processor
- self.RunCmd(cmd)
-
- #add command to history
+ self.parent.RunCmd(cmd)
+
+ # add command to history
self.cmdbuffer.append(line)
- #keep command history to a managable size
+ # keep command history to a managable size
if len(self.cmdbuffer) > 200:
del self.cmdbuffer[0]
self.cmdindex = len(self.cmdbuffer)
-
+
else:
event.Skip()
-
+
def GetTextLeft(self):
"""!Returns all text left of the caret"""
entry = ''
@@ -1059,44 +920,14 @@
return usage.strip(), description
else:
return ''
-
- def OnDestroy(self, evt):
+
+ def OnDestroy(self, event):
"""!The clipboard contents can be preserved after
the app has exited"""
-
wx.TheClipboard.Flush()
- evt.Skip()
-
+ event.Skip()
+
def OnCmdErase(self, event):
"""!Erase command prompt"""
self.Home()
self.DelLineRight()
-
- def OnRunCmd(self, event):
- """!Run command"""
- cmdString = event.GetString()
-
- if self.parent.GetName() != "LayerManager":
- return
-
- if cmdString[:2] == 'd.' and not self.parent.curr_page:
- self.parent.NewDisplay(show=True)
-
- cmd = shlex.split(str(cmdString))
- if len(cmd) > 1:
- self.parent.goutput.RunCmd(cmd, switchPage = True)
- else:
- self.parent.goutput.RunCmd(cmd, switchPage = False)
-
- self.OnUpdateStatusBar(None)
-
- def OnUpdateStatusBar(self, event):
- """!Update Layer Manager status bar"""
- if self.parent.GetName() != "LayerManager":
- return
-
- if event is None:
- self.parent.statusbar.SetStatusText("")
- else:
- self.parent.statusbar.SetStatusText(_("Type GRASS command and run by pressing ENTER"))
- event.Skip()
Modified: grass/branches/develbranch_6/gui/wxpython/wxgui.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/wxgui.py 2009-12-24 11:43:07 UTC (rev 40124)
+++ grass/branches/develbranch_6/gui/wxpython/wxgui.py 2009-12-24 11:50:22 UTC (rev 40125)
@@ -129,9 +129,9 @@
# creating widgets
# -> self.notebook, self.goutput, self.outpage
- self.notebook = self.__createNoteBook()
self.menubar, self.menudata = self.__createMenuBar()
self.statusbar = self.CreateStatusBar(number=1)
+ self.notebook = self.__createNoteBook()
self.toolbar = self.__createToolBar()
# bindings
More information about the grass-commit
mailing list