[GRASS-SVN] r44823 - in grass/trunk: gui/wxpython gui/wxpython/gui_modules include lib/vector/vedit

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Jan 1 14:26:54 EST 2011


Author: martinl
Date: 2011-01-01 11:26:54 -0800 (Sat, 01 Jan 2011)
New Revision: 44823

Added:
   grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
   grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
   grass/trunk/lib/vector/vedit/render.c
Removed:
   grass/trunk/gui/wxpython/vdigit/
Modified:
   grass/trunk/gui/wxpython/Makefile
   grass/trunk/gui/wxpython/gui_modules/__init__.py
   grass/trunk/gui/wxpython/gui_modules/mapdisp.py
   grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py
   grass/trunk/gui/wxpython/gui_modules/toolbars.py
   grass/trunk/gui/wxpython/gui_modules/vdigit.py
   grass/trunk/include/vedit.h
   grass/trunk/lib/vector/vedit/chtype.c
   grass/trunk/lib/vector/vedit/distance.c
   grass/trunk/lib/vector/vedit/select.c
Log:
wxGUI/vdigit: converted to python & veditlib updated - Vedit_render_map()
	      very initial version - displays features to PseudoDC
	      todo1: complete conversion (full functionality)
	      todo2: improve bulk data processing (replacing PseudoDC)


Modified: grass/trunk/gui/wxpython/Makefile
===================================================================
--- grass/trunk/gui/wxpython/Makefile	2010-12-31 13:44:07 UTC (rev 44822)
+++ grass/trunk/gui/wxpython/Makefile	2011-01-01 19:26:54 UTC (rev 44823)
@@ -1,8 +1,7 @@
 MODULE_TOPDIR = ../..
 
-SUBDIRS = docs vdigit
+SUBDIRS = docs
 EXTRA_CLEAN_FILES = menustrings.py build_ext.pyc
-CLEAN_SUBDIRS = vdigit
 
 include $(MODULE_TOPDIR)/include/Make/Dir.make
 include $(MODULE_TOPDIR)/include/Make/Doxygen.make
