[GRASS-SVN] r54331 - in grass-addons/grass7/gui/wxpython: . wx.rdigit wx.rdigit/rdigit

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Dec 18 05:26:26 PST 2012


Author: rashadkm
Date: 2012-12-18 05:26:25 -0800 (Tue, 18 Dec 2012)
New Revision: 54331

Added:
   grass-addons/grass7/gui/wxpython/wx.rdigit/
   grass-addons/grass7/gui/wxpython/wx.rdigit/frame.py
   grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/
   grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/__init__.py
   grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/dialogs_core.py
   grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/main.py
   grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/mapwindow.py
   grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/toolbars.py
   grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/wxdigit.py
   grass-addons/grass7/gui/wxpython/wx.rdigit/toolbars.py
Log:
Added wxGUI Raster Digitizer

Added: grass-addons/grass7/gui/wxpython/wx.rdigit/frame.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/frame.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/frame.py	2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,392 @@
+"""!
+ at package frame.py
+
+ at brief wxIClass frame with toolbar for digitizing training areas and
+for spectral signature analysis.
+
+Classes:
+ - frame::RDigitMapFrame
+ - frame::MapManager
+
+(C) 2006-2011 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.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+"""
+
+import os
+import sys
+import copy
+import tempfile
+
+if __name__ == "__main__":
+    sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
+
+import wx
+
+from ctypes import *
+import grass.script as grass
+from core import globalvar
+from core.gcmd          import GError, GMessage
+from mapdisp            import statusbar as sb
+from mapdisp.mapwindow  import BufferedWindow
+from gui_core.mapdisp   import SingleMapFrame
+from core.render        import Map, MapLayer
+from core.gcmd          import RunCommand, GMessage
+
+from toolbars    import RDigitMapToolbar,      RDigitMapManagerToolbar
+
+from rdigit.mapwindow import RDigitWindow
+from rdigit.toolbars    import RDigitToolbar
+from rdigit.main import haveRDigit, RDigit
+        
+class RDigitMapFrame(SingleMapFrame):
+    """! RDigitMapFrame main frame    
+    This is the raster digitizer main window. It holds a minimal layer manager from wxIClass
+    """
+    def __init__(self, parent = None, giface = None, title = _("Raster Digitizer"),
+                 toolbars = ["digitMap","rdigit"],
+                 size = (875, 600), name = 'RDigitWindow', **kwargs):
+        """!
+        @param parent (no parent is expected)
+        @param title window title
+        @param toolbars dictionary of active toolbars (defalult value represents all toolbars)
+        @param size default size
+        """
+        SingleMapFrame.__init__(self, parent = parent, title = title, name = name, Map = Map(), **kwargs)
+        self._giface = giface
+        
+        self.MapWindow = BufferedWindow(parent = self,giface = self._giface, Map = self.Map, frame = self)
+        self.outMapName = None
+        
+        self.mapManager = MapManager(self, mapWindow = self.GetWindow(),
+                                             Map = self.GetMap())
+        self.SetSize(size)
+       
+        self.MapWindowRDigit = RDigitWindow(parent = self, giface = self._giface,
+                                                id = wx.ID_ANY, frame = self,
+                                                Map = self.Map)  
+        
+        # Add toolbars
+        
+        toolbarsCopy = toolbars[:]
+        if sys.platform == 'win32':
+            self.AddToolbar(toolbarsCopy.pop(1))
+            toolbarsCopy.reverse()
+        else:
+            self.AddToolbar(toolbarsCopy.pop(0))
+        for toolb in toolbarsCopy:
+            self.AddToolbar(toolb)
+            
+        self.GetMapToolbar().Bind(wx.EVT_CHOICE, self.OnUpdateActive)
+        
+        #
+        # Add statusbar
+        #
+        
+        # items for choice
+        self.statusbarItems = [sb.SbCoordinates,
+                               sb.SbRegionExtent,
+                               sb.SbCompRegionExtent,
+                               sb.SbShowRegion,
+                               sb.SbAlignExtent,
+                               sb.SbResolution,
+                               sb.SbDisplayGeometry,
+                               sb.SbMapScale,
+                               sb.SbGoTo,
+                               sb.SbProjection]
+        
+        # create statusbar and its manager
+        statusbar = self.CreateStatusBar(number = 4, style = 0)
+        statusbar.SetStatusWidths([-5, -2, -1, -1])
+        self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar)
+        
+        # fill statusbar manager
+        self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar)
+        self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2))
+        self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3))
+        
+        self.statusbarManager.Update()
+        
+        self.changes = False
+        self.exportVector = None
+        self.MapWindowCopy = None
+
+                                   
+        self._addPanes()
+        self._mgr.Update()
+        
+        self.mapManager.SetToolbar(self.toolbars['digitMap'])
+        
+        # default action
+        self.OnPan(event = None)
+        
+        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+        
+    def OnCloseWindow(self, event):
+        self.Destroy()
+        
+    def GetWindow(self):
+      return self.MapWindow
+
+    def GetMap(self):
+      return self.Map
+     
+      
+    def OnHelp(self, event):
+        """!Show help page"""
+        helpInProgress = True
+        
+    def GetToolbar(self,name):
+        if name in self.toolbars:
+            return self.toolbars[name]
+        
+        return None    
+        
+    def AddToolbar(self, name):
+        """!Add toolbars to the frame
+        """
+        if name == "digitMap":
+            self.toolbars[name] = RDigitMapToolbar(self)
+            
+            self._mgr.AddPane(self.toolbars[name],
+                              wx.aui.AuiPaneInfo().
+                              Name(name).Caption(_("Map Toolbar")).
+                              ToolbarPane().Top().
+                              LeftDockable(False).RightDockable(False).
+                              BottomDockable(False).TopDockable(True).
+                              CloseButton(False).Layer(2).Row(1).
+                              BestSize((self.toolbars[name].GetBestSize())))
+                              
+        elif name == "rdigit":
+          self.toolbars[name] = RDigitToolbar(parent = self, MapWindow = self.MapWindowRDigit,
+                                             digitClass = RDigit, layerTree = self.mapManager)
+                                                
+          self._mgr.AddPane(self.toolbars[name],
+                          wx.aui.AuiPaneInfo().
+                          Name("rdigittoolbar").Caption(_("Raster Digitizer Toolbar")).
+                          ToolbarPane().Top().Row(1).
+                          LeftDockable(False).RightDockable(False).
+                          BottomDockable(False).TopDockable(True).
+                          CloseButton(False).Layer(0).
+                          BestSize((self.toolbars['rdigit'].GetBestSize())))                                                
+          self.MapWindowRDigit.SetToolbar(self.toolbars[name])
+          self._mgr.GetPane('rdigittoolbar').Hide()
+          
+
+                              
+    def _addPanes(self):
+      """!Add mapwindows and toolbars to aui manager"""
+
+      self._addPaneMapWindow()
+      self._addPaneToolbar(name = 'digitMap')
+     
+
+        
+    def _addPaneToolbar(self, name):
+      
+        self.toolbars[name] = RDigitMapManagerToolbar(self, self.mapManager)
+        self._mgr.AddPane(self.toolbars[name],
+                          wx.aui.AuiPaneInfo().ToolbarPane().Movable().
+                          Name(name).
+                          CloseButton(False).Center().Layer(0).
+                          BestSize((self.toolbars[name].GetBestSize())))
+        
+    def _addPaneMapWindow(self):
+        
+        self._mgr.AddPane(self.MapWindow, wx.aui.AuiPaneInfo().CentrePane().
+                          Dockable(False).BestSize((-1,-1)).Name('window').
+                          CloseButton(False).DestroyOnClose(True).
+                          Layer(0))
+
+        self._mgr.AddPane(self.MapWindowRDigit, wx.aui.AuiPaneInfo().CentrePane().
+                          Dockable(True).BestSize((-1,-1)).Name('rdigit').
+                          CloseButton(False).DestroyOnClose(True).
+                          Layer(0))
+                          
+        
+
+        self._mgr.GetPane('window').Show()
+        self._mgr.GetPane('rdigit').Hide()
+                               
+                    
+        
+    def IsStandalone(self):
+        """!Check if Map display is standalone"""
+        return True
+    
+    def OnUpdateActive(self, event):
+        """!
+        @todo move to DoubleMapFrame?
+        """
+        self.StatusbarUpdate() 
+      
+        
+    def GetMapToolbar(self):
+        """!Returns toolbar with zooming tools"""
+        return self.toolbars['digitMap']
+        
+    def AddRasterMap(self, name, firstMap = True, secondMap = True):
+        """!Add raster map to Map"""
+        cmdlist = ['d.rast', 'map=%s' % name]
+        if firstMap:
+            self.GetFirstMap().AddLayer(type='raster', command=cmdlist, l_active=True,
+                                        name=name, l_hidden=False, l_opacity=1.0, l_render=False)
+            self.GetWindow().UpdateMap(render = True, renderVector = False)
+            
+    def OnZoomMenu(self, event):
+        """!Popup Zoom menu """
+        zoommenu = wx.Menu()
+        zoommenu.Destroy()             
+
+    def OnZoomIn(self, event):
+        super(RDigitMapFrame, self).OnZoomIn(event)
+        
+    def OnZoomOut(self, event):
+        super(RDigitMapFrame, self).OnZoomOut(event)
+        
+    def OnPan(self, event):
+        super(RDigitMapFrame, self).OnPan(event)
+
+    def GetOutputMap(self):
+      return self.outMapName
+
+    def RemoveToolbar(self, name):
+    
+        self.outMapName = self.toolbars['rdigit'].GetMapName()
+        self.mapManager.AddLayer(name = self.outMapName)
+        self._mgr.GetPane('window').Show()
+        self._mgr.GetPane('rdigit').Hide()
+        self._mgr.GetPane('rdigittoolbar').Hide()
+        self.MapWindow = self.MapWindowCopy
+        self._mgr.Update()
+        
+    def OnDrawArea(self, event):
+
+      if not self._mgr.GetPane('rdigit').IsShown():
+        self._mgr.GetPane('window').Hide()
+        self._mgr.GetPane('rdigit').Show()
+        self._mgr.GetPane('rdigittoolbar').Show()
+        self._mgr.Update()
+        self.MapWindowCopy = self.MapWindow
+        self.MapWindow = self.MapWindowRDigit
+        self.MapWindow.mouse['box'] = "point"
+        self.MapWindow.zoomtype     = 0
+        self.MapWindow.pen          = wx.Pen(colour = 'red',   width = 2, style = wx.SOLID)
+        self.MapWindow.polypen      = wx.Pen(colour = 'green', width = 2, style = wx.SOLID)  
+      else:
+        self.MapWindow = self.MapWindowCopy
+        self._mgr.GetPane('window').Show()
+        self._mgr.GetPane('rdigit').Hide()                     
+ 
+
+
+        
+class MapManager:
+    """! Class for managing map renderer.
+    
+    It is connected with iClassMapManagerToolbar.
+    """
+    def __init__(self, frame, mapWindow, Map):
+        """!
+        
+        It is expected that \a mapWindow is conected with \a Map.
+        
+        @param frame application main window
+        @param mapWindow map window instance
+        @param Map map renderer instance
+        """
+        self.map = Map
+        self.frame = frame
+        self.mapWindow = mapWindow
+        self.toolbar = None
+        
+        self.layerName = {}
+        
+        
+    def SetToolbar(self, toolbar):
+        self.toolbar = toolbar
+        
+    def AddLayer(self, name, alias = None, resultsLayer = False):
+        """!Adds layer to Map and update toolbar 
+        
+        @param name layer (raster) name
+        @param resultsLayer True if layer is temp. raster showing the results of computation
+        """
+        if (resultsLayer and
+            name in [l.GetName() for l in self.map.GetListOfLayers(l_name = name)]):
+            self.frame.Render(self.mapWindow)
+            return
+            
+        cmdlist = ['d.rast', 'map=%s' % name]
+        self.map.AddLayer(type = 'raster', command = cmdlist, l_active = True,
+                          name = name, l_hidden = False, l_opacity = 1.0, l_render = True)
+        #self.frame.Render(self.GetWindow().Render())
+        self.frame.GetWindow().UpdateMap(render = True, renderVector = False)
+        
+        
+        if alias is not None:
+            alias = self._addSuffix(alias)
+            self.layerName[alias] = name
+            name = alias
+        else:
+            self.layerName[name] = name
+            
+        self.toolbar.choice.Insert(name, 0)
+        self.toolbar.choice.SetSelection(0)
+        
+
+        
+    def RemoveLayer(self, name, idx):
+        """!Removes layer from Map and update toolbar"""
+        name = self.layerName[name]
+        self.map.RemoveLayer(name = name)
+        del self.layerName[name]
+        self.toolbar.choice.Delete(idx)
+        if not self.toolbar.choice.IsEmpty():
+            self.toolbar.choice.SetSelection(0)
+
+        self.frame.GetWindow().UpdateMap(render = True, renderVector = False)            
+        #self.frame.Render(self.mapWindow)
+            
+    def SelectLayer(self, name):
+        """!Moves selected layer to top"""
+        layers = self.map.GetListOfLayers(l_type = 'raster')
+        idx = None
+        for i, layer in enumerate(layers):
+            if self.layerName[name] == layer.GetName():
+                idx = i
+                break
+                
+        if idx is not None: # should not happen
+            layers.append(layers.pop(idx))
+            
+            choice = self.toolbar.choice
+            idx = choice.FindString(name)
+            choice.Delete(idx)
+            choice.Insert(name, 0)
+            choice.SetSelection(0)
+            
+            #layers.reverse()
+            self.map.ReorderLayers(layers)
+            self.frame.GetWindow().UpdateMap(render = True, renderVector = False)
+        
+
+def test():
+    import gettext
+    import core.render as render
+    
+    gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
+    
+    app = wx.PySimpleApp()
+    wx.InitAllImageHandlers()
+    
+    frame = RDigitMapFrame()
+    frame.Show()
+    app.MainLoop()
+
+if __name__ == "__main__":
+    test()
+    

Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/__init__.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/__init__.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/__init__.py	2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,6 @@
+all = [
+    'mapwindow',
+    'main',
+    'toolbars',
+    'wxdigit',
+    ]

Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/dialogs_core.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/dialogs_core.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/dialogs_core.py	2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,233 @@
+
+import os
+import sys
+import re
+from bisect import bisect
+
+import wx
+#import wx.lib.filebrowsebutton as filebrowse
+#import wx.lib.mixins.listctrl as listmix
+#from wx.lib.newevent import NewEvent
+
+from gui_core.dialogs import ElementDialog
+
+from grass.script import core as grass
+from grass.lib import gis as gis
+from grass.lib import raster as grast
+
+from core             import globalvar
+from core.gcmd        import GError, RunCommand, GMessage
+from gui_core.gselect import ElementSelect, LocationSelect, MapsetSelect, Select, OgrTypeSelect, GdalSelect, MapsetSelect
+from gui_core.forms   import GUI
+from gui_core.widgets import SingleSymbolPanel, EVT_SYMBOL_SELECTION_CHANGED, GListCtrl
+from core.utils       import GetLayerNameFromCmd, GetValidLayerName
+from core.settings    import UserSettings, GetDisplayVectSettings
+from core.debug       import Debug
+import ctypes
+
+
+class NewRasterDialog(ElementDialog):
+    def __init__(self, parent, id = wx.ID_ANY, title = _('Create new vector map'),
+                 disableAdd = False, showType = False,
+                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, *kwargs):
+        """!Dialog for creating new vector map
+
+        @param parent parent window
+        @param id window id
+        @param title window title
+        @param disableAdd disable 'add layer' checkbox
+        @param showType True to show feature type selector (used for creating new empty OGR layers)
+        @param style window style
+        @param kwargs other argumentes for ElementDialog
+        
+        @return dialog instance       
+        """
+        ElementDialog.__init__(self, parent, title, label = _("Name for new raster map:"))
+        
+        self.element = Select(parent = self.panel, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
+                              type = 'raster', mapsets = [grass.gisenv()['MAPSET'],])
+        
+        # determine output format
+        if showType:
+            self.ftype = GdalSelect(parent = self, panel = self.panel)
+        else:
+            self.ftype = None
+        
+        
+        self.addbox = wx.CheckBox(parent = self.panel,
+                                  label = _('Add created map into layer tree'), style = wx.NO_BORDER)
+        if disableAdd:
+            self.addbox.SetValue(True)
+            self.addbox.Enable(False)
+        else:
+            self.addbox.SetValue(UserSettings.Get(group = 'cmd', key = 'addNewLayer', subkey = 'enabled'))
+
+       
+        
+        self.PostInit()
+        
+        self._layout()
+        self.SetMinSize(self.GetSize())
+        
+    def OnMapName(self, event):
+        """!Name for vector map layer given"""
+        self.OnElement(event)
+        
+
+        
+    def _layout(self):
+        """!Do layout"""
+        self.dataSizer.Add(item = self.element, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL, border = 1)
+        if self.ftype:
+            self.dataSizer.AddSpacer(1)
+            self.dataSizer.Add(item = self.ftype, proportion = 0,
+                               flag = wx.EXPAND | wx.ALL, border = 1)
+      
+    
+            
+        self.dataSizer.AddSpacer(5)
+        
+        self.dataSizer.Add(item = self.addbox, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL, border = 1)
+        
+        self.panel.SetSizer(self.sizer)
+        self.sizer.Fit(self)
+
+    def GetName(self, full = False):
+        """!Get name of vector map to be created
+
+        @param full True to get fully qualified name
+        """
+        name = self.GetElement()
+        if full:
+            if '@' in name:
+                return name
+            else:
+                return name + '@' + grass.gisenv()['MAPSET']
+        
+        return name.split('@', 1)[0]
+
+    def GetKey(self):
+        """!Get key column name"""
+ 
+    
+    def IsChecked(self, key):
+        """!Get dialog properties
+
+        @param key window key ('add', 'table')
+
+        @return True/False
+        @return None on error
+        """
+        if key == 'add':
+            return self.addbox.IsChecked()
+
+        
+        return None
+    
+    def GetFeatureType(self):
+        """!Get feature type for OGR
+
+        @return feature type as string
+        @return None for native format
+        """
+        if self.ftype:
+            return self.ftype.GetType()
+        
+        return None
+
+def CreateNewRaster(parent, title = _('Create new vector map'),
+                    exceptMap = None,
+                    disableAdd = False):
+    """!Create new vector map layer
+    
+    @param cmd (prog, **kwargs)
+    @param title window title
+    @param exceptMap list of maps to be excepted
+    @param disableAdd disable 'add layer' checkbox
+    
+    @return dialog instance
+    @return None on error
+    """
+    vExternalOut = grass.parse_command('r.external.out', flags = 'p', delimiter = ':')
+
+    
+    UsingGDAL  = vExternalOut.has_key('Not using GDAL') == False
+
+    
+    if not UsingGDAL:
+        showType = False
+    else:
+        showType = True
+
+    dlg = NewRasterDialog(parent, title = title,
+                          disableAdd = disableAdd, showType = showType)
+    
+    if dlg.ShowModal() != wx.ID_OK:
+        dlg.Destroy()
+        return None
+
+    outmap = dlg.GetName()
+    #key    = dlg.GetKey()
+    if outmap == exceptMap:
+        GError(parent = parent,
+               message = _("Unable to create raster map <%s>.") % outmap)
+        dlg.Destroy()
+        return None
+
+        
+    if outmap == '': # should not happen
+        dlg.Destroy()
+        return None
+
+
+        
+    if not UsingGDAL:
+        listOfRasters = grass.list_grouped('rast')[grass.gisenv()['MAPSET']]
+    else:
+        listOfRasters = RunCommand('r.external',
+                                   quiet = True,
+                                   parent = parent,
+                                   read = True,
+                                   flags = 'l',
+                                   out = outmap,
+                                   source = vExternalOut['directory']).splitlines()
+
+    if not UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled') and \
+            outmap in listOfRasters:
+        dlgOw = wx.MessageDialog(parent, message = _("Raster map <%s> already exists "
+                                                     "in the current mapset. "
+                                                     "Do you want to overwrite it?") % outmap,
+                                 caption = _("Overwrite?"),
+                                 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+        if dlgOw.ShowModal() == wx.ID_YES:
+            overwrite = True
+        else:
+            dlgOw.Destroy()
+            dlg.Destroy()
+            return None
+        
+    if UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled'):
+        overwrite = True
+
+
+
+    
+    if UsingGDAL:
+        # create link for OGR layers
+        RunCommand('r.external',
+                   overwrite = overwrite,
+                   parent = parent,
+                   directory = vExternalOut['directory'],
+                   layer = outmap)
+        
+  
+    # return fully qualified map name
+    if '@' not in outmap:
+        outmap += '@' + grass.gisenv()['MAPSET']
+        
+    #if log:
+    #    log.WriteLog(_("New raster map <%s> created") % outmap)   
+    return dlg
+

Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/main.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/main.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/main.py	2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,36 @@
+"""!
+ at package vdigit.main
+
+ at brief wxGUI vector digitizer
+
+Classes:
+ - main::VDigit
+
+(C) 2007-2011 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.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+try:
+    from rdigit.wxdigit import IRDigit, GV_LINES, CFUNCTYPE
+    haveRDigit = True
+    errorMsg   = ''
+except (ImportError, NameError), err:
+    haveRDigit = False
+    errorMsg   = err
+    print errorMsg
+    GV_LINES   = -1
+    class IRDigit:
+        def __init__(self):
+            pass
+
+class RDigit(IRDigit):
+    def __init__(self, mapwindow):
+        """!Base class of vector digitizer
+        
+        @param mapwindow reference to mapwindow (mapdisp_window.BufferedWindow) instance
+        """
+        IRDigit.__init__(self, mapwindow)

Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/mapwindow.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/mapwindow.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/mapwindow.py	2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,448 @@
+"""!
+ at package vdigit.mapwindow
+
+ at brief Map display canvas for wxGUI vector digitizer
+
+Classes:
+ - mapwindow::RDigitWindow
+
+(C) 2011 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.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+"""
+
+import wx
+
+from core.gcmd      import RunCommand, GMessage, GError
+from core.debug     import Debug
+from mapdisp.mapwindow import BufferedWindow
+from core.settings  import UserSettings
+from core.utils     import ListOfCatsToRange
+from core.globalvar import QUERYLAYER
+
+
+class Circle:
+  def __init__(self, pt, r):
+    self.point = pt
+    self.radius = r
+
+class RDigitWindow(BufferedWindow):
+    """!A Buffered window extended for raster digitizer.
+    """
+    def __init__(self, parent, giface, Map, frame,
+                 id = wx.ID_ANY, tree = None, lmgr = None,
+                 style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
+        BufferedWindow.__init__(self, parent = parent, giface = giface, id = id, Map = Map,
+                                frame = frame, tree = tree, style = style, **kwargs)
+        self.lmgr = lmgr
+        self.pdcVector = wx.PseudoDC()   
+        self.toolbar   = self.parent.GetToolbar('rdigit')
+        self.digit     = None # wxvdigit.IVDigit
+        self.existingCoords = list()
+        self.polygons = list()
+        self.circles = list()
+        self.idx = wx.ID_NEW + 1
+        self.selectid = None
+        self.selectid_circle = None
+        self.idxCats = dict()
+        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+       
+
+    def SetToolbar(self, toolbar):
+        """!Set up related toolbar
+        """
+        self.toolbar = toolbar
+        
+    def _onMotion(self, coord, precision):
+        """!Track mouse motion and update statusbar (see self.Motion)
+
+        @parem coord easting, northing
+        @param precision formatting precision
+        """
+        e, n = coord
+        
+        if self.toolbar.GetAction() != 'addLine' or \
+                self.toolbar.GetAction('type') not in ('line', 'boundary') or \
+                len(self.polycoords) == 0:
+            return False
+        
+        # for linear feature show segment and total length
+        distance_seg = self.Distance(self.polycoords[-1],
+                                     (e, n), screen = False)[0]
+        distance_tot = distance_seg
+        for idx in range(1, len(self.polycoords)):
+            distance_tot += self.Distance(self.polycoords[idx-1],
+                                          self.polycoords[idx],
+                                          screen = False)[0]
+        self.parent.SetStatusText("%.*f, %.*f (seg: %.*f; tot: %.*f)" % \
+                                                (precision, e, precision, n,
+                                                 precision, distance_seg,
+                                                 precision, distance_tot), 0)
+        
+        return True
+    
+    def OnKeyDown(self, event):
+        """!Key pressed"""
+        shift = event.ShiftDown()
+        kc = event.GetKeyCode()
+        
+        event = None
+        if not shift:
+            if kc == ord('P'):
+                event = wx.CommandEvent(winid = self.toolbar.addPoint)
+                tool = self.toolbar.OnAddPoint
+            elif kc == ord('L'):
+                event = wx.CommandEvent(winid = self.toolbar.addLine)
+                tool = self.toolbar.OnAddLine
+        if event:
+            self.toolbar.OnTool(event)
+            self.selectid = None
+            tool(event)
+            
+
+    def DrawLines2(self, plineid, pdc = None, polycoords = None):
+        """!Draw polyline in PseudoDC
+        
+        Set self.pline to wx.NEW_ID + 1
+        
+        polycoords - list of polyline vertices, geographical coordinates
+        (if not given, self.polycoords is used)
+        """
+        if not pdc:
+            pdc = self.pdcTmp
+
+        if not polycoords:
+            polycoords = self.polycoords
+        
+        if len(polycoords) > 0:
+            coords = []
+            for p in polycoords:
+                coords.append(self.Cell2Pixel(p))
+
+            self.Draw(pdc, drawid = plineid, pdctype = 'polyline', coords = coords)
+            
+            Debug.msg (2, "BufferedWindow.DrawLines2(): coords=%s, id=%s" % \
+                           (coords, plineid))
+            
+            return plineid
+        
+        return -1            
+        
+    def _updateMap(self):
+        if not self.toolbar or \
+                not self.toolbar.GetMapName():  
+            return
+       
+        self.pdcVector.RemoveAll()
+
+        for poly in self.polygons:
+            idx = poly.keys()[0]
+            #print idx
+            self.pdcVector.SetId(idx)
+            #if self.selectid:
+                  #if poly.has_key(self.selectid):
+                  #print poly[self.selectid]
+            if idx != self.selectid:
+                self.pen = self.polypen = wx.Pen(colour = wx.GREEN, width = 2)
+            else:
+                self.pen = self.polypen = wx.Pen(colour = wx.RED, width = 2)
+                
+            self.DrawLines2(idx, pdc = self.pdcVector, polycoords = poly[idx])
+
+        #print self.circles
+        for circle in self.circles:
+            idx = circle.keys()[0]
+            C = circle[idx]
+
+            if idx != self.selectid_circle:
+                self.pen = self.polypen = wx.Pen(colour = wx.GREEN, width = 2)
+            else:
+                self.pen = self.polypen = wx.Pen(colour = wx.RED, width = 2)
+
+            self.pdcVector.BeginDrawing()
+            self.pdcVector.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+            self.pdcVector.SetPen(self.pen)
+            self.pdcVector.SetId(idx)
+            self.pdcVector.DrawCircle(C.point[0],C.point[1],C.radius)
+            self.pdcVector.EndDrawing()
+            self.Refresh()       
+         
+        item = None
+        if self.tree:
+            try:
+                item = self.tree.FindItemByData('maplayer', self.toolbar.GetMapName())
+            except TypeError:
+                pass
+        
+        # translate tmp objects (pointer position)
+        if self.toolbar.GetAction() == 'moveLine' and \
+                hasattr(self, "moveInfo"):
+            if 'beginDiff' in self.moveInfo:
+                # move line
+                for id in self.moveInfo['id']:
+                    self.pdcTmp.TranslateId(id,
+                                            self.moveInfo['beginDiff'][0],
+                                            self.moveInfo['beginDiff'][1])
+                del self.moveInfo['beginDiff']
+        
+    def OnLeftDownAddLine(self, event):
+        """!Left mouse button pressed - add new feature
+        """
+        try:
+            mapLayer = self.toolbar.GetMapName()
+        except:
+            return
+        
+        if self.toolbar.GetAction('type') in ['point', 'centroid']:
+            # add new point / centroiud
+            east, north = self.Pixel2Cell(self.mouse['begin'])
+            nfeat, fids = self.digit.AddFeature(self.toolbar.GetAction('type'), [(east, north)])
+            #if nfeat < 1:
+                #return
+            
+            self.UpdateMap(render = False) # redraw map
+        
+        elif self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+            # add new point to the line
+            self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
+            self.DrawLines(pdc = self.pdcTmp)
+        
+
+    def _onLeftDown(self, event):
+        """!Left mouse button donw - vector digitizer various actions
+        """
+        try:
+            mapLayer = self.toolbar.GetMapName()
+        except:
+            GMessage(parent = self,
+                     message = _("No vector map selected for editing.1"))
+            event.Skip()
+            return
+        
+        action = self.toolbar.GetAction()
+        #print action
+        if not action:
+            GMessage(parent = self,
+                     message = _("Nothing to do. "
+                                 "Choose appropriate tool from digitizer toolbar."))
+            event.Skip()
+            return
+        
+        if action not in ("moveVertex",
+                          "addVertex",
+                          "removeVertex",
+                          "editLine"):
+            # set pen
+            self.pen = wx.Pen(colour = UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                                        subkey = ['newSegment', 'color']),
+                              width = 2, style = wx.SHORT_DASH)
+            self.polypen = wx.Pen(colour = UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                                            subkey = ['newLine', 'color']),
+                                  width = 2, style = wx.SOLID)
+        
+        if action in ("addVertex",
+                      "removeVertex",
+                      "splitLines"):
+            # unselect
+            self.digit.GetDisplay().SetSelected([])
+        
+        if action == "addLine":
+            self.OnLeftDownAddLine(event)
+            
+        elif action == "deleteCircle":
+            #print "delete:Circle"
+            x,y = event.GetPositionTuple()
+            ids = self.pdcVector.FindObjects(x,y)
+            #print ids
+            if len(ids) > 0:
+                self.selectid_circle = ids[0]
+            else:
+                self.selectid_circle = None
+           
+            ids = []
+            self.polycoords = []            
+            
+        elif action == "addCircle":
+          if len(self.polycoords) < 1: # ignore 'one-point' lines
+              self.polycoords.append(event.GetPositionTuple()[:])            
+            
+
+    def OnLeftUpVarious(self, event):
+        """!Left mouse button released - vector digitizer various
+        actions
+        """
+        pos1 = self.Pixel2Cell(self.mouse['begin'])
+        pos2 = self.Pixel2Cell(self.mouse['end'])
+        
+        nselected = 0
+        action = self.toolbar.GetAction()
+
+        if action in ("deleteLine", "deleteCircle",
+                      "deleteArea"):
+
+            if action in ["deleteArea", "deleteLine"]:
+                
+                x,y = event.GetPositionTuple()
+                ids = self.pdcVector.FindObjectsByBBox(x,y)
+                if len(ids) > 0:
+                    self.selectid = ids[0]
+                else:
+                    self.selectid = None
+             
+                ids = [] 
+                self.polycoords = []      
+                self.UpdateMap(render = False)
+            
+    def _onLeftUp(self, event):
+        """!Left mouse button released"""
+        
+        # eliminate initial mouse moving efect
+        self.mouse['begin'] = self.mouse['end'] 
+        
+        action = self.toolbar.GetAction()
+
+        if action in ("deleteLine",
+                      "deleteArea",
+                      "deleteCircle"):
+            self.OnLeftUpVarious(event)
+            
+        elif action == "addCircle":
+          if len(self.polycoords) > 0: # ignore 'one-point' lines
+
+              beginpt =self.polycoords[0]
+              endpt = event.GetPositionTuple()[:]
+              dist, (north, east) = self.Distance(beginpt, endpt,False)
+              #print dist
+              circle = dict()
+              c = Circle(beginpt, dist)
+              circle[self.idx] = c
+              self.idx = self.idx + 1
+              self.circles.append(circle)
+              
+              self._updateMap()
+              self.polycoords = []          
+        
+    def _onRightDown(self, event):
+        # digitization tool (confirm action)
+        action = self.toolbar.GetAction()
+
+        
+    def _onRightUp(self, event):
+        """!Right mouse button released (confirm action)
+        """
+        action = self.toolbar.GetAction()
+        
+        if action == "addLine" and \
+                self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+            # -> add new line / boundary
+            try:
+                mapName = self.toolbar.GetMapName()
+            except:
+                mapName = None
+                GError(parent = self,
+                       message = _("No vector map selected for editing.2"))
+                                 
+            if mapName:
+                if len(self.polycoords) < 2: # ignore 'one-point' lines
+                    return
+                                   
+                self.idxCats[self.idx] = self.digit.AddFeature(self.toolbar.GetAction('type'), self.polycoords)
+                if self.toolbar.GetAction('type') == 'boundary': 
+                    x0,y0 = self.polycoords[0]
+                    for coord in self.polycoords:
+                        x,y = coord #self.Cell2Pixel(coord)
+                        c = wx.Point(x,y)
+                        self.existingCoords.append(c)
+                    
+                    self.existingCoords.append(wx.Point(x0,y0))
+
+                    coordIdx = dict()
+                    coordIdx[self.idx] = self.existingCoords
+                    self.polygons.append(coordIdx)
+                    self.idx = self.idx+1
+                    self.existingCoords = []
+
+
+                if self.toolbar.GetAction('type') == 'line':
+                    for coord in self.polycoords:
+                        x,y = coord #self.Cell2Pixel(coord)
+                        c = wx.Point(x,y)
+                        self.existingCoords.append(c)
+
+                    coordIdx = dict()
+                    coordIdx[self.idx] = self.existingCoords
+                    self.polygons.append(coordIdx)
+                    self.idx = self.idx+1
+                    self.existingCoords = []
+                    
+                    
+                #Update Map 
+                self.polycoords = []
+                self.UpdateMap(render = False)
+                self.redrawAll = True
+                self.Refresh()                
+
+        elif action in ["deleteArea", "deleteLine"]:
+            # -> delete selected vector features
+            x,y = event.GetPositionTuple()
+            ids = self.pdcVector.FindObjectsByBBox(x,y)
+            idx = ids[0]
+            cat = None
+            if self.idxCats.has_key(idx):
+                cat = self.idxCats[idx]
+                self.digit.DeleteArea(cat)
+            
+            polygonsCopy = self.polygons
+            self.polygons = []
+            for poly in polygonsCopy:
+                id = poly.keys()[0]
+                if idx != id:
+                    self.polygons.append(poly)            
+
+
+        elif action == "deleteCircle":
+            x,y = event.GetPositionTuple()
+            ids = self.pdcVector.FindObjectsByBBox(x,y)
+            idx = ids[0]
+            cat = None
+            #print self.idxCats
+            #print self.idxCats.has_key(idx) , idx
+            if self.idxCats.has_key(idx):
+                cat = self.idxCats[idx]
+                #print cat
+                #self.digit.DeleteCircle(cat)
+
+            circlesCopy = self.circles
+            self.circles = []
+            for circle in circlesCopy:
+                id = circle.keys()[0]
+                if idx != id:
+                    self.circles.append(circle)                
+ 
+        
+    def _onMouseMoving(self, event):
+        self.mouse['end'] = event.GetPositionTuple()[:]
+        
+        Debug.msg (5, "BufferedWindow.OnMouseMoving(): coords=%f,%f" % \
+                       (self.mouse['end'][0], self.mouse['end'][1]))
+
+        action = self.toolbar.GetAction()
+        if action == "addLine" and \
+                self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+            if len(self.polycoords) > 0:
+                self.MouseDraw(pdc = self.pdcTmp, begin = self.Cell2Pixel(self.polycoords[-1]))
+                
+
+            self.Refresh() # TODO: use RefreshRect()
+            self.mouse['begin'] = self.mouse['end']
+            
+    def _zoom(self, event):
+        tmp1 = self.mouse['end']
+        tmp2 = self.Cell2Pixel(self.moveInfo['begin'])
+        dx = tmp1[0] - tmp2[0]
+        dy = tmp1[1] - tmp2[1]
+      
+        

Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/toolbars.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/toolbars.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/toolbars.py	2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,561 @@
+"""!
+ at package rdigit.toolbars
+
+ at brief wxGUI raster digitizer toolbars
+
+List of classes:
+ - toolbars::RDigitToolbar
+
+(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.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+"""
+import wx
+
+from grass.script import core as grass
+
+from gui_core.toolbars  import BaseToolbar, BaseIcons
+from gui_core.dialogs   import CreateNewVector
+from dialogs_core   import CreateNewRaster
+from vdigit.preferences import VDigitSettingsDialog
+from core.debug         import Debug
+from core.settings      import UserSettings
+from core.gcmd          import GError
+from icons.icon         import MetaIcon
+from iclass.digit       import IClassVDigit
+
+class RDigitToolbar(BaseToolbar):
+    """!Toolbar for digitization
+    """
+    def __init__(self, parent, MapWindow, digitClass, tools = [], layerTree = None, log = None):
+        self.MapWindow     = MapWindow
+        self.Map           = MapWindow.GetMap() # Map class instance
+        self.layerTree     = layerTree  # reference to layer tree associated to map display
+        self.log           = log        # log area
+        self.tools         = tools
+        self.digitClass    = digitClass
+        BaseToolbar.__init__(self, parent)
+        self.digit         = None
+        
+        # currently selected map layer for editing (reference to MapLayer instance)
+        self.mapLayer = None
+        self.mapName  = None
+        # list of vector layers from Layer Manager (only in the current mapset)
+        #self.laayers   = [] 
+        
+        self.comboid  = self.combo = None
+        self.undo     = -1
+        self.redo     = -1
+        
+        # only one dialog can be open
+        self.settingsDialog   = None
+        
+        # create toolbars (two rows optionally)
+        self.InitToolbar(self._toolbarData())
+        self.Bind(wx.EVT_TOOL, self._toolChosen)
+        
+        # default action (digitize new point, line, etc.)
+        self.action = { 'desc' : '',
+                        'type' : '',
+                        'id'   : -1 }
+        
+        # list of available vector maps
+        self.UpdateListOfLayers(updateTool = True)
+        
+        self.layerNameList = []
+        layers = self.Map.GetListOfLayers(l_type = "raster",
+                                                      l_mapset = grass.gisenv()['MAPSET'])
+        
+        for layer in layers:
+            if not layer.name in self.layerNameList: # do not duplicate layer
+                self.layerNameList.append (layer.GetName())
+
+        # realize toolbar
+        self.Realize()
+        # workaround for Mac bug. May be fixed by 2.8.8, but not before then.
+        if self.combo:
+            self.combo.Hide()
+            self.combo.Show()
+        
+        # disable undo/redo
+        if self.undo > 0:
+            self.EnableTool(self.undo, False)
+        if self.redo > 0:
+            self.EnableTool(self.redo, False)
+        
+        # toogle to pointer by default
+        self.OnTool(None)
+        
+        self.FixSize(width = 105)
+                
+    def _toolbarData(self):
+        """!Toolbar data
+        """
+        data = []
+        
+        icons = {
+
+            'addLine'         : MetaIcon(img = 'line-create',
+                                         label = _('Digitize new line'),
+                                         desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+            'addBoundary'     : MetaIcon(img = 'polygon-create',
+                                         label = _('Digitize new boundary'),
+                                         desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')), 
+            'addCircle'        : MetaIcon(img = 'draw-circle',
+                                         label = _('Digitize new Cirlce'),
+                                         desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+
+
+            'deleteLine'      : MetaIcon(img = 'line-delete',
+                                         label = _('Delete feature(s)'),
+                                         desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+            'deleteArea'      : MetaIcon(img = 'polygon-delete',
+                                         label = _('Delete area(s)'),
+                                         desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+            'deleteCircle'        : MetaIcon(img = 'delete-circle',
+                                         label = _('Digitize new Cirlce'),
+                                         desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+ 
+            'settings'        : BaseIcons['settings'].SetLabel(_('Digitization settings')),
+            'quit'            : BaseIcons['quit'].SetLabel(label = _('Quit digitizer'),
+                                                           desc = _('Quit digitizer and save changes')),
+            'help'            : BaseIcons['help'].SetLabel(label = _('Vector Digitizer manual'),
+                                                           desc = _('Show Vector Digitizer manual')),
+            'undo'            : MetaIcon(img = 'undo',
+                                         label = _('Undo'),
+                                         desc = _('Undo previous changes')),
+            'redo'            : MetaIcon(img = 'redo',
+                                         label = _('Redo'),
+                                         desc = _('Redo previous changes')),
+            }
+        
+        if not self.tools or 'selector' in self.tools:
+            data.append((None, ))
+
+        if not self.tools or 'addLine' in self.tools:
+            data.append(("addLine", icons["addLine"],
+                        self.OnAddLine,
+                        wx.ITEM_CHECK))
+
+        if not self.tools or 'addBoundary' in self.tools:
+            data.append(("addBoundary", icons["addBoundary"],
+                         self.OnAddBoundary,
+                         wx.ITEM_CHECK))
+                         
+#        if not self.tools or 'addCircle' in self.tools:
+#            data.append(("addCircle", icons["addCircle"],
+#                         self.OnAddCircle,
+#                         wx.ITEM_CHECK))
+                         
+        data.append((None, ))
+
+        if not self.tools or 'deleteLine' in self.tools:
+            data.append(("deleteLine", icons["deleteLine"],
+                         self.OnDeleteLine,
+                         wx.ITEM_CHECK))
+        if not self.tools or 'deleteArea' in self.tools:
+            data.append(("deleteArea", icons["deleteArea"],
+                         self.OnDeleteArea,
+                         wx.ITEM_CHECK))
+#        if not self.tools or 'deleteCircle' in self.tools:
+#            data.append(("deleteCircle", icons["deleteCircle"],
+#                         self.OnDeleteCircle,
+#                         wx.ITEM_CHECK))
+
+#        if not self.tools or 'undo' in self.tools or \
+#                'redo' in self.tools:
+#            data.append((None, ))
+#        if not self.tools or 'undo' in self.tools:
+#            data.append(("undo", icons["undo"],
+#                         self.OnUndo))
+#        if not self.tools or 'redo' in self.tools:
+#            data.append(("redo", icons["redo"],
+#                         self.OnRedo))
+#        if not self.tools or 'settings' in self.tools or \
+#                'help' in self.tools or \
+#                'quit' in self.tools:
+#            data.append((None, ))
+            
+        if not self.tools or 'help' in self.tools:
+            data.append(("help", icons["help"],
+                         self.OnHelp))
+        if not self.tools or 'quit' in self.tools:
+            data.append(("quit", icons["quit"],
+                         self.OnExit))
+        
+        return self._getToolbarData(data)
+    
+    def _toolChosen(self, event):
+        """!Tool selected -> untoggles selected tools in other
+        toolbars
+
+        @todo implement iclass front-end
+        """
+        self.parent.MapWindow.UnregisterAllHandlers()
+        
+        if hasattr(self.parent, "UpdateTools"):
+            self.parent.UpdateTools(event)
+        self.OnTool(event)
+        
+    def OnTool(self, event):
+        """!Tool selected -> untoggles previusly selected tool in
+        toolbar"""
+        # set cursor
+        cursor = self.parent.cursors["cross"]
+        self.MapWindow.SetCursor(cursor)
+        
+        # pointer
+        self.parent.OnPointer(None)
+         
+        aId = self.action.get('id', -1)       
+        BaseToolbar.OnTool(self, event)
+
+        # clear tmp canvas
+        if self.action['id'] != aId or aId == -1:
+            self.MapWindow.polycoords = []
+            self.MapWindow.ClearLines(pdc = self.MapWindow.pdcTmp)
+#            if self.digit and \
+#                    len(self.MapWindow.digit.GetDisplay().GetSelected()) > 0:
+#                # cancel action
+#                self.MapWindow.OnMiddleDown(None)
+#        
+        # set no action
+        if self.action['id'] == -1:
+            self.action = { 'desc' : '',
+                            'type' : '',
+                            'id'   : -1 }
+        
+        # set focus
+        self.MapWindow.SetFocus()
+        
+
+        
+    def OnAddLine(self, event):
+        """!Add line to the vector map layer"""
+        
+        Debug.msg (2, "RDigitToolbar.OnAddLine()")
+        
+        self.action = { 'desc' : "addLine",
+                        'type' : "line",
+                        'id'   : self.addLine }
+        self.MapWindow.mouse['box'] = 'line'
+
+        
+    def OnAddBoundary(self, event):
+        """!Add boundary to the vector map layer"""
+        
+        Debug.msg (2, "RDigitToolbar.OnAddBoundary()")
+        
+        if self.action['desc'] != 'addLine' or \
+                self.action['type'] != 'boundary':
+            self.MapWindow.polycoords = [] # reset temp line
+        self.action = { 'desc' : "addLine",
+                        'type' : "boundary",
+                        'id'   : self.addBoundary }
+        self.MapWindow.mouse['box'] = 'line'
+        
+    def OnAddCircle(self, event):
+        """!Add cirlce to the vector map layer"""
+        
+        Debug.msg (2, "RDigitToolbar.OnAddCircle()")
+        
+        if self.action['desc'] != 'addCircle':
+            self.MapWindow.polycoords = [] # reset temp line
+        self.action = { 'desc' : "addCircle",
+                        'type' : "circle",
+                        'id'   : self.addCircle }
+        self.MapWindow.mouse['box'] = 'line'        
+
+    def OnExit (self, event=None):
+        """!Quit digitization tool"""
+        
+        # stop editing of the currently selected map layer
+        if self.mapLayer:
+            self.StopEditing()
+        
+        # close dialogs if still open
+        if self.settingsDialog:
+            self.settingsDialog.OnCancel(None)
+            
+        # set default mouse settings
+        self.MapWindow.mouse['use'] = "pointer"
+        self.MapWindow.mouse['box'] = "point"
+        self.MapWindow.polycoords = []
+        
+        # disable the toolbar
+        self.parent.RemoveToolbar("rdigit")
+        
+
+
+    def OnDeleteLine(self, event):
+        """!Delete line"""
+        
+        Debug.msg(2, "RDigittoolbar.OnDeleteLine():")
+        
+        self.action = { 'desc' : "deleteLine",
+                        'id'   : self.deleteLine }
+        self.MapWindow.mouse['box'] = 'box'
+
+    def OnDeleteArea(self, event):
+        """!Delete Area"""
+        
+        Debug.msg(2, "RDigittoolbar.OnDeleteArea():")
+        
+        self.action = { 'desc' : "deleteArea",
+                        'id'   : self.deleteArea }
+        self.MapWindow.mouse['box'] = 'line'
+
+    def OnDeleteCircle(self, event):
+        """!Delete Circle"""
+        
+        Debug.msg(2, "RDigittoolbar.OnDeleteCircle():")
+        
+        self.action = { 'desc' : "deleteCircle",
+                        'id'   : self.deleteCircle }
+        self.MapWindow.mouse['box'] = 'line'
+
+        
+    def OnUndo(self, event):
+        """!Undo previous changes"""
+        self.digit.Undo()
+        
+        event.Skip()
+
+    def OnRedo(self, event):
+        """!Undo previous changes"""
+        self.digit.Undo(level = 1)
+        
+        event.Skip()
+        
+    def EnableUndo(self, enable = True):
+        """!Enable 'Undo' in toolbar
+        
+        @param enable False for disable
+        """
+        self._enableTool(self.undo, enable)
+
+    def EnableRedo(self, enable = True):
+        """!Enable 'Redo' in toolbar
+        
+        @param enable False for disable
+        """
+        self._enableTool(self.redo, enable)
+        
+    def _enableTool(self, tool, enable):
+        if not self.FindById(tool):
+            return
+        
+        if enable:
+            if self.GetToolEnabled(tool) is False:
+                self.EnableTool(tool, True)
+        else:
+            if self.GetToolEnabled(tool) is True:
+                self.EnableTool(tool, False)
+        
+
+    def OnHelp(self, event):
+        """!Show digitizer help page in web browser"""
+        helpInProgress = True
+        #log = self.parent.GetLayerManager().GetLogWindow()
+        #log.RunCmd(['g.manual', 'entry=wxGUI.Vector_Digitizer'])
+
+    def GetListOfLayers(self):
+      return self.layerNameList
+
+
+    def GetMapName(self):
+      return self.mapName
+      
+      
+    def OnSelectMap (self, event):
+        """!Select raster map layer for editing
+        If there is a raster map layer already edited, this action is
+        firstly terminated. The map layer is closed. After this the
+        selected map layer activated for editing.
+        """
+        
+        selectedMapName = None
+        selection = -1
+        if event.GetSelection() == 0: # create new raster map layer
+            if self.mapLayer:
+                openVectorMap = self.mapLayer.GetName(fullyQualified = False)['name']
+            else:
+                openVectorMap = None
+            dlg = CreateNewRaster(self.parent, exceptMap = openVectorMap,disableAdd = True)
+                                  
+                                  
+            
+            if dlg and dlg.GetName():
+                # add layer to map layer tree(layer tree is map manager)
+                
+                mapName = str(dlg.GetName() + '@' + grass.gisenv()['MAPSET'])
+                self.combo.Append(mapName)
+                self.mapName = selectedMapName = mapName
+                self.layerNameList.append(mapName)
+                vectLayers = self.GetListOfLayers()
+                selection = vectLayers.index(mapName)
+            else:
+                self.combo.SetValue(_('Select raster map'))
+                if dlg:
+                    dlg.Destroy()
+                return
+        else:
+            selection = event.GetSelection() - 1 # first option is 'New raster map'
+            selectedMapName = self.combo.GetValue()
+        
+        # skip currently selected map FIXME
+        #if self.layers[selection] == self.mapLayer:
+            #return
+        
+        if selection == -1: #FIXME
+            # deactive map layer for editing 
+            self.StopEditing()
+
+        
+        # select the given map layer for editing FIXME
+        if selectedMapName:
+          self.combo.SetValue(selectedMapName)
+
+          self.StartEditing(selectedMapName)
+          self.digit.setOutputName(selectedMapName)
+        
+        event.Skip()
+        
+    def StartEditing (self, mapLayer):
+        """!Start editing selected vector map layer.
+
+        @param mapLayer MapLayer to be edited
+        """
+        # deactive layer FIXME
+        #self.Map.ChangeLayerActive(mapLayer, False)
+        
+        # clean map canvas
+        self.MapWindow.EraseMap()
+        
+#        # unset background map if needed
+#        if mapLayer:
+#            if UserSettings.Get(group = 'vdigit', key = 'bgmap',
+#                                subkey = 'value', internal = True) == mapLayer:
+#                UserSettings.Set(group = 'vdigit', key = 'bgmap',
+#                                 subkey = 'value', value = '', internal = True)
+#            
+#            self.parent.SetStatusText(_("Please wait, "
+#                                        "opening vector map <%s> for editing...") % mapLayer,
+#                                        0)
+#        
+        self.MapWindow.pdcVector = wx.PseudoDC()
+        self.digit = self.MapWindow.digit = self.digitClass(mapwindow = self.MapWindow)
+        
+        self.mapLayer = mapLayer
+
+        self.EnableAll()
+        self.EnableUndo(False)
+        self.EnableRedo(False)       
+        
+        Debug.msg (4, "RDigitToolbar.StartEditing(): layer=%s" % mapLayer)
+        
+        # change cursor
+        if self.MapWindow.mouse['use'] == 'pointer':
+            self.MapWindow.SetCursor(self.parent.cursors["cross"])
+
+        if not self.MapWindow.resize:
+            self.MapWindow.UpdateMap(render = True)
+        
+        # respect opacity
+        opacity = 100 # FIXME mapLayer.GetOpacity(float = True)
+        
+        if opacity < 1.0:
+            alpha = int(opacity * 255)
+            self.digit.GetDisplay().UpdateSettings(alpha = alpha)
+        
+        return True
+
+    def StopEditing(self):
+        """!Stop editing of selected vector map layer.
+
+        @return True on success
+        @return False on failure
+        """
+        if self.combo:
+            self.combo.SetValue (_('Select vector map'))
+        
+        # save changes
+        if self.mapLayer:
+            Debug.msg (4, "RDigitToolbar.StopEditing(): layer=%s" % self.mapLayer)
+
+            dlg = wx.MessageDialog(parent = self.parent,
+                                   message = _("Do you want to save changes "
+                                             "in vector map <%s>?") % self.mapLayer,
+                                   caption = _("Save changes?"),
+                                   style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+            if dlg.ShowModal() == wx.ID_NO:
+                # revert changes
+                self.digit.saveMap = False
+            dlg.Destroy()
+
+            #FIXME self.digit.CloseMap()
+            
+        #FIXME self.Map.ChangeLayerActive(self.mapLayer, True)
+        
+        # change cursor
+        self.MapWindow.SetCursor(self.parent.cursors["default"])
+        self.MapWindow.pdcVector = None
+
+        del self.digit
+        del self.MapWindow.digit
+        
+        self.mapLayer = None
+        
+        self.MapWindow.redrawAll = True
+        
+        return True
+    
+    def UpdateListOfLayers (self, updateTool = False):
+        """!Update list of available vector map layers.
+        This list consists only editable layers (in the current mapset)
+
+        @param updateTool True to update also toolbar
+        """
+        Debug.msg (4, "RDigitToolbar.UpdateListOfLayers(): updateTool=%d" % updateTool)
+        
+        layerNameSelected = None
+         # name of currently selected layer
+        if self.mapLayer:
+            layerNameSelected = self.mapLayer
+        
+        # select vector map layer in the current mapset
+        layerNameList = []
+        self.layers = self.Map.GetListOfLayers(l_type = "raster",
+                                                      l_mapset = grass.gisenv()['MAPSET'])
+        
+        for layer in self.layers:
+            if not layer.name in layerNameList: # do not duplicate layer
+                layerNameList.append (layer.GetName())
+        
+        if updateTool: # update toolbar
+            if not self.mapLayer:
+                value = _('Select vector map')
+            else:
+                value = layerNameSelected
+            
+            if not self.comboid:
+                if not self.tools or 'selector' in self.tools:
+                    self.combo = wx.ComboBox(self, id = wx.ID_ANY, value = value,
+                                             choices = [_('New raster map'), ] + layerNameList, size = (80, -1),
+                                             style = wx.CB_READONLY)
+                    self.comboid = self.InsertControl(0, self.combo)
+                    self.parent.Bind(wx.EVT_COMBOBOX, self.OnSelectMap, self.comboid)
+            else:
+                self.combo.SetItems([_('New raster map'), ] + layerNameList)
+            
+            self.Realize()
+        
+        return layerNameList
+
+    def GetLayer(self):
+        """!Get selected layer for editing -- MapLayer instance"""
+        return self.mapLayer
+

Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/wxdigit.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/wxdigit.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/wxdigit.py	2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,201 @@
+"""!
+ at package vdigit.wxdigit
+
+ at brief wxGUI raster digitizer (base class)
+
+List of classes:
+
+ - wxvdigit::IRDigit
+
+(C) 2007-2011 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.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+ at author Martin Landa <landa.martin gmail.com>(original wxvdigit)
+"""
+
+import grass.script.core as grass
+#from pygrass.modules import Module
+from core.gconsole import GConsole
+from core.gcmd        import GError, RunCommand, CommandThread
+from core.debug       import Debug
+from core.settings    import UserSettings
+
+import sys
+import os
+import tempfile
+
+try:
+    from grass.lib.gis    import *
+    from grass.lib.vector import *
+    from grass.lib.raster import *
+except ImportError:
+    pass
+
+
+class RasterObject:
+  def __init__(self,cat,coords,ft):
+    self.catId = cat
+    self.coords = coords
+    self.ftype = ft
+  
+        
+class IRDigit:
+    def __init__(self, mapwindow):
+        """!Base class for vector digitizer (ctypes interface)
+        
+        @param mapwindow reference for map window (BufferedWindow)
+        """
+        self.mapWindow = mapwindow
+        
+        self.objects = list()
+
+        self.toolbar = mapwindow.parent.toolbars['rdigit']
+   
+        self.polyfile = tempfile.NamedTemporaryFile(delete=False)
+        
+        Debug.msg(2, "IRDigit.__init__() %s ", self.polyfile.name)
+ 
+        self.cat = 1
+        self.saveMap = True
+        
+        self.outputName = None
+
+        
+        
+    def __del__(self):
+        Debug.msg(1, "IVDigit.__del__()")
+        
+        if self.saveMap == True:
+        
+            for obj in self.objects:
+                if obj.ftype == GV_BOUNDARY:
+                    self.polyfile.write("AREA\n");
+                    for coor in obj.coords:
+                        east, north = coor
+                        locbuf = " %s %s\n" % (east,north)
+                        self.polyfile.write(locbuf);
+
+                elif obj.ftype == GV_LINE:    
+                    self.polyfile.write("LINE\n");
+                    for coor in obj.coords:
+                        east, north = coor
+                        locbuf = " %s %s\n" % (east,north)            
+                        self.polyfile.write(locbuf);
+                        
+                catbuf = "=%d a\n" % (obj.catId)
+                self.polyfile.write(catbuf);
+
+            self.polyfile.close()
+
+            region_settings = grass.parse_command('g.region', flags = 'p', delimiter = ':')
+            RunCommand('r.in.poly', input=self.polyfile.name, 
+                                    rows=region_settings['rows'], output=self.getOutputName(),overwrite=True)
+            
+            os.unlink(self.polyfile.name)
+
+
+    def setOutputName(self, name):
+      if name:
+        self.outputName = name
+
+    def getOutputName(self):
+      return self.outputName
+
+    def DeleteArea(self, cat):
+      self.objectsCopy = self.objects
+      self.objects = []
+      for obj in self.objectsCopy:
+        if obj.catId != cat:
+          self.objects.append(obj)
+    
+    def AddFeature(self, ftype, points):
+        """!Add new feature
+        
+        @param ftype feature type (point, line, centroid, boundary)
+        @param points tuple of points ((x, y), (x, y), ...)
+        
+        @return tuple (number of added features, feature ids)
+        """
+        
+        #layer = self._getNewFeaturesLayer()
+        #cat = self._getNewFeaturesCat()
+        
+        if ftype == 'point':
+            vtype = GV_POINT
+        elif ftype == 'line':
+            vtype = GV_LINE
+        elif ftype == 'centroid':
+            vtype = GV_CENTROID
+        elif ftype == 'boundary':
+            vtype = GV_BOUNDARY
+        elif ftype == 'area':
+            vtype = GV_AREA
+        elif ftype == 'circle':
+            vtype = 'circle'         
+        else:
+            GError(parent = self.mapWindow,
+                   message = _("Unknown feature type '%s'") % ftype)
+            return (-1, None)
+            
+        Debug.msg(2, "IRRDigit1()")            
+        
+        if vtype & GV_LINES and len(points) < 2:
+            GError(parent = self.mapWindow,
+                   message = _("Not enough points for line"))
+            return (-1, None)
+        
+        self.toolbar.EnableUndo()
+        
+        
+        return self._addFeature(vtype, points)
+
+    def _checkMap(self):
+        """!Check if map is open
+        """
+        if not self.polyfile.name:
+            self._NoMap()
+            return False
+            
+        return True
+        
+    def NoMap(self, name = None):
+        """!No map for editing"""
+        if name:
+            message = _('Unable to open vector map <%s>.') % name
+        else:
+            message =  _('No vector map open for editing.3')
+        GError(message + ' ' + _('Operation canceled.'),
+               parent  = self.parent,
+               caption = self.caption)        
+
+    def _addFeature(self, ftype, coords):
+        """!Add new feature(s) to the vector map
+
+        @param ftype feature type (GV_POINT, GV_LINE, GV_BOUNDARY, ...)
+        @coords tuple of coordinates ((x, y), (x, y), ...)
+        @param layer layer number (-1 for no cat)
+        @param cat category number
+        @param snap snap to node/vertex
+        @param threshold threshold for snapping
+        
+        @return tuple (number of added features, list of fids)
+        @return number of features -1 on error
+        """
+
+        if not self._checkMap():
+            return (-1, None)
+        
+        #is3D = bool(Vect_is_3d(self.poMapInfo))
+        
+        Debug.msg(2, "IVDigit._addFeature(): npoints=%d, ftype=%d",
+                  len(coords), ftype)
+        
+        obj = RasterObject(self.cat, coords,ftype)
+        self.objects.append(obj)
+        self.cat = self.cat + 1    
+        return self.cat - 1
+    
+

Added: grass-addons/grass7/gui/wxpython/wx.rdigit/toolbars.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/toolbars.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/toolbars.py	2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,152 @@
+"""!
+ at package iclass.toolbars
+
+ at brief wxIClass toolbars and icons.
+
+Classes:
+ - toolbars::IClassMapToolbar
+ - toolbars::IClassToolbar
+ - toolbars::IClassMapManagerToolbar
+
+(C) 2006-2011 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.
+
+ at author Vaclav Petras <wenzeslaus gmail.com>
+ at author Anna Kratochvilova <kratochanna gmail.com>
+"""
+
+import wx
+
+from gui_core.toolbars import BaseToolbar, BaseIcons
+from icons.icon import MetaIcon
+
+import grass.script as grass
+
+iClassIcons = {
+        'opacity' : MetaIcon(img = 'layer-opacity',
+                             label = _('Set opacity level')),
+        'tools' : MetaIcon(img = 'tools',
+                                  label = _('Load Digitizer tools')),
+        'selectGroup' : MetaIcon(img = 'layer-group-add',
+                                 label = _('Select imagery group')),
+        'run' : MetaIcon(img = 'execute',
+                         label = _('Run analysis')),
+        'sigFile' : MetaIcon(img = 'script-save',
+                             label = _('Save signature file')),
+        'delCmd' : MetaIcon(img = 'layer-remove',
+                            label = _('Delete selected map layer')),
+        'exportAreas' : MetaIcon(img = 'layer-export',
+                            label = _('Export training areas')),
+        'importAreas' : MetaIcon(img = 'layer-import',
+                            label = _('Import training areas')),
+        }
+        
+class RDigitMapToolbar(BaseToolbar):
+    """!IClass Map toolbar
+    """
+    def __init__(self, parent):
+        """!IClass Map toolbar constructor
+        """
+        BaseToolbar.__init__(self, parent)
+        
+        self.InitToolbar(self._toolbarData())
+        
+
+
+        # realize the toolbar
+        self.Realize()
+        
+        self.action = { 'id' : self.pan }
+        self.defaultAction = { 'id' : self.pan,
+                               'bind' : self.parent.OnPan }
+        
+        self.OnTool(None)
+        
+        self.EnableTool(self.zoomBack, False)
+        
+
+        
+    def _toolbarData(self):
+        """!Toolbar data"""
+        icons = BaseIcons
+        return self._getToolbarData((("displaymap", icons["display"],
+                                      self.parent.OnDraw),
+                                     ("rendermap", icons["render"],
+                                      self.parent.OnRender),
+                                     ("erase", icons["erase"],
+                                      self.parent.OnErase),
+                                     (None, ),
+                                     ("pan", icons["pan"],
+                                      self.parent.OnPan,
+                                      wx.ITEM_CHECK),
+                                     ("zoomIn", icons["zoomIn"],
+                                      self.parent.OnZoomIn,
+                                      wx.ITEM_CHECK),
+                                     ("zoomOut", icons["zoomOut"],
+                                      self.parent.OnZoomOut,
+                                      wx.ITEM_CHECK),
+                                     ("zoomMenu", icons["zoomMenu"],
+                                      self.parent.OnZoomMenu),
+                                     (None, ),
+                                     ("zoomBack", icons["zoomBack"],
+                                      self.parent.OnZoomBack),
+                                     ("zoomToMap", icons["zoomExtent"],
+                                      self.parent.OnZoomToMap),
+                                      
+                                     ("drawArea", iClassIcons["tools"],
+                                     self.parent.OnDrawArea),                                
+                                    ))
+
+        
+
+
+        
+class RDigitMapManagerToolbar(BaseToolbar):
+    """!IClass toolbar
+    """
+    def __init__(self, parent, mapManager):
+        """!IClass toolbar constructor
+        """
+        BaseToolbar.__init__(self, parent)
+        
+        self.InitToolbar(self._toolbarData())
+        self.choice = wx.Choice(parent = self, id = wx.ID_ANY, size = (300, -1))
+        
+        self.choiceid = self.AddControl(self.choice)
+        
+        self.choice.Bind(wx.EVT_CHOICE, self.OnSelectLayer)
+        
+        self.mapManager = mapManager
+        # realize the toolbar
+        self.Realize()
+        
+    def _toolbarData(self):
+        """!Toolbar data"""
+        return self._getToolbarData((("addRast", BaseIcons['addRast'],
+                                      self.OnAddRast),
+                                      ("delRast", iClassIcons['delCmd'],
+                                      self.OnDelRast),
+
+                                    ))
+                                    
+    def OnSelectLayer(self, event):
+        layer = self.choice.GetStringSelection()
+        self.mapManager.SelectLayer(name = layer)
+        
+    def OnAddRast(self, event):
+        dlg = IClassMapDialog(self, title = _("Add raster map"), element = 'raster')
+        if dlg.ShowModal() == wx.ID_OK:
+            raster = grass.find_file(name = dlg.GetMap(), element = 'cell')
+            if raster['fullname']:
+                self.mapManager.AddLayer(name = raster['fullname'])
+                
+        dlg.Destroy()
+        
+    def OnDelRast(self, event):
+        layer = self.choice.GetStringSelection()
+        idx = self.choice.GetSelection()
+        if layer:
+            self.mapManager.RemoveLayer(name = layer, idx = idx)
+            



More information about the grass-commit mailing list