@@ -13,7 +12,7 @@
 SRCFILES := $(wildcard scripts/* compat/* gui_modules/* icons/*.* icons/silk/* images/* xml/*) gis_set.py gis_set_error.py wxgui.py README
 DSTFILES := $(patsubst %,$(ETCDIR)/%,$(SRCFILES)) $(patsubst %.py,$(ETCDIR)/%.pyc,$(filter %.py,$(SRCFILES)))
 
-DSTDIRS := $(patsubst %,$(ETCDIR)/%,compat gui_modules icons icons/silk images scripts vdigit xml)
+DSTDIRS := $(patsubst %,$(ETCDIR)/%,compat gui_modules icons icons/silk images scripts xml)
 
 default: $(DSTFILES) menustrings.py
 	$(MAKE) parsubdirs

Modified: grass/trunk/gui/wxpython/gui_modules/__init__.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/__init__.py	2010-12-31 13:44:07 UTC (rev 44822)
+++ grass/trunk/gui/wxpython/gui_modules/__init__.py	2011-01-01 19:26:54 UTC (rev 44823)
@@ -40,4 +40,6 @@
     "vdigit.py",
     "workspace.py",
     "wxnviz.py",
+    "wxvdriver.py",
+    "wxvdigit.py",
 ]

Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2010-12-31 13:44:07 UTC (rev 44822)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2011-01-01 19:26:54 UTC (rev 44823)
@@ -542,7 +542,7 @@
         
         # deselect features in vdigit
         if self.toolbars['vdigit'] and self.digit:
-            self.digit.driver.SetSelected([])
+            self.digit.GetDisplay().SetSelected(None)
             self.MapWindow.UpdateMap(render = True, renderVector = True)
         else:
             self.MapWindow.UpdateMap(render = True)

Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py	2010-12-31 13:44:07 UTC (rev 44822)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py	2011-01-01 19:26:54 UTC (rev 44823)
@@ -42,7 +42,6 @@
 from vdigit import VDigitCategoryDialog
 from vdigit import VDigitZBulkDialog
 from vdigit import VDigitDuplicatesDialog
-from vdigit import PseudoDC as VDigitPseudoDC
 
 class MapWindow(object):
     """!Abstract map window class
@@ -303,45 +302,18 @@
         self.dragid   = -1
         self.lastpos  = (0, 0)
 
-    def DefinePseudoDC(self, vdigit = False):
-        """!Define PseudoDC class to use
-
-        @vdigit True to use PseudoDC from vdigit
+    def DefinePseudoDC(self):
+        """!Define PseudoDC objects to use
         """
         # create PseudoDC used for background map, map decorations like scales and legends
-        self.pdc = self.PseudoDC(vdigit)
+        self.pdc = wx.PseudoDC()
         # used for digitization tool
         self.pdcVector = None
         # decorations (region box, etc.)
-        self.pdcDec = self.PseudoDC(vdigit)
+        self.pdcDec = wx.PseudoDC()
         # pseudoDC for temporal objects (select box, measurement tool, etc.)
-        self.pdcTmp = self.PseudoDC(vdigit)
-        
-    def PseudoDC(self, vdigit = False):
-        """!Create PseudoDC instance"""
-        if vdigit:
-            PseudoDC = VDigitPseudoDC
-        else:
-            PseudoDC = wx.PseudoDC
-        
-        return PseudoDC()
+        self.pdcTmp = wx.PseudoDC()
     
-    def CheckPseudoDC(self):
-        """!Try to draw background
-        
-        @return True on success
-        @return False on failure
-        """
-        try:
-            self.pdc.BeginDrawing()
-            self.pdc.SetBackground(wx.Brush(self.GetBackgroundColour()))
-            self.pdc.BeginDrawing()
-        except StandardError, e:
-            traceback.print_exc(file = sys.stderr)
-            return False
-        
-        return True
-    
     def Draw(self, pdc, img = None, drawid = None, pdctype = 'image', coords = [0, 0, 0, 0]):
         """!Draws map and overlay decorations
         """
@@ -808,9 +780,9 @@
         if renderVector and digitToolbar and \
                 digitToolbar.GetLayer():
             # set region
-            self.parent.digit.driver.UpdateRegion()
+            self.parent.digit.GetDisplay().UpdateRegion()
             # re-calculate threshold for digitization tool
-            self.parent.digit.driver.GetThreshold()
+            # self.parent.digit.driver.GetThreshold()
             # draw map
             if self.pdcVector:
                 self.pdcVector.Clear()
@@ -821,7 +793,7 @@
                 item = None
             
             if item and self.tree.IsItemChecked(item):
-                self.parent.digit.driver.DrawMap()
+                self.parent.digit.GetDisplay().DrawMap()
 
             # translate tmp objects (pointer position)
             if digitToolbar.GetAction() == 'moveLine':
@@ -906,7 +878,7 @@
         else:
             self.parent.statusbarWin['mask'].SetLabel('')
         
-        Debug.msg (2, "BufferedWindow.UpdateMap(): render=%s, renderVector=%s -> time=%g" % \
+        Debug.msg (1, "BufferedWindow.UpdateMap(): render=%s, renderVector=%s -> time=%g" % \
                    (render, renderVector, (stop-start)))
         
         return True
@@ -2334,10 +2306,10 @@
         event.Skip()
 
     def OnMiddleDown(self, event):
-        """!
-        Middle mouse button pressed
+        """!Middle mouse button pressed
         """
-        self.mouse['begin'] = event.GetPositionTuple()[:]
+        if event:
+            self.mouse['begin'] = event.GetPositionTuple()[:]
         
         digitToolbar = self.parent.toolbars['vdigit']
         # digitization tool
@@ -2751,7 +2723,7 @@
             elif l.type == 'vector':
                 digitToolbar = self.parent.toolbars['vdigit']
                 if digitToolbar and digitToolbar.GetLayer() == l:
-                    w, s, b, e, n, t = self.parent.digit.driver.GetMapBoundingBox()
+                    w, s, b, e, n, t = self.parent.digit.GetDisplay().GetMapBoundingBox()
                     self.Map.GetRegion(n = n, s = s, w = w, e = e,
                                        update = True)
                     updated = True

Modified: grass/trunk/gui/wxpython/gui_modules/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/toolbars.py	2010-12-31 13:44:07 UTC (rev 44822)
+++ grass/trunk/gui/wxpython/gui_modules/toolbars.py	2011-01-01 19:26:54 UTC (rev 44823)
@@ -35,8 +35,7 @@
 import globalvar
 import gcmd
 import gdialogs
-import vdigit
-from vdigit import VDigitSettingsDialog, haveVDigit
+from vdigit import VDigitSettingsDialog, haveVDigit, VDigit
 from debug import Debug
 from preferences import globalSettings as UserSettings
 from nviz import haveNviz
@@ -193,6 +192,7 @@
                            'In the meantime you can use "NVIZ" from the File menu.'), wrap = 60)
             
             self.toolId['3d'] = -1
+
         if haveVDigit:
             choices.append(_('Digitize'))
             if self.toolId['3d'] > -1:
@@ -787,7 +787,7 @@
         if self.action['id'] != id:
             self.parent.MapWindow.ClearLines(pdc = self.parent.MapWindow.pdcTmp)
             if self.parent.digit and \
-                    len(self.parent.digit.driver.GetSelected()) > 0:
+                    len(self.parent.digit.GetDisplay().GetSelected()) > 0:
                 # cancel action
                 self.parent.MapWindow.OnMiddleDown(None)
         
@@ -986,10 +986,8 @@
     def OnSettings(self, event):
         """!Show settings dialog"""
         if self.parent.digit is None:
-            reload(vdigit)
-            from vdigit import VDigit as VDigit
             try:
-                self.parent.digit = VDigit(mapwindow=self.parent.MapWindow)
+                self.parent.digit = VDigit(mapwindow = self.parent.MapWindow)
             except SystemExit:
                 self.parent.digit = None
         
@@ -1268,13 +1266,13 @@
     def StartEditing (self, mapLayer):
         """!Start editing selected vector map layer.
 
-        @param mapLayer reference to MapLayer instance
+        @param mapLayer MapLayer to be edited
         """
         # deactive layer
         self.mapcontent.ChangeLayerActive(mapLayer, False)
         
         # clean map canvas
-        ### self.parent.MapWindow.EraseMap()
+        self.parent.MapWindow.EraseMap()
         
         # unset background map if needed
         if mapLayer:
@@ -1284,25 +1282,17 @@
                                  subkey = 'value', value = '', internal = True)
             
             self.parent.statusbar.SetStatusText(_("Please wait, "
-                                                  "opening vector map <%s> for editing...") % \
-                                                    mapLayer.GetName(),
+                                                  "opening vector map <%s> for editing...") % mapLayer.GetName(),
                                                 0)
-        
-        # reload vdigit module
-        reload(vdigit)
-        from vdigit import VDigit as VDigit
-        # use vdigit's PseudoDC
-        self.parent.MapWindow.DefinePseudoDC(vdigit = True)
+
+        self.parent.MapWindow.pdcVector = wx.PseudoDC()
         self.parent.digit = VDigit(mapwindow = self.parent.MapWindow)
         
         self.mapLayer = mapLayer
         
         # open vector map
         try:
-            if not self.parent.MapWindow.CheckPseudoDC():
-                raise gcmd.GException(_("Unable to initialize display driver of vector "
-                                        "digitizer. See 'Command output' for details."))
-            self.parent.digit.SetMapName(mapLayer.GetName())
+            self.parent.digit.OpenMap(mapLayer.GetName())
         except gcmd.GException, e:
             self.mapLayer = None
             self.StopEditing()
@@ -1320,10 +1310,6 @@
         if self.parent.MapWindow.mouse['use'] == 'pointer':
             self.parent.MapWindow.SetCursor(self.parent.cursors["cross"])
         
-        # create pseudoDC for drawing the map
-        self.parent.MapWindow.pdcVector = vdigit.PseudoDC()
-        self.parent.digit.driver.SetDevice(self.parent.MapWindow.pdcVector)
-
         if not self.parent.MapWindow.resize:
             self.parent.MapWindow.UpdateMap(render = True)
         
@@ -1340,9 +1326,6 @@
         @return True on success
         @return False on failure
         """
-        # use wx's PseudoDC
-        self.parent.MapWindow.DefinePseudoDC(vdigit = False)
-        
         self.combo.SetValue (_('Select vector map'))
         
         # save changes
@@ -1364,9 +1347,9 @@
                                                   "closing and rebuilding topology of "
                                                   "vector map <%s>...") % self.mapLayer.GetName(),
                                                 0)
-        
-            self.parent.digit.SetMapName(None) # -> close map
-        
+            
+            self.parent.digit.CloseMap()
+            
             # re-active layer 
             item = self.parent.tree.FindItemByData('maplayer', self.mapLayer)
             if item and self.parent.tree.IsItemChecked(item):
@@ -1374,10 +1357,7 @@
         
         # change cursor
         self.parent.MapWindow.SetCursor(self.parent.cursors["default"])
-        
-        # disable pseudodc for vector map layer
         self.parent.MapWindow.pdcVector = None
-        self.parent.digit.driver.SetDevice(None)
         
         # close dialogs
         for dialog in ('attributes', 'category'):

Modified: grass/trunk/gui/wxpython/gui_modules/vdigit.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/vdigit.py	2010-12-31 13:44:07 UTC (rev 44822)
+++ grass/trunk/gui/wxpython/gui_modules/vdigit.py	2011-01-01 19:26:54 UTC (rev 44823)
@@ -1,13 +1,9 @@
 """!
 @package vdigit
 
- at brief wxGUI vector digitizer user interface
+ at brief Dialogs for wxGUI vector digitizer
 
 Classes:
- - AbstractDigit 
- - VDigit
- - AbstractDisplayDriver
- - CDisplayDriver
  - VDigitSettingsDialog
  - VDigitCategoryDialog
  - CategoryListCtrl
@@ -43,1098 +39,33 @@
 from units import Units
 from preferences import globalSettings as UserSettings
 try:
-    digitPath = os.path.join(globalvar.ETCWXDIR, "vdigit")
-    sys.path.append(digitPath)
-    import grass7_wxvdigit as wxvdigit
-    GV_LINES = wxvdigit.GV_LINES
-    PseudoDC = wxvdigit.PseudoDC
+    from wxvdigit  import IVDigit
     haveVDigit = True
+    GV_LINES = 10
     errorMsg = ''
 except ImportError, err:
     haveVDigit = False
     GV_LINES = None
-    PseudoDC = wx.PseudoDC
     errorMsg = err
     
-class AbstractDigit:
-    """!Abstract digitization class
-    """
+class VDigit(IVDigit):
     def __init__(self, mapwindow):
-        """!Initialization
-
-        @param mapwindow reference to mapwindow (MapFrame) instance
-        @param settings  initial settings of digitization tool
-        """
-        self.map       = None
-        self.mapWindow = mapwindow
+        """!Base class of vector digitizer
         
-        Debug.msg (3, "AbstractDigit.__init__(): map=%s" % \
-                   self.map)
-
-        #self.SetCategory()
-
-        self.driver = CDisplayDriver(self, mapwindow)
-
-    def __del__(self):
-        pass
-    
-    def SetCategoryNextToUse(self):
-        """!Find maximum category number in the map layer
-        and update Digit.settings['category']
-
-        @return 'True' on success, 'False' on failure
-        """
-        # vector map layer without categories, reset to '1'
-        UserSettings.Set(group='vdigit', key='category', subkey='value', value=1)
-
-        if self.map:
-            cat = self.digit.GetCategory(UserSettings.Get(group='vdigit', key='layer', subkey='value'))
-            cat += 1
-            UserSettings.Set(group='vdigit', key='category', subkey='value',
-                             value=cat)
-        
-    def SetCategory(self):
-        """!Return category number to use (according Settings)"""
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 0:
-            self.SetCategoryNextToUse()
-
-        return UserSettings.Get(group='vdigit', key="category", subkey='value')
-
-    def SetMapName(self, map):
-        """!Set map name
-
-        @param map map name to be set up or None (will close currently edited map)
-        """
-        Debug.msg (3, "AbstractDigit.SetMapName map=%s" % map)
-        self.map = map
-
-        try:
-            ret = self.driver.Reset(self.map)
-        except StandardError, e:
-            raise gcmd.GException(_("Unable to initialize display driver of vector "
-                              "digitizer. See 'Command output' for details.\n\n"
-                              "Details: ") + e)
-        
-        if map and ret == -1:
-            raise gcmd.GException(_('Unable to open vector map <%s> for editing.\n\n'
-                                    'Data are probably corrupted, '
-                                    'try to run v.build to rebuild '
-                                    'the topology (Vector->Develop vector map->'
-                                    'Create/rebuild topology).') % map)
-        if not map and ret != 0:
-            raise gcmd.GException(_('Unable to open vector map <%s> for editing.\n\n'
-                                    'Data are probably corrupted, '
-                                    'try to run v.build to rebuild '
-                                    'the topology (Vector->Develop vector map->'
-                                    'Create/rebuild topology).') % map)
-        
-        if self.digit:
-            self.digit.InitCats()
-        
-    def SelectLinesByQueryThresh(self):
-        """!Generic method used for SelectLinesByQuery()
-        -- to get threshold value"""
-        thresh = 0.0
-        if UserSettings.Get(group='vdigit', key='query', subkey='selection') == 0:
-            thresh = UserSettings.Get(group='vdigit', key='queryLength', subkey='thresh')
-            if UserSettings.Get(group='vdigit', key="queryLength", subkey='than-selection') == 0:
-                thresh = -1 * thresh
-        else:
-            thresh = UserSettings.Get(group='vdigit', key='queryDangle', subkey='thresh')
-            if UserSettings.Get(group='vdigit', key="queryDangle", subkey='than-selection') == 0:
-                thresh = -1 * thresh
-
-        return thresh
-
-    def GetSelectType(self):
-        """!Get type(s) to be selected
-
-        Used by SelectLinesByBox() and SelectLinesByPoint()"""
-
-        type = 0
-        for feature in (('point', wxvdigit.GV_POINT),
-                        ('line', wxvdigit.GV_LINE),
-                        ('centroid', wxvdigit.GV_CENTROID),
-                        ('boundary', wxvdigit.GV_BOUNDARY)):
-            if UserSettings.Get(group='vdigit', key='selectType',
-                                subkey=[feature[0], 'enabled']) is True:
-                type |= feature[1]
-
-        return type
-
-    def SelectLinesFromBackgroundMap(self, pos1, pos2):
-        """!Select features from background map
-
-        @param pos1,pos2 bounding box
-        """
-        bgmap = str(UserSettings.Get(group='vdigit', key='bgmap', subkey='value',
-                                     internal=True))
-        
-        if bgmap == '':
-            Debug.msg(4, "VEdit.SelectLinesFromBackgroundMap(): []")
-            return []
-
-        x1, y1 = pos1
-        x2, y2 = pos2
-        ret = gcmd.RunCommand('v.edit',
-                              parent = self,
-                              quiet = True,
-                              read = True,
-                              map = bgmap,
-                              tool = 'select',
-                              bbox = '%f,%f,%f,%f' % (x1, y1, x2, y2))
-
-        if not ret:
-            x, y = pos1
-            ret = gcmd.RunCommand('v.edit',
-                                  parent = self,
-                                  quiet = True,
-                                  read = True,
-                                  map = bgmap,
-                                  tool = 'select',
-                                  coords = '%f,%f' % (x, y),
-                                  thresh = self.driver.GetThreshold(type='selectThresh'))
-        
-        if not ret:
-            return []
-        
-        output = ret.splitlines()[0] # first line
-        ids = output.split(',') 
-        ids = map(int, ids) # str -> int
-        
-        Debug.msg(4, "VEdit.SelectLinesFromBackgroundMap(): %s" % \
-                      ",".join(["%d" % v for v in ids]))
-        
-        return ids
-
-class VDigit(AbstractDigit):
-    """!Prototype of digitization class based on v.digit
-    reimplementation (wxWidgets C/C++)
-    """
-    def __init__(self, mapwindow):
-        """!VDigit constructor
-        
         @param mapwindow reference to mapwindow (MapFrame) instance
         """
-        AbstractDigit.__init__(self, mapwindow)
+        IVDigit.__init__(self, mapwindow)
         
-        if not mapwindow.parent.IsStandalone():
-            self.log = mapwindow.parent.GetLayerManager().goutput.cmd_stderr
-        else:
-            self.log = sys.stderr
-        
-        self.toolbar = mapwindow.parent.toolbars['vdigit']
-        
-        try:
-            self.digit = wxvdigit.Digit(self.driver.GetDevice(),
-                                        mapwindow)
-        except (ImportError, NameError, TypeError), e:
-            # print traceback
-            traceback.print_exc(file = self.log)
-            self.digit = None
-        self.UpdateSettings()
-        
-    def __del__(self):
-        del self.digit
-        
-    def AddPoint (self, map, point, x, y, z=None):
-        """!Add new point/centroid
-
-        @param map   map name (unused, for compatability with VEdit)
-        @param point feature type (if true point otherwise centroid)
-        @param x,y,z coordinates
+class VDigitSettingsDialog(wx.Dialog):
+    def __init__(self, parent, title, style = wx.DEFAULT_DIALOG_STYLE):
+        """!Standard settings dialog for digitization purposes
         """
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
-            layer = -1 # -> no category
-            cat   = -1
-        else:
-            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
-            cat   = self.SetCategory()
-            
-        if point:
-            type = wxvdigit.GV_POINT 
-        else:
-            type = wxvdigit.GV_CENTROID 
+        wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style)
 
-        snap, thresh = self.__getSnapThreshold()
-
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        if z:
-            ret = self.digit.AddLine(type, [x, y, z], layer, cat,
-                                     bgmap, snap, thresh)
-        else:
-            ret = self.digit.AddLine(type, [x, y], layer, cat,
-                                     bgmap, snap, thresh)
-        self.toolbar.EnableUndo()
-
-        return ret
-        
-    def AddLine (self, map, line, coords):
-        """!Add line/boundary
-
-        @param map    map name (unused, for compatability with VEdit)
-        @param line   feature type (if True line, otherwise boundary)
-        @param coords list of coordinates
-        """
-        if len(coords) < 2:
-            return
-        
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
-            layer = -1 # -> no category
-            cat   = -1
-        else:
-            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
-            cat   = self.SetCategory()
-        
-        if line:
-            type = wxvdigit.GV_LINE
-        else:
-            type = wxvdigit.GV_BOUNDARY
-        
-        listCoords = []
-        for c in coords:
-            for x in c:
-                listCoords.append(x)
-        
-        snap, thresh = self.__getSnapThreshold()
-        
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        ret = self.digit.AddLine(type, listCoords, layer, cat,
-                                 bgmap, snap, thresh)
-
-        self.toolbar.EnableUndo()
-        
-        return ret
-    
-    def DeleteSelectedLines(self):
-        """!Delete selected features
-
-        @return number of deleted lines
-        """
-        nlines = self.digit.DeleteLines(UserSettings.Get(group='vdigit', key='delRecord', subkey='enabled'))
-        
-        if nlines > 0:
-            self.toolbar.EnableUndo()
-            
-        return nlines
-
-    def MoveSelectedLines(self, move):
-        """!Move selected features
-
-        @param move direction (x, y)
-        """
-        snap, thresh = self.__getSnapThreshold()
-        
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        try:
-            nlines = self.digit.MoveLines(move[0], move[1], 0.0, # TODO 3D
-                                          bgmap, snap, thresh)
-        except SystemExit:
-            pass
-        
-        if nlines > 0:
-            self.toolbar.EnableUndo()
-        
-        return nlines
-
-    def MoveSelectedVertex(self, coords, move):
-        """!Move selected vertex of the line
-
-        @param coords click coordinates
-        @param move   X,Y direction
-
-        @return id of new feature
-        @return 0 vertex not moved (not found, line is not selected)
-        """
-        snap, thresh = self.__getSnapThreshold()
-
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        moved = self.digit.MoveVertex(coords[0], coords[1], 0.0, # TODO 3D
-                                      move[0], move[1], 0.0,
-                                      bgmap, snap,
-                                      self.driver.GetThreshold(type='selectThresh'), thresh)
-
-        if moved:
-            self.toolbar.EnableUndo()
-
-        return moved
-
-    def AddVertex(self, coords):
-        """!Add new vertex to the selected line/boundary on position 'coords'
-
-        @param coords coordinates to add vertex
-
-        @return id of new feature
-        @return 0 nothing changed
-        @return -1 on failure
-        """
-        added = self.digit.ModifyLineVertex(1, coords[0], coords[1], 0.0, # TODO 3D
-                                            self.driver.GetThreshold(type='selectThresh'))
-
-        if added > 0:
-            self.toolbar.EnableUndo()
-
-        return added
-
-    def RemoveVertex(self, coords):
-        """!Remove vertex from the selected line/boundary on position 'coords'
-
-        @param coords coordinates to remove vertex
-
-        @return id of new feature
-        @return 0 nothing changed
-        @return -1 on failure
-        """
-        deleted = self.digit.ModifyLineVertex(0, coords[0], coords[1], 0.0, # TODO 3D
-                                              self.driver.GetThreshold(type='selectThresh'))
-
-        if deleted > 0:
-            self.toolbar.EnableUndo()
-
-        return deleted
-
-
-    def SplitLine(self, coords):
-        """!Split selected line/boundary on position 'coords'
-
-        @param coords coordinates to split line
-
-        @return 1 line modified
-        @return 0 nothing changed
-        @return -1 error
-        """
-        ret = self.digit.SplitLine(coords[0], coords[1], 0.0, # TODO 3D
-                                   self.driver.GetThreshold('selectThresh'))
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def EditLine(self, line, coords):
-        """!Edit existing line/boundary
-
-        @param line id of line to be modified
-        @param coords list of coordinates of modified line
-
-        @return feature id of new line
-        @return -1 on error
-        """
-        try:
-            lineid = line[0]
-        except:
-            lineid = -1
-
-        if len(coords) < 2:
-            self.DeleteSelectedLines()
-            return 0
-            
-        listCoords = []
-        for c in coords:
-            for x in c:
-                listCoords.append(x)
-
-        snap, thresh = self.__getSnapThreshold()
-        
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        try:
-            ret = self.digit.RewriteLine(lineid, listCoords,
-                                         bgmap, snap, thresh)
-        except SystemExit:
-            pass
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def FlipLine(self):
-        """!Flip selected lines/boundaries
-
-        @return number of modified lines
-        @return -1 on error
-        """
-        ret = self.digit.FlipLines()
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def MergeLine(self):
-        """!Merge selected lines/boundaries
-
-        @return number of modified lines
-        @return -1 on error
-        """
-        ret = self.digit.MergeLines()
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def BreakLine(self):
-        """!Break selected lines/boundaries
-
-        @return number of modified lines
-        @return -1 on error
-        """
-        ret = self.digit.BreakLines()
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def SnapLine(self):
-        """!Snap selected lines/boundaries
-
-        @return on success
-        @return -1 on error
-        """
-        snap, thresh = self.__getSnapThreshold()
-        ret = self.digit.SnapLines(thresh)
-        
-        if ret == 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def ConnectLine(self):
-        """!Connect selected lines/boundaries
-
-        @return 1 lines connected
-        @return 0 lines not connected
-        @return -1 on error
-        """
-        snap, thresh = self.__getSnapThreshold()
-        ret = self.digit.ConnectLines(thresh)
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-        
-    def CopyLine(self, ids=[]):
-        """!Copy features from (background) vector map
-
-        @param ids list of line ids to be copied
-
-        @return number of copied features
-        @return -1 on error
-        """
-        bgmap = str(UserSettings.Get(group='vdigit', key='bgmap',
-                                     subkey='value', internal=True))
-        
-        if len(bgmap) > 0:
-            ret = self.digit.CopyLines(ids, bgmap)
-        else:
-            ret = self.digit.CopyLines(ids, None)
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def CopyCats(self, fromId, toId, copyAttrb=False):
-        """!Copy given categories to objects with id listed in ids
-
-        @param cats ids of 'from' feature
-        @param ids  ids of 'to' feature(s)
-
-        @return number of modified features
-        @return -1 on error
-        """
-        if len(fromId) == 0 or len(toId) == 0:
-            return 0
-        
-        ret = self.digit.CopyCats(fromId, toId, copyAttrb)
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def SelectLinesByQuery(self, pos1, pos2):
-        """!Select features by query
-
-        @param pos1, pos2 bounding box definition
-        """
-        thresh = self.SelectLinesByQueryThresh()
-        
-        w, n = pos1
-        e, s = pos2
-
-        query = wxvdigit.QUERY_UNKNOWN
-        if UserSettings.Get(group='vdigit', key='query', subkey='selection') == 0:
-            query = wxvdigit.QUERY_LENGTH
-        else:
-            query = wxvdigit.QUERY_DANGLE
-
-        type = wxvdigit.GV_POINTS | wxvdigit.GV_LINES # TODO: 3D
-        
-        ids = self.digit.SelectLinesByQuery(w, n, 0.0, e, s, 1000.0,
-                                            UserSettings.Get(group='vdigit', key='query', subkey='box'),
-                                            query, type, thresh)
-
-        Debug.msg(4, "VDigit.SelectLinesByQuery(): %s" % \
-                      ",".join(["%d" % v for v in ids]))
-        
-        return ids
-
-    def GetLineCats(self, line=-1):
-        """!Get layer/category pairs from given (selected) line
-        
-        @param line feature id (-1 for first selected line)
-        """
-        return dict(self.digit.GetLineCats(line))
-
-    def GetLineLength(self, line):
-        """!Get line length
-
-        @param line feature id
-
-        @return line length
-        @return -1 on error
-        """
-        return self.digit.GetLineLength(line)
-
-    def GetAreaSize(self, centroid):
-        """!Get area size
-
-        @param centroid centroid id
-
-        @return area size
-        @return -1 on error
-        """
-        return self.digit.GetAreaSize(centroid)
-        
-    def GetAreaPerimeter(self, centroid):
-        """!Get area perimeter
-
-        @param centroid centroid id
-
-        @return area size
-        @return -1 on error
-        """
-        return self.digit.GetAreaPerimeter(centroid)
-
-    def SetLineCats(self, line, layer, cats, add=True):
-        """!Set categories for given line and layer
-
-        @param line feature id
-        @param layer layer number (-1 for first selected line)
-        @param cats list of categories
-        @param add if True to add, otherwise do delete categories
-
-        @return new feature id (feature need to be rewritten)
-        @return -1 on error
-        """
-        ret = self.digit.SetLineCats(line, layer, cats, add)
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def GetLayers(self):
-        """!Get list of layers"""
-        return self.digit.GetLayers()
-
-    def TypeConvForSelectedLines(self):
-        """!Feature type conversion for selected objects.
-
-        Supported conversions:
-         - point <-> centroid
-         - line <-> boundary
-
-        @return number of modified features
-        @return -1 on error
-        """
-        ret = self.digit.TypeConvLines()
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def Undo(self, level=-1):
-        """!Undo action
-
-        @param level levels to undo (0 to revert all)
-
-        @return id of current changeset
-        """
-        try:
-            ret = self.digit.Undo(level)
-        except SystemExit:
-            ret = -2
-
-        if ret == -2:
-            raise gcmd.GException(_("Undo failed, data corrupted."))
-
-        self.mapWindow.UpdateMap(render=False)
-        
-        if ret < 0: # disable undo tool
-            self.toolbar.EnableUndo(False)
-
-    def GetUndoLevel(self):
-        """!Get undo level (number of active changesets)
-        
-        Note: Changesets starts wiht 0
-        """
-        if not self.digit:
-            return -1
-        
-        return self.digit.GetUndoLevel()
-
-    def UpdateSettings(self):
-        """!Update digit settigs"""
-        if not self.digit:
-            return
-        
-        self.digit.UpdateSettings(UserSettings.Get(group='vdigit', key='breakLines',
-                                                   subkey='enabled'),
-                                  UserSettings.Get(group='vdigit', key='addCentroid',
-                                                   subkey='enabled'),
-                                  UserSettings.Get(group='vdigit', key='catBoundary',
-                                                   subkey='enabled'))
-        
-    def ZBulkLines(self, pos1, pos2, start, step):
-        """!Z-bulk labeling
-
-        @param pos1 reference line (start point)
-        @param pos1 reference line (end point)
-        @param start starting value
-        @param step step value
-
-        @return number of modified lines
-        @return -1 on error
-        """
-        ret = self.digit.ZBulkLabeling(pos1[0], pos1[1], pos2[0], pos2[1],
-                                       start, step)
-        
-        if ret > 0:
-            self.toolbar.EnableUndo()
-        
-        return ret
-    
-    def __getSnapThreshold(self):
-        """!Get snap mode and threshold value
-
-        @return (snap, thresh)
-        """
-        thresh = self.driver.GetThreshold()
-
-        if thresh > 0.0:
-            if UserSettings.Get(group='vdigit', key='snapToVertex', subkey='enabled') is True:
-                snap = wxvdigit.SNAPVERTEX
-            else:
-                snap = wxvdigit.SNAP
-        else:
-            snap = wxvdigit.NO_SNAP
-
-        return (snap, thresh)
-
-class AbstractDisplayDriver:
-    """!Abstract classs for display driver"""
-    def __init__(self, parent, mapwindow):
-        """!Initialization
-
-        @param parent
-        @param mapwindow reference to mapwindow (MFrame)
-        """
-        self.parent      = parent
-        self.mapwindow   = mapwindow
-        
-        self.ids         = {}   # dict[g6id] = [pdcId]
-        self.selected    = []   # list of selected objects (grassId!)
-
-    def GetThreshold(self, type='snapping', value=None, units=None):
-        """!Return threshold in map units
-
-        @param value threshold to be set up
-        @param units units (map, screen)
-        """
-        if value is None:
-            value = UserSettings.Get(group='vdigit', key=type, subkey='value')
-
-        if units is None:
-            units = UserSettings.Get(group='vdigit', key=type, subkey='units')
-
-        reg = self.mapwindow.Map.region
-        if value < 0:
-            value = (reg['nsres'] + reg['ewres']) / 2.
-        
-        if units == "screen pixels":
-            # pixel -> cell
-            if reg['nsres'] > reg['ewres']:
-                res = reg['nsres']
-            else:
-                res = reg['ewres']
-
-            threshold = value * res
-        else:
-            threshold = value
-
-        Debug.msg(4, "AbstractDisplayDriver.GetThreshold(): type=%s, thresh=%f" % (type, threshold))
-        
-        return threshold
-
-class CDisplayDriver(AbstractDisplayDriver):
-    """
-    Display driver using grass7_wxdriver module
-    """
-    def __init__(self, parent, mapwindow):
-        """!Initialization
-
-        @param parent
-        @param mapwindow reference to mapwindow (MFrame)
-        """
-        AbstractDisplayDriver.__init__(self, parent, mapwindow)
-
-        self.mapWindow = mapwindow
-
-        if not self.mapwindow.parent.IsStandalone():
-            logerr = self.mapwindow.parent.GetLayerManager().goutput.cmd_stderr
-        else:
-            logerr = None
-
-        # initialize wx display driver
-        try:
-            self.__display = wxvdigit.DisplayDriver(mapwindow.pdcVector,
-                                                    mapwindow.pdcTmp,
-                                                    logerr)
-        except:
-            self.__display = None
-            
-        self.UpdateSettings()
-
-    def GetDevice(self):
-        """!Get device"""
-        return self.__display
-    
-    def SetDevice(self, pdc):
-        """!Set device for driver
-
-        @param pdc wx.PseudoDC instance
-        """
-        if self.__display:
-            self.__display.SetDevice(pdc)
-            
-    def Reset(self, map):
-        """!Reset map
-
-        Open or close the vector map by driver.
-
-        @param map map name or None to close the map
-
-        @return 0 on success (close map)
-        @return topo level on success (open map)
-        @return non-zero (close map)
-        @return -1 on error (open map)
-        """
-        if map:
-            name, mapset = map.split('@')
-            try:
-                ret = self.__display.OpenMap(str(name), str(mapset), True)
-            except SystemExit:
-                ret = -1
-        else:
-            ret = self.__display.CloseMap()
-
-        return ret
-    
-    def ReloadMap(self):
-        """!Reload map (close and re-open).
-
-        Needed for v.edit, TODO: get rid of that..."""
-        
-        Debug.msg(4, "CDisplayDriver.ReloadMap():")
-        self.__display.ReloadMap()
-
-    def DrawMap(self):
-        """!Draw vector map layer content
-
-        @return wx.Image instance
-        """
-        if not self.__display:
-            return 0
-        
-        nlines = self.__display.DrawMap(True) # force
-        Debug.msg(3, "CDisplayDriver.DrawMap(): nlines=%d" % nlines)
-
-        return nlines
-
-    def SelectLinesByBox(self, begin, end, type=0, drawSeg=False):
-        """!Select vector features by given bounding box.
-
-        If type is given, only vector features of given type are selected.
-
-        @param begin,end bounding box definition
-        @param type      select only objects of given type
-        """
-        x1, y1 = begin
-        x2, y2 = end
-
-        inBox = UserSettings.Get(group='vdigit', key='selectInside', subkey='enabled')
-        
-        nselected = self.__display.SelectLinesByBox(x1, y1, -1.0 * wxvdigit.PORT_DOUBLE_MAX,
-                                                    x2, y2, wxvdigit.PORT_DOUBLE_MAX,
-                                                    type, inBox, drawSeg)
-        
-        Debug.msg(4, "CDisplayDriver.SelectLinesByBox(): selected=%d" % \
-                      nselected)
-        
-        return nselected
-
-    def SelectLineByPoint(self, point, type=0):
-        """!Select vector feature by coordinates of click point (in given threshold).
-
-        If type is given, only vector features of given type are selected.
-
-        @param point click coordinates (bounding box given by threshold)
-        @param type  select only objects of given type
-        """
-        pointOnLine = self.__display.SelectLineByPoint(point[0], point[1], 0.0,
-                                                       self.GetThreshold(type='selectThresh'),
-                                                       type, 0); # without_z
-
-        if len(pointOnLine) > 0:
-            Debug.msg(4, "CDisplayDriver.SelectLineByPoint(): pointOnLine=%f,%f" % \
-                          (pointOnLine[0], pointOnLine[1]))
-            return pointOnLine
-        else:
-            Debug.msg(4, "CDisplayDriver.SelectLineByPoint(): no line found")
-            return None
-        
-    def GetSelected(self, grassId=True):
-        """!Return ids of selected vector features
-        
-        @param grassId if grassId is True returns GRASS ids, otherwise
-        internal ids of objects drawn in PseudoDC"""
-        if not self.__display:
-            return list()
-        
-        if grassId:
-            selected = self.__display.GetSelected(True)
-        else:
-            selected = self.__display.GetSelected(False)
-            
-        Debug.msg(4, "CDisplayDriver.GetSelected(): grassId=%d, ids=%s" % \
-                      (grassId, (",".join(["%d" % v for v in selected]))))
-            
-        return selected
-
-    def GetSelectedCoord(self):
-        """!Return ids of selected vector features and their coordinates"""
-        return dict(self.__display.GetSelectedCoord())
-        
-    def GetRegionSelected(self):
-        """!Get minimal region extent of selected features (ids/cats)"""
-        return self.__display.GetRegionSelected()
-    
-    def GetDuplicates(self):
-        """!Return ids of (selected) duplicated vector features
-        """
-        # -> id : (list of ids)
-        dupl = dict(self.__display.GetDuplicates())
-
-        # -> id : ((id, cat), ...)
-        dupl_full = {}
-        for key in dupl.keys():
-            dupl_full[key] = []
-            for id in dupl[key]:
-                catStr = ''
-                
-                cats = self.parent.GetLineCats(line=id)
-                
-                for layer in cats.keys():
-                    if len(cats[layer]) > 0:
-                        catStr = "%d: (" % layer
-                        for cat in cats[layer]:
-                            catStr += "%d," % cat
-                        catStr = catStr.rstrip(',')
-                        catStr += ')'
-                
-                dupl_full[key].append([id, catStr])
-
-        return dupl_full
-
-    def GetSelectedVertex(self, coords):
-        """!Get PseudoDC id(s) of vertex (of selected line)
-        on position 'coords'
-
-        @param coords click position
-        """
-        x, y = coords
-
-        id = self.__display.GetSelectedVertex(x, y, self.GetThreshold(type='selectThresh'))
-
-        Debug.msg(4, "CDisplayDriver.GetSelectedVertex(): id=%s" % \
-                      (",".join(["%d" % v for v in id])))
-
-        return id 
-
-    def SetSelected(self, id, field=-1):
-        """!Set selected vector features
-
-        @param id list of feature ids/categories to be selected
-        @param field field(layer) number, -1 for ids instead of cats
-        """
-        Debug.msg(4, "CDisplayDriver.SetSelected(): id=%s" % \
-                      id)
-
-        self.__display.SetSelected(id, field)
-
-    def UnSelect(self, id):
-        """!Unselect vector features
-
-        @param id list of feature id(s)
-        """
-
-        Debug.msg(4, "CDisplayDriver.UnSelect(): id=%s" % \
-                      ",".join(["%d" % v for v in id]))
-        
-        self.__display.UnSelect(id)
-
-    def UpdateRegion(self):
-        """!Set geographical region
-        
-        Needed for 'cell2pixel' conversion"""
-        if not self.__display:
-            return
-        
-        map = self.mapwindow.Map
-        reg = map.region
-        
-        self.__display.SetRegion(reg['n'],
-                                 reg['s'],
-                                 reg['e'],
-                                 reg['w'],
-                                 reg['nsres'],
-                                 reg['ewres'],
-                                 reg['center_easting'],
-                                 reg['center_northing'],
-                                 map.width, map.height)
-
-    def GetMapBoundingBox(self):
-        """!Return bounding box of given vector map layer
-
-        @return (w,s,b,e,n,t)
-        """
-
-        return self.__display.GetMapBoundingBox()
-
-    def Is3D(self):
-        """!Check if open vector map is 3D
-
-        @return True if 3D
-        @return False if not 3D"""
-        return self.__display.Is3D()
-    
-    def DrawSelected(self, draw=True):
-        """!Show/hide selected features"""
-        self.__display.DrawSelected(draw)
-        
-    def UpdateSettings(self, alpha=255):
-        """!Update display driver settings"""
-        # TODO map units
-
-        if not self.__display:
-            return
-        
-        color = {}
-        for symbol in ("highlight",
-                       "highlightDupl",
-                       "point",
-                       "line",
-                       "boundaryNo",
-                       "boundaryOne",
-                       "boundaryTwo",
-                       "centroidIn",
-                       "centroidOut",
-                       "centroidDup",
-                       "nodeOne",
-                       "nodeTwo",
-                       "vertex",
-                       "area",
-                       "direction"):
-            color[symbol] = wx.Color(UserSettings.Get(group='vdigit', key='symbol',
-                                                      subkey=[symbol, 'color'])[0],
-                                     UserSettings.Get(group='vdigit', key='symbol',
-                                                      subkey=[symbol, 'color'])[1],
-                                     UserSettings.Get(group='vdigit', key='symbol',
-                                                      subkey=[symbol, 'color'])[2]).GetRGB()
-
-        self.__display.UpdateSettings (color['highlight'],
-                                       UserSettings.Get(group='vdigit', key='checkForDupl',
-                                                        subkey='enabled'),
-                                       color['highlightDupl'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['point', 'enabled']),
-                                       color['point'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['line', 'enabled']),
-                                       color['line'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['boundaryNo', 'enabled']),
-                                       color['boundaryNo'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['boundaryOne', 'enabled']),
-                                       color['boundaryOne'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['boundaryTwo', 'enabled']),
-                                       color['boundaryTwo'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['centroidIn', 'enabled']),
-                                       color['centroidIn'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['centroidOut', 'enabled']),
-                                       color['centroidOut'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['centroidDup', 'enabled']),
-                                       color['centroidDup'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['nodeOne', 'enabled']),
-                                       color['nodeOne'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['nodeTwo', 'enabled']),
-                                       color['nodeTwo'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['vertex', 'enabled']),
-                                       color['vertex'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['area', 'enabled']),
-                                       color['area'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['direction', 'enabled']),
-                                       color['direction'],
-                                       UserSettings.Get(group='vdigit', key='lineWidth',
-                                                        subkey='value'),
-                                       alpha)
-
-class VDigitSettingsDialog(wx.Dialog):
-    """
-    Standard settings dialog for digitization purposes
-    """
-    def __init__(self, parent, title, style=wx.DEFAULT_DIALOG_STYLE):
-        wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title, style=style)
-
         self.parent = parent # mapdisplay.BufferedWindow class instance
 
         # notebook
-        notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
+        notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
         self.__CreateSymbologyPage(notebook)
         parent.digit.SetCategory() # update category number (next to use)
         self.__CreateGeneralPage(notebook)
@@ -1164,9 +95,9 @@
         btnSizer.Realize()
         
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        mainSizer.Add(item = notebook, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
         
         self.Bind(wx.EVT_CLOSE, self.OnCancel)
         
@@ -1176,36 +107,36 @@
     def __CreateSymbologyPage(self, notebook):
         """!Create notebook page concerning with symbology settings"""
 
-        panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
-        notebook.AddPage(page=panel, text=_("Symbology"))
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
+        notebook.AddPage(page = panel, text = _("Symbology"))
 
         sizer = wx.BoxSizer(wx.VERTICAL)
         
-        flexSizer = wx.FlexGridSizer (cols=3, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 3, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
 
         self.symbology = {}
         for label, key in self.__SymbologyData():
             textLabel = wx.StaticText(panel, wx.ID_ANY, label)
-            color = csel.ColourSelect(panel, id=wx.ID_ANY,
-                                      colour=UserSettings.Get(group='vdigit', key='symbol',
-                                                              subkey=[key, 'color']), size=globalvar.DIALOG_COLOR_SIZE)
-            isEnabled = UserSettings.Get(group='vdigit', key='symbol',
-                                         subkey=[key, 'enabled'])
+            color = csel.ColourSelect(panel, id = wx.ID_ANY,
+                                      colour = UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                                              subkey = [key, 'color']), size = globalvar.DIALOG_COLOR_SIZE)
+            isEnabled = UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                         subkey = [key, 'enabled'])
             if isEnabled is not None:
-                enabled = wx.CheckBox(panel, id=wx.ID_ANY, label="")
+                enabled = wx.CheckBox(panel, id = wx.ID_ANY, label = "")
                 enabled.SetValue(isEnabled)
                 self.symbology[key] = (enabled, color)
             else:
                 enabled = (1, 1)
                 self.symbology[key] = (None, color)
             
-            flexSizer.Add(textLabel, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-            flexSizer.Add(enabled, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-            flexSizer.Add(color, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
+            flexSizer.Add(textLabel, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+            flexSizer.Add(enabled, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+            flexSizer.Add(color, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
             color.SetName("GetColour")
         
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=10)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 10)
         
         panel.SetSizer(sizer)
         
@@ -1214,144 +145,144 @@
     def __CreateGeneralPage(self, notebook):
         """!Create notebook page concerning with symbology settings"""
 
-        panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
-        notebook.AddPage(page=panel, text=_("General"))
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
+        notebook.AddPage(page = panel, text = _("General"))
 
         border = wx.BoxSizer(wx.VERTICAL)
         
         #
         # display section
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Display"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Display"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        flexSizer = wx.FlexGridSizer (cols=3, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 3, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
         # line width
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width"))
-        self.lineWidthValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(75, -1),
-                                          initial=UserSettings.Get(group='vdigit', key="lineWidth", subkey='value'),
-                                          min=1, max=1e6)
-        units = wx.StaticText(parent=panel, id=wx.ID_ANY, size=(115, -1),
-                              label=UserSettings.Get(group='vdigit', key="lineWidth", subkey='units'),
-                              style=wx.ALIGN_LEFT)
-        flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.lineWidthValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(units, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
-                      border=10)
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Line width"))
+        self.lineWidthValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (75, -1),
+                                          initial = UserSettings.Get(group = 'vdigit', key = "lineWidth", subkey = 'value'),
+                                          min = 1, max = 1e6)
+        units = wx.StaticText(parent = panel, id = wx.ID_ANY, size = (115, -1),
+                              label = UserSettings.Get(group = 'vdigit', key = "lineWidth", subkey = 'units'),
+                              style = wx.ALIGN_LEFT)
+        flexSizer.Add(text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.lineWidthValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(units, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
+                      border = 10)
 
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
 
         #
         # snapping section
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Snapping"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Snapping"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        flexSizer = wx.FlexGridSizer (cols=3, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer(cols = 3, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
 
         # snapping
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Snapping threshold"))
-        self.snappingValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(75, -1),
-                                         initial=UserSettings.Get(group='vdigit', key="snapping", subkey='value'),
-                                         min=-1, max=1e6)
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Snapping threshold"))
+        self.snappingValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (75, -1),
+                                         initial = UserSettings.Get(group = 'vdigit', key = "snapping", subkey = 'value'),
+                                         min = -1, max = 1e6)
         self.snappingValue.Bind(wx.EVT_SPINCTRL, self.OnChangeSnappingValue)
         self.snappingValue.Bind(wx.EVT_TEXT, self.OnChangeSnappingValue)
-        self.snappingUnit = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
-                                      choices=["screen pixels", "map units"])
-        self.snappingUnit.SetStringSelection(UserSettings.Get(group='vdigit', key="snapping", subkey='units'))
+        self.snappingUnit = wx.Choice(parent = panel, id = wx.ID_ANY, size = (125, -1),
+                                      choices = ["screen pixels", "map units"])
+        self.snappingUnit.SetStringSelection(UserSettings.Get(group = 'vdigit', key = "snapping", subkey = 'units'))
         self.snappingUnit.Bind(wx.EVT_CHOICE, self.OnChangeSnappingUnits)
-        flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.snappingValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(self.snappingUnit, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
+        flexSizer.Add(text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.snappingValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(self.snappingUnit, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
 
         vertexSizer = wx.BoxSizer(wx.VERTICAL)
-        self.snapVertex = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                      label=_("Snap also to vertex"))
-        self.snapVertex.SetValue(UserSettings.Get(group='vdigit', key="snapToVertex", subkey='enabled'))
-        vertexSizer.Add(item=self.snapVertex, proportion=0, flag=wx.EXPAND)
+        self.snapVertex = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                      label = _("Snap also to vertex"))
+        self.snapVertex.SetValue(UserSettings.Get(group = 'vdigit', key = "snapToVertex", subkey = 'enabled'))
+        vertexSizer.Add(item = self.snapVertex, proportion = 0, flag = wx.EXPAND)
         self.mapUnits = self.parent.MapWindow.Map.GetProjInfo()['units']
-        self.snappingInfo = wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                          label=_("Snapping threshold is %(value).1f %(units)s") % \
-                                              {'value' : self.parent.digit.driver.GetThreshold(),
+        self.snappingInfo = wx.StaticText(parent = panel, id = wx.ID_ANY,
+                                          label = _("Snapping threshold is %(value).1f %(units)s") % \
+                                              {'value' : self.parent.digit.GetDisplay().GetThreshold(),
                                                'units' : self.mapUnits})
-        vertexSizer.Add(item=self.snappingInfo, proportion=0,
-                        flag=wx.ALL | wx.EXPAND, border=1)
+        vertexSizer.Add(item = self.snappingInfo, proportion = 0,
+                        flag = wx.ALL | wx.EXPAND, border = 1)
 
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.EXPAND)
-        sizer.Add(item=vertexSizer, proportion=1, flag=wx.EXPAND)
-        border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.EXPAND)
+        sizer.Add(item = vertexSizer, proportion = 1, flag = wx.EXPAND)
+        border.Add(item = sizer, proportion = 0, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
 
         #
         # select box
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Select vector features"))
+        box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Select vector features"))
         # feature type
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
         inSizer = wx.BoxSizer(wx.HORIZONTAL)
         self.selectFeature = {}
         for feature in ('point', 'line',
                         'centroid', 'boundary'):
-            chkbox = wx.CheckBox(parent=panel, label=feature)
+            chkbox = wx.CheckBox(parent = panel, label = feature)
             self.selectFeature[feature] = chkbox.GetId()
-            chkbox.SetValue(UserSettings.Get(group='vdigit', key='selectType',
-                                             subkey=[feature, 'enabled']))
-            inSizer.Add(item=chkbox, proportion=0,
-                        flag=wx.EXPAND | wx.ALL, border=5)
-        sizer.Add(item=inSizer, proportion=0, flag=wx.EXPAND)
+            chkbox.SetValue(UserSettings.Get(group = 'vdigit', key = 'selectType',
+                                             subkey = [feature, 'enabled']))
+            inSizer.Add(item = chkbox, proportion = 0,
+                        flag = wx.EXPAND | wx.ALL, border = 5)
+        sizer.Add(item = inSizer, proportion = 0, flag = wx.EXPAND)
         # threshold
-        flexSizer = wx.FlexGridSizer (cols=3, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 3, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Select threshold"))
-        self.selectThreshValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(75, -1),
-                                             initial=UserSettings.Get(group='vdigit', key="selectThresh", subkey='value'),
-                                             min=1, max=1e6)
-        units = wx.StaticText(parent=panel, id=wx.ID_ANY, size=(115, -1),
-                              label=UserSettings.Get(group='vdigit', key="lineWidth", subkey='units'),
-                              style=wx.ALIGN_LEFT)
-        flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.selectThreshValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(units, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
-                      border=10)
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Select threshold"))
+        self.selectThreshValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (75, -1),
+                                             initial = UserSettings.Get(group = 'vdigit', key = "selectThresh", subkey = 'value'),
+                                             min = 1, max = 1e6)
+        units = wx.StaticText(parent = panel, id = wx.ID_ANY, size = (115, -1),
+                              label = UserSettings.Get(group = 'vdigit', key = "lineWidth", subkey = 'units'),
+                              style = wx.ALIGN_LEFT)
+        flexSizer.Add(text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.selectThreshValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(units, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
+                      border = 10)
 
-        self.selectIn = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                    label=_("Select only features inside of selection bounding box"))
-        self.selectIn.SetValue(UserSettings.Get(group='vdigit', key="selectInside", subkey='enabled'))
+        self.selectIn = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                    label = _("Select only features inside of selection bounding box"))
+        self.selectIn.SetValue(UserSettings.Get(group = 'vdigit', key = "selectInside", subkey = 'enabled'))
         self.selectIn.SetToolTipString(_("By default are selected all features overlapping selection bounding box "))
         
-        self.checkForDupl = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                        label=_("Check for duplicates"))
-        self.checkForDupl.SetValue(UserSettings.Get(group='vdigit', key="checkForDupl", subkey='enabled'))
+        self.checkForDupl = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                        label = _("Check for duplicates"))
+        self.checkForDupl.SetValue(UserSettings.Get(group = 'vdigit', key = "checkForDupl", subkey = 'enabled'))
 
 
-        sizer.Add(item=flexSizer, proportion=0, flag=wx.EXPAND)
-        sizer.Add(item=self.selectIn, proportion=0, flag=wx.EXPAND | wx.ALL, border=1)
-        sizer.Add(item=self.checkForDupl, proportion=0, flag=wx.EXPAND | wx.ALL, border=1)        
-        border.Add(item=sizer, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+        sizer.Add(item = flexSizer, proportion = 0, flag = wx.EXPAND)
+        sizer.Add(item = self.selectIn, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 1)
+        sizer.Add(item = self.checkForDupl, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 1)        
+        border.Add(item = sizer, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
 
         #
         # digitize lines box
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Digitize line features"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Digitize line features"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
-        self.intersect = wx.CheckBox(parent=panel, label=_("Break lines at intersection"))
-        self.intersect.SetValue(UserSettings.Get(group='vdigit', key='breakLines', subkey='enabled'))
+        self.intersect = wx.CheckBox(parent = panel, label = _("Break lines at intersection"))
+        self.intersect.SetValue(UserSettings.Get(group = 'vdigit', key = 'breakLines', subkey = 'enabled'))
         
-        sizer.Add(item=self.intersect, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        sizer.Add(item = self.intersect, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
 
-        border.Add(item=sizer, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+        border.Add(item = sizer, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
 
         #
         # save-on-exit box
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Save changes"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Save changes"))
         # save changes on exit?
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        self.save = wx.CheckBox(parent=panel, label=_("Save changes on exit"))
-        self.save.SetValue(UserSettings.Get(group='vdigit', key='saveOnExit', subkey='enabled'))
-        sizer.Add(item=self.save, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+        self.save = wx.CheckBox(parent = panel, label = _("Save changes on exit"))
+        self.save.SetValue(UserSettings.Get(group = 'vdigit', key = 'saveOnExit', subkey = 'enabled'))
+        sizer.Add(item = self.save, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
 
         panel.SetSizer(border)
         
@@ -1359,73 +290,72 @@
 
     def __CreateQueryPage(self, notebook):
         """!Create notebook page for query tool"""
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
+        notebook.AddPage(page = panel, text = _("Query tool"))
 
-        panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
-        notebook.AddPage(page=panel, text=_("Query tool"))
-
         border = wx.BoxSizer(wx.VERTICAL)
 
         #
         # query tool box
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Choose query tool"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Choose query tool"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
         LocUnits = self.parent.MapWindow.Map.GetProjInfo()['units']
 
-        self.queryBox = wx.CheckBox(parent=panel, id=wx.ID_ANY, label=_("Select by box"))
-        self.queryBox.SetValue(UserSettings.Get(group='vdigit', key="query", subkey='box'))
+        self.queryBox = wx.CheckBox(parent = panel, id = wx.ID_ANY, label = _("Select by box"))
+        self.queryBox.SetValue(UserSettings.Get(group = 'vdigit', key = "query", subkey = 'box'))
 
-        sizer.Add(item=self.queryBox, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        sizer.Add(item = self.queryBox, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
         sizer.Add((0, 5))
 
         #
         # length
         #
-        self.queryLength = wx.RadioButton(parent=panel, id=wx.ID_ANY, label=_("length"))
+        self.queryLength = wx.RadioButton(parent = panel, id = wx.ID_ANY, label = _("length"))
         self.queryLength.Bind(wx.EVT_RADIOBUTTON, self.OnChangeQuery)
-        sizer.Add(item=self.queryLength, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        flexSizer = wx.FlexGridSizer (cols=4, hgap=5, vgap=5)
+        sizer.Add(item = self.queryLength, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        flexSizer = wx.FlexGridSizer (cols = 4, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
-        txt = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Select lines"))
-        self.queryLengthSL = wx.Choice (parent=panel, id=wx.ID_ANY, 
-                                        choices = [_("shorter than"), _("longer than")])
-        self.queryLengthSL.SetSelection(UserSettings.Get(group='vdigit', key="queryLength", subkey='than-selection'))
-        self.queryLengthValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
-                                            initial=1,
-                                            min=0, max=1e6)
-        self.queryLengthValue.SetValue(UserSettings.Get(group='vdigit', key="queryLength", subkey='thresh'))
-        units = wx.StaticText(parent=panel, id=wx.ID_ANY, label="%s" % LocUnits)
-        flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.queryLengthSL, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(self.queryLengthValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(units, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        sizer.Add(item=flexSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        txt = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Select lines"))
+        self.queryLengthSL = wx.Choice (parent = panel, id = wx.ID_ANY, 
+                                        choices  =  [_("shorter than"), _("longer than")])
+        self.queryLengthSL.SetSelection(UserSettings.Get(group = 'vdigit', key = "queryLength", subkey = 'than-selection'))
+        self.queryLengthValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (100, -1),
+                                            initial = 1,
+                                            min = 0, max = 1e6)
+        self.queryLengthValue.SetValue(UserSettings.Get(group = 'vdigit', key = "queryLength", subkey = 'thresh'))
+        units = wx.StaticText(parent = panel, id = wx.ID_ANY, label = "%s" % LocUnits)
+        flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.queryLengthSL, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(self.queryLengthValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(units, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        sizer.Add(item = flexSizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
 
         #
         # dangle
         #
-        self.queryDangle = wx.RadioButton(parent=panel, id=wx.ID_ANY, label=_("dangle"))
+        self.queryDangle = wx.RadioButton(parent = panel, id = wx.ID_ANY, label = _("dangle"))
         self.queryDangle.Bind(wx.EVT_RADIOBUTTON, self.OnChangeQuery)
-        sizer.Add(item=self.queryDangle, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        flexSizer = wx.FlexGridSizer (cols=4, hgap=5, vgap=5)
+        sizer.Add(item = self.queryDangle, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        flexSizer = wx.FlexGridSizer (cols = 4, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
-        txt = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Select dangles"))
-        self.queryDangleSL = wx.Choice (parent=panel, id=wx.ID_ANY, 
+        txt = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Select dangles"))
+        self.queryDangleSL = wx.Choice (parent = panel, id = wx.ID_ANY, 
                                         choices = [_("shorter than"), _("longer than")])
-        self.queryDangleSL.SetSelection(UserSettings.Get(group='vdigit', key="queryDangle", subkey='than-selection'))
-        self.queryDangleValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
-                                       initial=1,
-                                       min=0, max=1e6)
-        self.queryDangleValue.SetValue(UserSettings.Get(group='vdigit', key="queryDangle", subkey='thresh'))
-        units = wx.StaticText(parent=panel, id=wx.ID_ANY, label="%s" % LocUnits)
-        flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.queryDangleSL, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(self.queryDangleValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(units, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        sizer.Add(item=flexSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        self.queryDangleSL.SetSelection(UserSettings.Get(group = 'vdigit', key = "queryDangle", subkey = 'than-selection'))
+        self.queryDangleValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (100, -1),
+                                       initial = 1,
+                                       min = 0, max = 1e6)
+        self.queryDangleValue.SetValue(UserSettings.Get(group = 'vdigit', key = "queryDangle", subkey = 'thresh'))
+        units = wx.StaticText(parent = panel, id = wx.ID_ANY, label = "%s" % LocUnits)
+        flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.queryDangleSL, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(self.queryDangleValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(units, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        sizer.Add(item = flexSizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
 
-        if UserSettings.Get(group='vdigit', key="query", subkey='selection') == 0:
+        if UserSettings.Get(group = 'vdigit', key = "query", subkey = 'selection') == 0:
             self.queryLength.SetValue(True)
         else:
             self.queryDangle.SetValue(True)
@@ -1433,7 +363,7 @@
         # enable & disable items
         self.OnChangeQuery(None)
 
-        border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
 
         panel.SetSizer(border)
         
@@ -1441,91 +371,90 @@
 
     def __CreateAttributesPage(self, notebook):
         """!Create notebook page for query tool"""
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
+        notebook.AddPage(page = panel, text = _("Attributes"))
 
-        panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
-        notebook.AddPage(page=panel, text=_("Attributes"))
-
         border = wx.BoxSizer(wx.VERTICAL)
 
         #
         # add new record
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Digitize new feature"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Digitize new feature"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
         # checkbox
-        self.addRecord = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                     label=_("Add new record into table"))
-        self.addRecord.SetValue(UserSettings.Get(group='vdigit', key="addRecord", subkey='enabled'))
-        sizer.Add(item=self.addRecord, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        self.addRecord = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                     label = _("Add new record into table"))
+        self.addRecord.SetValue(UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled'))
+        sizer.Add(item = self.addRecord, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
         # settings
-        flexSizer = wx.FlexGridSizer(cols=2, hgap=3, vgap=3)
+        flexSizer = wx.FlexGridSizer(cols = 2, hgap = 3, vgap = 3)
         flexSizer.AddGrowableCol(0)
         settings = ((_("Layer"), 1), (_("Category"), 1), (_("Mode"), _("Next to use")))
         # layer
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Layer"))
-        self.layer = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(125, -1),
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Layer"))
+        self.layer = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (125, -1),
                                  min = 1, max = 1e3)
-        self.layer.SetValue(int(UserSettings.Get(group='vdigit', key="layer", subkey='value')))
-        flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=self.layer, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        self.layer.SetValue(int(UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')))
+        flexSizer.Add(item = text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = self.layer, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
         # category number
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Category number"))
-        self.category = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(125, -1),
-                                    initial=UserSettings.Get(group='vdigit', key="category", subkey='value'),
-                                    min=-1e9, max=1e9) 
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') != 1:
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Category number"))
+        self.category = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (125, -1),
+                                    initial = UserSettings.Get(group = 'vdigit', key = "category", subkey = 'value'),
+                                    min = -1e9, max = 1e9) 
+        if UserSettings.Get(group = 'vdigit', key = "categoryMode", subkey = 'selection') != 1:
             self.category.Enable(False)
-        flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=self.category, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = self.category, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
         # category mode
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Category mode"))
-        self.categoryMode = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
-                                      choices=[_("Next to use"), _("Manual entry"), _("No category")])
-        self.categoryMode.SetSelection(UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection'))
-        flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=self.categoryMode, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Category mode"))
+        self.categoryMode = wx.Choice(parent = panel, id = wx.ID_ANY, size = (125, -1),
+                                      choices = [_("Next to use"), _("Manual entry"), _("No category")])
+        self.categoryMode.SetSelection(UserSettings.Get(group = 'vdigit', key = "categoryMode", subkey = 'selection'))
+        flexSizer.Add(item = text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = self.categoryMode, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
 
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0,
-                   flag=wx.ALL | wx.EXPAND, border=5)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0,
+                   flag = wx.ALL | wx.EXPAND, border = 5)
 
         #
         # digitize new area
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Digitize new area"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Digitize new area"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
         
         # add centroid
-        self.addCentroid = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                       label=_("Add centroid to left/right area"))
-        self.addCentroid.SetValue(UserSettings.Get(group='vdigit', key="addCentroid", subkey='enabled'))
-        sizer.Add(item=self.addCentroid, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        self.addCentroid = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                       label = _("Add centroid to left/right area"))
+        self.addCentroid.SetValue(UserSettings.Get(group = 'vdigit', key = "addCentroid", subkey = 'enabled'))
+        sizer.Add(item = self.addCentroid, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
         
         # attach category to boundary
-        self.catBoundary = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                       label=_("Do not attach category to boundaries"))
-        self.catBoundary.SetValue(UserSettings.Get(group='vdigit', key="catBoundary", subkey='enabled'))
-        sizer.Add(item=self.catBoundary, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0,
-                   flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+        self.catBoundary = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                       label = _("Do not attach category to boundaries"))
+        self.catBoundary.SetValue(UserSettings.Get(group = 'vdigit', key = "catBoundary", subkey = 'enabled'))
+        sizer.Add(item = self.catBoundary, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0,
+                   flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
         
         #
         # delete existing record
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Delete existing feature(s)"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Delete existing feature(s)"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
         
         # checkbox
-        self.deleteRecord = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                        label=_("Delete record from table"))
-        self.deleteRecord.SetValue(UserSettings.Get(group='vdigit', key="delRecord", subkey='enabled'))
-        sizer.Add(item=self.deleteRecord, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0,
-                   flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+        self.deleteRecord = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                        label = _("Delete record from table"))
+        self.deleteRecord.SetValue(UserSettings.Get(group = 'vdigit', key = "delRecord", subkey = 'enabled'))
+        sizer.Add(item = self.deleteRecord, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0,
+                   flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
 
         #
         # geometry attributes (currently only length and area are supported)
@@ -1533,7 +462,7 @@
         box   = wx.StaticBox (parent = panel, id = wx.ID_ANY,
                               label = " %s " % _("Geometry attributes"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(hgap=3, vgap=3)
+        gridSizer = wx.GridBagSizer(hgap = 3, vgap = 3)
         gridSizer.AddGrowableCol(0)
         self.geomAttrb = { 'length' : { 'label' : _('length') },
                            'area' : { 'label' : _('area') },
@@ -1544,7 +473,7 @@
             vectorName = digitToolbar.GetLayer().GetName()
         except AttributeError:
             vectorName = None # no vector selected for editing
-        layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
+        layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')
         mapLayer = self.parent.toolbars['vdigit'].GetLayer()
         tree = self.parent.tree
         item = tree.FindItemByData('maplayer', mapLayer)
@@ -1556,7 +485,7 @@
             ### self.deleteRecord.SetValue(UserSettings.Get(group='vdigit', key="delRecord", subkey='enabled'))
             check.Bind(wx.EVT_CHECKBOX, self.OnGeomAttrb)
             # column (only numeric)
-            column = gselect.ColumnSelect(parent = panel, size=(200, -1))
+            column = gselect.ColumnSelect(parent = panel, size = (200, -1))
             column.InsertColumns(vector = vectorName,
                                  layer = layer, excludeKey = True,
                                  type = ['integer', 'double precision'])
@@ -1566,7 +495,7 @@
             else:
                 choices = Units.GetUnitsList('length')
             win_units = wx.Choice(parent = panel, id = wx.ID_ANY,
-                                  choices = choices, size=(120, -1))
+                                  choices = choices, size = (120, -1))
             
             # default values
             check.SetValue(False)
@@ -1608,12 +537,12 @@
                                          "preferences."), 55))
         gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
                                            label = note),
-                      pos = (3, 0), span=(1, 3))
+                      pos = (3, 0), span = (1, 3))
                       
-        sizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0,
-                   flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+        sizer.Add(item = gridSizer, proportion = 1,
+                  flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0,
+                   flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
 
         # bindings
         self.Bind(wx.EVT_CHECKBOX, self.OnChangeAddRecord, self.addRecord)
@@ -1625,8 +554,7 @@
         return panel
 
     def __SymbologyData(self):
-        """
-        Data for __CreateSymbologyPage()
+        """!Data for __CreateSymbologyPage()
 
         label | checkbox | color
         """
@@ -1667,9 +595,8 @@
         
     def OnChangeCategoryMode(self, event):
         """!Change category mode"""
-
         mode = event.GetSelection()
-        UserSettings.Set(group='vdigit', key="categoryMode", subkey='selection', value=mode)
+        UserSettings.Set(group = 'vdigit', key = "categoryMode", subkey = 'selection', value = mode)
         if mode == 1: # manual entry
             self.category.Enable(True)
         elif self.category.IsEnabled(): # disable
@@ -1679,15 +606,15 @@
             self.addRecord.SetValue(False)
 
         self.parent.digit.SetCategory()
-        self.category.SetValue(UserSettings.Get(group='vdigit', key='category', subkey='value'))
+        self.category.SetValue(UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value'))
 
     def OnChangeLayer(self, event):
         """!Layer changed"""
         layer = event.GetInt()
         if layer > 0:
-            UserSettings.Set(group='vdigit', key='layer', subkey='value', value=layer)
+            UserSettings.Set(group = 'vdigit', key = 'layer', subkey = 'value', value = layer)
             self.parent.digit.SetCategory()
-            self.category.SetValue(UserSettings.Get(group='vdigit', key='category', subkey='value'))
+            self.category.SetValue(UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value'))
             
         event.Skip()
 
@@ -1702,12 +629,12 @@
         if value < 0:
             region = self.parent.MapWindow.Map.GetRegion()
             res = (region['nsres'] + region['ewres']) / 2.
-            threshold = self.parent.digit.driver.GetThreshold(value=res)
+            threshold = self.parent.digit.driver.GetThreshold(value = res)
         else:
             if self.snappingUnit.GetStringSelection() == "map units":
                 threshold = value
             else:
-                threshold = self.parent.digit.driver.GetThreshold(value=value)
+                threshold = self.parent.digit.driver.GetThreshold(value = value)
             
         if value == 0:
             self.snappingInfo.SetLabel(_("Snapping disabled"))
@@ -1727,7 +654,7 @@
         """!Snapping units change -> update static text"""
         value = self.snappingValue.GetValue()
         units = self.snappingUnit.GetStringSelection()
-        threshold = self.parent.digit.driver.GetThreshold(value=value, units=units)
+        threshold = self.parent.digit.driver.GetThreshold(value = value, units = units)
 
         if units == "map units":
             self.snappingInfo.SetLabel(_("Snapping threshold is %(value).1f %(units)s") % 
@@ -1761,8 +688,8 @@
         self.parent.toolbars['vdigit'].settingsDialog = None
 
         fileSettings = {}
-        UserSettings.ReadSettingsFile(settings=fileSettings)
-        fileSettings['vdigit'] = UserSettings.Get(group='vdigit')
+        UserSettings.ReadSettingsFile(settings = fileSettings)
+        fileSettings['vdigit'] = UserSettings.Get(group = 'vdigit')
         
         file = UserSettings.SaveToFile(fileSettings)
         self.parent.GetLayerManager().goutput.WriteLog(_('Vector digitizer settings saved to file <%s>.') % file)
@@ -1784,52 +711,52 @@
             event.Skip()
         
     def UpdateSettings(self):
-        """!Update UserSettings"""
-
+        """!Update digitizer settings
+        """
         # symbology
         for key, (enabled, color) in self.symbology.iteritems():
             if enabled:
-                UserSettings.Set(group='vdigit', key='symbol',
-                                 subkey=[key, 'enabled'],
-                                 value=enabled.IsChecked())
-                UserSettings.Set(group='vdigit', key='symbol',
-                                 subkey=[key, 'color'],
-                                 value=tuple(color.GetColour()))
+                UserSettings.Set(group = 'vdigit', key = 'symbol',
+                                 subkey = [key, 'enabled'],
+                                 value = enabled.IsChecked())
+                UserSettings.Set(group = 'vdigit', key = 'symbol',
+                                 subkey = [key, 'color'],
+                                 value = tuple(color.GetColour()))
             else:
-                UserSettings.Set(group='vdigit', key='symbol',
-                                 subkey=[key, 'color'],
-                                 value=tuple(color.GetColour()))
+                UserSettings.Set(group = 'vdigit', key = 'symbol',
+                                 subkey = [key, 'color'],
+                                 value = tuple(color.GetColour()))
         # display
-        UserSettings.Set(group='vdigit', key="lineWidth", subkey='value',
-                         value=int(self.lineWidthValue.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "lineWidth", subkey = 'value',
+                         value = int(self.lineWidthValue.GetValue()))
 
         # snapping
-        UserSettings.Set(group='vdigit', key="snapping", subkey='value',
-                         value=int(self.snappingValue.GetValue()))
-        UserSettings.Set(group='vdigit', key="snapping", subkey='units',
-                         value=self.snappingUnit.GetStringSelection())
-        UserSettings.Set(group='vdigit', key="snapToVertex", subkey='enabled',
-                         value=self.snapVertex.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "snapping", subkey = 'value',
+                         value = int(self.snappingValue.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "snapping", subkey = 'units',
+                         value = self.snappingUnit.GetStringSelection())
+        UserSettings.Set(group = 'vdigit', key = "snapToVertex", subkey = 'enabled',
+                         value = self.snapVertex.IsChecked())
         
         # digitize new feature
-        UserSettings.Set(group='vdigit', key="addRecord", subkey='enabled',
-                         value=self.addRecord.IsChecked())
-        UserSettings.Set(group='vdigit', key="layer", subkey='value',
-                         value=int(self.layer.GetValue()))
-        UserSettings.Set(group='vdigit', key="category", subkey='value',
-                         value=int(self.category.GetValue()))
-        UserSettings.Set(group='vdigit', key="categoryMode", subkey='selection',
-                         value=self.categoryMode.GetSelection())
+        UserSettings.Set(group = 'vdigit', key = "addRecord", subkey = 'enabled',
+                         value = self.addRecord.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "layer", subkey = 'value',
+                         value = int(self.layer.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "category", subkey = 'value',
+                         value = int(self.category.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "categoryMode", subkey = 'selection',
+                         value = self.categoryMode.GetSelection())
 
         # digitize new area
-        UserSettings.Set(group='vdigit', key="addCentroid", subkey='enabled',
-                         value=self.addCentroid.IsChecked())
-        UserSettings.Set(group='vdigit', key="catBoundary", subkey='enabled',
-                         value=self.catBoundary.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "addCentroid", subkey = 'enabled',
+                         value = self.addCentroid.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "catBoundary", subkey = 'enabled',
+                         value = self.catBoundary.IsChecked())
         
         # delete existing feature
-        UserSettings.Set(group='vdigit', key="delRecord", subkey='enabled',
-                         value=self.deleteRecord.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "delRecord", subkey = 'enabled',
+                         value = self.deleteRecord.IsChecked())
 
         # geometry attributes (workspace)
         mapLayer = self.parent.toolbars['vdigit'].GetLayer()
@@ -1855,74 +782,65 @@
                         tree.GetPyData(item)[0]['vdigit']['geomAttr'].has_key(key):
                     del tree.GetPyData(item)[0]['vdigit']['geomAttr'][key]
         
-        # snapping threshold
-        self.parent.digit.threshold = self.parent.digit.driver.GetThreshold()
-
         # query tool
         if self.queryLength.GetValue():
-            UserSettings.Set(group='vdigit', key="query", subkey='selection',
-                             value=0)
+            UserSettings.Set(group = 'vdigit', key = "query", subkey = 'selection',
+                             value = 0)
         else:
-            UserSettings.Set(group='vdigit', key="query", subkey='type',
-                             value=1)
-        UserSettings.Set(group='vdigit', key="query", subkey='box',
-                         value=self.queryBox.IsChecked())
-        UserSettings.Set(group='vdigit', key="queryLength", subkey='than-selection',
-                         value=self.queryLengthSL.GetSelection())
-        UserSettings.Set(group='vdigit', key="queryLength", subkey='thresh',
-                         value=int(self.queryLengthValue.GetValue()))
-        UserSettings.Set(group='vdigit', key="queryDangle", subkey='than-selection',
-                         value=self.queryDangleSL.GetSelection())
-        UserSettings.Set(group='vdigit', key="queryDangle", subkey='thresh',
-                         value=int(self.queryDangleValue.GetValue()))
+            UserSettings.Set(group = 'vdigit', key = "query", subkey = 'type',
+                             value = 1)
+        UserSettings.Set(group = 'vdigit', key = "query", subkey = 'box',
+                         value = self.queryBox.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "queryLength", subkey = 'than-selection',
+                         value = self.queryLengthSL.GetSelection())
+        UserSettings.Set(group = 'vdigit', key = "queryLength", subkey = 'thresh',
+                         value = int(self.queryLengthValue.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "queryDangle", subkey = 'than-selection',
+                         value = self.queryDangleSL.GetSelection())
+        UserSettings.Set(group = 'vdigit', key = "queryDangle", subkey = 'thresh',
+                         value = int(self.queryDangleValue.GetValue()))
 
         # select features
         for feature in ('point', 'line',
                         'centroid', 'boundary'):
-            UserSettings.Set(group='vdigit', key='selectType',
-                             subkey=[feature, 'enabled'],
-                             value=self.FindWindowById(self.selectFeature[feature]).IsChecked())
-        UserSettings.Set(group='vdigit', key="selectThresh", subkey='value',
-                         value=int(self.selectThreshValue.GetValue()))
-        UserSettings.Set(group='vdigit', key="checkForDupl", subkey='enabled',
-                         value=self.checkForDupl.IsChecked())
-        UserSettings.Set(group='vdigit', key="selectInside", subkey='enabled',
-                         value=self.selectIn.IsChecked())
+            UserSettings.Set(group = 'vdigit', key = 'selectType',
+                             subkey = [feature, 'enabled'],
+                             value = self.FindWindowById(self.selectFeature[feature]).IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "selectThresh", subkey = 'value',
+                         value = int(self.selectThreshValue.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "checkForDupl", subkey = 'enabled',
+                         value = self.checkForDupl.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "selectInside", subkey = 'enabled',
+                         value = self.selectIn.IsChecked())
 
         # on-exit
-        UserSettings.Set(group='vdigit', key="saveOnExit", subkey='enabled',
-                         value=self.save.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "saveOnExit", subkey = 'enabled',
+                         value = self.save.IsChecked())
 
         # break lines
-        UserSettings.Set(group='vdigit', key="breakLines", subkey='enabled',
-                         value=self.intersect.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "breakLines", subkey = 'enabled',
+                         value = self.intersect.IsChecked())
         
-        # update driver settings
-        self.parent.digit.driver.UpdateSettings()
-
-        # update digit settings
-        self.parent.digit.UpdateSettings()
+        self.parent.digit.GetDisplay().UpdateSettings()
         
         # redraw map if auto-rendering is enabled
         if self.parent.statusbarWin['render'].GetValue(): 
             self.parent.OnRender(None)
 
 class VDigitCategoryDialog(wx.Dialog, listmix.ColumnSorterMixin):
-    """
-    Dialog used to display/modify categories of vector objects
-    
-    @param parent
-    @param title dialog title
-    @param query {coordinates, qdist} - used by v.edit/v.what
-    @param cats  directory of lines (layer/categories) - used by vdigit
-    @param pos
-    @param style
-    """
     def __init__(self, parent, title,
-                 map, query=None, cats=None,
-                 pos=wx.DefaultPosition,
-                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
-
+                 map, query = None, cats = None,
+                 pos = wx.DefaultPosition,
+                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
+        """!Dialog used to display/modify categories of vector objects
+        
+        @param parent
+        @param title dialog title
+        @param query {coordinates, qdist} - used by v.edit/v.what
+        @param cats  directory of lines (layer/categories) - used by vdigit
+        @param pos
+        @param style
+        """
         # parent
         self.parent = parent # mapdisplay.BufferedWindow class instance
 
@@ -1949,15 +867,15 @@
         # make copy of cats (used for 'reload')
         self.cats_orig = copy.deepcopy(self.cats)
         
-        wx.Dialog.__init__(self, parent=self.parent, id=wx.ID_ANY, title=title,
-                          style=style, pos=pos)
+        wx.Dialog.__init__(self, parent = self.parent, id = wx.ID_ANY, title = title,
+                          style = style, pos = pos)
         
         # list of categories
-        box = wx.StaticBox(parent=self, id=wx.ID_ANY,
-                           label=" %s " % _("List of categories - right-click to delete"))
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("List of categories - right-click to delete"))
         listSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        self.list = CategoryListCtrl(parent=self, id=wx.ID_ANY,
-                                     style=wx.LC_REPORT |
+        self.list = CategoryListCtrl(parent = self, id = wx.ID_ANY,
+                                     style = wx.LC_REPORT |
                                      wx.BORDER_NONE |
                                      wx.LC_SORT_ASCENDING |
                                      wx.LC_HRULES |
@@ -1966,10 +884,10 @@
         self.fid = self.cats.keys()[0]
         self.itemDataMap = self.list.Populate(self.cats[self.fid])
         listmix.ColumnSorterMixin.__init__(self, 2)
-        self.fidMulti = wx.Choice(parent=self, id=wx.ID_ANY,
-                                  size=(150, -1))
+        self.fidMulti = wx.Choice(parent = self, id = wx.ID_ANY,
+                                  size = (150, -1))
         self.fidMulti.Bind(wx.EVT_CHOICE, self.OnFeature)
-        self.fidText = wx.StaticText(parent=self, id=wx.ID_ANY)
+        self.fidText = wx.StaticText(parent = self, id = wx.ID_ANY)
         if len(self.cats.keys()) == 1:
             self.fidMulti.Show(False)
             self.fidText.SetLabel(str(self.fid))
@@ -1981,44 +899,44 @@
             self.fidMulti.SetItems(choices)
             self.fidMulti.SetSelection(0)
         
-        listSizer.Add(item=self.list, proportion=1, flag=wx.EXPAND)
+        listSizer.Add(item = self.list, proportion = 1, flag = wx.EXPAND)
 
         # add new category
-        box = wx.StaticBox(parent=self, id=wx.ID_ANY,
-                           label=" %s " % _("Add new category"))
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("Add new category"))
         addSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        flexSizer = wx.FlexGridSizer (cols=5, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 5, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(3)
 
-        layerNewTxt = wx.StaticText(parent=self, id=wx.ID_ANY,
-                                 label="%s:" % _("Layer"))
-        self.layerNew = wx.Choice(parent=self, id=wx.ID_ANY, size=(75, -1),
-                                  choices=layers)
+        layerNewTxt = wx.StaticText(parent = self, id = wx.ID_ANY,
+                                 label = "%s:" % _("Layer"))
+        self.layerNew = wx.Choice(parent = self, id = wx.ID_ANY, size = (75, -1),
+                                  choices = layers)
         if len(layers) > 0:
             self.layerNew.SetSelection(0)
         
-        catNewTxt = wx.StaticText(parent=self, id=wx.ID_ANY,
-                               label="%s:" % _("Category"))
+        catNewTxt = wx.StaticText(parent = self, id = wx.ID_ANY,
+                               label = "%s:" % _("Category"))
 
         try:
             newCat = max(self.cats[self.fid][1]) + 1
         except KeyError:
             newCat = 1
-        self.catNew = wx.SpinCtrl(parent=self, id=wx.ID_ANY, size=(75, -1),
-                                  initial=newCat, min=0, max=1e9)
+        self.catNew = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (75, -1),
+                                  initial = newCat, min = 0, max = 1e9)
         btnAddCat = wx.Button(self, wx.ID_ADD)
-        flexSizer.Add(item=layerNewTxt, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=self.layerNew, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=catNewTxt, proportion=0,
-                      flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
-                      border=10)
-        flexSizer.Add(item=self.catNew, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=btnAddCat, proportion=0,
-                      flag=wx.EXPAND | wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
-        addSizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
+        flexSizer.Add(item = layerNewTxt, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = self.layerNew, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = catNewTxt, proportion = 0,
+                      flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
+                      border = 10)
+        flexSizer.Add(item = self.catNew, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = btnAddCat, proportion = 0,
+                      flag = wx.EXPAND | wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
+        addSizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
 
         # buttons
         btnApply = wx.Button(self, wx.ID_APPLY)
@@ -2039,24 +957,24 @@
         btnSizer.Realize()
         
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=listSizer, proportion=1,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
-        mainSizer.Add(item=addSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALIGN_CENTER |
-                      wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+        mainSizer.Add(item = listSizer, proportion = 1,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
+        mainSizer.Add(item = addSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALIGN_CENTER |
+                      wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
         fidSizer = wx.BoxSizer(wx.HORIZONTAL)
-        fidSizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY,
-                                        label=_("Feature id:")),
-                     proportion=0, border=5,
-                     flag=wx.ALIGN_CENTER_VERTICAL)
-        fidSizer.Add(item=self.fidMulti, proportion=0,
-                     flag=wx.EXPAND | wx.ALL,  border=5)
-        fidSizer.Add(item=self.fidText, proportion=0,
-                     flag=wx.EXPAND | wx.ALL,  border=5)
-        mainSizer.Add(item=fidSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        fidSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
+                                        label = _("Feature id:")),
+                     proportion = 0, border = 5,
+                     flag = wx.ALIGN_CENTER_VERTICAL)
+        fidSizer.Add(item = self.fidMulti, proportion = 0,
+                     flag = wx.EXPAND | wx.ALL,  border = 5)
+        fidSizer.Add(item = self.fidText, proportion = 0,
+                     flag = wx.EXPAND | wx.ALL,  border = 5)
+        mainSizer.Add(item = fidSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
         
         self.SetSizer(mainSizer)
         mainSizer.Fit(self)
@@ -2144,9 +1062,9 @@
             self.popupID1 = wx.NewId()
             self.popupID2 = wx.NewId()
             self.popupID3 = wx.NewId()
-            self.Bind(wx.EVT_MENU, self.OnItemDelete,    id=self.popupID1)
-            self.Bind(wx.EVT_MENU, self.OnItemDeleteAll, id=self.popupID2)
-            self.Bind(wx.EVT_MENU, self.OnReload, id=self.popupID3)
+            self.Bind(wx.EVT_MENU, self.OnItemDelete,    id = self.popupID1)
+            self.Bind(wx.EVT_MENU, self.OnItemDeleteAll, id = self.popupID2)
+            self.Bind(wx.EVT_MENU, self.OnReload, id = self.popupID3)
 
         # generate popup-menu
         menu = wx.Menu()
@@ -2190,7 +1108,7 @@
         self.fid = int(event.GetString())
         
         self.itemDataMap = self.list.Populate(self.cats[self.fid],
-                                              update=True)
+                                              update = True)
 
         try:
             newCat = max(self.cats[self.fid][1]) + 1
@@ -2238,7 +1156,7 @@
 
         # polulate list
         self.itemDataMap = self.list.Populate(self.cats[self.fid],
-                                              update=True)
+                                              update = True)
 
         event.Skip()
 
@@ -2247,7 +1165,7 @@
         self.parent.parent.dialogs['category'] = None
         if self.parent.parent.digit:
             self.parent.parent.digit.driver.SetSelected([])
-            self.parent.UpdateMap(render=False)
+            self.parent.UpdateMap(render = False)
         else:
             self.parent.parent.OnRender(None)
             
@@ -2299,8 +1217,8 @@
                     
                     fid = newfid
                     if self.fid < 0:
-                        wx.MessageBox(parent=self, message=_("Unable to update vector map."),
-                                      caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
+                        wx.MessageBox(parent = self, message = _("Unable to update vector map."),
+                                      caption = _("Error"), style = wx.OK | wx.ICON_ERROR)
         
         self.cats_orig[fid] = copy.deepcopy(cats)
         
@@ -2336,7 +1254,7 @@
 
         # reload list
         self.itemDataMap = self.list.Populate(self.cats[self.fid],
-                                              update=True)
+                                              update = True)
 
         # update category number for add
         self.catNew.SetValue(cat + 1)
@@ -2349,7 +1267,7 @@
         """!Get id of selected line of 'None' if no line is selected"""
         return self.cats.keys()
 
-    def UpdateDialog(self, query=None, cats=None):
+    def UpdateDialog(self, query = None, cats = None):
         """!Update dialog
         
         @param query {coordinates, distance} - v.edit/v.what
@@ -2377,7 +1295,7 @@
         # polulate list
         self.fid = self.cats.keys()[0]
         self.itemDataMap = self.list.Populate(self.cats[self.fid],
-                                              update=True)
+                                              update = True)
 
         try:
             newCat = max(self.cats[self.fid][1]) + 1
@@ -2405,11 +1323,9 @@
 class CategoryListCtrl(wx.ListCtrl,
                        listmix.ListCtrlAutoWidthMixin,
                        listmix.TextEditMixin):
-    """!List of layers/categories"""
-
-    def __init__(self, parent, id, pos=wx.DefaultPosition,
-                 size=wx.DefaultSize, style=0):
-        
+    def __init__(self, parent, id, pos = wx.DefaultPosition,
+                 size = wx.DefaultSize, style = 0):
+        """!List of layers/categories"""
         self.parent = parent
         
         wx.ListCtrl.__init__(self, parent, id, pos, size, style)
@@ -2417,9 +1333,8 @@
         listmix.ListCtrlAutoWidthMixin.__init__(self)
         listmix.TextEditMixin.__init__(self)
 
-    def Populate(self, cats, update=False):
+    def Populate(self, cats, update = False):
         """!Populate the list"""
-
         itemData = {} # requested by sorter
 
         if not update:
@@ -2448,11 +1363,10 @@
         return itemData
 
 class VDigitZBulkDialog(wx.Dialog):
-    """
-    Dialog used for Z bulk-labeling tool
-    """
-    def __init__(self, parent, title, nselected, style=wx.DEFAULT_DIALOG_STYLE):
-        wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title, style=style)
+    def __init__(self, parent, title, nselected, style = wx.DEFAULT_DIALOG_STYLE):
+        """!Dialog used for Z bulk-labeling tool
+        """
+        wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style)
 
         self.parent = parent # mapdisplay.BufferedWindow class instance
 
@@ -2460,35 +1374,35 @@
 
         border = wx.BoxSizer(wx.VERTICAL)
         
-        txt = wx.StaticText(parent=self,
-                            label=_("%d lines selected for z bulk-labeling") % nselected);
-        border.Add(item=txt, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
+        txt = wx.StaticText(parent = self,
+                            label = _("%d lines selected for z bulk-labeling") % nselected);
+        border.Add(item = txt, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
 
-        box   = wx.StaticBox (parent=self, id=wx.ID_ANY, label=" %s " % _("Set value"))
+        box   = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Set value"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        flexSizer = wx.FlexGridSizer (cols=2, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
 
         # starting value
-        txt = wx.StaticText(parent=self,
-                            label=_("Starting value"));
-        self.value = wx.SpinCtrl(parent=self, id=wx.ID_ANY, size=(150, -1),
-                                 initial=0,
-                                 min=-1e6, max=1e6)
-        flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.value, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        txt = wx.StaticText(parent = self,
+                            label = _("Starting value"));
+        self.value = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (150, -1),
+                                 initial = 0,
+                                 min = -1e6, max = 1e6)
+        flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.value, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
 
         # step
-        txt = wx.StaticText(parent=self,
-                            label=_("Step"))
-        self.step  = wx.SpinCtrl(parent=self, id=wx.ID_ANY, size=(150, -1),
-                                 initial=0,
-                                 min=0, max=1e6)
-        flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.step, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        txt = wx.StaticText(parent = self,
+                            label = _("Step"))
+        self.step  = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (150, -1),
+                                 initial = 0,
+                                 min = 0, max = 1e6)
+        flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.step, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
 
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=0)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 0)
 
         # buttons
         btnCancel = wx.Button(self, wx.ID_CANCEL)
@@ -2502,23 +1416,21 @@
         btnSizer.Realize()
         
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=border, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        mainSizer.Add(item = border, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
 
         self.SetSizer(mainSizer)
         mainSizer.Fit(self)
 
 class VDigitDuplicatesDialog(wx.Dialog):
-    """
-    Show duplicated feature ids
-    """
-    def __init__(self, parent, data, title=_("List of duplicates"),
-                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
-                 pos=wx.DefaultPosition):
-
-        wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title, style=style,
-                           pos=pos)
+    def __init__(self, parent, data, title = _("List of duplicates"),
+                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+                 pos = wx.DefaultPosition):
+        """!Show duplicated feature ids
+        """
+        wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style,
+                           pos = pos)
         
         self.parent = parent # BufferedWindow
         self.data = data
@@ -2527,21 +1439,21 @@
         # panel  = wx.Panel(parent=self, id=wx.ID_ANY)
 
         # notebook
-        self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
+        self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
 
         id = 1
         for key in self.data.keys():
-            panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
-            self.notebook.AddPage(page=panel, text=" %d " % (id))
+            panel = wx.Panel(parent = self.notebook, id = wx.ID_ANY)
+            self.notebook.AddPage(page = panel, text = " %d " % (id))
             
             # notebook body
             border = wx.BoxSizer(wx.VERTICAL)
 
-            win = CheckListFeature(parent=panel, data=list(self.data[key]))
+            win = CheckListFeature(parent = panel, data = list(self.data[key]))
             self.winList.append(win.GetId())
 
-            border.Add(item=win, proportion=1,
-                       flag=wx.ALL | wx.EXPAND, border=5)
+            border.Add(item = win, proportion = 1,
+                       flag = wx.ALL | wx.EXPAND, border = 5)
 
             panel.SetSizer(border)
 
@@ -2559,9 +1471,9 @@
         btnSizer.Realize()
         
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=self.notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        mainSizer.Add(item = self.notebook, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
 
         self.SetSizer(mainSizer)
         mainSizer.Fit(self)
@@ -2586,14 +1498,14 @@
         return ids
 
 class CheckListFeature(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin):
-    """!List of mapset/owner/group"""
     def __init__(self, parent, data,
-                 pos=wx.DefaultPosition, log=None):
+                 pos = wx.DefaultPosition, log = None):
+        """!List of mapset/owner/group"""
         self.parent = parent
         self.data = data
 
         wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
-                             style=wx.LC_REPORT)
+                             style = wx.LC_REPORT)
 
         listmix.CheckListCtrlMixin.__init__(self)
 
@@ -2617,8 +1529,8 @@
         for item in range(self.GetItemCount()):
             self.CheckItem(item, True)
 
-        self.SetColumnWidth(col=0, width=wx.LIST_AUTOSIZE_USEHEADER)
-        self.SetColumnWidth(col=1, width=wx.LIST_AUTOSIZE_USEHEADER)
+        self.SetColumnWidth(col = 0, width = wx.LIST_AUTOSIZE_USEHEADER)
+        self.SetColumnWidth(col = 1, width = wx.LIST_AUTOSIZE_USEHEADER)
                 
     def OnCheckItem(self, index, flag):
         """!Mapset checked/unchecked"""

Added: grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxvdigit.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/gui_modules/wxvdigit.py	2011-01-01 19:26:54 UTC (rev 44823)
@@ -0,0 +1,798 @@
+"""!
+ at package wxvdigit.py
+
+ at brief wxGUI vector digitizer (base class)
+
+Code based on wxVdigit C++ component from GRASS 6.4.0. Converted to
+Python in 2010/12-2011/01.
+
+List of classes:
+ - IVDigit
+
+(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>
+"""
+
+from debug       import Debug
+from preferences import globalSettings as UserSettings
+
+from wxvdriver import DisplayDriver
+
+from grass.lib.grass  import *
+from grass.lib.vector import *
+
+class IVDigit:
+    def __init__(self, mapwindow):
+        self.map       = None
+        self.mapWindow = mapwindow
+        
+        if not mapwindow.parent.IsStandalone():
+            self.log = mapwindow.parent.GetLayerManager().goutput.cmd_stderr
+        else:
+            self.log = sys.stderr
+        
+        self.toolbar = mapwindow.parent.toolbars['vdigit']
+        
+        self._display = DisplayDriver(device    = mapwindow.pdcVector,
+                                      deviceTmp = mapwindow.pdcTmp,
+                                      mapObj    = mapwindow.Map,
+                                      log       = self.log)
+        
+        # self.SetCategory()
+        
+        # layer / max category
+        self.cats = dict()
+        # settings
+        self._settings = {
+            'breakLines'  : None,
+            'addCentroid' : None,
+            'catBoundary' : None
+            }
+        # undo/redo
+        self.changesets = dict()
+        self.changesetCurrent = None # first changeset to apply
+        self.changesetEnd     = None # last changeset to be applied
+        
+        if self._display.mapInfo:
+            self.InitCats()
+        
+        # initial value for undo/redo
+        self.changesetEnd = self.changesetCurrent = -1
+        
+    def __del__(self):
+        pass # free changesets ?
+
+    def _setCategory(self):
+        pass
+    
+    def _openBackgroundVectorMap(self):
+        pass
+
+    def _breakLineAtIntersection(self):
+        pass
+    
+    def _addActionsBefore(self):
+        """!Register action before operation
+  
+        @return changeset id
+        """
+        pass
+    
+    def _addActionsAfter(self):
+        pass
+
+    def _addActionToChangeset(self):
+        pass
+
+    def _applyChangeset(self):
+        pass
+
+    def _freeChangeset(self):
+        pass
+
+    def _removeActionFromChangeset(self):
+        pass
+
+    def AddPoint (self, map, point, x, y, z=None):
+        """!Add new point/centroid
+
+        @param map   map name (unused, for compatability with VEdit)
+        @param point feature type (if true point otherwise centroid)
+        @param x,y,z coordinates
+        """
+        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
+            layer = -1 # -> no category
+            cat   = -1
+        else:
+            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
+            cat   = self.SetCategory()
+            
+        if point:
+            type = wxvdigit.GV_POINT 
+        else:
+            type = wxvdigit.GV_CENTROID 
+
+        snap, thresh = self.__getSnapThreshold()
+
+        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
+                                     subkey='value', internal=True))
+        if z:
+            ret = self.digit.AddLine(type, [x, y, z], layer, cat,
+                                     bgmap, snap, thresh)
+        else:
+            ret = self.digit.AddLine(type, [x, y], layer, cat,
+                                     bgmap, snap, thresh)
+        self.toolbar.EnableUndo()
+
+        return ret
+        
+    def AddLine (self, map, line, coords):
+        """!Add line/boundary
+
+        @param map    map name (unused, for compatability with VEdit)
+        @param line   feature type (if True line, otherwise boundary)
+        @param coords list of coordinates
+        """
+        if len(coords) < 2:
+            return
+        
+        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
+            layer = -1 # -> no category
+            cat   = -1
+        else:
+            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
+            cat   = self.SetCategory()
+        
+        if line:
+            type = wxvdigit.GV_LINE
+        else:
+            type = wxvdigit.GV_BOUNDARY
+        
+        listCoords = []
+        for c in coords:
+            for x in c:
+                listCoords.append(x)
+        
+        snap, thresh = self.__getSnapThreshold()
+        
+        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
+                                     subkey='value', internal=True))
+        
+        ret = self.digit.AddLine(type, listCoords, layer, cat,
+                                 bgmap, snap, thresh)
+
+        self.toolbar.EnableUndo()
+        
+        return ret
+    
+    def DeleteSelectedLines(self):
+        """!Delete selected features
+
+        @return number of deleted lines
+        """
+        nlines = self.digit.DeleteLines(UserSettings.Get(group='vdigit', key='delRecord', subkey='enabled'))
+        
+        if nlines > 0:
+            self.toolbar.EnableUndo()
+            
+        return nlines
+
+    def MoveSelectedLines(self, move):
+        """!Move selected features
+
+        @param move direction (x, y)
+        """
+        snap, thresh = self.__getSnapThreshold()
+        
+        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
+                                     subkey='value', internal=True))
+        
+        try:
+            nlines = self.digit.MoveLines(move[0], move[1], 0.0, # TODO 3D
+                                          bgmap, snap, thresh)
+        except SystemExit:
+            pass
+        
+        if nlines > 0:
+            self.toolbar.EnableUndo()
+        
+        return nlines
+
+    def MoveSelectedVertex(self, coords, move):
+        """!Move selected vertex of the line
+
+        @param coords click coordinates
+        @param move   X,Y direction
+
+        @return id of new feature
+        @return 0 vertex not moved (not found, line is not selected)
+        """
+        snap, thresh = self.__getSnapThreshold()
+
+        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
+                                     subkey='value', internal=True))
+        
+        moved = self.digit.MoveVertex(coords[0], coords[1], 0.0, # TODO 3D
+                                      move[0], move[1], 0.0,
+                                      bgmap, snap,
+                                      self.driver.GetThreshold(type='selectThresh'), thresh)
+
+        if moved:
+            self.toolbar.EnableUndo()
+
+        return moved
+
+    def AddVertex(self, coords):
+        """!Add new vertex to the selected line/boundary on position 'coords'
+
+        @param coords coordinates to add vertex
+
+        @return id of new feature
+        @return 0 nothing changed
+        @return -1 on failure
+        """
+        added = self.digit.ModifyLineVertex(1, coords[0], coords[1], 0.0, # TODO 3D
+                                            self.driver.GetThreshold(type='selectThresh'))
+
+        if added > 0:
+            self.toolbar.EnableUndo()
+
+        return added
+
+    def RemoveVertex(self, coords):
+        """!Remove vertex from the selected line/boundary on position 'coords'
+
+        @param coords coordinates to remove vertex
+
+        @return id of new feature
+        @return 0 nothing changed
+        @return -1 on failure
+        """
+        deleted = self.digit.ModifyLineVertex(0, coords[0], coords[1], 0.0, # TODO 3D
+                                              self.driver.GetThreshold(type='selectThresh'))
+
+        if deleted > 0:
+            self.toolbar.EnableUndo()
+
+        return deleted
+
+
+    def SplitLine(self, coords):
+        """!Split selected line/boundary on position 'coords'
+
+        @param coords coordinates to split line
+
+        @return 1 line modified
+        @return 0 nothing changed
+        @return -1 error
+        """
+        ret = self.digit.SplitLine(coords[0], coords[1], 0.0, # TODO 3D
+                                   self.driver.GetThreshold('selectThresh'))
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def EditLine(self, line, coords):
+        """!Edit existing line/boundary
+
+        @param line id of line to be modified
+        @param coords list of coordinates of modified line
+
+        @return feature id of new line
+        @return -1 on error
+        """
+        try:
+            lineid = line[0]
+        except:
+            lineid = -1
+
+        if len(coords) < 2:
+            self.DeleteSelectedLines()
+            return 0
+            
+        listCoords = []
+        for c in coords:
+            for x in c:
+                listCoords.append(x)
+
+        snap, thresh = self.__getSnapThreshold()
+        
+        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
+                                     subkey='value', internal=True))
+        
+        try:
+            ret = self.digit.RewriteLine(lineid, listCoords,
+                                         bgmap, snap, thresh)
+        except SystemExit:
+            pass
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def FlipLine(self):
+        """!Flip selected lines/boundaries
+
+        @return number of modified lines
+        @return -1 on error
+        """
+        ret = self.digit.FlipLines()
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def MergeLine(self):
+        """!Merge selected lines/boundaries
+
+        @return number of modified lines
+        @return -1 on error
+        """
+        ret = self.digit.MergeLines()
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def BreakLine(self):
+        """!Break selected lines/boundaries
+
+        @return number of modified lines
+        @return -1 on error
+        """
+        ret = self.digit.BreakLines()
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def SnapLine(self):
+        """!Snap selected lines/boundaries
+
+        @return on success
+        @return -1 on error
+        """
+        snap, thresh = self.__getSnapThreshold()
+        ret = self.digit.SnapLines(thresh)
+        
+        if ret == 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def ConnectLine(self):
+        """!Connect selected lines/boundaries
+
+        @return 1 lines connected
+        @return 0 lines not connected
+        @return -1 on error
+        """
+        snap, thresh = self.__getSnapThreshold()
+        ret = self.digit.ConnectLines(thresh)
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+        
+    def CopyLine(self, ids=[]):
+        """!Copy features from (background) vector map
+
+        @param ids list of line ids to be copied
+
+        @return number of copied features
+        @return -1 on error
+        """
+        bgmap = str(UserSettings.Get(group='vdigit', key='bgmap',
+                                     subkey='value', internal=True))
+        
+        if len(bgmap) > 0:
+            ret = self.digit.CopyLines(ids, bgmap)
+        else:
+            ret = self.digit.CopyLines(ids, None)
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def CopyCats(self, fromId, toId, copyAttrb=False):
+        """!Copy given categories to objects with id listed in ids
+
+        @param cats ids of 'from' feature
+        @param ids  ids of 'to' feature(s)
+
+        @return number of modified features
+        @return -1 on error
+        """
+        if len(fromId) == 0 or len(toId) == 0:
+            return 0
+        
+        ret = self.digit.CopyCats(fromId, toId, copyAttrb)
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def SelectLinesByQuery(self, pos1, pos2):
+        """!Select features by query
+
+        @param pos1, pos2 bounding box definition
+        """
+        thresh = self.SelectLinesByQueryThresh()
+        
+        w, n = pos1
+        e, s = pos2
+
+        query = wxvdigit.QUERY_UNKNOWN
+        if UserSettings.Get(group='vdigit', key='query', subkey='selection') == 0:
+            query = wxvdigit.QUERY_LENGTH
+        else:
+            query = wxvdigit.QUERY_DANGLE
+
+        type = wxvdigit.GV_POINTS | wxvdigit.GV_LINES # TODO: 3D
+        
+        ids = self.digit.SelectLinesByQuery(w, n, 0.0, e, s, 1000.0,
+                                            UserSettings.Get(group='vdigit', key='query', subkey='box'),
+                                            query, type, thresh)
+
+        Debug.msg(4, "VDigit.SelectLinesByQuery(): %s" % \
+                      ",".join(["%d" % v for v in ids]))
+        
+        return ids
+
+    def GetLineCats(self, line=-1):
+        """!Get layer/category pairs from given (selected) line
+        
+        @param line feature id (-1 for first selected line)
+        """
+        return dict(self.digit.GetLineCats(line))
+
+    def GetLineLength(self, line):
+        """!Get line length
+
+        @param line feature id
+
+        @return line length
+        @return -1 on error
+        """
+        return self.digit.GetLineLength(line)
+
+    def GetAreaSize(self, centroid):
+        """!Get area size
+
+        @param centroid centroid id
+
+        @return area size
+        @return -1 on error
+        """
+        return self.digit.GetAreaSize(centroid)
+        
+    def GetAreaPerimeter(self, centroid):
+        """!Get area perimeter
+
+        @param centroid centroid id
+
+        @return area size
+        @return -1 on error
+        """
+        return self.digit.GetAreaPerimeter(centroid)
+
+    def SetLineCats(self, line, layer, cats, add=True):
+        """!Set categories for given line and layer
+
+        @param line feature id
+        @param layer layer number (-1 for first selected line)
+        @param cats list of categories
+        @param add if True to add, otherwise do delete categories
+
+        @return new feature id (feature need to be rewritten)
+        @return -1 on error
+        """
+        ret = self.digit.SetLineCats(line, layer, cats, add)
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def GetLayers(self):
+        """!Get list of layers"""
+        return self.digit.GetLayers()
+
+    def TypeConvForSelectedLines(self):
+        """!Feature type conversion for selected objects.
+
+        Supported conversions:
+         - point <-> centroid
+         - line <-> boundary
+
+        @return number of modified features
+        @return -1 on error
+        """
+        ret = self.digit.TypeConvLines()
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def Undo(self, level=-1):
+        """!Undo action
+
+        @param level levels to undo (0 to revert all)
+
+        @return id of current changeset
+        """
+        try:
+            ret = self.digit.Undo(level)
+        except SystemExit:
+            ret = -2
+
+        if ret == -2:
+            raise gcmd.GException(_("Undo failed, data corrupted."))
+
+        self.mapWindow.UpdateMap(render=False)
+        
+        if ret < 0: # disable undo tool
+            self.toolbar.EnableUndo(False)
+
+    def ZBulkLines(self, pos1, pos2, start, step):
+        """!Z-bulk labeling
+
+        @param pos1 reference line (start point)
+        @param pos1 reference line (end point)
+        @param start starting value
+        @param step step value
+
+        @return number of modified lines
+        @return -1 on error
+        """
+        ret = self.digit.ZBulkLabeling(pos1[0], pos1[1], pos2[0], pos2[1],
+                                       start, step)
+        
+        if ret > 0:
+            self.toolbar.EnableUndo()
+        
+        return ret
+    
+    def __getSnapThreshold(self):
+        """!Get snap mode and threshold value
+
+        @return (snap, thresh)
+        """
+        thresh = self.driver.GetThreshold()
+
+        if thresh > 0.0:
+            if UserSettings.Get(group='vdigit', key='snapToVertex', subkey='enabled') is True:
+                snap = wxvdigit.SNAPVERTEX
+            else:
+                snap = wxvdigit.SNAP
+        else:
+            snap = wxvdigit.NO_SNAP
+
+        return (snap, thresh)
+
+    def GetDisplay(self):
+        """!Get display driver instance"""
+        return self._display
+    
+    def OpenMap(self, name):
+        """!Open vector map for editing
+        
+        @param map name of vector map to be set up
+        """
+        Debug.msg (3, "AbstractDigit.SetMapName map=%s" % name)
+        self.map = name
+        
+        name, mapset = name.split('@')
+        try:
+            ret = self._display.OpenMap(str(name), str(mapset), True)
+        except SystemExit:
+                ret = -1
+        
+        # except StandardError, e:
+        #     raise gcmd.GException(_("Unable to initialize display driver of vector "
+        #                             "digitizer. See 'Command output' for details.\n\n"
+        #                             "Details: ") + repr(e))
+        
+        # if map and ret == -1:
+        #     raise gcmd.GException(_('Unable to open vector map <%s> for editing.\n\n'
+        #                             'Data are probably corrupted, '
+        #                             'try to run v.build to rebuild '
+        #                             'the topology (Vector->Develop vector map->'
+        #                             'Create/rebuild topology).') % map)
+        # if not map and ret != 0:
+        #     raise gcmd.GException(_('Unable to open vector map <%s> for editing.\n\n'
+        #                             'Data are probably corrupted, '
+        #                             'try to run v.build to rebuild '
+        #                             'the topology (Vector->Develop vector map->'
+        #                             'Create/rebuild topology).') % map)
+        
+        self.InitCats()
+
+    def CloseMap(self):
+        """!Close currently open vector map
+        """
+        if not self.map:
+            return
+        
+        self._display.CloseMap()
+
+    def InitCats(self):
+        """!Initialize categories information
+        
+        @return 0 on success
+        @return -1 on error
+        """
+        self.cats.clear()
+        mapInfo = self._display.mapInfo
+        if not mapInfo:
+            return -1
+        
+        ndblinks = Vect_get_num_dblinks(byref(mapInfo))
+        for i in range(ndblinks):
+            fi = Vect_get_dblink(byref(mapInfo), i).contents
+            if fi:
+                self.cats[fi.number] = None
+        
+        # find max category
+        nfields = Vect_cidx_get_num_fields(byref(mapInfo))
+        Debug.msg(2, "wxDigit.InitCats(): nfields=%d", nfields)
+        
+        for i in range(nfields):
+            field = Vect_cidx_get_field_number(byref(mapInfo), i)
+            ncats = Vect_cidx_get_num_cats_by_index(byref(mapInfo), i)
+            if field <= 0:
+                continue
+            for j in range(ncats):
+                cat = c_int()
+                type = c_int()
+                id = c_int()
+                Vect_cidx_get_cat_by_index(byref(mapInfo), i, j,
+                                           byref(cat), byref(type), byref(id))
+                if self.cats.has_key(field):
+                    if cat > self.cats[field]:
+                        self.cats[field] = cat.value
+                else:
+                    self.cats[field] = cat.value
+            Debug.msg(3, "wxDigit.InitCats(): layer=%d, cat=%d", field, self.cats[field])
+            
+        # set default values
+        for field, cat in self.cats.iteritems():
+            if cat == None:
+                self.cats[field] = 0 # first category 1
+	    Debug.msg(3, "wxDigit.InitCats(): layer=%d, cat=%d", field, self.cats[field])
+        
+    def AddLine(self):
+        pass
+
+    def RewriteLine(self):
+        pass
+    
+    def SplitLine(self):
+        pass
+
+    def DeleteLines(self):
+        pass
+
+    def MoveLines(self):
+        pass
+
+    def FlipLines(self):
+        pass
+
+    def MergeLines(self):
+        pass
+
+    def BreakLines(self):
+        pass
+
+    def SnapLines(self):
+        pass
+
+    def ConnectLines(self):
+        pass
+
+    def TypeConvLines(self):
+        pass
+
+    def ZBulkLabeling(self):
+        pass
+
+    def CopyLines(self):
+        pass
+
+    def MoveVertex(self):
+        pass
+
+    def ModifyLineVertex(self):
+        pass
+
+    def SelectLinesByQuery(self):
+        pass
+
+    def GetLineLength(self):
+        pass
+
+    def GetAreaSize(self):
+        pass
+
+    def GetAreaPerimeter(self):
+        pass
+
+    def CopyCats(self):
+        pass
+
+    def GetCategory(self, layer):
+        """!Get max category number for layer
+        
+        @param layer layer number
+        
+        @return category number (0 if no category found)
+        @return -1 on error
+        """
+        if cats.find(layer) != cats.end():
+            Debug.msg(3, "vdigit.GetCategory(): layer=%d, cat=%d", layer, cats[layer])
+            return cats[layer]
+        
+        return 0
+    
+    def GetLineCats(self):
+        pass
+
+    def SetLineCats(self):
+        pass
+    
+    def GetLayers(self):
+        pass
+    
+    def Undo(self):
+        pass
+
+    def GetUndoLevel(self):
+        pass
+
+    def UpdateSettings(self, breakLines, addCentroid, catBoundary):
+        """!Update digit settings
+        
+        @param breakLines break lines on intersection
+        @param addCentroid add centroid to left/right area
+        @param catBoundary attach category to boundary
+        """
+        self._settings['breakLines']  = breakLines
+        self._settings['addCentroid'] = addCentroid
+        self._settings['catBoundary'] = None # !catBoundary # do not attach
+
+    def SetCategory(self):
+        """!Return category number to use (according Settings)"""
+        if not UserSettings.Get(group = 'vdigit', key = 'categoryMode', subkey = 'selection'):
+            self.SetCategoryNextToUse()
+        
+        return UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value')
+
+    def SetCategoryNextToUse(self):
+        """!Find maximum category number in the map layer
+        and update Digit.settings['category']
+
+        @return 'True' on success, 'False' on failure
+        """
+        # vector map layer without categories, reset to '1'
+        UserSettings.Set(group = 'vdigit', key = 'category', subkey = 'value', value = 1)
+        
+        if self.map:
+            cat = self.GetCategory(UserSettings.Get(group = 'vdigit', key = 'layer', subkey = 'value'))
+            cat += 1
+            UserSettings.Set(group = 'vdigit', key = 'category', subkey = 'value',
+                             value = cat)


Property changes on: grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxvdriver.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/gui_modules/wxvdriver.py	2011-01-01 19:26:54 UTC (rev 44823)
@@ -0,0 +1,567 @@
+"""!
+ at package wxvdriver.py
+
+ at brief wxGUI vector digitizer (display driver)
+
+Code based on wxVdigit C++ component from GRASS 6.4.0. Converted to
+Python in 2010/12-2011/01.
+
+List of classes:
+ - DisplayDriver
+
+(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>
+"""
+
+import math
+
+import wx
+
+from debug import Debug as Debug
+from preferences import globalSettings as UserSettings
+
+from grass.lib.grass  import *
+from grass.lib.vector import *
+from grass.lib.vedit  import *
+
+class DisplayDriver:
+    def __init__(self, device, deviceTmp, mapObj, log = None):
+        """Display driver used by vector digitizer
+        
+        @param device    wx.PseudoDC device where to draw vector objects
+        @param deviceTmp wx.PseudoDC device where to draw temporary vector objects
+        """
+        G_gisinit("")             # initialize GRASS libs
+        
+        self.mapInfo = None       # open vector map (Map_Info structure)
+        self.dc      = device     # PseudoDC devices
+        self.dcTmp   = deviceTmp
+        self.mapObj  = mapObj
+        self.region  = mapObj.GetCurrentRegion()
+        self.log     = log        # log device
+        
+        # objects used by GRASS vector library
+        self.points       = line_pnts()
+        self.pointsScreen = list()
+        self.cats         = line_cats()
+        
+        # selected objects
+        self.selected = {
+            'field'   : -1,      # field number
+            'cats'    : list(),  # list of cats
+            'ids'     : list(),  # list of ids
+            'idsDupl' : list(),  # list of duplicated features
+            }
+        
+        # digitizer settings
+        self.settings = {
+            'highlight'     : None,
+            'highlightDupl' : { 'enabled' : False,
+                                'color'   : None },
+            'point'         : { 'enabled' : False,
+                                'color'   : None },
+            'line'          : { 'enabled' : False,
+                                'color'   : None },
+            'boundaryNo'    : { 'enabled' : False,
+                                'color'   : None },
+            'boundaryOne'   : { 'enabled' : False,
+                                'color'   : None },
+            'boundaryTwo'   : { 'enabled' : False,
+                                'color'   : None },
+            'centroidIn'    : { 'enabled' : False,
+                                'color'   : None },
+            'centroidOut'   : { 'enabled' : False,
+                                'color'   : None },
+            'centroidDup'   : { 'enabled' : False,
+                                'color'   : None },
+            'nodeOne'       : { 'enabled' : False,
+                                'color'   : None },
+            'nodeTwo'       : { 'enabled' : False,
+                                'color'   : None },
+            'vertex'        : { 'enabled' : False,
+                                'color'   : None },
+            'area'          : { 'enabled' : False,
+                                'color'   : None },
+            'direction'     : { 'enabled' : False,
+                                'color'   : None },
+            'lineWidth'     : -1,    # screen units 
+            }
+        
+        # topology
+        self.topology = {
+            'highlight'   : 0,
+            'point'       : 0,
+            'line'        : 0,
+            'boundaryNo'  : 0,
+            'boundaryOne' : 0,
+            'boundaryTwo' : 0,
+            'centroidIn'  : 0,
+            'centroidOut' : 0,
+            'centroidDup' : 0,
+            'nodeOne'     : 0,
+            'nodeTwo'     : 0,
+            'vertex'      : 0,
+            }
+        
+        self.drawSelected = None
+        self.drawSegments = False
+
+        self.UpdateSettings()
+        
+    # def __del__(self):
+    #     """!Close currently open vector map"""
+    #     if self.mapInfo:
+    #         self.CloseMap()
+    
+    def _cell2Pixel(self, east, north, elev):
+        """!Conversion from geographic coordinates (east, north)
+        to screen (x, y)
+  
+        @todo 3D stuff...
+
+        @param east, north, elev geographical coordinates
+
+        @return x, y screen coordinates (integer)
+        """
+        map_res = max(self.region['ewres'], self.region['nsres'])
+        w = self.region['center_easting']  - (self.mapObj.width  / 2) * map_res
+        n = self.region['center_northing'] + (self.mapObj.height / 2) * map_res
+        
+        return int((east - w) / map_res), int((n - north) / map_res)
+    
+    def _drawCross(self, pdc, point, size = 5):
+        """!Draw cross symbol of given size to device content
+   
+        Used for points, nodes, vertices
+
+        @param[in,out] PseudoDC where to draw
+        @param point coordinates of center
+        @param size size of the cross symbol
+   
+        @return 0 on success
+        @return -1 on failure
+        """
+        if not pdc or not point:
+            return -1;
+        
+        pdc.DrawLine(point.x - size, point.y, point.x + size, point.y)
+        pdc.DrawLine(point.x, point.y - size, point.x, point.y + size)
+        
+        return 0
+    
+    def _drawObject(self, robj):
+        """!Draw given object to the device
+        
+        The object is defined as robject() from vedit.h.
+        
+        @param robj object to be rendered
+        
+        @return  1 on success
+        @return -1 on failure (vector feature marked as dead, etc.)
+        """
+        if not self.dc or not self.dcTmp:
+            return -1
+        
+        dcId = 0
+        pdc = self.dc
+        # draw object to the device
+        pdc.SetId(dcId) # 0 | 1 (selected)
+        
+        Debug.msg(3, "_drawObject(): type=%d npoints=%d", robj.type, robj.npoints)
+        points = list() 
+        self._setPen(robj.type, pdc)
+        
+        for i in range(robj.npoints):
+            p = robj.point[i]
+
+            if robj.type & (TYPE_POINT | TYPE_CENTROIDIN | TYPE_CENTROIDOUT | TYPE_CENTROIDDUP |
+                            TYPE_NODEONE | TYPE_NODETWO | TYPE_VERTEX): # -> point
+                self._drawCross(pdc, p)
+            else: # -> line
+                # if dcId > 0 and self.drawSegments:
+                #     dcId = 2 # first segment
+                #     i = 0
+                #     while (i < len(self.pointsScreen) - 2):
+                #         point_beg = wx.Point(self.pointsScreen[i])
+                #         point_end = wx.Point(self.pointsScreen[i + 1])
+                        
+                #         pdc.SetId(dcId) # set unique id & set bbox for each segment
+                #         pdc.SetPen(pen)
+                #         rect = wx.Rect(point_beg, point_end)
+                #         pdc.SetIdBounds(dcId, rect)
+                #         pdc.DrawLine(point_beg.x, point_beg.y,
+                #                      point_end.x, point_end.y)
+                #         i    += 2
+                #         dcId += 2
+                # else:
+                points.append(wx.Point(p.x, p.y))
+        
+        if points:
+            if robj.type == TYPE_AREA:
+                pdc.DrawPolygon(points)
+            else:
+                pdc.DrawLines(points)
+        
+    def _setPen(self, rtype, pdc):
+        """!Set pen/brush based on rendered object)
+        
+        Updates also self.topology dict
+        """
+        if rtype == TYPE_POINT:
+            key = 'point'
+        elif rtype == TYPE_LINE:
+            key = 'line'
+        elif rtype == TYPE_BOUNDARYNO:
+            key = 'boundaryNo'
+        elif rtype == TYPE_BOUNDARYTWO:
+            key = 'boundaryTwo'
+        elif rtype == TYPE_BOUNDARYONE:
+            key = 'boundaryOne'
+        elif rtype == TYPE_CENTROIDIN:
+            key = 'centroidIn'
+        elif rtype == TYPE_CENTROIDOUT:
+            key = 'centroidOut'
+        elif rtype == TYPE_CENTROIDDUP:
+            key = 'centroidDup'
+        elif rtype == TYPE_NODEONE:
+            key = 'nodeOne'
+        elif rtype == TYPE_NODETWO:
+            key = 'nodeTwo'
+        elif rtype == TYPE_VERTEX:
+            key = 'vertex'
+        elif rtype == TYPE_AREA:
+            key = 'area' 
+        elif rtype == TYPE_ISLE:
+            key = 'isle'
+        elif rtype == TYPE_DIRECTION:
+            key = 'direction'
+        
+        if key not in ('direction', 'area', 'isle'):
+            self.topology[key] += 1
+        
+        if key in ('area', 'isle'):
+            pen = wx.TRANSPARENT_PEN
+            if key == 'area':
+                pdc.SetBrush(wx.Brush(self.settings[key]['color'], wx.SOLID))
+            else:
+                pdc.SetBrush(wx.TRANSPARENT_BRUSH)
+        else:
+            pdc.SetPen(wx.Pen(self.settings[key]['color'], self.settings['lineWidth'], wx.SOLID))
+        
+    def _getDrawFlag(self):
+        """!Get draw flag from the settings
+
+        See vedit.h for list of draw flags.
+        
+        @return draw flag (int)
+        """
+        ret = 0
+        if self.settings['point']['enabled']:
+            ret |= TYPE_POINT
+        if self.settings['line']['enabled']:
+            ret |= TYPE_LINE
+        if self.settings['boundaryNo']['enabled']:
+            ret |= TYPE_BOUNDARYNO
+        if self.settings['boundaryTwo']['enabled']:
+            ret |= TYPE_BOUNDARYTWO
+        if self.settings['boundaryOne']['enabled']:
+            ret |= TYPE_BOUNDARYONE
+        if self.settings['centroidIn']['enabled']:
+            ret |= TYPE_CENTROIDIN
+        if self.settings['centroidOut']['enabled']:
+            ret |= TYPE_CENTROIDOUT
+        if self.settings['centroidDup']['enabled']:
+            ret |= TYPE_CENTROIDDUP
+        if self.settings['nodeOne']['enabled']:
+            ret |= TYPE_NODEONE
+        if self.settings['nodeTwo']['enabled']:
+            ret |= TYPE_NODETWO
+        if self.settings['vertex']['enabled']:
+            ret |= TYPE_VERTEX
+        if self.settings['area']['enabled']:
+            ret |= TYPE_AREA
+        if self.settings['direction']['enabled']:
+            ret |= TYPE_DIRECTION
+        
+        return ret
+        
+    def _printIds(self):
+        pass
+
+    def _isSelected(self, featId, foo = False):
+        return False
+
+    def _isDuplicated(self, featId):
+        return False
+
+    def _resetTopology(self):
+        pass
+
+    def _getRegionBox(self):
+        """!Get bound_box() from current region
+
+        @return bound_box
+        """
+        box = bound_box()
+        
+        box.N = self.region['n']
+        box.S = self.region['s']
+        box.E = self.region['e']
+        box.W = self.region['w']
+        box.T = PORT_DOUBLE_MAX
+        box.B = -PORT_DOUBLE_MAX
+        
+        return box
+
+    def DrawMap(self, force = False):
+        """!Draw content of the vector map to the device
+        
+        @param force force drawing
+        @return number of drawn features
+        @return -1 on error
+        """
+        Debug.msg(1, "DisplayDriver.DrawMap(): force=%d", force)
+        
+        if not self.mapInfo or not self.dc or not self.dcTmp:
+            return -1
+        
+        rlist = Vedit_render_map(byref(self.mapInfo), byref(self._getRegionBox()), self._getDrawFlag(),
+                                 self.region['center_easting'], self.region['center_northing'],
+                                 self.mapObj.width, self.mapObj.height,
+                                 max(self.region['nsres'], self.region['ewres'])).contents
+        # ResetTopology()
+        
+        self.dc.BeginDrawing()
+        self.dcTmp.BeginDrawing()
+        
+        # draw objects
+        for i in range(rlist.nitems):
+            robj = rlist.item[i].contents
+            self._drawObject(robj)
+        
+        self.dc.EndDrawing()
+        self.dcTmp.EndDrawing()
+        
+        # reset list of selected features by cat 
+        # list of ids - see IsSelected()
+        ### selected.field = -1;
+        ### Vect_reset_list(selected.cats);
+        
+    def SelectLinesByBox(self):
+        pass
+
+    def SelectLineByPoint(self):
+        pass
+
+    def GetSelected(self, grassId = False):
+        """!Get ids of selected objects
+        
+        @param grassId if true return GRASS line ids, false to return PseudoDC ids
+   
+        @return list of ids of selected vector objects
+        """
+        if grassId:
+            # return ListToVector(selected.ids);
+            pass
+
+        dc_ids = list()
+
+        if not self.drawSegments:
+            dc_ids.append(1)
+        else:
+            # only first selected feature
+            # Vect_read_line(byref(self.mapInfo), byref(self.points), None,
+            # self.selected.ids->value[0]);
+            npoints = self.points.n_points
+            # node - segment - vertex - segment - node
+            for i in range(1, 2 * self.points.npoints):
+                dc_ids.append(i)
+        
+        return dc_ids
+
+
+    def GetSelectedCoord(self):
+        pass
+
+    def GetDuplicates(self):
+        pass
+
+    def GetRegionSelected(self):
+        pass
+
+    def SetSelected(self, ids, layer = -1):
+        """!Set selected vector objects
+   
+        @param ids list of feature ids to be set
+        @param layer field number (-1 for ids instead of cats)
+        """
+        if ids:
+            self.drawSelected = True
+        else:
+            self.drawSelected = False
+            return
+
+        if layer > 0:
+            selected.field = layer
+            # VectorToList(selected.cats, id);
+        else:
+            field = -1
+            # VectorToList(selected.ids, id);
+        
+        return 1
+
+    def UnSelect(self):
+        pass
+
+    def GetSelectedVertex(self):
+        pass
+
+    def DrawSelected(self):
+        pass
+    
+    def CloseMap(self):
+        """!Close vector map
+        
+        @return 0 on success
+        @return non-zero on error
+        """
+        ret = 0
+        if self.mapInfo:
+            if self.mapInfo.mode == GV_MODE_RW:
+                # rebuild topology
+                Vect_build_partial(byref(self.mapInfo), GV_BUILD_NONE)
+                Vect_build(byref(self.mapInfo))
+
+            # close map and store topo/cidx
+            ret = Vect_close(byref(self.mapInfo))
+            del self.mapInfo
+            self.mapInfo = None
+        
+        return ret
+    
+    def OpenMap(self, name, mapset, update = True):
+        """!Open vector map by the driver
+        
+        @param name name of vector map to be open
+        @param mapset name of mapset where the vector map lives
+   
+        @return topo level on success
+        @return -1 on error
+        """
+        Debug.msg("DisplayDriver.OpenMap(): name=%s mapset=%s updated=%d",
+                  name, mapset, update)
+        if not self.mapInfo:
+            self.mapInfo = Map_info()
+        
+        # define open level (level 2: topology)
+        Vect_set_open_level(2)
+        
+        # avoid GUI crash when G_fatal_error() is called (opening the vector map)
+        Vect_set_fatal_error(GV_FATAL_PRINT)
+        
+        # open existing map
+        if update:
+            ret = Vect_open_update(byref(self.mapInfo), name, mapset)
+        else:
+            ret = Vect_open_old(byref(self.mapInfo), name, mapset)
+        
+        if ret == -1: # error
+            del self.mapInfo
+            self.mapInfo = None
+        
+        return ret
+    
+    def ReloadMap(self):
+        pass
+
+    def SetDevice(self):
+        pass
+
+    def GetMapBoundingBox(self):
+        """!Get bounding box of (opened) vector map layer
+
+        @return (w,s,b,e,n,t)
+        """
+        if not self.mapInfo:
+            return None
+        
+        bbox = bound_box()
+        Vect_get_map_box(byref(self.mapInfo), byref(bbox))
+
+        return bbox.W, bbox.S, bbox.B, \
+            bbox.E, bbox.N, bbox.T
+    
+    def Is3D(self):
+        pass
+
+    def SetRegion(self):
+        pass
+    
+    def UpdateSettings(self, alpha = 255):
+        """!Update display driver settings
+
+        @todo map units
+        
+        @alpha color value for aplha channel
+        """
+        color = dict()
+        for key in self.settings.keys():
+            if key == 'lineWidth':
+                self.settings[key] = int(UserSettings.Get(group = 'vdigit', key = 'lineWidth',
+                                                          subkey = 'value'))
+                continue
+            
+            color = wx.Color(UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                              subkey = [key, 'color'])[0],
+                             UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                              subkey = [key, 'color'])[1],
+                             UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                              subkey = [key, 'color'])[2])
+            
+            if key == 'highlight':
+                self.settings[key] = color
+                continue
+            
+            if key == 'highlightDupl':
+                self.settings[key]['enabled'] = bool(UserSettings.Get(group = 'vdigit', key = 'checkForDupl',
+                                                                      subkey = 'enabled'))
+            else:
+                self.settings[key]['enabled'] = bool(UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                                                      subkey = [key, 'enabled']))
+            
+            self.settings[key]['color'] = color
+        
+    def UpdateRegion(self):
+        """!Update geographical region used by display driver.
+        """
+        self.region = self.mapObj.GetCurrentRegion()
+        
+    def GetThreshold(self, type = 'snapping', value = None, units = None):
+        """!Return threshold in map units
+        
+        @param value threshold to be set up
+        @param units units (map, screen)
+        """
+        if value is None:
+            value = UserSettings.Get(group = 'vdigit', key = type, subkey =' value')
+
+        if units is None:
+            units = UserSettings.Get(group = 'vdigit', key = type, subkey = 'units')
+        
+        if value < 0:
+            value = (self.region['nsres'] + self.region['ewres']) / 2.0
+        
+        if units == "screen pixels":
+            # pixel -> cell
+            res = max(self.region['nsres'], self.region['ewres'])
+            threshold = value * res
+        else:
+            threshold = value
+        
+        Debug.msg(4, "DisplayDriver.GetThreshold(): type=%s, thresh=%f" % (type, threshold))
+        
+        return threshold


Property changes on: grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Modified: grass/trunk/include/vedit.h
===================================================================
--- grass/trunk/include/vedit.h	2010-12-31 13:44:07 UTC (rev 44822)
+++ grass/trunk/include/vedit.h	2011-01-01 19:26:54 UTC (rev 44823)
@@ -12,6 +12,54 @@
 #define QUERY_LENGTH   0	/* select by line length */
 #define QUERY_DANGLE   1	/* select dangles */
 
+/* used by Vedit_render_map() */
+#define TYPE_POINT           0x01
+#define TYPE_LINE	     0x02
+#define TYPE_BOUNDARYNO      0x04
+#define TYPE_BOUNDARYTWO     0x08
+#define TYPE_BOUNDARYONE     0x10
+#define TYPE_CENTROIDIN      0x20
+#define TYPE_CENTROIDOUT     0x40
+#define TYPE_CENTROIDDUP     0x80
+#define TYPE_NODEONE         0x100
+#define TYPE_NODETWO         0x200
+#define TYPE_VERTEX          0x400
+#define TYPE_AREA            0x800
+#define TYPE_ISLE            0x1000
+#define TYPE_DIRECTION       0x2000
+
+#define DRAW_POINT           0x01
+#define DRAW_LINE	     0x02
+#define DRAW_BOUNDARYNO      0x04
+#define DRAW_BOUNDARYTWO     0x08
+#define DRAW_BOUNDARYONE     0x10
+#define DRAW_CENTROIDIN      0x20
+#define DRAW_CENTROIDOUT     0x40
+#define DRAW_CENTROIDDUP     0x80
+#define DRAW_NODEONE         0x100
+#define DRAW_NODETWO         0x200
+#define DRAW_VERTEX          0x400
+#define DRAW_AREA            0x800
+#define DRAW_DIRECTION       0x1000
+
+struct rpoint {
+    /* screen coordinates */
+    int x, y;
+};
+
+struct robject {
+    /* object to be rendered */
+    int            type;
+    int            npoints;
+    struct rpoint *point;   /* list of points */
+};
+
+struct robject_list {
+    /* list of objects to be rendered */
+    int              nitems;
+    struct robject **item;
+};
+
 /* break.c */
 int Vedit_split_lines(struct Map_info *, struct ilist *,
 		      struct line_pnts *, double, struct ilist *);
@@ -45,6 +93,10 @@
 int Vedit_move_lines(struct Map_info *, struct Map_info **, int,
 		     struct ilist *, double, double, double, int, double);
 
+/* render.c */
+struct robject_list *Vedit_render_map(struct Map_info *, struct bound_box *, int,
+				      double, double, int, int, double);
+
 /* select.c */
 int Vedit_select_by_query(struct Map_info *,
 			  int, int, double, int, struct ilist *);


Property changes on: grass/trunk/lib/vector/vedit/chtype.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc


Property changes on: grass/trunk/lib/vector/vedit/distance.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc

Added: grass/trunk/lib/vector/vedit/render.c
===================================================================
--- grass/trunk/lib/vector/vedit/render.c	                        (rev 0)
+++ grass/trunk/lib/vector/vedit/render.c	2011-01-01 19:26:54 UTC (rev 44823)
@@ -0,0 +1,491 @@
+/*!
+   \file lib/vector/vedit/render.c
+
+   \brief Vedit library - render vector features (used by wxGUI digitizer)
+
+   (C) 2010 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.
+
+   \author Martin Landa <landa.martin gmail.com>
+ */
+
+#include <math.h>
+
+#include <grass/vedit.h>
+
+struct _region
+{
+    double center_easting;
+    double center_northing;
+    double map_west;
+    double map_north;
+    int map_width;
+    int map_height;
+    double map_res;
+} region;
+
+struct _state
+{
+    int nitems_alloc;
+
+    int type;
+    struct line_pnts *Points;
+} state;
+
+static struct robject *draw_line(struct Map_info *, int, int);
+static struct robject *draw_line_vertices();
+static void draw_line_nodes(struct Map_info *, int, int,
+			    struct robject_list *);
+static int draw_line_dir(struct robject_list *);
+static void list_append(struct robject_list *, struct robject *);
+static struct robject *robj_alloc(int, int);
+static void robj_points(struct robject *, const struct line_pnts *);
+static double dist_in_px(double);
+static void en_to_xy(double, double, int *, int *);
+static void draw_arrow(int, int, int, int, double, int,
+		       struct robject_list *);
+static void draw_area(struct Map_info *, int, struct robject_list *);
+
+/*!
+   \brief Render vector features into list
+
+   \param Map pointer to Map_info structure
+   \param box bounding box of region to be rendered
+   \param draw_flag types of objects to be rendered (see vedit.h)
+   \param center_easing, center_northing, map_width, map_height, map_res values used for conversion en->xy
+
+   \return pointer to robject_list structure
+ */
+struct robject_list *Vedit_render_map(struct Map_info *Map,
+				      struct bound_box *box, int draw_flag,
+				      double center_easting,
+				      double center_northing, int map_width,
+				      int map_height, double map_res)
+{
+    int i, nfeat, fid;
+    struct ilist *list;
+    struct robject_list *list_obj;
+    struct robject *robj;
+
+    /* define region */
+    region.center_easting = center_easting;
+    region.center_northing = center_northing;
+    region.map_width = map_width;
+    region.map_height = map_height;
+    region.map_res = map_res;
+    region.map_west = center_easting - (map_width / 2.) * map_res;
+    region.map_north = center_northing + (map_height / 2.) * map_res;
+
+    list = Vect_new_list();
+    list_obj = NULL;
+    state.nitems_alloc = 1000;
+
+    list_obj = (struct robject_list *)G_malloc(sizeof(struct robject_list));
+    list_obj->nitems = 0;
+    list_obj->item =
+	(struct robject **)G_malloc(state.nitems_alloc *
+				    sizeof(struct robject *));
+
+    /* area */
+    if (draw_flag & DRAW_AREA) {
+	nfeat = Vect_select_areas_by_box(Map, box, list);
+	for (i = 0; i < nfeat; i++) {
+	    fid = list->value[i];
+	    draw_area(Map, fid, list_obj);
+	}
+    }
+
+    /* draw lines inside of current display region */
+    nfeat = Vect_select_lines_by_box(Map, box, GV_POINTS | GV_LINES,	// fixme
+				     list);
+    G_debug(1, "Vedit_render_map(): region: w=%f, e=%f, s=%f, n=%f nlines=%d",
+	    box->W, box->E, box->S, box->N, nfeat);
+
+    /* features */
+    for (i = 0; i < list->n_values; i++) {
+	fid = list->value[i];
+	robj = draw_line(Map, fid, draw_flag);
+	if (!robj)
+	    continue;
+	list_append(list_obj, robj);
+
+	if (state.type & GV_LINES) {
+	    /* vertices */
+	    if (draw_flag & DRAW_VERTEX) {
+		robj = draw_line_vertices();
+		if (robj)
+		    list_append(list_obj, robj);
+	    }
+	    /* nodes */
+	    if (draw_flag & (DRAW_NODEONE | DRAW_NODETWO)) {
+		draw_line_nodes(Map, fid, draw_flag, list_obj);
+	    }
+	    /* direction */
+	    if (draw_flag & DRAW_DIRECTION) {
+		draw_line_dir(list_obj);
+	    }
+	}
+    }
+
+    list_obj->item =
+	(struct robject **)G_realloc(list_obj->item,
+				     list_obj->nitems *
+				     sizeof(struct robject *));
+
+    Vect_destroy_list(list);
+
+    return list_obj;
+}
+
+/*!
+   \brief Draw one feature
+ */
+struct robject *draw_line(struct Map_info *Map, int line, int draw_flag)
+{
+    int draw;
+    struct robject *obj;
+
+    if (!state.Points)
+	state.Points = Vect_new_line_struct();
+
+    if (!Vect_line_alive(Map, line))
+	return NULL;
+
+    state.type = Vect_read_line(Map, state.Points, NULL, line);
+
+    obj = (struct robject *)G_malloc(sizeof(struct robject));
+    draw = FALSE;
+    if (state.type & GV_LINES) {
+	if (state.type == GV_LINE) {
+	    obj->type = TYPE_LINE;
+	    draw = draw_flag & DRAW_LINE;
+	}
+	else if (state.type == GV_BOUNDARY) {
+	    int left, right;
+
+	    Vect_get_line_areas(Map, line, &left, &right);
+	    if (left == 0 && right == 0) {
+		obj->type = TYPE_BOUNDARYNO;
+		draw = draw_flag & DRAW_BOUNDARYNO;
+	    }
+	    else if (left > 0 && right > 0) {
+		obj->type = TYPE_BOUNDARYTWO;
+		draw = draw_flag & DRAW_BOUNDARYTWO;
+	    }
+	    else {
+		obj->type = TYPE_BOUNDARYONE;
+		draw = draw_flag & DRAW_BOUNDARYONE;
+	    }
+	}
+    }
+    else if (state.type & GV_POINTS) {
+	if (state.type == GV_POINT) {
+	    obj->type = TYPE_POINT;
+	    draw = draw_flag & DRAW_POINT;
+	}
+	else if (state.type == GV_CENTROID) {
+	    int cret = Vect_get_centroid_area(Map, line);
+
+	    if (cret > 0) {	// -> area
+		obj->type = TYPE_CENTROIDIN;
+		draw = draw_flag & DRAW_CENTROIDIN;
+	    }
+	    else if (cret == 0) {
+		obj->type = TYPE_CENTROIDOUT;
+		draw = draw_flag & DRAW_CENTROIDOUT;
+	    }
+	    else {
+		obj->type = TYPE_CENTROIDDUP;
+		draw = draw_flag & DRAW_CENTROIDDUP;
+	    }
+	}
+    }
+    G_debug(3, "  draw_line(): type=%d rtype=%d npoints=%d draw=%d",
+	    state.type, obj->type, state.Points->n_points, draw);
+
+    if (!draw)
+	return NULL;
+
+    obj->npoints = state.Points->n_points;
+    obj->point =
+	(struct rpoint *)G_malloc(obj->npoints * sizeof(struct rpoint));
+    robj_points(obj, state.Points);
+
+    return obj;
+}
+
+/*!
+   \brief Convert geographic coordinates to the screen
+ */
+void en_to_xy(double east, double north, int *x, int *y)
+{
+    double n, w;
+
+    w = region.center_easting - (region.map_width / 2) * region.map_res;
+    n = region.center_northing + (region.map_height / 2) * region.map_res;
+
+    if (x)
+	*x = (east - w) / region.map_res;
+    if (y)
+	*y = (n - north) / region.map_res;
+
+    return;
+}
+
+/*!
+   \brief Draw line nodes
+ */
+void draw_line_nodes(struct Map_info *Map, int line, int draw_flag,
+		     struct robject_list *list)
+{
+    unsigned int i;
+    int type, nodes[2];
+    int x, y;
+    double east, north;
+    struct robject *robj;
+
+    Vect_get_line_nodes(Map, line, &(nodes[0]), &(nodes[1]));
+
+    for (i = 0; i < sizeof(nodes) / sizeof(int); i++) {
+	type = 0;
+	if (Vect_get_node_n_lines(Map, nodes[i]) == 1) {
+	    if (draw_flag & DRAW_NODEONE) {
+		type = TYPE_NODEONE;
+	    }
+	}
+	else {
+	    if (draw_flag & DRAW_NODETWO) {
+		type = TYPE_NODETWO;
+	    }
+	}
+
+	if (type == 0)
+	    continue;
+
+	Vect_get_node_coor(Map, nodes[i], &east, &north, NULL);
+
+	robj = robj_alloc(type, 1);
+	en_to_xy(east, north, &x, &y);
+	robj->point->x = x;
+	robj->point->y = y;
+
+	list_append(list, robj);
+    }
+}
+
+/*!
+   \brief Append object to the list
+ */
+void list_append(struct robject_list *list, struct robject *obj)
+{
+    if (list->nitems >= state.nitems_alloc) {
+	state.nitems_alloc += 1000;
+	list->item =
+	    (struct robject **)G_realloc(list->item,
+					 state.nitems_alloc *
+					 sizeof(struct robject *));
+    }
+    list->item[list->nitems++] = obj;
+}
+
+/*!
+   \brief Allocate robject 
+ */
+struct robject *robj_alloc(int type, int npoints)
+{
+    struct robject *robj;
+
+    robj = (struct robject *)G_malloc(sizeof(struct robject));
+    robj->type = type;
+    robj->npoints = npoints;
+    robj->point = (struct rpoint *)G_malloc(npoints * sizeof(struct rpoint));
+
+    return robj;
+}
+
+/*!
+   \brief Draw line vertices
+ */
+struct robject *draw_line_vertices()
+{
+    int i;
+    int x, y;
+    struct robject *robj;
+
+    robj = robj_alloc(TYPE_VERTEX, state.Points->n_points - 2);	/* ignore nodes */
+
+    for (i = 1; i < state.Points->n_points - 1; i++) {
+	en_to_xy(state.Points->x[i], state.Points->y[i], &x, &y);
+	robj->point[i - 1].x = x;
+	robj->point[i - 1].y = y;
+    }
+
+    return robj;
+}
+
+/*!
+   \brief Draw line dirs
+ */
+int draw_line_dir(struct robject_list *list)
+{
+    int narrows;
+    int size;			/* arrow length in pixels */
+    int limit;			/* segment length limit for drawing symbol (in pixels) */
+    double dist, angle, pos;
+    double e, n;
+    int x0, y0, x1, y1;
+
+    narrows = 0;
+    size = 5;
+    limit = 5;			// 5px for line segment
+
+    dist = Vect_line_length(state.Points);
+
+    if (dist_in_px(dist) >= limit) {
+	while (1) {
+	    pos = (narrows + 1) * 8 * limit * region.map_res;
+
+	    if (Vect_point_on_line(state.Points, pos,
+				   &e, &n, NULL, NULL, NULL) < 1) {
+		break;
+	    }
+
+	    en_to_xy(e, n, &x0, &y0);
+
+	    if (Vect_point_on_line
+		(state.Points, pos - 3 * size * region.map_res, &e, &n, NULL,
+		 &angle, NULL) < 1) {
+		break;
+	    }
+
+	    en_to_xy(e, n, &x1, &y1);
+
+	    draw_arrow(x0, y0, x1, y1, angle, size, list);
+
+	    if (narrows > 1e2)	// low resolution, break
+		break;
+
+	    narrows++;
+	}
+
+	// draw at least one arrow in the middle of line
+	if (narrows < 1) {
+	    dist /= 2.;
+	    if (Vect_point_on_line(state.Points, dist,
+				   &e, &n, NULL, NULL, NULL) > 0) {
+
+		en_to_xy(e, n, &x0, &y0);
+
+		if (Vect_point_on_line
+		    (state.Points, dist - 3 * size * region.map_res, &e, &n,
+		     NULL, &angle, NULL) > 0) {
+
+		    en_to_xy(e, n, &x1, &y1);
+
+		    draw_arrow(x0, y0, x1, y1, angle, size, list);
+		}
+	    }
+	}
+    }
+
+    return narrows;
+}
+
+/*!
+   \brief Calculate distance in pixels (on screen)
+ */
+double dist_in_px(double dist)
+{
+    int x, y;
+
+    en_to_xy(region.map_west + dist, region.map_north, &x, &y);
+
+    return sqrt(x * x);
+}
+
+/*!
+   \brief Draw arrow
+ */
+void draw_arrow(int x0, int y0, int x1, int y1, double angle, int size,
+		struct robject_list *list)
+{
+    double angle_symb;
+    struct robject *robj;
+
+    robj = robj_alloc(TYPE_DIRECTION, 3);
+
+    angle_symb = angle - M_PI / 2.;
+    robj->point[0].x = (int)x1 + size * cos(angle_symb);
+    robj->point[0].y = (int)y1 - size * sin(angle_symb);
+
+    robj->point[1].x = x0;
+    robj->point[1].y = y0;
+
+    angle_symb = M_PI / 2. + angle;
+    robj->point[2].x = (int)x1 + size * cos(angle_symb);
+    robj->point[2].y = (int)y1 - size * sin(angle_symb);
+
+    list_append(list, robj);
+}
+
+/*!
+   \brief Draw area
+ */
+void draw_area(struct Map_info *Map, int area, struct robject_list *list)
+{
+    int i, centroid, isle;
+    int num_isles;
+    struct line_pnts *ipoints;
+
+    struct robject *robj;
+
+    if (!state.Points)
+	state.Points = Vect_new_line_struct();
+
+    if (!Vect_area_alive(Map, area))
+	return;
+
+    /* check for other centroids -- only area with one centroid is valid */
+    centroid = Vect_get_area_centroid(Map, area);
+    if (centroid <= 0)
+	return;
+
+    ipoints = Vect_new_line_struct();
+    /* get area's boundary */
+    Vect_get_area_points(Map, area, state.Points);
+    robj = robj_alloc(TYPE_AREA, state.Points->n_points);
+    robj_points(robj, state.Points);
+    list_append(list, robj);
+
+    /* check for isles */
+    num_isles = Vect_get_area_num_isles(Map, area);
+    for (i = 0; i < num_isles; i++) {
+	isle = Vect_get_area_isle(Map, area, i);
+	if (!Vect_isle_alive(Map, isle))
+	    continue;
+
+	Vect_get_isle_points(Map, isle, ipoints);
+	robj = robj_alloc(TYPE_ISLE, ipoints->n_points);
+	robj_points(robj, ipoints);
+	list_append(list, robj);
+    }
+
+    Vect_destroy_line_struct(ipoints);
+}
+
+/*!
+   \brief convert EN -> XY
+ */
+void robj_points(struct robject *robj, const struct line_pnts *points)
+{
+    int i;
+    int x, y;
+
+    for (i = 0; i < points->n_points; i++) {
+	en_to_xy(points->x[i], points->y[i], &x, &y);
+	robj->point[i].x = x;
+	robj->point[i].y = y;
+    }
+}


Property changes on: grass/trunk/lib/vector/vedit/render.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc
Added: svn:eol-style
   + native


Property changes on: grass/trunk/lib/vector/vedit/select.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc



More information about the grass-commit mailing list