[GRASS-SVN] r32788 - grass/branches/develbranch_6/gui/wxpython/gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Aug 15 16:05:46 EDT 2008


Author: martinl
Date: 2008-08-15 16:05:46 -0400 (Fri, 15 Aug 2008)
New Revision: 32788

Added:
   grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_mapdisp.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_tools.py
Modified:
   grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz.py
Log:
wxGUI: nviz splitted into two modules (mapdisp/tools)

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz.py	2008-08-15 19:56:23 UTC (rev 32787)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz.py	2008-08-15 20:05:46 UTC (rev 32788)
@@ -1,13 +1,15 @@
 """
- at package nviz.py
+ at package nviz_mapdisp.py (core)
 
- at brief 2.5/3D visialization mode for Map Display Window
+ at brief Nviz extension for wxGUI
 
+This module enables to visualize data in 2.5/3D space.
+
+Map Display supports standard 2D mode ('mapdisp' module) and
+the 2.5/3D mode ('nviz_mapdisp' module).
+
 List of classes:
  - GLWindow
- - NvizToolWindow
- - ViewPositionWindow
- - IsoSurfList
 
 (C) 2008 by the GRASS Development Team
 
@@ -18,19 +20,9 @@
 @author Martin Landa <landa.martin gmail.com> (Google SoC 2008)
 """
 
-import os
-import sys
-import time
-import copy
+errorMsg = ''
 
-from threading import Thread
-
 import wx
-import wx.lib.colourselect as csel
-import wx.lib.scrolledpanel as scrolled
-from wx.lib.newevent import NewEvent
-
-errorMsg = ''
 try:
     from wx import glcanvas
     haveGLCanvas = True
@@ -46,3764 +38,16 @@
     errorMsg = e
 
 import globalvar
-import gcmd
-import gselect
-from debug import Debug as Debug
-from mapdisp import MapWindow as MapWindow
-from preferences import globalSettings as UserSettings
 try:
-    nvizPath = os.path.join(globalvar.ETCWXDIR, "nviz")
-    sys.path.append(nvizPath)
+    sys.path.append(os.path.join(globalvar.ETCWXDIR, "nviz"))
     import grass6_wxnviz as wxnviz
     haveNviz = True
 except ImportError, e:
     haveNviz = False
     errorMsg = e
 
-wxUpdateProperties, EVT_UPDATE_PROP = NewEvent()
+import nviz_mapdisp
+import nviz_tools
 
-class GLWindow(MapWindow, glcanvas.GLCanvas):
-    """OpenGL canvas for Map Display Window"""
-    def __init__(self, parent, id,
-                 pos=wx.DefaultPosition,
-                 size=wx.DefaultSize,
-                 style=wx.NO_FULL_REPAINT_ON_RESIZE,
-                 Map=None, tree=None, gismgr=None):
-
-        self.parent = parent # MapFrame
-        self.Map = Map
-        self.tree = tree
-        self.gismgr = gismgr
-        
-        glcanvas.GLCanvas.__init__(self, parent, id)
-        MapWindow.__init__(self, parent, id, pos, size, style,
-                           Map, tree, gismgr)
-
-
-        self.parent = parent # MapFrame
-
-        self.init = False
-        # render mode 
-        self.render = { 'quick' : False,
-                        # do not render vector lines in quick mode
-                        'vlines' : False,
-                        'vpoints' : False }
-
-        # list of loaded map layers
-        self.layers = {}
-        for type in ('raster', 'vlines', 'vpoints', '3d-raster'):
-            self.layers[type] = {}
-            self.layers[type]['name'] = []
-            self.layers[type]['id'] = []
-
-        #
-        # create nviz instance
-        #
-        self.nvizClass = wxnviz.Nviz(sys.stderr)
-
-        #
-        # set current display
-        #
-        self.nvizClass.SetDisplay(self)
-
-        #
-        # initialize mouse position
-        #
-        self.lastX = self.x = 30
-        self.lastY = self.y = 30
-
-        #
-        # default values
-        #
-        self.view = copy.deepcopy(UserSettings.Get(group='nviz', key='view')) # copy
-        self.iview = UserSettings.Get(group='nviz', key='view', internal=True)
-        self.update = [] # list of properties to be updated
-
-        self.size = None
-        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
-        self.Bind(wx.EVT_SIZE, self.OnSize)
-        self.Bind(wx.EVT_PAINT, self.OnPaint)
-        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
-        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
-        self.Bind(wx.EVT_MOTION, self.OnMouseAction)
-        self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseAction)
-
-        self.Bind(EVT_UPDATE_PROP, self.UpdateLayerProperties)
-        
-    def OnEraseBackground(self, event):
-        pass # do nothing, to avoid flashing on MSW
-
-    def OnSize(self, event):
-        self.size = self.parent.GetClientSize()
-        if self.GetContext():
-            Debug.msg(3, "GLCanvas.OnPaint(): w=%d, h=%d" % \
-                      (self.size.width, self.size.height))
-            self.SetCurrent()
-            self.nvizClass.ResizeWindow(self.size.width,
-                                        self.size.height)
-        
-        event.Skip()
-
-    def OnPaint(self, event):
-        Debug.msg(3, "GLCanvas.OnPaint()")
-
-        dc = wx.PaintDC(self)
-        self.SetCurrent()
-        
-        if not self.init:
-            self.nvizClass.InitView()
-
-            self.LoadDataLayers()
-
-            self.ResetView()
-            
-            if hasattr(self.parent, "nvizToolWin"):
-                self.parent.nvizToolWin.UpdatePage('view')
-                layer = self.GetSelectedLayer()
-                if layer:
-                    if layer.type == 'raster':
-                        self.parent.nvizToolWin.UpdatePage('surface')
-                    elif layer.type == 'vector':
-                        self.parent.nvizToolWin.UpdatePage('vector')
-
-                self.parent.nvizToolWin.UpdateSettings()
-
-                # update widgets
-                win = self.parent.nvizToolWin.FindWindowById( \
-                    self.parent.nvizToolWin.win['vector']['lines']['surface'])
-                win.SetItems(self.layers['raster']['name'])
-
-            self.init = True
-
-        self.UpdateMap()
-
-    def OnMouseAction(self, event):
-        # change position
-        if event.Dragging() and event.LeftIsDown():
-            self.lastX = self.lastY = self.x = self.y
-            self.x, self.y = event.GetPosition()
-            self.Refresh(False)
-
-        # change perspective with mouse wheel
-        wheel = event.GetWheelRotation()
-
-        if wheel != 0:
-            current  = event.GetPositionTuple()[:]
-            Debug.msg (5, "GLWindow.OnMouseMotion(): wheel=%d" % wheel)
-            prev_value = self.view['persp']['value']
-            if wheel > 0:
-                value = -1 * self.view['persp']['step']
-            else:
-                value = self.view['persp']['step']
-            self.view['persp']['value'] += value
-            if self.view['persp']['value'] < 1:
-                self.view['persp']['value'] = 1
-            elif self.view['persp']['value'] > 100:
-                self.view['persp']['value'] = 100
-
-            if prev_value != self.view['persp']['value']:
-                if hasattr(self.parent, "nvizToolWin"):
-                    self.parent.nvizToolWin.UpdateSettings()
-
-                    self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
-                                           self.iview['height']['value'],
-                                           self.view['persp']['value'],
-                                           self.view['twist']['value'])
-
-                # redraw map
-                self.OnPaint(None)
-
-                # update statusbar
-                ### self.parent.StatusbarUpdate()
-
-    def OnLeftDown(self, event):
-        self.CaptureMouse()
-        self.x, self.y = self.lastX, self.lastY = event.GetPosition()
-        
-    def OnLeftUp(self, event):
-        self.ReleaseMouse()
-
-    def UpdateMap(self, render=True):
-        """
-        Updates the canvas anytime there is a change to the
-        underlaying images or to the geometry of the canvas.
-
-        @param render re-render map composition
-        """
-        start = time.clock()
-
-        self.resize = False
-
-        # if self.size is None:
-        #    self.size = self.GetClientSize()
-        
-        #         w, h = self.size
-        #         w = float(max(w, 1.0))
-        #         h = float(max(h, 1.0))
-        #         d = float(min(w, h))
-        #         xScale = d / w
-        #         yScale = d / h
-        # print w, h, d, xScale, yScale
-        # print self.y, self.lastY, self.x, self.lastX
-        # print (self.y - self.lastY) * yScale, (self.x - self.lastX) * xScale 
-        # print self.x * xScale
-        
-        #glRotatef((self.y - self.lastY) * yScale, 1.0, 0.0, 0.0);
-        #glRotatef((self.x - self.lastX) * xScale, 0.0, 1.0, 0.0);
-
-        if self.render['quick'] is False:
-            self.parent.onRenderGauge.Show()
-            self.parent.onRenderGauge.SetRange(2)
-            self.parent.onRenderGauge.SetValue(0)
-
-        if 'view' in self.update:
-            if 'z-exag' in self.update:
-                self.nvizClass.SetZExag(self.view['z-exag']['value'])
-                self.update.remove('z-exag')
-            
-            self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
-                                   self.iview['height']['value'],
-                                   self.view['persp']['value'],
-                                   self.view['twist']['value'])
-
-            self.update.remove('view')
-
-        if self.render['quick'] is False:
-            self.parent.onRenderGauge.SetValue(1)
-            wx.Yield()
-            self.nvizClass.Draw(False, -1)
-        elif self.render['quick'] is True:
-            # quick
-            mode = wxnviz.DRAW_QUICK_SURFACE | wxnviz.DRAW_QUICK_VOLUME
-            if self.render['vlines']:
-                mode |= wxnviz.DRAW_QUICK_VLINES
-            if self.render['vpoints']:
-                mode |= wxnviz.DRAW_QUICK_VPOINTS
-            self.nvizClass.Draw(True, mode)
-        else: # None -> reuse last rendered image
-            pass # TODO
-
-        self.SwapBuffers()
-
-        stop = time.clock()
-
-        if self.render['quick'] is False:
-            self.parent.onRenderGauge.SetValue(2)
-            # hide process bar
-            self.parent.onRenderGauge.Hide()
-
-        #
-        # update statusbar
-        #
-        # self.parent.StatusbarUpdate()
-
-        Debug.msg(3, "GLWindow.UpdateMap(): quick=%d, -> time=%g" % \
-                      (self.render['quick'], (stop-start)))
-
-        # print stop-start
-
-    def EraseMap(self):
-        """
-        Erase the canvas
-        """
-        self.nvizClass.EraseMap()
-        self.SwapBuffers()
-
-    def IsLoaded(self, item):
-        """Check if layer (item) is already loaded
-
-        @param item layer item
-        """
-        layer = self.tree.GetPyData(item)[0]['maplayer']
-        data = self.tree.GetPyData(item)[0]['nviz']
-
-        if not data:
-            return 0
-
-        if layer.type == 'raster':
-            if not data['surface'].has_key('object'):
-                return 0
-        elif layer.type == 'vector':
-            if not data['vlines'].has_key('object') and \
-                    not data['points'].has_key('object'):
-                return 0
-
-        return 1
-
-    def LoadDataLayers(self):
-        """Load raster/vector from current layer tree
-
-        @todo volumes
-        """
-        listOfItems = []
-        # load raster & vector maps
-        item = self.tree.GetFirstChild(self.tree.root)[0]
-        while item and item.IsOk():
-            type = self.tree.GetPyData(item)[0]['type']
-            if not item.IsChecked() or \
-                    type not in ('raster', 'vector', '3d-raster'):
-                item = self.tree.GetNextSibling(item)
-                continue
-
-            listOfItems.append(item)
-
-            item = self.tree.GetNextSibling(item)
-
-        start = time.time()
-
-        while(len(listOfItems) > 0):
-            item = listOfItems.pop()
-            type = self.tree.GetPyData(item)[0]['type']
-            
-            try:
-                if type == 'raster':
-                    self.LoadRaster(item)
-                elif type == '3d-raster':
-                    self.LoadRaster3d(item)
-            except gcmd.NvizError, e:
-                print >> sys.stderr, "Nviz:" + e.message
-
-            try:
-                if type == 'vector':
-                    data = self.tree.GetPyData(item)[0]['nviz']
-                    vecType = []
-                    if data and data.has_key('vector'):
-                        for v in ('lines', 'points'):
-                            if data['vector'][v]:
-                                vecType.append(v)
-                    self.LoadVector(item, vecType)
-            except gcmd.NvizError, e:
-                print >> sys.stderr, "Nviz:" + e.message
-            
-        stop = time.time()
-        
-        Debug.msg(3, "GLWindow.LoadDataLayers(): time=%f" % (stop-start))
-
-        # print stop - start
-
-    def SetLayerData(self, item, id, nvizType):
-        """Set map object properties
-
-        @param item layer item
-        @param id nviz layer id (or -1)
-        @param nvizType nviz data type (surface, points, vector)
-        """
-        type = self.tree.GetPyData(item)[0]['maplayer'].type
-        # reference to original layer properties (can be None)
-        data = self.tree.GetPyData(item)[0]['nviz']
-
-        if data is None:
-            # init data structure
-            self.tree.GetPyData(item)[0]['nviz'] = {}
-            data = self.tree.GetPyData(item)[0]['nviz']
-
-            if type == 'raster':
-                data[nvizType] = {}
-                for sec in ('attribute', 'draw', 'mask', 'position'):
-                    data[nvizType][sec] = {}
-
-                # reset to default properties
-                self.SetSurfaceDefaultProp(data[nvizType])
-                        
-            elif type == 'vector':
-                data['vector'] = {}
-                for sec in ('lines', 'points'):
-                    data['vector'][sec] = {}
-
-                # reset to default properties (lines/points)
-                self.SetVectorDefaultProp(data['vector'])
-
-            elif type == '3d-raster':
-                data[nvizType] = {}
-                for sec in ('attribute', 'draw', 'position'):
-                    data[nvizType][sec] = {}
-                for sec in ('isosurface', 'slice'):
-                    data[nvizType][sec] = []
-                
-
-                # reset to default properties 
-                self.SetVolumeDefaultProp(data[nvizType])
-        
-        else:
-            # check data
-            if type == 'vector':
-                if not data['vector']['lines']:
-                    self.SetVectorLinesDefaultProp(data['vector']['lines'])
-                if not data['vector']['points']:
-                    self.SetVectorPointsDefaultProp(data['vector']['points'])
-                    
-            # set updates
-            for sec in data.keys():
-                for sec1 in data[sec].keys():
-                    for sec2 in data[sec][sec1].keys():
-                        if sec2 not in ('object'):
-                            self.update.append('%s:%s:%s' % (sec, sec1, sec2))
-
-        # set id
-        if id > 0:
-            if type in ('raster', '3d-raster'):
-               data[nvizType]['object'] = { 'id' : id,
-                                            'init' : False }
-            elif type == 'vector':
-                data['vector'][nvizType]['object'] = { 'id' : id,
-                                                       'init' : False }
-        
-        return data
-
-    def LoadRaster(self, item):
-        """Load 2d raster map and set surface attributes
-
-        @param layer item
-        """
-        return self._loadRaster(item)
-
-    def LoadRaster3d(self, item):
-        """Load 3d raster map and set surface attributes
-
-        @param layer item
-        """
-        return self._loadRaster(item)
-
-    def _loadRaster(self, item):
-        """Load 2d/3d raster map and set its attributes
-
-        @param layer item
-        """
-        layer = self.tree.GetPyData(item)[0]['maplayer']
-
-        if layer.type not in ('raster', '3d-raster'):
-            return
-
-        if layer.type == 'raster':
-            id = self.nvizClass.LoadSurface(str(layer.name), None, None)
-            nvizType = 'surface'
-            errorMsg = _("Loading raster map")
-        elif layer.type == '3d-raster':
-            id = self.nvizClass.LoadVolume(str(layer.name), None, None)
-            nvizType = 'volume'
-            errorMsg = _("Loading 3d raster map")
-        else:
-            id = -1
-        
-        if id < 0:
-            if layer.type in ('raster', '3d-raster'):
-                print >> sys.stderr, "Nviz:" + "%s <%s> %s" % (errorMsg, layer.name, _("failed"))
-            else:
-                print >> sys.stderr, "Nviz:" + _("Unsupported layer type '%s'") % layer.type
-        
-        self.layers[layer.type]['name'].append(layer.name)
-        self.layers[layer.type]['id'].append(id)
-
-        # set default/workspace layer properties
-        data = self.SetLayerData(item, id, nvizType)
-        print data
-        # update properties
-        event = wxUpdateProperties(layer=item)
-        wx.PostEvent(self, event)
-        
-        # update tools window
-        if hasattr(self.parent, "nvizToolWin") and \
-                item == self.GetSelectedLayer(type='item'):
-            toolWin = self.parent.nvizToolWin
-            if layer.type == 'raster':
-                win = toolWin.FindWindowById( \
-                    toolWin.win['vector']['lines']['surface'])
-                win.SetItems(self.layers[layer.type]['name'])
-
-            toolWin.UpdatePage(nvizType)
-            toolWin.SetPage(nvizType)
-            
-        return id
-
-    def UnloadRaster(self, item):
-        """Unload 2d raster map
-
-        @param layer item
-        """
-        return self._unloadRaster(item)
-
-    def UnloadRaster3d(self, item):
-        """Unload 3d raster map
-
-        @param layer item
-        """
-        return self._unloadRaster(item)
-
-    def _unloadRaster(self, item):
-        """Unload 2d/3d raster map
-
-        @param item layer item
-        """
-        layer = self.tree.GetPyData(item)[0]['maplayer']
-
-        if layer.type not in ('raster', '3d-raster'):
-            return
-
-        data = self.tree.GetPyData(item)[0]['nviz']
-
-        if layer.type == 'raster':
-            nvizType = 'surface'
-            unloadFn = self.nvizClass.UnloadSurface
-            errorMsg = _("Unable to unload raster map")
-            successMsg = _("Raster map")
-        else:
-            nvizType = 'volume'
-            unloadFn = self.nvizClass.UnloadVolume
-            errorMsg = _("Unable to unload 3d raster map")
-            successMsg = _("3d raster map")
-
-        id = data[nvizType]['object']['id']
-
-        if unloadFn(id) == 0:
-            print >> sys.stderr, "Nviz:" + "%s <%s>" % (errorMsg, layer.name)
-        else:
-            print "Nviz:" + "%s <%s> %s" % (successMsg, layer.name, _("unloaded successfully"))
-
-        data[nvizType].pop('object')
-
-        idx = self.layers[layer.type]['id'].index(id)
-        del self.layers[layer.type]['name'][idx]
-        del self.layers[layer.type]['id'][idx]
-
-        # update tools window
-        if hasattr(self.parent, "nvizToolWin") and \
-                layer.type == 'raster':
-            toolWin = self.parent.nvizToolWin
-            win = toolWin.FindWindowById( \
-                toolWin.win['vector']['lines']['surface'])
-            win.SetItems(self.layers[layer.type]['name'])
-
-            # remove surface page
-            if toolWin.notebook.GetSelection() == toolWin.page[nvizType]['id']:
-                toolWin.notebook.RemovePage(toolWin.page[nvizType]['id'])
-                toolWin.page[nvizType]['id'] = -1
-                toolWin.page['settings']['id'] = 1
-
-    def LoadVector(self, item, vecType=None):
-        """Load 2D or 3D vector map overlay
-
-        @param item layer item
-        @param vecType vector type (lines / points)
-        """
-        layer = self.tree.GetPyData(item)[0]['maplayer']
-
-        if layer.type != 'vector':
-            return
-
-        if vecType is None:
-            # load data type by default
-            vecType = []
-            for v in ('lines', 'points'):
-                if UserSettings.Get(group='nviz', key='vector',
-                                    subkey=[v, 'show']):
-                    vecType.append(v)
-
-        # set default properties
-        self.SetLayerData(item, -1, 'lines')
-        self.SetLayerData(item, -1, 'points')
-
-        id = -1
-        for type in vecType:
-            if type == 'lines':
-                id = self.nvizClass.LoadVector(str(layer.name), False)
-            else:
-                id = self.nvizClass.LoadVector(str(layer.name), True)
-
-            if id < 0:
-                print >> sys.stderr, "Nviz:" + _("Loading vector map <%(name)s> (%(type)s) failed") % \
-                    { 'name' : layer.name, 'type' : type }
-                continue
-
-            # update layer properties
-            self.SetLayerData(item, id, type)
-        
-            self.layers['v' + type]['name'].append(layer.name)
-            self.layers['v'  + type]['id'].append(id)
-        
-        # update properties
-        event = wxUpdateProperties(layer=item)
-        wx.PostEvent(self, event)
-        
-        # update tools window
-        if hasattr(self.parent, "nvizToolWin") and \
-                item == self.GetSelectedLayer(type='item'):
-            toolWin = self.parent.nvizToolWin
-
-            toolWin.UpdatePage('vector')
-            toolWin.SetPage('vector')
-        
-        return id
-
-    def UnloadVector(self, item, vecType=None):
-        """Unload vector map overlay
-
-        @param item layer item
-        @param vecType vector type (lines, points)
-        """
-        layer = self.tree.GetPyData(item)[0]['maplayer']
-        data = self.tree.GetPyData(item)[0]['nviz']['vector']
-
-        if vecType is None:
-            vecType = []
-            for v in ('lines', 'points'):
-                if UserSettings.Get(group='nviz', key='vector',
-                                    subkey=[v, 'show']):
-                    vecType.append(v)
-
-        for vtype in vecType:
-            if not data[vtype].has_key('object'):
-                continue
-
-            id = data[vtype]['object']['id']
-
-            if vtype == 'lines':
-                ret = self.nvizClass.UnloadVector(id, False)
-            else:
-                ret = self.nvizClass.UnloadVector(id, True)
-            if ret == 0:
-                print >> sys.stderr, "Nviz:" + _("Unable to unload vector map <%(name)s> (%(type)s)") % \
-                    { 'name': layer.name, 'type' : vtype }
-            else:
-                print "Nviz:" + _("Vector map <%(name)s> (%(type)s) unloaded successfully") % \
-                    { 'name' : layer.name, 'type' : vtype }
-
-            
-            data[vtype].pop('object')
-
-            idx = self.layers['v' + vtype]['id'].index(id)
-            del self.layers['v' + vtype]['name'][idx]
-            del self.layers['v' + vtype]['id'][idx]
-
-        # update tools window
-        if hasattr(self.parent, "nvizToolWin") and \
-                vecType is None:
-            toolWin = self.parent.nvizToolWin
-            # remove surface page
-            if toolWin.notebook.GetSelection() == toolWin.page['surface']['id']:
-                toolWin.notebook.RemovePage(toolWin.page['surface']['id'])
-                toolWin.page['surface']['id'] = -1
-                toolWin.page['settings']['id'] = 1
-        
-    def GetDrawMode(self, mode=None, style=None, shade=None, string=False):
-        """Get surface draw mode (value) from description/selection
-
-        @param mode,style,shade modes
-        @param string if True input parameters are strings otherwise
-        selections
-        """
-        value = 0
-        desc = {}
-
-        if string:
-            if mode is not None:
-                if mode == 'coarse':
-                    value |= wxnviz.DM_WIRE
-                elif mode == 'fine':
-                    value |= wxnviz.DM_POLY
-                else: # both
-                    value |= wxnviz.DM_WIRE_POLY
-
-            if style is not None:
-                if style == 'wire':
-                    value |= wxnviz.DM_GRID_WIRE
-                else: # surface
-                    value |= wxnviz.DM_GRID_SURF
-                    
-            if shade is not None:
-                if shade == 'flat':
-                    value |= wxnviz.DM_FLAT
-                else: # surface
-                    value |= wxnviz.DM_GOURAUD
-
-            return value
-
-        # -> string is False
-        if mode is not None:
-            if mode == 0: # coarse
-                value |= wxnviz.DM_WIRE
-                desc['mode'] = 'coarse'
-            elif mode == 1: # fine
-                value |= wxnviz.DM_POLY
-                desc['mode'] = 'fine'
-            else: # both
-                value |= wxnviz.DM_WIRE_POLY
-                desc['mode'] = 'both'
-
-        if style is not None:
-            if style == 0: # wire
-                value |= wxnviz.DM_GRID_WIRE
-                desc['style'] = 'wire'
-            else: # surface
-                value |= wxnviz.DM_GRID_SURF
-                desc['style'] = 'surface'
-
-        if shade is not None:
-            if shade == 0:
-                value |= wxnviz.DM_FLAT
-                desc['shading'] = 'flat'
-            else: # surface
-                value |= wxnviz.DM_GOURAUD
-                desc['shading'] = 'gouraud'
-        
-        return (value, desc)
-    
-    def SetSurfaceDefaultProp(self, data):
-        """Set default surface properties, add actions to update list"""
-        #
-        # attributes
-        #
-        for attrb in ('shine', ):
-            data['attribute'][attrb] = {}
-            for key, value in UserSettings.Get(group='nviz', key='volume',
-                                               subkey=attrb).iteritems():
-                data['attribute'][attrb][key] = value
-            self.update.append('surface:attribute:%s' % attrb)
-        
-        #
-        # draw
-        #
-        data['draw']['all'] = False # apply only for current surface
-        for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
-            if control[:3] == 'res':
-                if not data['draw'].has_key('resolution'):
-                    data['draw']['resolution'] = {}
-                if 'surface:draw:%s' % 'resolution' not in self.update:
-                    self.update.append('surface:draw:%s' % 'resolution')
-                data['draw']['resolution'][control[4:]] = value
-                continue
-            
-            elif control not in ('style', 'shading'):
-                self.update.append('surface:draw:%s' % control)
-
-            if control == 'wire-color':
-                value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
-            elif control in ('mode', 'style', 'shading'):
-                if not data['draw'].has_key('mode'):
-                    data['draw']['mode'] = {}
-                continue
-
-            data['draw'][control] = { 'value' : value }
-            
-        value, desc = self.GetDrawMode(UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'mode']),
-                                       UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'style']),
-                                       UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading']))
-
-        data['draw']['mode'] = { 'value' : value,
-                                 'desc' : desc, }
-
-    def SetVolumeDefaultProp(self, data):
-        """Set default volume properties and add actions to update list"""
-        #
-        # draw
-        #
-        for control, value in UserSettings.Get(group='nviz', key='volume', subkey='draw').iteritems():
-            if control == 'mode':
-                continue
-            if 'volume:draw:%s' % control not in self.update:
-                self.update.append('volume:draw:%s' % control)
-            if control == 'shading':
-                sel = UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading'])
-                value, desc = self.GetDrawMode(shade=sel, string=False)
-
-                data['draw']['shading'] = { 'value' : value,
-                                            'desc' : desc['shading'] }
-            elif control == 'mode':
-                sel = UserSettings.Get(group='nviz', key='volume', subkey=['draw', 'mode'])
-                if sel == 0:
-                    desc = 'isosurface'
-                else:
-                    desc = 'slice'
-                data['draw']['mode'] = { 'value' : sel,
-                                         'desc' : desc, }
-            else:
-                data['draw'][control] = { 'value' : value }
-        
-        #
-        # isosurface attributes
-        #
-        for attrb in ('shine', ):
-            data['attribute'][attrb] = {}
-            for key, value in UserSettings.Get(group='nviz', key='volume',
-                                               subkey=attrb).iteritems():
-                data['attribute'][attrb][key] = value
-        
-    def SetVectorDefaultProp(self, data):
-        """Set default vector properties, add actions to update list"""
-        self.SetVectorLinesDefaultProp(data['lines'])
-        self.SetVectorPointsDefaultProp(data['points'])
-
-    def SetVectorLinesDefaultProp(self, data):
-        """Set default vector properties -- lines"""
-        # width
-        data['width'] = UserSettings.Get(group='nviz', key='vector',
-                                                  subkey=['lines', 'width'])
-        
-        # color
-        value = UserSettings.Get(group='nviz', key='vector',
-                                 subkey=['lines', 'color'])
-        color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
-        data['color'] = color
-
-        # mode
-        if UserSettings.Get(group='nviz', key='vector',
-                            subkey=['lines', 'flat']):
-            type = 'flat'
-            map  = None
-        else:
-            if len(self.layers['raster']['name']) > 0:
-                type = 'surface'
-                map  = self.layers['raster']['name'][0]
-            else:
-                type = 'flat'
-                map = None
-
-        data['mode'] = {}
-        data['mode']['type'] = type
-        if map:
-            data['mode']['surface'] = map
-
-        # height
-        data['height'] = UserSettings.Get(group='nviz', key='vector',
-                                                   subkey=['lines', 'height'])
-
-        if data.has_key('object'):
-            self.update.append('vector:lines:color')
-            self.update.append('vector:lines:width')
-            self.update.append('vector:lines:mode')
-            self.update.append('vector:lines:height')
-
-    def SetVectorPointsDefaultProp(self, data):
-        """Set default vector properties -- points"""
-        # size
-        data['size'] = UserSettings.Get(group='nviz', key='vector',
-                                        subkey=['points', 'size'])
-
-        # width
-        data['width'] = UserSettings.Get(group='nviz', key='vector',
-                                         subkey=['points', 'width'])
-
-        # marker
-        data['marker'] = UserSettings.Get(group='nviz', key='vector',
-                                          subkey=['points', 'marker'])
-
-        # color
-        value = UserSettings.Get(group='nviz', key='vector',
-                                 subkey=['points', 'color'])
-        color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
-        data['color'] = color
-
-        # mode
-        data['mode'] = { 'type' : 'surface',
-                         'surface' : '' }
-        if len(self.layers['raster']['name']) > 0:
-            data['mode']['surface'] = self.layers['raster']['name'][0]
-        
-        # height
-        data['height'] = UserSettings.Get(group='nviz', key='vector',
-                                          subkey=['points', 'height'])
-
-        if data.has_key('object'):
-            self.update.append('vector:points:size')
-            self.update.append('vector:points:width')
-            self.update.append('vector:points:marker')
-            self.update.append('vector:points:color')
-            self.update.append('vector:points:surface')
-            self.update.append('vector:points:height')
-
-    def Reset(self):
-        """Reset (unload data)"""
-        self.nvizClass.Reset()
-        self.init = False
-
-    def OnZoomToMap(self, event):
-        """
-        Set display extents to match selected raster
-        or vector map or volume.
-
-        @todo vector, volume
-        """
-        layer = self.GetSelectedLayer()
-
-        if layer is None:
-            return
-
-        Debug.msg (3, "GLWindow.OnZoomToMap(): layer=%s, type=%s" % \
-                       (layer.name, layer.type))
-
-        self.nvizClass.SetViewportDefault()
-
-    def ResetView(self):
-        """Reset to default view"""
-        self.view['z-exag']['value'], \
-            self.iview['height']['value'], \
-            self.iview['height']['min'], \
-            self.iview['height']['max'] = self.nvizClass.SetViewDefault()
-        
-        self.view['pos']['x'] = UserSettings.Get(group='nviz', key='view',
-                                                 subkey=('pos', 'x'))
-        self.view['pos']['y'] = UserSettings.Get(group='nviz', key='view',
-                                                 subkey=('pos', 'x'))
-        self.view['persp']['value'] = UserSettings.Get(group='nviz', key='view',
-                                                       subkey=('persp', 'value'))
-
-        self.view['twist']['value'] = UserSettings.Get(group='nviz', key='view',
-                                                       subkey=('twist', 'value'))
-
-        self.update.append('view')
-
-    def UpdateLayerProperties(self, event):
-        """Update data layer properties"""
-        print self.update
-        if not hasattr(event, "layer"):
-            mapLayer = self.GetSelectedLayer()
-            data = self.GetSelectedLayer(type='nviz')
-        else:
-            mapLayer = self.tree.GetPyData(event.layer)[0]['maplayer']
-            data = self.tree.GetPyData(event.layer)[0]['nviz']
-
-        if mapLayer.type == 'raster':
-            id = data['surface']['object']['id']
-            self.UpdateSurfaceProperties(id, data['surface'])
-            # -> initialized
-            data['surface']['object']['init'] = True
-
-        elif mapLayer.type == '3d-raster':
-            id = data['volume']['object']['id']
-            if hasattr(event, "isoSurfId"):
-                self.UpdateVolumeProperties(id, data['volume'], isosurfId)
-            else:
-                self.UpdateVolumeProperties(id, data['volume'])
-            # -> initialized
-            data['volume']['object']['init'] = True
-
-        elif mapLayer.type == 'vector':
-            for type in ('lines', 'points'):
-                if data['vector'][type].has_key('object'):
-                    id = data['vector'][type]['object']['id']
-                    self.UpdateVectorProperties(id, data['vector'], type)
-                    # -> initialized
-                    data['vector'][type]['object']['init'] = True
-        print self.update
-    def UpdateSurfaceProperties(self, id, data):
-        """Update surface layer properties"""
-        # surface attributes
-        for attrb in ('topo', 'color', 'mask',
-                     'transp', 'shine', 'emit'):
-            attrb, 'surface:attribute:%s' % attrb in self.update
-            if 'surface:attribute:%s' % attrb in self.update:
-                map = data['attribute'][attrb]['map']
-                value = data['attribute'][attrb]['value']
-
-                if map is None: # unset
-                    # only optional attributes
-                    if attrb == 'mask':
-                        # TODO: invert mask
-                        # TODO: broken in NVIZ
-                        self.nvizClass.UnsetSurfaceMask(id)
-                    elif attrb == 'transp':
-                        self.nvizClass.UnsetSurfaceTransp(id)
-                    elif attrb == 'emit':
-                        self.nvizClass.UnsetSurfaceEmit(id) 
-                else:
-                    if type(value) == type('') and \
-                            len(value) <= 0: # ignore empty values (TODO: warning)
-                        continue
-                    if attrb == 'topo':
-                        self.nvizClass.SetSurfaceTopo(id, map, str(value)) 
-                    elif attrb == 'color':
-                        self.nvizClass.SetSurfaceColor(id, map, str(value))
-                    elif attrb == 'mask':
-                        # TODO: invert mask
-                        # TODO: broken in NVIZ
-                        self.nvizClass.SetSurfaceMask(id, False, str(value))
-                    elif attrb == 'transp':
-                        self.nvizClass.SetSurfaceTransp(id, map, str(value)) 
-                    elif attrb == 'shine':
-                        self.nvizClass.SetSurfaceShine(id, map, str(value)) 
-                    elif attrb == 'emit':
-                        self.nvizClass.SetSurfaceEmit(id, map, str(value)) 
-                self.update.remove('surface:attribute:%s' % attrb)
-
-        # draw res
-        if 'surface:draw:resolution' in self.update:
-            coarse = data['draw']['resolution']['coarse']
-            fine   = data['draw']['resolution']['fine']
-
-            if data['draw']['all']:
-                self.nvizClass.SetSurfaceRes(-1, fine, coarse)
-            else:
-                self.nvizClass.SetSurfaceRes(id, fine, coarse)
-            self.update.remove('surface:draw:resolution')
-
-        # draw style
-        if 'surface:draw:mode' in self.update:
-            if data['draw']['mode']['value'] < 0: # need to calculate
-                data['draw']['mode']['value'] = \
-                    self.GetDrawMode(mode=data['draw']['mode']['desc']['mode'],
-                                        style=data['draw']['mode']['desc']['style'],
-                                        shade=data['draw']['mode']['desc']['shading'],
-                                        string=True)
-            style = data['draw']['mode']['value']
-            if data['draw']['all']:
-                self.nvizClass.SetSurfaceStyle(-1, style)
-            else:
-                self.nvizClass.SetSurfaceStyle(id, style)
-            self.update.remove('surface:draw:mode')
-
-        # wire color
-        if 'surface:draw:wire-color' in self.update:
-            color = data['draw']['wire-color']['value']
-            if data['draw']['all']:
-                self.nvizClass.SetWireColor(-1, str(color))
-            else:
-                self.nvizClass.SetWireColor(id, str(color))
-                self.update.remove('surface:draw:wire-color')
-        
-        # position
-        if 'surface:position' in self.update:
-            x = data['position']['x']
-            y = data['position']['y']
-            z = data['position']['z']
-            self.nvizClass.SetSurfacePosition(id, x, y, z)
-            self.update.remove('surface:position')
-            
-    def UpdateVolumeProperties(self, id, data, isosurfId=None):
-        """Apply volume layer properties"""
-        #
-        # draw
-        #
-        if 'volume:draw:resolution' in self.update:
-            self.nvizClass.SetIsosurfaceRes(id, data['draw']['resolution']['value'])
-            self.update.remove('volume:draw:resolution')
-        
-        if 'volume:draw:shading' in self.update:
-            if data['draw']['shading']['value'] < 0: # need to calculate
-                data['draw']['shading']['value'] = \
-                    self.GetDrawMode(shade=data['draw']['shading'],
-                                     string=False)
-            self.update.remove('volume:draw:shading')
-            
-        #
-        # isosurface attributes
-        #
-        for attrb in ('color', 'mask',
-                      'transp', 'shine', 'emit'):
-            if 'volume:attribute:%s' % attrb in self.update:
-                map = data['attribute'][attrb]['map']
-                value = data['attribute'][attrb]['value']
-
-                if map is None: # unset
-                    # only optional attributes
-                    if attrb == 'mask':
-                        # TODO: invert mask
-                        # TODO: broken in NVIZ
-                        # self.nvizClass.UnsetSurfaceMask(id)
-                        pass
-                    elif attrb == 'transp':
-                        # self.nvizClass.UnsetSurfaceTransp(id)
-                        pass
-                    elif attrb == 'emit':
-                        # self.nvizClass.UnsetSurfaceEmit(id) 
-                        pass
-                else:
-                    if type(value) == type('') and \
-                            len(value) <= 0: # ignore empty values (TODO: warning)
-                        continue
-                    elif attrb == 'color' and isosurfId:
-                        self.nvizClass.SetIsosurfaceColor(id, isosurfId, map, str(value))
-                    elif attrb == 'mask':
-                        # TODO: invert mask
-                        # TODO: broken in NVIZ
-                        # self.nvizClass.SetSurfaceMask(id, False, str(value))
-                        pass
-                    elif attrb == 'transp':
-                        # self.nvizClass.SetSurfaceTransp(id, map, str(value)) 
-                        pass
-                    elif attrb == 'shine':
-                        # self.nvizClass.SetSurfaceShine(id, map, str(value)) 
-                        pass
-                    elif attrb == 'emit':
-                        # self.nvizClass.SetSurfaceEmit(id, map, str(value)) 
-                        pass
-                self.update.remove('volume:attribute:%s' % attrb)
-
-    def UpdateVectorProperties(self, id, data, type):
-        """Update vector layer properties
-
-        @param id layer id
-        @param data properties
-        @param type lines/points
-        """
-        if type == 'points':
-            self.UpdateVectorPointsProperties(id, data[type])
-        else:
-            self.UpdateVectorLinesProperties(id, data[type])
-    
-    def UpdateVectorLinesProperties(self, id, data):
-        """Apply changes for vector line layer"""
-        # mode
-        if 'vector:lines:color' in self.update or \
-                'vector:lines:width' in self.update or \
-                'vector:lines:mode' in self.update:
-            width = data['width']
-            color = data['color']
-            if data['mode']['type'] == 'flat':
-                flat = True
-                if data.has_key('surface'):
-                    data.pop('surface')
-            else:
-                flat = False
-                if not 'vector:lines:surface' in self.update:
-                    self.update.append('vector:lines:surface')
-
-            self.nvizClass.SetVectorLineMode(id, color,
-                                             width, flat)
-            if 'vector:lines:color' in self.update:
-                self.update.remove('vector:lines:color')
-            if 'vector:lines:width' in self.update:
-                self.update.remove('vector:lines:width')
-            if 'vector:lines:mode' in self.update:
-                self.update.remove('vector:lines:mode')
-        # height
-        if 'vector:lines:height' in self.update:
-            self.nvizClass.SetVectorLineHeight(id,
-                                               data['height'])
-            self.update.remove('vector:lines:height')
-
-        # surface
-        if 'vector:lines:surface' in self.update:
-            idx = self.layers['raster']['name'].index(data['mode']['surface'])
-            if idx > -1:
-                self.nvizClass.SetVectorLineSurface(id,
-                                                    self.layers['raster']['id'][idx])
-            self.update.remove('vector:lines:surface')
-
-    def UpdateVectorPointsProperties(self, id, data):
-        """Apply changes for vector point layer"""
-        if 'vector:points:size' in self.update or \
-                'vector:points:width' in self.update or \
-                'vector:points:marker' in self.update or \
-                'vector:points:color' in self.update:
-            ret = self.nvizClass.SetVectorPointMode(id, data['color'],
-                                                    data['width'], float(data['size']),
-                                                    data['marker'] + 1)
-
-            error = None
-            if ret == -1:
-                error = _("Vector point layer not found (id=%d)") % id
-            elif ret == -2:
-                error = _("Unable to set data layer properties (id=%d)") % id
-
-            if error:
-                raise gcmd.NvizError(parent=self.parent,
-                                     message=_("Setting data layer properties failed.\n\n%s") % error)
-
-            for prop in ('size', 'width', 'marker', 'color'):
-                if 'vector:points:%s' % prop in self.update:
-                    self.update.remove('vector:points:%s' % prop)
-        
-        # height
-        if 'vector:points:height' in self.update:
-            self.nvizClass.SetVectorPointHeight(id,
-                                                data['height'])
-            self.update.remove('vector:points:height')
-
-        # surface
-        if 'vector:points:surface' in self.update:
-            idx = self.layers['raster']['name'].index(data['mode']['surface'])
-            if idx > -1:
-                self.nvizClass.SetVectorPointSurface(id,
-                                                     self.layers['raster']['id'][idx])
-            self.update.remove('vector:points:surface')
-
-class NvizToolWindow(wx.Frame):
-    """Experimental window for Nviz tools
-
-    @todo integrate with Map display
-    """
-    def __init__(self, parent=None, id=wx.ID_ANY, title=_("Nviz tools"),
-                 pos=wx.DefaultPosition, size=wx.DefaultSize,
-                 style=wx.DEFAULT_FRAME_STYLE, mapWindow=None):
-        
-        self.parent = parent # MapFrame
-        self.lmgr = self.parent.gismanager # GMFrame
-        self.mapWindow = mapWindow
-
-        wx.Frame.__init__(self, parent, id, title, pos, size, style)
-
-        #
-        # icon
-        #
-        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_nviz.ico'), wx.BITMAP_TYPE_ICO))
-
-        #
-        # dialog body
-        #
-        mainSizer = wx.BoxSizer(wx.VERTICAL)
-
-        self.win = {} # window ids
-
-        #
-        # notebook
-        #
-        self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
-
-        self.page = {}
-        # view page
-        self.__createViewPage()
-        self.page['view'] = { 'id' : 0 }
-        # surface page
-        size = self.__createSurfacePage()
-        size = (size[0] + 25, size[0] + 20)
-        # vector page
-        self.__createVectorPage()
-        # volume page
-        self.__createVolumePage()
-        # settings page
-        self.__createSettingsPage()
-        self.page['settings'] = { 'id' : 1 }
-        self.UpdatePage('settings')
-        self.pageChanging = False
-
-        mainSizer.Add(item=self.notebook, proportion=1,
-                      flag=wx.EXPAND | wx.ALL, border=5)
-
-        #
-        # bindings
-        #
-        self.Bind(wx.EVT_CLOSE, self.OnClose)
-
-        #
-        # layout
-        #
-        self.SetSizer(mainSizer)
-        mainSizer.Fit(self)
-
-        self.SetSize(size)
-
-    def __createViewPage(self):
-        """Create view settings page"""
-        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
-        self.notebook.AddPage(page=panel,
-                              text=" %s " % _("View"))
-        
-        pageSizer = wx.BoxSizer(wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
-
-        self.win['view'] = {}
-
-        # position
-        posSizer = wx.GridBagSizer(vgap=3, hgap=3)
-        posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("W")),
-                     pos=(1, 0), flag=wx.ALIGN_CENTER)
-        posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("N")),
-                     pos=(0, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM)
-        viewPos = ViewPositionWindow(panel, id=wx.ID_ANY, size=(175, 175),
-                                     mapwindow=self.mapWindow)
-        self.win['view']['pos'] = viewPos.GetId()
-        posSizer.Add(item=viewPos,
-                     pos=(1, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL)
-        posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("S")),
-                     pos=(2, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_TOP)
-        posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("E")),
-                     pos=(1, 2), flag=wx.ALIGN_CENTER)
-        gridSizer.Add(item=posSizer, pos=(0, 0))
-                  
-        # perspective
-        range = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
-        self.CreateControl(panel, dict=self.win['view'], name='persp',
-                           range=(range['min'], range['max']),
-                           bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
-        gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Perspective:")),
-                      pos=(1, 0), flag=wx.ALIGN_CENTER)
-        gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['slider']), pos=(2, 0))
-        gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['spin']), pos=(3, 0),
-                      flag=wx.ALIGN_CENTER)        
-
-        # twist
-        range = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
-        self.CreateControl(panel, dict=self.win['view'], name='twist',
-                           range=(range['min'], range['max']),
-                           bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
-        gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Twist:")),
-                      pos=(1, 1), flag=wx.ALIGN_CENTER)
-        gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['slider']), pos=(2, 1))
-        gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['spin']), pos=(3, 1),
-                      flag=wx.ALIGN_CENTER)        
-
-        # height + z-exag
-        self.CreateControl(panel, dict=self.win['view'], name='height', sliderHor=False,
-                           range=(0, 1),
-                           bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
-        self.CreateControl(panel, dict=self.win['view'], name='z-exag', sliderHor=False,
-                           range=(0, 1),
-                           bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
-        heightSizer = wx.GridBagSizer(vgap=3, hgap=3)
-        heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Height:")),
-                      pos=(0, 0), flag=wx.ALIGN_LEFT, span=(1, 2))
-        heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['slider']),
-                        flag=wx.ALIGN_RIGHT, pos=(1, 0))
-        heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['spin']),
-                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
-                        wx.BOTTOM | wx.RIGHT, pos=(1, 1))
-        heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Z-exag:")),
-                      pos=(0, 2), flag=wx.ALIGN_LEFT, span=(1, 2))
-        heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['slider']),
-                        flag=wx.ALIGN_RIGHT, pos=(1, 2))
-        heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['spin']),
-                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
-                        wx.BOTTOM | wx.RIGHT, pos=(1, 3))
-
-        gridSizer.Add(item=heightSizer, pos=(0, 1), flag=wx.ALIGN_RIGHT)
-
-        # view setup + reset
-        viewSizer = wx.BoxSizer(wx.HORIZONTAL)
-
-        viewSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY,
-                                         label=_("Look at:")),
-                      flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
-        
-        viewType = wx.Choice (parent=panel, id=wx.ID_ANY, size=(125, -1),
-                              choices = [_("top"),
-                                         _("north"),
-                                         _("south"),
-                                         _("east"),
-                                         _("west"),
-                                         _("north-west"),
-                                         _("north-east"),
-                                         _("south-east"),
-                                         _("south-west")])
-        viewType.SetSelection(0)
-        viewType.Bind(wx.EVT_CHOICE, self.OnLookAt)
-        # self.win['lookAt'] = viewType.GetId()
-        viewSizer.Add(item=viewType, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
-                      border=5)
-
-        reset = wx.Button(panel, id=wx.ID_ANY, label=_("Reset"))
-        reset.SetToolTipString(_("Reset to default view"))
-        # self.win['reset'] = reset.GetId()
-        reset.Bind(wx.EVT_BUTTON, self.OnResetView)
-
-        viewSizer.Add(item=reset, proportion=1,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT,
-                      border=5)
-
-        gridSizer.AddGrowableCol(3)
-        gridSizer.Add(item=viewSizer, pos=(4, 0), span=(1, 2),
-                      flag=wx.EXPAND)
-
-        # body
-        pageSizer.Add(item=gridSizer, proportion=1,
-                      flag=wx.EXPAND | wx.ALL,
-                      border=5)
-
-        panel.SetSizer(pageSizer)
-
-        return panel.GetBestSize()
-
-    def __createSurfacePage(self):
-        """Create view settings page"""
-        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
-        self.page['surface'] = {}
-        self.page['surface']['id'] = -1
-        self.page['surface']['panel'] = panel.GetId()
-
-        # panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY)
-        # panel.SetupScrolling(scroll_x=True, scroll_y=True)
-
-        pageSizer = wx.BoxSizer(wx.VERTICAL)
-
-        self.win['surface'] = {}
-        #
-        # surface attributes
-        #
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Surface attributes")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
-
-        # type 
-        self.win['surface']['attr'] = {}
-        row = 0
-        for code, attrb in (('topo', _("Topography")),
-                           ('color', _("Color")),
-                           ('mask', _("Mask")),
-                           ('transp', _("Transparency")),
-                           ('shine', _("Shininess")),
-                           ('emit', _("Emission"))):
-            self.win['surface'][code] = {} 
-            gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label=attrb + ':'),
-                          pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-            use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                             choices = [_("map")])
-            if code not in ('topo', 'color', 'shine'):
-                use.Insert(item=_("unset"), pos=0)
-                self.win['surface'][code]['required'] = False
-            else:
-                self.win['surface'][code]['required'] = True
-            if code != 'mask':
-                use.Append(item=_('constant'))
-            self.win['surface'][code]['use'] = use.GetId()
-            use.Bind(wx.EVT_CHOICE, self.OnMapObjUse)
-            gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
-                          pos=(row, 1))
-
-            map = gselect.Select(parent=panel, id=wx.ID_ANY,
-                                 # size=globalvar.DIALOG_GSELECT_SIZE,
-                                 size=(200, -1),
-                                 type="raster")
-            self.win['surface'][code]['map'] = map.GetId() - 1 # FIXME
-            map.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
-            # changing map topography not allowed
-            if code == 'topo':
-                map.Enable(False)
-            gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
-                          pos=(row, 2))
-
-            if code == 'color':
-                value = csel.ColourSelect(panel, id=wx.ID_ANY,
-                                          colour=UserSettings.Get(group='nviz', key='surface',
-                                                                  subkey=['color', 'value']))
-                value.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceMap)
-            elif code == 'mask':
-                value = None
-            else:
-                value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                                    initial=0)
-                if code == 'topo':
-                    value.SetRange(minVal=-1e9, maxVal=1e9)
-                elif code in ('shine', 'transp', 'emit'):
-                    value.SetRange(minVal=0, maxVal=255)
-                else:
-                    value.SetRange(minVal=0, maxVal=100)
-                value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
-            
-            if value:
-                self.win['surface'][code]['const'] = value.GetId()
-                value.Enable(False)
-                gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
-                              pos=(row, 3))
-            else:
-                self.win['surface'][code]['const'] = None
-
-            self.SetMapObjUseMap(nvizType='surface',
-                                 attrb=code) # -> enable map / disable constant
-                
-            row += 1
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL,
-                      border=5)
-
-        #
-        # draw
-        #
-        self.win['surface']['draw'] = {}
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Draw")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
-        gridSizer.AddGrowableCol(4)
-
-        # mode
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Mode:")),
-                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                          choices = [_("coarse"),
-                                     _("fine"),
-                                     _("both")])
-        mode.SetSelection(0)
-        mode.SetName("selection")
-        mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
-        self.win['surface']['draw']['mode'] = mode.GetId()
-        gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(0, 1))
-
-        # resolution (mode)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Resolution:")),
-                      pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
-        resSizer = wx.BoxSizer(wx.HORIZONTAL)
-        resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                        label=_("coarse:")),
-                     flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
-        resC = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=1,
-                           min=1,
-                           max=100)
-        resC.SetName("value")
-        self.win['surface']['draw']['res-coarse'] = resC.GetId()
-        resC.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
-        resSizer.Add(item=resC, flag=wx.ALL, border=3)
-        
-        resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                        label=_("fine:")),
-                     flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
-        resF = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=1,
-                           min=1,
-                           max=100)
-        resF.SetName("value")
-        self.win['surface']['draw']['res-fine'] = resF.GetId()
-        resF.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
-        resSizer.Add(item=resF, flag=wx.ALL, border=3)
-
-        gridSizer.Add(item=resSizer, pos=(0, 3), span=(1, 2))
-
-        # style
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Coarse style:")),
-                      pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        style = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                          choices = [_("wire"),
-                                     _("surface")])
-        style.SetName("selection")
-        self.win['surface']['draw']['style'] = style.GetId()
-        style.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
-        gridSizer.Add(item=style, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(1, 1))
-
-        # shading
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Shading:")),
-                      pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
-        shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                           choices = [_("flat"),
-                                      _("gouraud")])
-        shade.SetName("selection")
-        self.win['surface']['draw']['shading'] = shade.GetId()
-        shade.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
-        gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(1, 3))
-
-        # color
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Wire color:")),
-                      pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        color = csel.ColourSelect(panel, id=wx.ID_ANY)
-        color.SetName("colour")
-        color.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceWireColor)
-        self.win['surface']['draw']['wire-color'] = color.GetId()
-        gridSizer.Add(item=color, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(2, 1))
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-
-        all = wx.Button(panel, id=wx.ID_ANY, label=_("All"))
-        all.SetToolTipString(_("Use for all loaded surfaces"))
-        # self.win['reset'] = reset.GetId()
-        all.Bind(wx.EVT_BUTTON, self.OnSurfaceModeAll)
-        gridSizer.Add(item=all, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
-                      pos=(2, 4))
-
-        #
-        # mask
-        #
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Mask")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
-
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Mask zeros:")),
-                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-
-        elev = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                           label=_("by elevation"))
-        elev.Enable(False) # TODO: not implemented yet
-        gridSizer.Add(item=elev, pos=(0, 1))
-
-        color = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                           label=_("by color"))
-        color.Enable(False) # TODO: not implemented yet
-        gridSizer.Add(item=color, pos=(0, 2))
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-
-        #
-        # position
-        #
-        self.win['surface']['position'] = {}
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Position")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
-
-        # position
-        axis = wx.Choice (parent=panel, id=wx.ID_ANY, size=(75, -1),
-                          choices = ["X",
-                                     "Y",
-                                     "Z"])
-        axis.SetSelection(0)
-        self.win['surface']['position']['axis'] = axis.GetId()
-        axis.Bind(wx.EVT_CHOICE, self.OnSurfaceAxis)
-        gridSizer.Add(item=axis, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(0, 0))
-        value = wx.Slider(parent=panel, id=wx.ID_ANY,
-                          value=0,
-                          minValue=-1e4,
-                          maxValue=1e4,
-                          style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
-                              wx.SL_TOP | wx.SL_LABELS,
-                          size=(350, -1))
-        self.win['surface']['position']['pos'] = value.GetId()
-        value.Bind(wx.EVT_SCROLL, self.OnSurfacePosition)
-        gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(0, 1))
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-        
-        panel.SetSizer(pageSizer)
-        
-        return panel.GetBestSize()
-
-    def __createVectorPage(self):
-        """Create view settings page"""
-        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
-        self.page['vector'] = {}
-        self.page['vector']['id'] = -1
-        self.page['vector']['panel'] = panel.GetId()
-
-        pageSizer = wx.BoxSizer(wx.VERTICAL)
-
-        self.win['vector'] = {}
-
-        #
-        # desc
-        #
-        desc = wx.StaticText(parent=panel, id=wx.ID_ANY,
-                             label="")
-        self.win['vector']['desc'] = desc.GetId()
-        pageSizer.Add(item=desc, proportion=0,
-                      flag=wx.EXPAND | wx.ALL,
-                      border=10)
-
-        #
-        # vector lines
-        #
-        self.win['vector']['lines'] = {}
-
-        showLines = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                label=_("Show vector lines"))
-        self.win['vector']['lines']['show'] = showLines.GetId()
-        showLines.Bind(wx.EVT_CHECKBOX, self.OnVectorShow)
-
-        pageSizer.Add(item=showLines, proportion=0,
-                      flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
-
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Vector lines")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
-
-        # width
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Width:")),
-                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-
-        width = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                            initial=1,
-                            min=1,
-                            max=100)
-        self.win['vector']['lines']['width'] = width.GetId()
-        width.Bind(wx.EVT_SPINCTRL, self.OnVectorLines)
-        gridSizer.Add(item=width, pos=(0, 1),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        gridSizer.AddGrowableCol(2)
-
-        # color
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Color:")),
-                      pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL)
-
-        color = csel.ColourSelect(panel, id=wx.ID_ANY,
-                                  colour=UserSettings.Get(group='nviz', key='vector',
-                                                          subkey=['lines', 'color']))
-        self.win['vector']['lines']['color'] = color.GetId()
-        color.Bind(csel.EVT_COLOURSELECT, self.OnVectorLines)
-
-        gridSizer.Add(item=color, pos=(0, 4))
-
-        gridSizer.AddGrowableCol(5)
-
-        # display
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Display:")),
-                      pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
-
-        display = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                             choices = [_("on surface"),
-                                        _("flat")])
-        self.win['vector']['lines']['flat'] = display.GetId()
-        display.Bind(wx.EVT_CHOICE, self.OnVectorDisplay)
-
-        gridSizer.Add(item=display, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(0, 7))
-
-        # hight
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Hight above surface:")),
-                      pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL,
-                      span=(1, 2))
-        
-        surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
-                              style=wx.CB_SIMPLE | wx.CB_READONLY,
-                              choices=[])
-        surface.Bind(wx.EVT_COMBOBOX, self.OnVectorSurface)
-        self.win['vector']['lines']['surface'] = surface.GetId()
-        gridSizer.Add(item=surface, 
-                      pos=(1, 2), span=(1, 6),
-                      flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-
-        self.CreateControl(panel, dict=self.win['vector']['lines'], name='height', size=300,
-                           range=(0, 1000),
-                           bind=(self.OnVectorHeight, self.OnVectorHeightFull, self.OnVectorHeightSpin))
-        gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['slider']),
-                      pos=(2, 2), span=(1, 6))
-        gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['spin']),
-                      pos=(3, 4),
-                      flag=wx.ALIGN_CENTER)
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                     flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-
-        #
-        # vector points
-        #
-        self.win['vector']['points'] = {}
-
-        showPoints = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                 label=_("Show vector points"))
-        self.win['vector']['points']['show'] = showPoints.GetId()
-        showPoints.Bind(wx.EVT_CHECKBOX, self.OnVectorShow)
-
-        pageSizer.Add(item=showPoints, proportion=0,
-                      flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
-
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Vector points")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
-
-        # icon size
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Icon size:")),
-                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-
-        isize = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                            initial=1,
-                            min=1,
-                            max=1e6)
-        isize.SetName('value')
-        self.win['vector']['points']['size'] = isize.GetId()
-        isize.Bind(wx.EVT_SPINCTRL, self.OnVectorPoints)
-        gridSizer.Add(item=isize, pos=(0, 1),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        # icon width
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("width:")),
-                      pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
-
-        iwidth = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                             initial=1,
-                             min=1,
-                             max=1e6)
-        iwidth.SetName('value')
-        self.win['vector']['points']['width'] = iwidth.GetId()
-        iwidth.Bind(wx.EVT_SPINCTRL, self.OnVectorPoints)
-        gridSizer.Add(item=iwidth, pos=(0, 3),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        # icon symbol
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("symbol:")),
-                      pos=(0, 4), flag=wx.ALIGN_CENTER_VERTICAL)
-        isym = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                          choices=UserSettings.Get(group='nviz', key='vector',
-                                                   subkey=['points', 'marker'], internal=True))
-        isym.SetName("selection")
-        self.win['vector']['points']['marker'] = isym.GetId()
-        isym.Bind(wx.EVT_CHOICE, self.OnVectorPoints)
-        gridSizer.Add(item=isym, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(0, 5))
-
-        # icon color
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("color:")),
-                      pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
-        icolor = csel.ColourSelect(panel, id=wx.ID_ANY)
-        icolor.SetName("color")
-        self.win['vector']['points']['color'] = icolor.GetId()
-        icolor.Bind(csel.EVT_COLOURSELECT, self.OnVectorPoints)
-        gridSizer.Add(item=icolor, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(0, 7))
-
-        # high
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Hight above surface:")),
-                      pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL,
-                      span=(1, 2))
-        
-        surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
-                              style=wx.CB_SIMPLE | wx.CB_READONLY,
-                              choices=[])
-        surface.Bind(wx.EVT_COMBOBOX, self.OnVectorSurface)
-        self.win['vector']['points']['surface'] = surface.GetId()
-        gridSizer.Add(item=surface, 
-                      pos=(1, 2), span=(1, 6),
-                      flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        self.CreateControl(panel, dict=self.win['vector']['points'], name='height', size=300,
-                           range=(0, 1000),
-                           bind=(self.OnVectorHeight, self.OnVectorHeightFull, self.OnVectorHeightSpin))
-        gridSizer.Add(item=self.FindWindowById(self.win['vector']['points']['height']['slider']),
-                      pos=(2, 2), span=(1, 6))
-        gridSizer.Add(item=self.FindWindowById(self.win['vector']['points']['height']['spin']),
-                      pos=(3, 4),
-                      flag=wx.ALIGN_CENTER)
-
-        
-        boxSizer.Add(item=gridSizer, proportion=1,
-                     flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-
-
-        panel.SetSizer(pageSizer)
-
-        return panel.GetBestSize()
-
-    def __createVolumePage(self):
-        """Create view settings page"""
-        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
-        self.page['volume'] = {}
-        self.page['volume']['id'] = -1
-        self.page['volume']['panel'] = panel.GetId()
-        
-        pageSizer = wx.BoxSizer(wx.VERTICAL)
-        
-        self.win['volume'] = {}
-
-        #
-        # draw
-        #
-        self.win['volume']['draw'] = {}
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Draw")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
-        gridSizer.AddGrowableCol(4)
-
-        # mode
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Mode:")),
-                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(150, -1),
-                          choices = [_("isosurfaces"),
-                                     _("slides")])
-        mode.SetSelection(0)
-        mode.SetName("selection")
-        # mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
-        self.win['volume']['draw']['mode'] = mode.GetId()
-        gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(0, 1))
-
-        # shading
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Shading:")),
-                      pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
-        shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                           choices = [_("flat"),
-                                      _("gouraud")])
-        shade.SetName("selection")
-        self.win['volume']['draw']['shading'] = shade.GetId()
-        shade.Bind(wx.EVT_CHOICE, self.OnVolumeIsosurfMode)
-        gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(0, 3))
-
-        # resolution (mode)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Resolution:")),
-                      pos=(0, 4), flag=wx.ALIGN_CENTER_VERTICAL)
-        resol = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                            initial=1,
-                            min=1,
-                            max=100)
-        resol.SetName("value")
-        self.win['volume']['draw']['resolution'] = resol.GetId()
-        resol.Bind(wx.EVT_SPINCTRL, self.OnVolumeIsosurfResolution)
-        gridSizer.Add(item=resol, pos=(0, 5))
-        
-        boxSizer.Add(item=gridSizer, proportion=1,
-                     flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL,
-                      border=5)
-
-        #
-        # manage isosurfaces
-        #
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("List of isosurfaces")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
-
-        # list
-        isolevel = IsoSurfList(parent=panel, win=self.win['volume'],
-                               size=(300, 150))
-        self.win['volume']['isosurfs'] = isolevel.GetId()
-        gridSizer.Add(item=isolevel, pos=(0, 0), span=(4, 1))
-        
-        # buttons (add, delete, move up, move down)
-        btnAdd = wx.Button(parent=panel, id=wx.ID_ADD)
-        self.win['volume']['btnIsosurfAdd'] = btnAdd.GetId()
-        btnAdd.Bind(wx.EVT_BUTTON, self.OnVolumeIsosurfAdd)
-        gridSizer.Add(item=btnAdd,
-                      pos=(0, 1))
-        btnDelete = wx.Button(parent=panel, id=wx.ID_DELETE)
-        self.win['volume']['btnIsosurfDelete'] = btnDelete.GetId()
-        btnDelete.Bind(wx.EVT_BUTTON, self.OnVolumeIsosurfDelete)
-        btnDelete.Enable(False)
-        gridSizer.Add(item=btnDelete,
-                      pos=(1, 1))
-        btnMoveUp = wx.Button(parent=panel, id=wx.ID_UP)
-        self.win['volume']['btnIsosurfMoveUp'] = btnMoveUp.GetId()
-        btnMoveUp.Bind(wx.EVT_BUTTON, self.OnVolumeIsosurfMoveUp)
-        btnMoveUp.Enable(False)
-        gridSizer.Add(item=btnMoveUp,
-                      pos=(2, 1))
-        btnMoveDown = wx.Button(parent=panel, id=wx.ID_DOWN)
-        self.win['volume']['btnIsosurfMoveDown'] = btnMoveDown.GetId()
-        btnMoveDown.Bind(wx.EVT_BUTTON, self.OnVolumeIsosurfMoveDown)
-        btnMoveDown.Enable(False)
-        gridSizer.Add(item=btnMoveDown,
-                      pos=(3, 1))
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                     flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-        
-        #
-        # isosurface attributes
-        #
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Isosurface attributes")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
-
-        self.win['volume']['attr'] = {}
-        row = 0
-        for code, attrb in (('topo', _("Topography level")),
-                            ('color', _("Color")),
-                            ('mask', _("Mask")),
-                            ('transp', _("Transparency")),
-                            ('shine', _("Shininess")),
-                            ('emit', _("Emission"))):
-            self.win['volume'][code] = {} 
-            # label
-            gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label=attrb + ':'),
-                          pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-            if code != 'topo':
-                use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                                 choices = [_("map")])
-            else:
-                use = None
-            # check for required properties
-            if code not in ('topo', 'color', 'shine'):
-                use.Insert(item=_("unset"), pos=0)
-                self.win['volume'][code]['required'] = False
-            else:
-                self.win['volume'][code]['required'] = True
-            if use and code != 'mask':
-                use.Append(item=_('constant'))
-            if use:
-                self.win['volume'][code]['use'] = use.GetId()
-                use.Bind(wx.EVT_CHOICE, self.OnMapObjUse)
-                gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
-                              pos=(row, 1))
-            
-            if code != 'topo':
-                map = gselect.Select(parent=panel, id=wx.ID_ANY,
-                                     # size=globalvar.DIALOG_GSELECT_SIZE,
-                                     size=(200, -1),
-                                     type="grid3")
-                self.win['volume'][code]['map'] = map.GetId() - 1 # FIXME
-                map.Bind(wx.EVT_TEXT, self.OnVolumeIsosurfMap)
-                gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
-                              pos=(row, 2))
-            else:
-                map = None
-            
-            if code == 'color':
-                value = csel.ColourSelect(panel, id=wx.ID_ANY,
-                                          colour=UserSettings.Get(group='nviz', key='volume',
-                                                                  subkey=['color', 'value']))
-                value.Bind(csel.EVT_COLOURSELECT, self.OnVolumeIsosurfMap)
-            elif code == 'mask':
-                value = None
-            else:
-                if code == 'topo':
-                    size = (200, -1)
-                else:
-                    size = (65, -1)
-                value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=size,
-                                    initial=0)
-                if code == 'topo':
-                    value.SetRange(minVal=-1e9, maxVal=1e9)
-                elif code in ('shine', 'transp', 'emit'):
-                    value.SetRange(minVal=0, maxVal=255)
-                else:
-                    value.SetRange(minVal=0, maxVal=100)
-                value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
-            
-            if value:
-                self.win['volume'][code]['const'] = value.GetId()
-                if code == 'topo':
-                    gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
-                                  pos=(row, 2))
-                else:
-                    value.Enable(False)
-                    gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
-                                  pos=(row, 3))
-            else:
-                self.win['volume'][code]['const'] = None
-            
-            if code != 'topo':
-                self.SetMapObjUseMap(nvizType='volume',
-                                     attrb=code) # -> enable map / disable constant
-                
-            row += 1
-        
-        boxSizer.Add(item=gridSizer, proportion=1,
-                     flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-        
-        panel.SetSizer(pageSizer)
-        
-        return panel.GetBestSize()
-    
-    def __createSettingsPage(self):
-        """Create settings page"""
-        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
-        self.notebook.AddPage(page=panel,
-                              text=" %s " % _("Settings"))
-        
-        pageSizer = wx.BoxSizer(wx.VERTICAL)
-
-        self.win['settings'] = {}
-
-        #
-        # general
-        #
-        self.win['settings']['general'] = {}
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("General")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
-
-        # background color
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Background color:")),
-                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-
-        color = csel.ColourSelect(panel, id=wx.ID_ANY,
-                                  colour=UserSettings.Get(group='nviz', key='settings',
-                                                          subkey=['general', 'bgcolor']))
-        self.win['settings']['general']['bgcolor'] = color.GetId()
-        color.Bind(csel.EVT_COLOURSELECT, self.OnBgColor)
-        gridSizer.Add(item=color, pos=(0, 1))
-
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL,
-                      border=5)
-
-        #
-        # view
-        #
-        self.win['settings']['view'] = {}
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("View")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
-
-
-        # perspective
-        self.win['settings']['view']['persp'] = {}
-        pvals = UserSettings.Get(group='nviz', key='view', subkey='persp')
-        ipvals = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Perspective:")),
-                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("(value)")),
-                      pos=(0, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        pval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=pvals['value'],
-                           min=ipvals['min'],
-                           max=ipvals['max'])
-        self.win['settings']['view']['persp']['value'] = pval.GetId()
-        gridSizer.Add(item=pval, pos=(0, 2),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("(step)")),
-                      pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        pstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=pvals['step'],
-                           min=ipvals['min'],
-                           max=ipvals['max']-1)
-        self.win['settings']['view']['persp']['step'] = pstep.GetId()
-        gridSizer.Add(item=pstep, pos=(0, 4),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        # position
-        self.win['settings']['view']['pos'] = {}
-        posvals = UserSettings.Get(group='nviz', key='view', subkey='pos')
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Position:")),
-                      pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("(x)")),
-                      pos=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        px = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=posvals['x'] * 100,
-                           min=0,
-                           max=100)
-        self.win['settings']['view']['pos']['x'] = px.GetId()
-        gridSizer.Add(item=px, pos=(1, 2),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label="(y)"),
-                      pos=(1, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        py = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=posvals['y'] * 100,
-                           min=0,
-                           max=100)
-        self.win['settings']['view']['pos']['y'] = py.GetId()
-        gridSizer.Add(item=py, pos=(1, 4),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        # height
-        self.win['settings']['view']['height'] = {}
-        hvals = UserSettings.Get(group='nviz', key='view', subkey='height')
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Height")),
-                      pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("(step)")),
-                      pos=(2, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        hstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=hvals['step'],
-                           min=1,
-                           max=1e6)
-        self.win['settings']['view']['height']['step'] = hstep.GetId()
-        gridSizer.Add(item=hstep, pos=(2, 2),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        # twist
-        self.win['settings']['view']['twist'] = {}
-        tvals = UserSettings.Get(group='nviz', key='view', subkey='twist')
-        itvals = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Twist")),
-                      pos=(3, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("(value)")),
-                      pos=(3, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        tval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=tvals['value'],
-                           min=itvals['min'],
-                           max=itvals['max'])
-        self.win['settings']['view']['twist']['value'] = tval.GetId()
-        gridSizer.Add(item=tval, pos=(3, 2),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("(step)")),
-                      pos=(3, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        tstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=tvals['step'],
-                           min=itvals['min'],
-                           max=itvals['max']-1)
-        self.win['settings']['view']['twist']['step'] = tstep.GetId()
-        gridSizer.Add(item=tstep, pos=(3, 4),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        # z-exag
-        self.win['settings']['view']['z-exag'] = {}
-        zvals = UserSettings.Get(group='nviz', key='view', subkey='z-exag')
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Z-exag")),
-                      pos=(4, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("(value)")),
-                      pos=(4, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        zval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=zvals['value'],
-                           min=-1e6,
-                           max=1e6)
-        self.win['settings']['view']['z-exag']['value'] = zval.GetId()
-        gridSizer.Add(item=zval, pos=(4, 2),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("(step):")),
-                      pos=(4, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-
-        zstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                           initial=zvals['step'],
-                           min=-1e6,
-                           max=1e6)
-        self.win['settings']['view']['z-exag']['step'] = zstep.GetId()
-        gridSizer.Add(item=zstep, pos=(4, 4),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-
-        #
-        # surface
-        #
-        self.win['settings']['surface'] = {}
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Surface")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
-
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-
-        #
-        # vector lines
-        #
-        self.win['settings']['vector'] = {}
-        self.win['settings']['vector']['lines'] = {}
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Vector lines")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
-
-        # show
-        row = 0
-        showLines = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                label=_("Show lines"))
-        self.win['settings']['vector']['lines']['show'] = showLines.GetId()
-        showLines.SetValue(UserSettings.Get(group='nviz', key='vector',
-                                            subkey=['lines', 'show']))
-        gridSizer.Add(item=showLines, pos=(row, 0))
-
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-
-        #
-        # vector points
-        #
-        self.win['settings']['vector']['points'] = {}
-        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
-                            label=" %s " % (_("Vector points")))
-        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap=3, hgap=5)
-
-        # show
-        row = 0
-        showPoints = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                 label=_("Show points"))
-        showPoints.SetValue(UserSettings.Get(group='nviz', key='vector',
-                                             subkey=['points', 'show']))
-        self.win['settings']['vector']['points']['show'] = showPoints.GetId()
-        gridSizer.Add(item=showPoints, pos=(row, 0), span=(1, 8))
-
-        # icon size
-        row += 1 
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Size:")),
-                      pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
-        
-        isize = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                            initial=100,
-                            min=1,
-                            max=1e6)
-        self.win['settings']['vector']['points']['size'] = isize.GetId()
-        isize.SetValue(UserSettings.Get(group='nviz', key='vector',
-                                        subkey=['points', 'size']))
-        gridSizer.Add(item=isize, pos=(row, 1),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-
-        # icon width
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Witdh:")),
-                      pos=(row, 2), flag=wx.ALIGN_CENTER_VERTICAL)
-        
-        iwidth = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
-                            initial=2,
-                            min=1,
-                            max=1e6)
-        self.win['settings']['vector']['points']['width'] = isize.GetId()
-        iwidth.SetValue(UserSettings.Get(group='nviz', key='vector',
-                                         subkey=['points', 'width']))
-        gridSizer.Add(item=iwidth, pos=(row, 3),
-                      flag=wx.ALIGN_CENTER_VERTICAL)
-
-        # icon symbol
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Marker:")),
-                      pos=(row, 4), flag=wx.ALIGN_CENTER_VERTICAL)
-        isym = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
-                          choices=UserSettings.Get(group='nviz', key='vector',
-                                                   subkey=['points', 'marker'], internal=True))
-        isym.SetName("selection")
-        self.win['settings']['vector']['points']['marker'] = isym.GetId()
-        isym.SetSelection(UserSettings.Get(group='nviz', key='vector',
-                                           subkey=['points', 'marker']))
-        gridSizer.Add(item=isym, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(row, 5))
-
-        # icon color
-        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=_("Color:")),
-                      pos=(row, 6), flag=wx.ALIGN_CENTER_VERTICAL)
-        icolor = csel.ColourSelect(panel, id=wx.ID_ANY)
-        icolor.SetName("color")
-        self.win['settings']['vector']['points']['color'] = icolor.GetId()
-        icolor.SetColour(UserSettings.Get(group='nviz', key='vector',
-                                          subkey=['points', 'color']))
-        gridSizer.Add(item=icolor, flag=wx.ALIGN_CENTER_VERTICAL,
-                      pos=(row, 7))
-
-        boxSizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=3)
-        pageSizer.Add(item=boxSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-                      border=5)
-
-        #
-        # buttons
-        #
-        btnDefault = wx.Button(panel, wx.ID_CANCEL, label=_("Default"))
-        btnSave = wx.Button(panel, wx.ID_SAVE)
-        btnApply = wx.Button(panel, wx.ID_APPLY)
-
-        btnDefault.Bind(wx.EVT_BUTTON, self.OnDefault)
-        btnDefault.SetToolTipString(_("Restore default settings"))
-        btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
-        btnApply.SetToolTipString(_("Apply changes for the current session"))
-        btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
-        btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
-        btnSave.SetDefault()
-
-        btnSizer = wx.StdDialogButtonSizer()
-        btnSizer.AddButton(btnDefault)
-        btnSizer.AddButton(btnApply)
-        btnSizer.AddButton(btnSave)
-        btnSizer.Realize()
-
-        pageSizer.Add(item=btnSizer, proportion=1,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM,
-                      border=5)
-
-        panel.SetSizer(pageSizer)
-
-        return panel.GetBestSize()
-
-    def CreateControl(self, parent, dict, name, range, bind, sliderHor=True, size=200):
-        """Add control (Slider + SpinCtrl)"""
-        dict[name] = {}
-        if sliderHor:
-            style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
-                wx.SL_BOTTOM
-            sizeW = (size, -1)
-        else:
-            style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | \
-                wx.SL_BOTTOM | wx.SL_INVERSE
-            sizeW = (-1, size)
-        try:
-            val = self.mapWindow.view[name]['value']
-        except KeyError:
-            val=-1
-        slider = wx.Slider(parent=parent, id=wx.ID_ANY,
-                           value=val,
-                           minValue=range[0],
-                           maxValue=range[1],
-                           style=style,
-                           size=sizeW)
-        slider.SetName('slider')
-        slider.Bind(wx.EVT_SCROLL, bind[0])
-        slider.Bind(wx.EVT_SCROLL_CHANGED, bind[1])
-        dict[name]['slider'] = slider.GetId()
-
-        spin = wx.SpinCtrl(parent=parent, id=wx.ID_ANY, size=(65, -1),
-                           initial=val,
-                           min=range[0],
-                           max=range[1])
-        #         spin = wx.SpinButton(parent=parent, id=wx.ID_ANY)
-        #         spin.SetValue (self.mapWindow.view[name]['value'])
-        #         spin.SetRange(self.mapWindow.view[name]['min'],
-        #                      self.mapWindow.view[name]['max'])
-
-        # no 'changed' event ... (FIXME)
-        spin.SetName('spin')
-        spin.Bind(wx.EVT_SPINCTRL, bind[2])
-        dict[name]['spin'] = spin.GetId()
-
-    def UpdateSettings(self):
-        """Update dialog settings"""
-        for control in ('height',
-                        'persp',
-                        'twist',
-                        'z-exag'):
-            for win in self.win['view'][control].itervalues():
-                if control == 'height':
-                    value = UserSettings.Get(group='nviz', key='view',
-                                             subkey=['height', 'value'], internal=True)
-                else:
-                    value = self.mapWindow.view[control]['value']
-                self.FindWindowById(win).SetValue(value)
-
-        self.FindWindowById(self.win['view']['pos']).Draw()
-        self.FindWindowById(self.win['view']['pos']).Refresh(False)
-        
-        self.Refresh(False)
-
-    def __GetWindowName(self, dict, id):
-        for name in dict.iterkeys():
-            if type(dict[name]) is type({}):
-                for win in dict[name].itervalues():
-                    if win == id:
-                        return name
-            else:
-                if dict[name] == id:
-                    return name
-
-        return None
-
-    def OnViewChange(self, event):
-        """Change view, render in quick mode"""
-        # find control
-        winName = self.__GetWindowName(self.win['view'], event.GetId())
-        if not winName:
-            return
-
-        if winName == 'height':
-            view = self.mapWindow.iview # internal
-        else:
-            view = self.mapWindow.view
-
-        view[winName]['value'] = event.GetInt()
-
-        for win in self.win['view'][winName].itervalues():
-            self.FindWindowById(win).SetValue(view[winName]['value'])
-
-        self.mapWindow.update.append('view')
-        if winName == 'z-exag':
-            self.mapWindow.update.append('z-exag')
-        
-        self.mapWindow.render['quick'] = True
-        self.mapWindow.Refresh(False)
-
-    def OnViewChanged(self, event):
-        """View changed, render in full resolution"""
-        self.mapWindow.render['quick'] = False
-        self.mapWindow.Refresh(False)
-
-    def OnViewChangedSpin(self, event):
-        """View changed, render in full resolution"""
-        # TODO: use step value instead
-
-        self.OnViewChange(event)
-        self.OnViewChanged(None)
-
-    def OnResetView(self, event):
-        """Reset to default view (view page)"""
-        self.mapWindow.ResetView()
-        self.UpdateSettings()
-        self.mapWindow.Refresh(False)
-
-    def OnLookAt(self, event):
-        """Look at (view page)"""
-        sel = event.GetSelection()
-        if sel == 0: # top
-            self.mapWindow.view['pos']['x'] = 0.5
-            self.mapWindow.view['pos']['y'] = 0.5
-        elif sel == 1: # north
-            self.mapWindow.view['pos']['x'] = 0.5
-            self.mapWindow.view['pos']['y'] = 0.0
-        elif sel == 2: # south
-            self.mapWindow.view['pos']['x'] = 0.5
-            self.mapWindow.view['pos']['y'] = 1.0
-        elif sel == 3: # east
-            self.mapWindow.view['pos']['x'] = 1.0
-            self.mapWindow.view['pos']['y'] = 0.5
-        elif sel == 4: # west
-            self.mapWindow.view['pos']['x'] = 0.0
-            self.mapWindow.view['pos']['y'] = 0.5
-        elif sel == 5: # north-west
-            self.mapWindow.view['pos']['x'] = 0.0
-            self.mapWindow.view['pos']['y'] = 0.0
-        elif sel == 6: # north-east
-            self.mapWindow.view['pos']['x'] = 1.0
-            self.mapWindow.view['pos']['y'] = 0.0
-        elif sel == 7: # south-east
-            self.mapWindow.view['pos']['x'] = 1.0
-            self.mapWindow.view['pos']['y'] = 1.0
-        elif sel == 8: # south-west
-            self.mapWindow.view['pos']['x'] = 0.0
-            self.mapWindow.view['pos']['y'] = 1.0
-
-        self.mapWindow.update.append('view')
-
-        self.UpdateSettings()
-
-        self.mapWindow.Refresh(False)
-
-    def OnDefault(self, event):
-        """Restore default settings"""
-        settings = copy.deepcopy(UserSettings.GetDefaultSettings()['nviz'])
-        UserSettings.Set(group='nviz',
-                         value=settings)
-        
-        for subgroup, key in settings.iteritems(): # view, surface, vector...
-            if subgroup != 'view':
-                continue
-            for subkey, value in key.iteritems():
-                for subvalue in value.keys():
-                    win = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue])
-                    val = settings[subgroup][subkey][subvalue]
-                    if subkey == 'pos':
-                        val = int(val * 100)
-
-                    win.SetValue(val)
-        
-        event.Skip()
-
-    def OnApply(self, event):
-        """Apply button pressed"""
-        if self.notebook.GetSelection() == self.page['settings']['id']:
-            self.ApplySettings()
-        
-        if event:
-            event.Skip()
-
-    def ApplySettings(self):
-        """Apply Nviz settings for current session"""
-        settings = UserSettings.Get(group='nviz')
-        for subgroup, key in settings.iteritems(): # view, surface, vector...
-            for subkey, value in key.iteritems():
-                for subvalue in value.keys():
-                    try: # TODO
-                        win = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue])
-                    except:
-                        # print 'e', subgroup, subkey, subvalue
-                        continue
-                    
-                    if win.GetName() == "selection":
-                        value = win.GetSelection()
-                    elif win.GetName() == "color":
-                        value = tuple(win.GetColour())
-                    else:
-                        value = win.GetValue()
-                    if subkey == 'pos':
-                        value = float(value) / 100
-                    
-                    settings[subgroup][subkey][subvalue] = value
-                    
-    def OnSave(self, event):
-        """OK button pressed
-        
-        Apply changes, update map and save settings of selected layer
-        """
-        #
-        # apply changes
-        #
-        self.OnApply(None)
-
-        if self.notebook.GetSelection() == self.page['settings']['id']:
-            fileSettings = {}
-            UserSettings.ReadSettingsFile(settings=fileSettings)
-            fileSettings['nviz'] = UserSettings.Get(group='nviz')
-            file = UserSettings.SaveToFile(fileSettings)
-            self.lmgr.goutput.WriteLog(_('Nviz settings saved to file <%s>.') % file)
-
-    def OnBgColor(self, event):
-        """Background color changed"""
-        color = event.GetValue()
-        color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
-
-        self.mapWindow.nvizClass.SetBgColor(str(color))
-
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-        
-    def OnClose(self, event):
-        """Close button pressed
-        
-        Close dialog
-        """
-        self.Hide()
-
-    def OnMapObjUse(self, event):
-        """Surface attribute -- use -- map/constant"""
-        if not self.mapWindow.init:
-            return
-
-        wx.Yield()
-
-        # find attribute row
-        attrb = self.__GetWindowName(self.win['surface'], event.GetId())
-        if not attrb:
-            attrb = self.__GetWindowName(self.win['volume'], event.GetId())
-            nvizType = 'volume'
-        else:
-            nvizType = 'surface'
-        
-        selection = event.GetSelection()
-        if self.win[nvizType][attrb]['required']: # no 'unset'
-            selection += 1
-        if selection == 0: # unset
-            useMap = None
-            value = ''
-        elif selection == 1: # map
-            useMap = True
-            value = self.FindWindowById(self.win[nvizType][attrb]['map']).GetValue()
-        elif selection == 2: # constant
-            useMap = False
-            if attrb == 'color':
-                value = self.FindWindowById(self.win[nvizType][attrb]['const']).GetColour()
-                value = self._getColorString(value)
-            else:
-                value = self.FindWindowById(self.win[nvizType][attrb]['const']).GetValue()
-
-        self.SetMapObjUseMap(nvizType=nvizType,
-                             attrb=attrb, map=useMap)
-        
-        self.mapWindow.update.append('%s:attribute:%s' % (nvizType, attrb))
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        data[nvizType]['attribute'][attrb] = { 'map' : useMap,
-                                               'value' : str(value),
-                                               }
-
-        # update properties
-        event = wxUpdateProperties()
-        wx.PostEvent(self.mapWindow, event)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-    def SetMapObjUseMap(self, nvizType, attrb, map=None):
-        if attrb in ('topo', 'color', 'shine'):
-            incSel = -1 # decrement selection (no 'unset')
-        else:
-            incSel = 0
-
-        if map is True: # map
-            if attrb != 'topo': # changing map topography not allowed
-                # not sure why, but here must be disabled both ids, should be fixed!
-                self.FindWindowById(self.win[nvizType][attrb]['map'] + 1).Enable(True)
-            if self.win[nvizType][attrb]['const']:
-                self.FindWindowById(self.win[nvizType][attrb]['const']).Enable(False)
-            self.FindWindowById(self.win[nvizType][attrb]['use']).SetSelection(1 + incSel)
-        elif map is False: # const
-            self.FindWindowById(self.win[nvizType][attrb]['map'] + 1).Enable(False)
-            if self.win[nvizType][attrb]['const']:
-                self.FindWindowById(self.win[nvizType][attrb]['const']).Enable(True)
-            self.FindWindowById(self.win[nvizType][attrb]['use']).SetSelection(2 + incSel)
-        else: # unset
-            self.FindWindowById(self.win[nvizType][attrb]['map'] + 1).Enable(False)
-            if self.win[nvizType][attrb]['const']:
-                self.FindWindowById(self.win[nvizType][attrb]['const']).Enable(False)
-            self.FindWindowById(self.win[nvizType][attrb]['use']).SetSelection(0)
-
-    def OnSurfaceMap(self, event):
-        """Set surface attribute"""
-        self.SetMapObjAttrb(nvizType='surface', winId=event.GetId())
-        
-    def SetMapObjAttrb(self, nvizType, winId):
-        """Set map object attrbite"""
-        if not self.mapWindow.init:
-            return
-
-        attrb = self.__GetWindowName(self.win[nvizType], winId) 
-        if not attrb:
-            return
-
-        selection = self.FindWindowById(self.win[nvizType][attrb]['use']).GetSelection()
-        if self.win[nvizType][attrb]['required']:
-            selection += 1
-
-        if selection == 0: # unset
-            map = None
-            value = ''
-        elif selection == 1: # map
-            value = self.FindWindowById(self.win[nvizType][attrb]['map']).GetValue()
-            map = True
-        else: # constant
-            if attrb == 'color':
-                value = self.FindWindowById(self.win[nvizType][attrb]['const']).GetColour()
-                # tuple to string
-                value = self._getColorString(value)
-            else:
-                value = self.FindWindowById(self.win[nvizType][attrb]['const']).GetValue()
-            map = False
-        
-        if not self.pageChanging:
-            self.mapWindow.update.append('%s:attribute:%s' % (nvizType, attrb))
-            data = self.mapWindow.GetSelectedLayer(type='nviz')
-            data[nvizType]['attribute'][attrb] = { 'map' : map,
-                                                   'value' : str(value),
-                                                   }
-            
-            # update properties
-            event = wxUpdateProperties()
-            wx.PostEvent(self.mapWindow, event)
-            
-            if self.parent.autoRender.IsChecked():
-                self.mapWindow.Refresh(False)
-
-    def OnSurfaceResolution(self, event):
-        """Draw resolution changed"""
-        self.SetSurfaceResolution()
-
-        if apply and self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-    def SetSurfaceResolution(self):
-        """Set draw resolution"""
-        coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
-        fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
-            
-        self.mapWindow.update.append('surface:draw:resolution')
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        data['surface']['draw']['resolution'] = { 'coarse' : coarse,
-                                                  'fine' : fine }
-        
-        # update properties
-        event = wxUpdateProperties(layer=item)
-        wx.PostEvent(self.mapWindow, event)
-        
-    def SetSurfaceMode(self):
-        """Set draw mode
-
-        @param apply allow auto-rendering
-        """
-        mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
-        if mode == 0: # coarse
-            self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
-            self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
-        elif mode == 1: # fine
-            self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
-            self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
-        else: # both
-            self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
-            self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
-
-        style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
-
-        shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
-
-        value, desc = self.mapWindow.GetDrawMode(mode, style, shade)
-
-        return value, desc
-
-    def OnSurfaceMode(self, event):
-        """Set draw mode"""
-        value, desc = self.SetSurfaceMode()
-
-        self.mapWindow.update.append('surface:draw:mode')
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        data['surface']['draw']['mode'] = { 'value' : value,
-                                            'desc' : desc }
-        
-        # update properties
-        event = wxUpdateProperties()
-        wx.PostEvent(self.mapWindow, event)
-        
-        if apply and self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-    def OnSurfaceModeAll(self, event):
-        """Set draw mode (including wire color) for all loaded surfaces"""
-        self.SetSurfaceMode(all=True)
-        self.SetSurfaceResolution(all=True)
-        ### color = self.FindWindowById(self.win['surface']['draw']['wire-color']).GetColour()
-
-        if apply and self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-    def _getColorString(self, color):
-        """Set wire color"""
-        return str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
-
-    def OnSurfaceWireColor(self, event):
-        """Set wire color"""
-        self.mapWindow.update.append('surface:draw:wire-color')
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        value = self._getColorString(event.GetValue())
-        data['surface']['draw']['wire-color'] = { 'value' : value }
-        
-        
-        # update properties
-        event = wxUpdateProperties()
-        wx.PostEvent(self.mapWindow, event)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-    def OnSurfaceAxis(self, event):
-        """Surface position, axis changed"""
-        mapLayer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        id = data['object']['id']
-
-        axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
-        win = self.FindWindowById(self.win['surface']['position']['pos'])
-
-        x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
-
-        if axis == 0: # x
-            win.SetRange(-1e4, 1e4)
-            win.SetValue(x)
-        elif axis == 1: # y
-            win.SetRange(-1e4, 1e4)
-            win.SetValue(y)
-        else: # z
-            win.SetRange(-1e3, 1e3)
-            win.SetValue(z)
-
-    def OnSurfacePosition(self, event):
-        """Surface position"""
-        axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
-        value = event.GetInt()
-
-        mapLayer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        id = data['object']['id']
-        x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
-
-        if axis == 0: # x
-            x = value
-        elif axis == 1: # y
-            y = value
-        else: # z
-            z = value
-        
-        self.mapWindow.update.append('surface:position')
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        data['surface']['position']['x'] = x
-        data['surface']['position']['y'] = y
-        data['surface']['position']['z'] = z
-        
-        # update properties
-        event = wxUpdateProperties(layer=item)
-        wx.PostEvent(self.mapWindow, event)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-    def UpdateVectorShow(self, vecType, enabled):
-        """Enable/disable lines/points widgets
-
-        @param vecType vector type (lines, points)
-        """
-        if vecType != 'lines' and vecType != 'points':
-            return False
-
-        for win in self.win['vector'][vecType].keys():
-            if win == 'show':
-                continue
-            if type(self.win['vector'][vecType][win]) == type({}):
-                for swin in self.win['vector'][vecType][win].keys():
-                    if enabled:
-                        self.FindWindowById(self.win['vector'][vecType][win][swin]).Enable(True)
-                    else:
-                        self.FindWindowById(self.win['vector'][vecType][win][swin]).Enable(False)
-            else:
-                if enabled:
-                    self.FindWindowById(self.win['vector'][vecType][win]).Enable(True)
-                else:
-                    self.FindWindowById(self.win['vector'][vecType][win]).Enable(False)
-
-        return True
-    
-    def OnVectorShow(self, event):
-        """Show vector lines/points"""
-        winId = event.GetId()
-        if winId == self.win['vector']['lines']['show']:
-            vecType = 'lines'
-        else: # points
-            vecType = 'points'
-
-        checked = event.IsChecked()
-        item = self.mapWindow.GetSelectedLayer(type='item')
-        data = self.mapWindow.GetSelectedLayer(type='nviz')['vector']
-        
-        if checked:
-            self.mapWindow.LoadVector(item, (vecType,))
-        else:
-            self.mapWindow.UnloadVector(item, (vecType,))
-        
-        self.UpdateVectorShow(vecType, checked)
-        
-        if checked:
-            try:
-                id = data[vecType]['object']['id']
-            except KeyError:
-                id = -1
-
-            if id > 0:
-                self.mapWindow.SetLayerData(item, id, vecType)
-        
-                # update properties
-                event = wxUpdateProperties(layer=item)
-                wx.PostEvent(self.mapWindow, event)
-                
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-        
-        event.Skip()
-    
-    def OnVectorDisplay(self, event):
-        """Display vector lines on surface/flat"""
-        if event.GetSelection() == 0: # surface
-            if len(self.mapWindow.layers['raster']['name']) < 1:
-                event.Veto()
-                return
-
-            self.FindWindowById(self.win['vector']['lines']['surface']).Enable(True)
-            # set first found surface
-            data = self.mapWindow.GetSelectedLayer(type='nviz')
-            data['vector']['lines']['mode']['surface'] = self.mapWindow.layers['raster']['name'][0]
-            self.FindWindowById(self.win['vector']['lines']['surface']).SetStringSelection( \
-                self.mapWindow.layers['raster']['name'][0])
-        else: # flat
-            self.FindWindowById(self.win['vector']['lines']['surface']).Enable(False)
-
-        self.OnVectorLines(event)
-
-        event.Skip()
-
-    def OnVectorLines(self, event):
-        """Set vector lines mode, apply changes if auto-rendering is enabled"""
-        width = self.FindWindowById(self.win['vector']['lines']['width']).GetValue()
-
-        color = self.FindWindowById(self.win['vector']['lines']['color']).GetColour()
-        color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
-
-        mode = {}
-        if self.FindWindowById(self.win['vector']['lines']['flat']).GetSelection() == 0:
-            mode['type'] = 'surface'
-            mode['surface'] = self.FindWindowById(self.win['vector']['lines']['surface']).GetValue()
-            self.mapWindow.update.append('vector:lines:surface')
-        else:
-            mode['type'] = 'flat'
-
-        self.mapWindow.update.append('vector:lines:width')
-        self.mapWindow.update.append('vector:lines:color')
-        self.mapWindow.update.append('vector:lines:mode')
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        data['vector']['lines']['width'] = width
-        data['vector']['lines']['color'] = color
-        data['vector']['lines']['mode'] = mode
-        
-        # update properties
-        event = wxUpdateProperties()
-        wx.PostEvent(self.mapWindow, event)
-                        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-        
-    def OnVectorHeight(self, event):
-        value = event.GetInt()
-        id = event.GetId()
-        if id == self.win['vector']['lines']['height']['spin'] or \
-                id == self.win['vector']['lines']['height']['slider']:
-            vtype = 'lines'
-        else:
-            vtype = 'points'
-        
-        if type(event) == type(wx.ScrollEvent()):
-            # slider
-            win = self.FindWindowById(self.win['vector'][vtype]['height']['spin'])
-        else:
-            # spin
-            win = self.FindWindowById(self.win['vector'][vtype]['height']['slider'])
-        win.SetValue(value)
-
-        self.mapWindow.update.append('vector:%s:height' % vtype)
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        
-        data['vector'][vtype]['height'] = value
-
-        # update properties
-        event = wxUpdateProperties()
-        wx.PostEvent(self.mapWindow, event)
-        
-        self.mapWindow.render['quick'] = True
-        self.mapWindow.render['v' + vtype] = True
-        self.mapWindow.Refresh(False)
-    
-    def OnVectorHeightFull(self, event):
-        """Vector height changed, render in full resolution"""
-        id = event.GetId()
-        if id == self.win['vector']['lines']['height']['spin'] or \
-                id == self.win['vector']['lines']['height']['slider']:
-            vtype = 'lines'
-        else:
-            vtype = 'points'
-
-        self.mapWindow.render['quick'] = False
-        self.mapWindow.render['v' + vtype] = False
-        self.mapWindow.Refresh(False)
-
-    def OnVectorHeightSpin(self, event):
-        """Vector height changed, render in full resolution"""
-        # TODO: use step value instead
-
-        self.OnVectorHeight(event)
-        self.OnVectorHeightFull(event)
-
-    def OnVectorSurface(self, event):
-        """Reference surface for vector map (lines/points)"""
-        id = event.GetId()
-        if id == self.win['vector']['lines']['surface']:
-            vtype = 'lines'
-        else:
-            vtype = 'points'
-
-        self.mapWindow.update.append('vector:%s:surface' % vtype)
-        
-        data['vector'][vtype]['mode']['surface'] = event.GetValue()
-        
-        # update properties
-        event = wxUpdateProperties()
-        wx.PostEvent(self.mapWindow, event)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-        
-    def OnVectorPoints(self, event):
-        """Set vector points mode, apply changes if auto-rendering is enabled"""
-        size  = self.FindWindowById(self.win['vector']['points']['size']).GetValue()
-        width = self.FindWindowById(self.win['vector']['points']['width']).GetValue()
-
-        color = self.FindWindowById(self.win['vector']['points']['color']).GetColour()
-        color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
-
-        marker = self.FindWindowById(self.win['vector']['points']['marker']).GetSelection()
-
-        self.mapWindow.update.append('vector:points:size')
-        self.mapWindow.update.append('vector:points:width')
-        self.mapWindow.update.append('vector:points:color')
-        self.mapWindow.update.append('vector:points:marker')
-        data = self.mapWindow.GetSelectedLayer(type='nviz')['vector']['points']
-        data['size'] = size
-        data['width'] = width
-        data['color'] = color
-        data['marker'] = marker
-
-        # update properties
-        event = wxUpdateProperties()
-        wx.PostEvent(self.mapWindow, event)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-    def UpdateIsosurfButtons(self, list):
-        """Enable/disable buttons 'add', 'delete',
-        'move up', 'move down'"""
-        nitems = list.GetCount()
-        add = self.parent.FindWindowById(self.win['volume']['btnIsosurfAdd'])
-        delete = self.parent.FindWindowById(self.win['volume']['btnIsosurfDelete'])
-        moveDown = self.parent.FindWindowById(self.win['volume']['btnIsosurfMoveDown'])
-        moveUp = self.parent.FindWindowById(self.win['volume']['btnIsosurfMoveUp'])
-        if nitems >= wxnviz.MAX_ISOSURFS:
-            # disable add button on max
-            add.Enable(False)
-        else:
-            add.Enable(True)
-
-        if nitems < 1:
-            # disable 'delete' if only one item in the lis
-            delete.Enable(False)
-        else:
-            delete.Enable(True)
-
-        if list.GetSelection() >= nitems - 1:
-            # disable 'move-down' if last
-            moveDown.Enable(False)
-        else:
-            moveDown.Enable(True)
-
-        if list.GetSelection() < 1:
-            # disable 'move-up' if first
-            moveUp.Enable(False)
-        else:
-            moveUp.Enable(True)
-        
-    def OnVolumeIsosurfMode(self, event):
-        """Set isosurface draw mode"""
-        self.SetIsosurfaceMode(event.GetSelection())
-    
-    def SetIsosurfaceMode(self, selection):
-        """Set isosurface draw mode"""
-        layer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
-        id = data['object']['id']
-
-        mode = 0
-        if selection == 0:
-            mode |= wxnviz.DM_FLAT
-        else:
-            mode |= wxnviz.DM_GOURAUD
-        
-        self.mapWindow.nvizClass.SetIsosurfaceMode(id, mode)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-        
-    def OnVolumeIsosurfResolution(self, event):
-        """Set isosurface draw resolution"""
-        self.SetIsosurfaceResolution(event.GetInt())
-    
-    def SetIsosurfaceResolution(self, res):
-        """Set isosurface draw resolution"""
-        layer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
-        id = data['object']['id']
-        self.mapWindow.nvizClass.SetIsosurfaceRes(id, res)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-    def OnVolumeIsosurfMap(self, event):
-        """Set surface attribute"""
-        self.SetMapObjAttrb(nvizType='surface', winId=event.GetId())
-                
-    def OnVolumeIsosurfAdd(self, event):
-        """Add new isosurface to the list"""
-        list = self.FindWindowById(self.win['volume']['isosurfs'])
-        level = self.FindWindowById(self.win['volume']['topo']['const']).GetValue()
-        
-        sel = list.GetSelection()
-        if sel < 0 or sel >= list.GetCount() - 1:
-            item = list.Append(item="%s %s" % (_("Level"), str(level)))
-        else:
-            list.Insert(item="%s %s" % (_("Level"), str(level)),
-                        pos=sel+1) # append
-            item = sel + 1
-        print item
-        list.Check(item)
-        list.SetSelection(item)
-        
-        layer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
-        id = data['object']['id']
-        
-        # collect properties
-        isosurfData = {}
-        for attrb in ('topo', 'color', 'mask',
-                      'transp', 'shine', 'emit'):
-            if attrb == 'topo':
-                isosurfData[attrb] = {}
-                win = self.FindWindowById(self.win['volume'][attrb]['const'])
-                isosurfData[attrb]['value'] = win.GetValue()
-            else:
-                uwin = self.FindWindowById(self.win['volume'][attrb]['use'])
-                sel = uwin.GetSelection()
-                if self.win['volume'][attrb]['required']:
-                    sel += 1
-                if sel == 0: # unset
-                    continue
-
-                isosurfData[attrb] = {}
-                if sel == 1: # map
-                    isosurfData[attrb]['map'] = True
-                    vwin = self.FindWindowById(self.win['volume'][attrb]['map'])
-                    value = vwin.GetValue()
-                else: # const
-                    isosurfData[attrb]['map'] = False
-                    vwin = self.FindWindowById(self.win['volume'][attrb]['const'])
-                    if vwin.GetName() == "color":
-                        value = self._getColorString(vwin.GetValue())
-                    else:
-                        value = vwin.GetValue()
-                isosurfData[attrb]['value'] = value
-
-        data['isosurface'].insert(item, isosurfData)
-        print '#', data
-
-        # add isosurface        
-        self.mapWindow.nvizClass.AddIsosurface(id, level)
-        self.mapWindow.nvizClass.SetIsosurfaceColor(id, 0, True, str(layer.name))
-
-        # update buttons
-        self.UpdateIsosurfButtons(list)
-
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-
-        event.Skip()
-        
-    def OnVolumeIsosurfDelete(self, event):
-        """Remove isosurface from list"""
-        list = self.FindWindowById(self.win['volume']['isosurfs'])
-        
-        # remove item from list
-        isosurfId = list.GetSelection()
-        list.Delete(isosurfId)
-        # select last item
-        if list.GetCount() > 0:
-            list.SetSelection(list.GetCount()-1)
-        
-        layer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
-        id = data['object']['id']
-
-        # delete isosurface
-        del data['isosurface'][isosurfId]
-        print '#', data
-        self.mapWindow.nvizClass.DeleteIsosurface(id, isosurfId)
-
-        # update buttons
-        self.UpdateIsosurfButtons(list)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-        
-        event.Skip()
-        
-    def OnVolumeIsosurfMoveUp(self, event):
-        """Move isosurface up in the list"""
-        list = self.FindWindowById(self.win['volume']['isosurfs'])
-        sel = list.GetSelection()
-
-        if sel < 1:
-            return # this should not happen
-
-        layer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
-        id = data['object']['id']
-
-        # move item up
-        text = list.GetStringSelection()
-        list.Insert(item=text, pos=sel-1)
-        list.Check(sel-1)
-        list.SetSelection(sel-1)
-        list.Delete(sel+1)
-        data['isosurface'].insert(sel-1, data['isosurface'][sel])
-        del data['isosurface'][sel+1]
-        self.mapWindow.nvizClass.MoveIsosurface(id, sel, True)
-
-        print '#', data
-        
-        # update buttons
-        self.UpdateIsosurfButtons(list)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-        
-        event.Skip()
-        
-    def OnVolumeIsosurfMoveDown(self, event):
-        """Move isosurface dowm in the list"""
-        list = self.FindWindowById(self.win['volume']['isosurfs'])
-        sel = list.GetSelection()
-
-        if sel >= list.GetCount() - 1:
-            return # this should not happen
-
-        layer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
-        id = data['object']['id']
-
-        # move item up
-        text = list.GetStringSelection()
-        list.Insert(item=text, pos=sel+2)
-        list.Check(sel+2)
-        list.SetSelection(sel+2)
-        list.Delete(sel)
-        data['isosurface'].insert(sel+2, data['isosurface'][sel])
-        del data['isosurface'][sel]
-        self.mapWindow.nvizClass.MoveIsosurface(id, sel, False)
-
-        print '#', data
-        
-        # update buttons
-        self.UpdateIsosurfButtons(list)
-        
-        if self.parent.autoRender.IsChecked():
-            self.mapWindow.Refresh(False)
-        
-        event.Skip()
-        
-    def UpdatePage(self, pageId):
-        """Update dialog (selected page)"""
-        self.pageChanging = True
-        layer = self.mapWindow.GetSelectedLayer()
-        data = self.mapWindow.GetSelectedLayer(type='nviz')
-        
-        if pageId == 'view':
-            max = self.mapWindow.view['z-exag']['value'] * 10
-            hmin = self.mapWindow.iview['height']['min']
-            hmax = self.mapWindow.iview['height']['max']
-            for control in ('spin', 'slider'):
-                self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(1,
-                                                                                  max)
-                self.FindWindowById(self.win['view']['height'][control]).SetRange(hmin,
-                                                                                  hmax)
-        elif pageId == 'surface':
-            if self.notebook.GetSelection() != self.page['surface']['id']:
-                for page in ('vector', 'volume'):
-                    if self.page[page]['id'] > -1:
-                        self.notebook.RemovePage(self.page[page]['id'])
-                        self.page[page]['id'] = -1
-
-                self.page['surface']['id'] = 1
-                self.page['settings']['id'] = 2
-
-                panel = wx.FindWindowById(self.page['surface']['panel'])
-                self.notebook.InsertPage(n=self.page['surface']['id'],
-                                         page=panel,
-                                         text=" %s " % _("Layer properties"),
-                                         select=True)
-            
-            self.UpdateSurfacePage(layer, data['surface'])
-        
-        elif pageId == 'vector':
-            if self.notebook.GetSelection() != self.page['vector']['id']:
-                for page in ('surface', 'volume'):
-                    if self.page[page]['id'] > -1:
-                        self.notebook.RemovePage(self.page[page]['id'])
-                        self.page[page]['id'] = -1
-                    
-                self.page['vector']['id'] = 1
-                self.page['settings']['id'] = 2
-                
-                panel = wx.FindWindowById(self.page['vector']['panel'])
-                self.notebook.InsertPage(n=self.page['vector']['id'],
-                                         page=panel,
-                                         text=" %s " % _("Layer properties"),
-                                         select=True)
-                
-            self.UpdateVectorPage(layer, data['vector'])
-            
-        elif pageId == 'volume':
-            if self.notebook.GetSelection() != self.page['volume']['id']:
-                for page in ('surface', 'vector'):
-                    if self.page[page]['id'] > -1:
-                        self.notebook.RemovePage(self.page[page]['id'])
-                        self.page[page]['id'] = -1
-                    
-                self.page['volume']['id'] = 1
-                self.page['settings']['id'] = 2
-
-                panel = wx.FindWindowById(self.page['volume']['panel'])
-                self.notebook.InsertPage(n=self.page['volume']['id'],
-                                         page=panel,
-                                         text=" %s " % _("Layer properties"),
-                                         select=True)
-                
-            self.UpdateVolumePage(layer, data['volume'])
-            
-        self.pageChanging = False
-        
-    def UpdateSurfacePage(self, layer, data):
-        #
-        # attributes
-        #
-        for attr in ('topo', 'color'): # required
-            if layer and layer.type == 'raster':
-                self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
-            else:
-                self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
-            self.SetMapObjUseMap(nvizType='surface',
-                                 attrb=attr, map=True) # -> map
-
-        if data['attribute'].has_key('color'):
-            value = data['attribute']['color']['value']
-            if data['attribute']['color']['map']:
-                self.FindWindowById(self.win['surface']['color']['map']).SetValue(value)
-            else: # constant
-                color = map(int, value.split(':'))
-                self.FindWindowById(self.win['surface']['color']['const']).SetColour(color)
-            self.SetMapObjUseMap(nvizType='surface',
-                                 attrb=attr, map=data['attribute']['color']['map'])
-
-        self.SetMapObjUseMap(nvizType='surface',
-                             attrb='shine', map=data['attribute']['shine']['map'])
-        value = data['attribute']['shine']['value']
-        if data['attribute']['shine']['map']:
-            self.FindWindowById(self.win['surface']['shine']['map']).SetValue(value)
-        else:
-            self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
-
-        #
-        # draw
-        #
-        for control, dict in data['draw'].iteritems():
-            if control == 'all': # skip 'all' property
-                continue
-            if control == 'resolution':
-                self.FindWindowById(self.win['surface']['draw']['res-coarse']).SetValue(dict['coarse'])
-                self.FindWindowById(self.win['surface']['draw']['res-fine']).SetValue(dict['fine'])
-                continue
-
-            if control == 'mode':
-                if dict['desc']['mode'] == 'coarse':
-                    self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(0)
-                elif dict['desc']['mode'] == 'fine':
-                    self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(1)
-                else: # both
-                    self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(2)
-                    
-                if dict['desc']['style'] == 'wire':
-                    self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(0)
-                else: # surface
-                    self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(1)
-
-                if dict['desc']['shading'] == 'flat':
-                    self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(0)
-                else: # gouraud
-                    self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(1)
-                
-                continue
-
-            value = dict['value']
-            win = self.FindWindowById(self.win['surface']['draw'][control])
-            
-            name = win.GetName()
-
-            if name == "selection":
-                win.SetSelection(value)
-            elif name == "colour":
-                color = map(int, value.split(':'))
-                win.SetColour(color)
-            else:
-                win.SetValue(value)
-        # enable/disable res widget + set draw mode
-        self.SetSurfaceMode()
-        color = self.FindWindowById(self.win['surface']['draw']['wire-color'])
-        
-    def UpdateVectorPage(self, layer, data):
-        vInfo = gcmd.Command(['v.info',
-                              'map=%s' % layer.name])
-        npoints = nprimitives = 0
-        for line in vInfo.ReadStdOutput():
-            if 'Map is 3D' in line:
-                mapIs3D = int(line.replace('|', '').split(':')[1].strip())
-            elif 'Number of points' in line:
-                npoints = int(line.replace('|', '').split(':')[1].strip().split(' ')[0])
-                nprimitives = npoints
-            elif 'Number of lines' in line:
-                nprimitives += int(line.replace('|', '').split(':')[1].strip().split(' ')[0])
-            elif 'Number of boundaries' in line:
-                nprimitives += int(line.replace('|', '').split(':')[1].strip().split(' ')[0]) # boundaries
-                nprimitives += int(line.replace('|', '').split(':')[2].strip()) # faces
-            elif 'Number of centroids' in line:
-                nprimitives += int(line.replace('|', '').split(':')[1].strip().split(' ')[0]) # centroids
-                nprimitives += int(line.replace('|', '').split(':')[2].strip()) # kernels
-
-        if mapIs3D:
-            desc = _("Vector map <%s> is 3D") % layer.name
-            enable = False
-        else:
-            desc = _("Vector map <%s> is 2D") % layer.name
-            enable = True
-        desc += " - " + _("%d primitives (%d points)") % (nprimitives, npoints)
-
-        self.FindWindowById(self.win['vector']['lines']['flat']).Enable(enable)
-        for v in ('lines', 'points'):
-            self.FindWindowById(self.win['vector'][v]['surface']).Enable(enable)
-            self.FindWindowById(self.win['vector'][v]['height']['slider']).Enable(enable)
-            self.FindWindowById(self.win['vector'][v]['height']['spin']).Enable(enable)
-            
-        self.FindWindowById(self.win['vector']['desc']).SetLabel(desc)
-        #
-        # lines
-        #
-        showLines = self.FindWindowById(self.win['vector']['lines']['show'])
-        if data['lines'].has_key('object'):
-            showLines.SetValue(True)
-        else:
-            showLines.SetValue(False)
-            if nprimitives - npoints > 0:
-                showLines.Enable(True)
-            else:
-                showLines.Enable(False)
-
-        self.UpdateVectorShow('lines',
-                              showLines.IsChecked())
-
-        width = self.FindWindowById(self.win['vector']['lines']['width'])
-        width.SetValue(data['lines']['width'])
-
-        color = self.FindWindowById(self.win['vector']['lines']['color'])
-        color.SetValue(map(int, data['lines']['color'].split(':')))
-
-        for vtype in ('lines', 'points'):
-            if vtype == 'lines':
-                display = self.FindWindowById(self.win['vector']['lines']['flat'])
-                if data[vtype]['mode']['type'] == 'flat':
-                    display.SetSelection(1)
-                else:
-                    display.SetSelection(0)
-
-            if data[vtype]['mode']['type'] == 'surface' and \
-                    len(self.mapWindow.layers['raster']['name']) > 0:
-                surface = self.FindWindowById(self.win['vector'][vtype]['surface'])
-                surface.SetItems(self.mapWindow.layers['raster']['name'])
-                surface.SetStringSelection(data[vtype]['mode']['surface'])
-                
-        for type in ('slider', 'spin'):
-            win = self.FindWindowById(self.win['vector']['lines']['height'][type])
-            win.SetValue(data['lines']['height'])
-
-        #
-        # points
-        #
-        showPoints = self.FindWindowById(self.win['vector']['points']['show'])
-        
-        if data['points'].has_key('object'):
-            showPoints.SetValue(True)
-        else:
-            showPoints.SetValue(False)
-            if npoints > 0:
-                showPoints.Enable(True)
-            else:
-                showPoints.Enable(False)
-        
-        self.UpdateVectorShow('points',
-                              showPoints.IsChecked())
-        # size, width, marker, color
-        for prop in ('size', 'width', 'marker', 'color'):
-            win = self.FindWindowById(self.win['vector']['points'][prop])
-            name = win.GetName()
-            if name == 'selection':
-                win.SetSelection(data['points'][prop])
-            elif name == 'color':
-                color = map(int, data['points'][prop].split(':'))
-                win.SetValue(color)
-            else:
-                win.SetValue(data['points'][prop])
-        # height
-        for type in ('slider', 'spin'):
-            win = self.FindWindowById(self.win['vector']['points']['height'][type])
-            win.SetValue(data['points']['height'])
-
-    def UpdateVolumePage(self, layer, data):
-        """Update volume layer properties page"""
-        list = self.FindWindowById(self.win['volume']['isosurfs'])
-
-        #
-        # draw
-        #
-        for control, dict in data['draw'].iteritems():
-            if control == 'all': # skip 'all' property
-                continue
-
-            win = self.FindWindowById(self.win['volume']['draw'][control])
-
-            if control == 'shading':
-                if data['draw']['shading']['desc'] == 'flat':
-                    value = 0
-                else:
-                    value = 1
-            else:
-                value = dict['value']
-
-            if win.GetName() == "selection":
-                win.SetSelection(value)
-            else:
-                win.SetValue(value)
-
-        self.SetIsosurfaceMode(data['draw']['shading']['value'])
-        self.SetIsosurfaceResolution(data['draw']['resolution']['value'])
-                
-        #
-        # isosurface attributes
-        #
-        for attr in ('color', ): # required
-            if layer and layer.type == '3d-raster':
-                self.FindWindowById(self.win['volume'][attr]['map']).SetValue(layer.name)
-            else:
-                self.FindWindowById(self.win['volume'][attr]['map']).SetValue('')
-            self.SetMapObjUseMap(nvizType='volume',
-                                 attrb=attr, map=True) # -> map
-        
-        if data['attribute'].has_key('color'):
-            value = data['attribute']['color']['value']
-            if data['attribute']['color']['map']:
-                self.FindWindowById(self.win['volume']['color']['map']).SetValue(value)
-            else: # constant
-                color = map(int, value.split(':'))
-                self.FindWindowById(self.win['volume']['color']['const']).SetColour(color)
-            self.SetMapObjUseMap(nvizType='volume',
-                                 attrb=attr, map=data['attribute']['color']['map'])
-
-        self.SetMapObjUseMap(nvizType='volume',
-                             attrb='shine', map=data['attribute']['shine']['map'])
-        value = data['attribute']['shine']['value']
-        if data['attribute']['shine']['map']:
-            self.FindWindowById(self.win['volume']['shine']['map']).SetValue(value)
-        else:
-            self.FindWindowById(self.win['volume']['shine']['const']).SetValue(value)
-        
-    def SetPage(self, name):
-        """Get named page"""
-        self.notebook.SetSelection(self.page[name]['id'])
-
-class ViewPositionWindow(wx.Window):
-    """Position control window (for NvizToolWindow)"""
-    def __init__(self, parent, id, mapwindow,
-                 pos=wx.DefaultPosition,
-                 size=wx.DefaultSize):
-        self.mapWindow = mapwindow
-
-        wx.Window.__init__(self, parent, id, pos, size)
-
-        self.SetBackgroundColour("WHITE")
-
-        self.pdc = wx.PseudoDC()
-
-        self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
-        self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
-
-        self.Draw()
-
-        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
-        self.Bind(wx.EVT_PAINT, self.OnPaint)
-        # self.Bind(wx.EVT_MOTION,       self.OnMouse)
-        self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
-
-    def Draw(self, pos=None):
-        w, h = self.GetClientSize()
-
-        if pos is None:
-            x = self.mapWindow.view['pos']['x']
-            y = self.mapWindow.view['pos']['y']
-            x = x * w
-            y = y * h
-        else:
-            x, y = pos
-
-        self.pdc.Clear()
-        self.pdc.BeginDrawing()
-        self.pdc.DrawLine(w / 2, h / 2, x, y)
-        self.pdc.DrawCircle(x, y, 5)
-        self.pdc.EndDrawing()
-
-    def OnPaint(self, event):
-        dc = wx.BufferedPaintDC(self)
-        dc.SetBackground(wx.Brush("White"))
-        dc.Clear()
-
-        self.PrepareDC(dc)
-        self.pdc.DrawToDC(dc)
-
-    def OnMouse(self, event):
-        if event.LeftIsDown():
-            x, y = event.GetPosition()
-            self.Draw(pos=(x, y))
-            self.Refresh(False)
-            w, h = self.GetClientSize()
-            x = float(x) / w
-            y = float(y) / h
-            if x >= 0 and x <= 1.0:
-                self.mapWindow.view['pos']['x'] = x
-            if y >= 0 and y <= 1.0:
-                self.mapWindow.view['pos']['y'] = y
-            self.mapWindow.update.append('view')
-
-            self.mapWindow.render['quick'] = True
-            self.mapWindow.Refresh(eraseBackground=False)
-
-        elif event.LeftUp():
-            self.mapWindow.render['quick'] = False
-            self.mapWindow.Refresh(eraseBackground=False)
-        
-        event.Skip()
-
-class IsoSurfList(wx.CheckListBox):
-    """List of loaded volume isosurfaces (volume properties page)"""
-    def __init__(self, parent, win, id=wx.ID_ANY, size=wx.DefaultSize):
-        self.parent = parent
-        self.win = win
-        
-        wx.CheckListBox.__init__(self, parent, id, size=size)
-    
-        self.Bind(wx.EVT_CHECKLISTBOX, self.OnCheck)
-        self.Bind(wx.EVT_LISTBOX, self.OnSelect)
-    
-    def OnCheck(self, event):
-        """Item checked/unchecked -> load/delete surface"""
-        print event.IsChecked()
-        
-    def OnSelect(self, event):
-        """Item selected"""
-        winUp = self.parent.FindWindowById(self.win['btnIsosurfMoveUp'])
-        winDown = self.parent.FindWindowById(self.win['btnIsosurfMoveDown'])
-        selection = event.GetSelection()
-        if selection == 0:
-            winUp.Enable(False)
-            if not winDown.IsEnabled():
-                winDown.Enable()
-        elif selection == self.GetCount() - 1:
-            winDown.Enable(False)
-            if not winUp.IsEnabled():
-                winUp.Enable()
-        else:
-            if not winDown.IsEnabled():
-                winDown.Enable()
-            if not winUp.IsEnabled():
-                winUp.Enable()
-        
+GLWindow = nviz_mapdisp.GLWindow
+NvizToolWindow = nviz_tools.NvizToolWindow

Added: grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_mapdisp.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_mapdisp.py	                        (rev 0)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_mapdisp.py	2008-08-15 20:05:46 UTC (rev 32788)
@@ -0,0 +1,1201 @@
+"""
+ at package nviz_mapdisp.py (core)
+
+ at brief Nviz extension for wxGUI
+
+This module enables to visualize data in 2.5/3D space.
+
+Map Display supports standard 2D mode ('mapdisp' module) and
+the 2.5/3D mode ('nviz_mapdisp' module).
+
+List of classes:
+ - GLWindow
+
+(C) 2008 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> (Google SoC 2008)
+"""
+
+import os
+import sys
+import time
+import copy
+
+from threading import Thread
+
+import wx
+import wx.lib.scrolledpanel as scrolled
+from wx.lib.newevent import NewEvent
+from wx import glcanvas
+
+import gcmd
+import globalvar
+from debug import Debug as Debug
+from preferences import globalSettings as UserSettings
+from mapdisp import MapWindow as MapWindow
+
+sys.path.append(os.path.join(globalvar.ETCWXDIR, "nviz"))
+import grass6_wxnviz as wxnviz
+
+wxUpdateProperties, EVT_UPDATE_PROP = NewEvent()
+
+class GLWindow(MapWindow, glcanvas.GLCanvas):
+    """OpenGL canvas for Map Display Window"""
+    def __init__(self, parent, id,
+                 pos=wx.DefaultPosition,
+                 size=wx.DefaultSize,
+                 style=wx.NO_FULL_REPAINT_ON_RESIZE,
+                 Map=None, tree=None, gismgr=None):
+
+        self.parent = parent # MapFrame
+        self.Map = Map
+        self.tree = tree
+        self.gismgr = gismgr
+        
+        glcanvas.GLCanvas.__init__(self, parent, id)
+        MapWindow.__init__(self, parent, id, pos, size, style,
+                           Map, tree, gismgr)
+
+
+        self.parent = parent # MapFrame
+        self.update = []
+        
+        self.init = False
+        # render mode 
+        self.render = { 'quick' : False,
+                        # do not render vector lines in quick mode
+                        'vlines' : False,
+                        'vpoints' : False }
+
+        # list of loaded map layers
+        self.layers = {}
+        for type in ('raster', 'vlines', 'vpoints', '3d-raster'):
+            self.layers[type] = {}
+            self.layers[type]['name'] = []
+            self.layers[type]['id'] = []
+
+        #
+        # create nviz instance
+        #
+        self.nvizClass = wxnviz.Nviz(sys.stderr)
+
+        #
+        # set current display
+        #
+        self.nvizClass.SetDisplay(self)
+
+        #
+        # initialize mouse position
+        #
+        self.lastX = self.x = 30
+        self.lastY = self.y = 30
+
+        #
+        # default values
+        #
+        self.view = copy.deepcopy(UserSettings.Get(group='nviz', key='view')) # copy
+        self.iview = UserSettings.Get(group='nviz', key='view', internal=True)
+
+        self.size = None
+        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+        self.Bind(wx.EVT_MOTION, self.OnMouseAction)
+        self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseAction)
+
+        self.Bind(EVT_UPDATE_PROP, self.UpdateLayerProperties)
+        
+    def OnEraseBackground(self, event):
+        pass # do nothing, to avoid flashing on MSW
+
+    def OnSize(self, event):
+        self.size = self.parent.GetClientSize()
+        if self.GetContext():
+            Debug.msg(3, "GLCanvas.OnPaint(): w=%d, h=%d" % \
+                      (self.size.width, self.size.height))
+            self.SetCurrent()
+            self.nvizClass.ResizeWindow(self.size.width,
+                                        self.size.height)
+        
+        event.Skip()
+
+    def OnPaint(self, event):
+        Debug.msg(3, "GLCanvas.OnPaint()")
+
+        dc = wx.PaintDC(self)
+        self.SetCurrent()
+        
+        if not self.init:
+            self.nvizClass.InitView()
+
+            self.LoadDataLayers()
+
+            self.ResetView()
+            
+            if hasattr(self.parent, "nvizToolWin"):
+                self.parent.nvizToolWin.UpdatePage('view')
+                layer = self.GetSelectedLayer()
+                if layer:
+                    if layer.type == 'raster':
+                        self.parent.nvizToolWin.UpdatePage('surface')
+                    elif layer.type == 'vector':
+                        self.parent.nvizToolWin.UpdatePage('vector')
+
+                self.parent.nvizToolWin.UpdateSettings()
+
+                # update widgets
+                win = self.parent.nvizToolWin.FindWindowById( \
+                    self.parent.nvizToolWin.win['vector']['lines']['surface'])
+                win.SetItems(self.layers['raster']['name'])
+
+            self.init = True
+
+        self.UpdateMap()
+
+    def OnMouseAction(self, event):
+        # change position
+        if event.Dragging() and event.LeftIsDown():
+            self.lastX = self.lastY = self.x = self.y
+            self.x, self.y = event.GetPosition()
+            self.Refresh(False)
+
+        # change perspective with mouse wheel
+        wheel = event.GetWheelRotation()
+
+        if wheel != 0:
+            current  = event.GetPositionTuple()[:]
+            Debug.msg (5, "GLWindow.OnMouseMotion(): wheel=%d" % wheel)
+            prev_value = self.view['persp']['value']
+            if wheel > 0:
+                value = -1 * self.view['persp']['step']
+            else:
+                value = self.view['persp']['step']
+            self.view['persp']['value'] += value
+            if self.view['persp']['value'] < 1:
+                self.view['persp']['value'] = 1
+            elif self.view['persp']['value'] > 100:
+                self.view['persp']['value'] = 100
+
+            if prev_value != self.view['persp']['value']:
+                if hasattr(self.parent, "nvizToolWin"):
+                    self.parent.nvizToolWin.UpdateSettings()
+
+                    self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
+                                           self.iview['height']['value'],
+                                           self.view['persp']['value'],
+                                           self.view['twist']['value'])
+
+                # redraw map
+                self.OnPaint(None)
+
+                # update statusbar
+                ### self.parent.StatusbarUpdate()
+
+    def OnLeftDown(self, event):
+        self.CaptureMouse()
+        self.x, self.y = self.lastX, self.lastY = event.GetPosition()
+        
+    def OnLeftUp(self, event):
+        self.ReleaseMouse()
+
+    def UpdateMap(self, render=True):
+        """
+        Updates the canvas anytime there is a change to the
+        underlaying images or to the geometry of the canvas.
+
+        @param render re-render map composition
+        """
+        start = time.clock()
+
+        self.resize = False
+
+        # if self.size is None:
+        #    self.size = self.GetClientSize()
+        
+        #         w, h = self.size
+        #         w = float(max(w, 1.0))
+        #         h = float(max(h, 1.0))
+        #         d = float(min(w, h))
+        #         xScale = d / w
+        #         yScale = d / h
+        # print w, h, d, xScale, yScale
+        # print self.y, self.lastY, self.x, self.lastX
+        # print (self.y - self.lastY) * yScale, (self.x - self.lastX) * xScale 
+        # print self.x * xScale
+        
+        #glRotatef((self.y - self.lastY) * yScale, 1.0, 0.0, 0.0);
+        #glRotatef((self.x - self.lastX) * xScale, 0.0, 1.0, 0.0);
+
+        if self.render['quick'] is False:
+            self.parent.onRenderGauge.Show()
+            self.parent.onRenderGauge.SetRange(2)
+            self.parent.onRenderGauge.SetValue(0)
+
+        if 'view' in self.update:
+            if 'z-exag' in self.update:
+                self.nvizClass.SetZExag(self.view['z-exag']['value'])
+                self.update.remove('z-exag')
+            
+            self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
+                                   self.iview['height']['value'],
+                                   self.view['persp']['value'],
+                                   self.view['twist']['value'])
+
+            self.update.remove('view')
+
+        if self.render['quick'] is False:
+            self.parent.onRenderGauge.SetValue(1)
+            wx.Yield()
+            self.nvizClass.Draw(False, -1)
+        elif self.render['quick'] is True:
+            # quick
+            mode = wxnviz.DRAW_QUICK_SURFACE | wxnviz.DRAW_QUICK_VOLUME
+            if self.render['vlines']:
+                mode |= wxnviz.DRAW_QUICK_VLINES
+            if self.render['vpoints']:
+                mode |= wxnviz.DRAW_QUICK_VPOINTS
+            self.nvizClass.Draw(True, mode)
+        else: # None -> reuse last rendered image
+            pass # TODO
+
+        self.SwapBuffers()
+
+        stop = time.clock()
+
+        if self.render['quick'] is False:
+            self.parent.onRenderGauge.SetValue(2)
+            # hide process bar
+            self.parent.onRenderGauge.Hide()
+
+        #
+        # update statusbar
+        #
+        # self.parent.StatusbarUpdate()
+
+        Debug.msg(3, "GLWindow.UpdateMap(): quick=%d, -> time=%g" % \
+                      (self.render['quick'], (stop-start)))
+
+        # print stop-start
+
+    def EraseMap(self):
+        """
+        Erase the canvas
+        """
+        self.nvizClass.EraseMap()
+        self.SwapBuffers()
+
+    def IsLoaded(self, item):
+        """Check if layer (item) is already loaded
+
+        @param item layer item
+        """
+        layer = self.tree.GetPyData(item)[0]['maplayer']
+        data = self.tree.GetPyData(item)[0]['nviz']
+
+        if not data:
+            return 0
+
+        if layer.type == 'raster':
+            if not data['surface'].has_key('object'):
+                return 0
+        elif layer.type == 'vector':
+            if not data['vlines'].has_key('object') and \
+                    not data['points'].has_key('object'):
+                return 0
+
+        return 1
+
+    def LoadDataLayers(self):
+        """Load raster/vector from current layer tree
+
+        @todo volumes
+        """
+        listOfItems = []
+        # load raster & vector maps
+        item = self.tree.GetFirstChild(self.tree.root)[0]
+        while item and item.IsOk():
+            type = self.tree.GetPyData(item)[0]['type']
+            if not item.IsChecked() or \
+                    type not in ('raster', 'vector', '3d-raster'):
+                item = self.tree.GetNextSibling(item)
+                continue
+
+            listOfItems.append(item)
+
+            item = self.tree.GetNextSibling(item)
+
+        start = time.time()
+
+        while(len(listOfItems) > 0):
+            item = listOfItems.pop()
+            type = self.tree.GetPyData(item)[0]['type']
+            
+            try:
+                if type == 'raster':
+                    self.LoadRaster(item)
+                elif type == '3d-raster':
+                    self.LoadRaster3d(item)
+            except gcmd.NvizError, e:
+                print >> sys.stderr, "Nviz:" + e.message
+
+            try:
+                if type == 'vector':
+                    data = self.tree.GetPyData(item)[0]['nviz']
+                    vecType = []
+                    if data and data.has_key('vector'):
+                        for v in ('lines', 'points'):
+                            if data['vector'][v]:
+                                vecType.append(v)
+                    self.LoadVector(item, vecType)
+            except gcmd.NvizError, e:
+                print >> sys.stderr, "Nviz:" + e.message
+            
+        stop = time.time()
+        
+        Debug.msg(3, "GLWindow.LoadDataLayers(): time=%f" % (stop-start))
+
+        # print stop - start
+
+    def SetLayerData(self, item, id, nvizType):
+        """Set map object properties
+
+        @param item layer item
+        @param id nviz layer id (or -1)
+        @param nvizType nviz data type (surface, points, vector)
+        """
+        type = self.tree.GetPyData(item)[0]['maplayer'].type
+        # reference to original layer properties (can be None)
+        data = self.tree.GetPyData(item)[0]['nviz']
+
+        if data is None:
+            # init data structure
+            self.tree.GetPyData(item)[0]['nviz'] = {}
+            data = self.tree.GetPyData(item)[0]['nviz']
+
+            if type == 'raster':
+                data[nvizType] = {}
+                for sec in ('attribute', 'draw', 'mask', 'position'):
+                    data[nvizType][sec] = {}
+
+                # reset to default properties
+                self.SetSurfaceDefaultProp(data[nvizType])
+                        
+            elif type == 'vector':
+                data['vector'] = {}
+                for sec in ('lines', 'points'):
+                    data['vector'][sec] = {}
+
+                # reset to default properties (lines/points)
+                self.SetVectorDefaultProp(data['vector'])
+
+            elif type == '3d-raster':
+                data[nvizType] = {}
+                for sec in ('attribute', 'draw', 'position'):
+                    data[nvizType][sec] = {}
+                for sec in ('isosurface', 'slice'):
+                    data[nvizType][sec] = []
+                
+
+                # reset to default properties 
+                self.SetVolumeDefaultProp(data[nvizType])
+        
+        else:
+            # check data
+            if type == 'vector':
+                if not data['vector']['lines']:
+                    self.SetVectorLinesDefaultProp(data['vector']['lines'])
+                if not data['vector']['points']:
+                    self.SetVectorPointsDefaultProp(data['vector']['points'])
+                    
+            # set updates
+            for sec in data.keys():
+                for sec1 in data[sec].keys():
+                    for sec2 in data[sec][sec1].keys():
+                        if sec2 not in ('object'):
+                            event = wxUpdateProperties(type='mapobj',
+                                                       data={'nvizType' : sec,
+                                                             'key' : sec1,
+                                                             'subkey' : sec2})
+                            
+        # set id
+        if id > 0:
+            if type in ('raster', '3d-raster'):
+               data[nvizType]['object'] = { 'id' : id,
+                                            'init' : False }
+            elif type == 'vector':
+                data['vector'][nvizType]['object'] = { 'id' : id,
+                                                       'init' : False }
+        
+        return data
+
+    def LoadRaster(self, item):
+        """Load 2d raster map and set surface attributes
+
+        @param layer item
+        """
+        return self._loadRaster(item)
+
+    def LoadRaster3d(self, item):
+        """Load 3d raster map and set surface attributes
+
+        @param layer item
+        """
+        return self._loadRaster(item)
+
+    def _loadRaster(self, item):
+        """Load 2d/3d raster map and set its attributes
+
+        @param layer item
+        """
+        layer = self.tree.GetPyData(item)[0]['maplayer']
+
+        if layer.type not in ('raster', '3d-raster'):
+            return
+
+        if layer.type == 'raster':
+            id = self.nvizClass.LoadSurface(str(layer.name), None, None)
+            nvizType = 'surface'
+            errorMsg = _("Loading raster map")
+        elif layer.type == '3d-raster':
+            id = self.nvizClass.LoadVolume(str(layer.name), None, None)
+            nvizType = 'volume'
+            errorMsg = _("Loading 3d raster map")
+        else:
+            id = -1
+        
+        if id < 0:
+            if layer.type in ('raster', '3d-raster'):
+                print >> sys.stderr, "Nviz:" + "%s <%s> %s" % (errorMsg, layer.name, _("failed"))
+            else:
+                print >> sys.stderr, "Nviz:" + _("Unsupported layer type '%s'") % layer.type
+        
+        self.layers[layer.type]['name'].append(layer.name)
+        self.layers[layer.type]['id'].append(id)
+
+        # set default/workspace layer properties
+        data = self.SetLayerData(item, id, nvizType)
+        print data
+        # update properties
+        event = wxUpdateProperties(layer=item)
+        wx.PostEvent(self, event)
+        
+        # update tools window
+        if hasattr(self.parent, "nvizToolWin") and \
+                item == self.GetSelectedLayer(type='item'):
+            toolWin = self.parent.nvizToolWin
+            if layer.type == 'raster':
+                win = toolWin.FindWindowById( \
+                    toolWin.win['vector']['lines']['surface'])
+                win.SetItems(self.layers[layer.type]['name'])
+
+            toolWin.UpdatePage(nvizType)
+            toolWin.SetPage(nvizType)
+            
+        return id
+
+    def UnloadRaster(self, item):
+        """Unload 2d raster map
+
+        @param layer item
+        """
+        return self._unloadRaster(item)
+
+    def UnloadRaster3d(self, item):
+        """Unload 3d raster map
+
+        @param layer item
+        """
+        return self._unloadRaster(item)
+
+    def _unloadRaster(self, item):
+        """Unload 2d/3d raster map
+
+        @param item layer item
+        """
+        layer = self.tree.GetPyData(item)[0]['maplayer']
+
+        if layer.type not in ('raster', '3d-raster'):
+            return
+
+        data = self.tree.GetPyData(item)[0]['nviz']
+
+        if layer.type == 'raster':
+            nvizType = 'surface'
+            unloadFn = self.nvizClass.UnloadSurface
+            errorMsg = _("Unable to unload raster map")
+            successMsg = _("Raster map")
+        else:
+            nvizType = 'volume'
+            unloadFn = self.nvizClass.UnloadVolume
+            errorMsg = _("Unable to unload 3d raster map")
+            successMsg = _("3d raster map")
+
+        id = data[nvizType]['object']['id']
+
+        if unloadFn(id) == 0:
+            print >> sys.stderr, "Nviz:" + "%s <%s>" % (errorMsg, layer.name)
+        else:
+            print "Nviz:" + "%s <%s> %s" % (successMsg, layer.name, _("unloaded successfully"))
+
+        data[nvizType].pop('object')
+
+        idx = self.layers[layer.type]['id'].index(id)
+        del self.layers[layer.type]['name'][idx]
+        del self.layers[layer.type]['id'][idx]
+
+        # update tools window
+        if hasattr(self.parent, "nvizToolWin") and \
+                layer.type == 'raster':
+            toolWin = self.parent.nvizToolWin
+            win = toolWin.FindWindowById( \
+                toolWin.win['vector']['lines']['surface'])
+            win.SetItems(self.layers[layer.type]['name'])
+
+            # remove surface page
+            if toolWin.notebook.GetSelection() == toolWin.page[nvizType]['id']:
+                toolWin.notebook.RemovePage(toolWin.page[nvizType]['id'])
+                toolWin.page[nvizType]['id'] = -1
+                toolWin.page['settings']['id'] = 1
+
+    def LoadVector(self, item, vecType=None):
+        """Load 2D or 3D vector map overlay
+
+        @param item layer item
+        @param vecType vector type (lines / points)
+        """
+        layer = self.tree.GetPyData(item)[0]['maplayer']
+
+        if layer.type != 'vector':
+            return
+
+        if vecType is None:
+            # load data type by default
+            vecType = []
+            for v in ('lines', 'points'):
+                if UserSettings.Get(group='nviz', key='vector',
+                                    subkey=[v, 'show']):
+                    vecType.append(v)
+
+        # set default properties
+        self.SetLayerData(item, -1, 'lines')
+        self.SetLayerData(item, -1, 'points')
+
+        id = -1
+        for type in vecType:
+            if type == 'lines':
+                id = self.nvizClass.LoadVector(str(layer.name), False)
+            else:
+                id = self.nvizClass.LoadVector(str(layer.name), True)
+
+            if id < 0:
+                print >> sys.stderr, "Nviz:" + _("Loading vector map <%(name)s> (%(type)s) failed") % \
+                    { 'name' : layer.name, 'type' : type }
+                continue
+
+            # update layer properties
+            self.SetLayerData(item, id, type)
+        
+            self.layers['v' + type]['name'].append(layer.name)
+            self.layers['v'  + type]['id'].append(id)
+        
+        # update properties
+        event = wxUpdateProperties(layer=item)
+        wx.PostEvent(self, event)
+        
+        # update tools window
+        if hasattr(self.parent, "nvizToolWin") and \
+                item == self.GetSelectedLayer(type='item'):
+            toolWin = self.parent.nvizToolWin
+
+            toolWin.UpdatePage('vector')
+            toolWin.SetPage('vector')
+        
+        return id
+
+    def UnloadVector(self, item, vecType=None):
+        """Unload vector map overlay
+
+        @param item layer item
+        @param vecType vector type (lines, points)
+        """
+        layer = self.tree.GetPyData(item)[0]['maplayer']
+        data = self.tree.GetPyData(item)[0]['nviz']['vector']
+
+        if vecType is None:
+            vecType = []
+            for v in ('lines', 'points'):
+                if UserSettings.Get(group='nviz', key='vector',
+                                    subkey=[v, 'show']):
+                    vecType.append(v)
+
+        for vtype in vecType:
+            if not data[vtype].has_key('object'):
+                continue
+
+            id = data[vtype]['object']['id']
+
+            if vtype == 'lines':
+                ret = self.nvizClass.UnloadVector(id, False)
+            else:
+                ret = self.nvizClass.UnloadVector(id, True)
+            if ret == 0:
+                print >> sys.stderr, "Nviz:" + _("Unable to unload vector map <%(name)s> (%(type)s)") % \
+                    { 'name': layer.name, 'type' : vtype }
+            else:
+                print "Nviz:" + _("Vector map <%(name)s> (%(type)s) unloaded successfully") % \
+                    { 'name' : layer.name, 'type' : vtype }
+
+            
+            data[vtype].pop('object')
+
+            idx = self.layers['v' + vtype]['id'].index(id)
+            del self.layers['v' + vtype]['name'][idx]
+            del self.layers['v' + vtype]['id'][idx]
+
+        # update tools window
+        if hasattr(self.parent, "nvizToolWin") and \
+                vecType is None:
+            toolWin = self.parent.nvizToolWin
+            # remove surface page
+            if toolWin.notebook.GetSelection() == toolWin.page['surface']['id']:
+                toolWin.notebook.RemovePage(toolWin.page['surface']['id'])
+                toolWin.page['surface']['id'] = -1
+                toolWin.page['settings']['id'] = 1
+        
+    def GetDrawMode(self, mode=None, style=None, shade=None, string=False):
+        """Get surface draw mode (value) from description/selection
+
+        @param mode,style,shade modes
+        @param string if True input parameters are strings otherwise
+        selections
+        """
+        value = 0
+        desc = {}
+
+        if string:
+            if mode is not None:
+                if mode == 'coarse':
+                    value |= wxnviz.DM_WIRE
+                elif mode == 'fine':
+                    value |= wxnviz.DM_POLY
+                else: # both
+                    value |= wxnviz.DM_WIRE_POLY
+
+            if style is not None:
+                if style == 'wire':
+                    value |= wxnviz.DM_GRID_WIRE
+                else: # surface
+                    value |= wxnviz.DM_GRID_SURF
+                    
+            if shade is not None:
+                if shade == 'flat':
+                    value |= wxnviz.DM_FLAT
+                else: # surface
+                    value |= wxnviz.DM_GOURAUD
+
+            return value
+
+        # -> string is False
+        if mode is not None:
+            if mode == 0: # coarse
+                value |= wxnviz.DM_WIRE
+                desc['mode'] = 'coarse'
+            elif mode == 1: # fine
+                value |= wxnviz.DM_POLY
+                desc['mode'] = 'fine'
+            else: # both
+                value |= wxnviz.DM_WIRE_POLY
+                desc['mode'] = 'both'
+
+        if style is not None:
+            if style == 0: # wire
+                value |= wxnviz.DM_GRID_WIRE
+                desc['style'] = 'wire'
+            else: # surface
+                value |= wxnviz.DM_GRID_SURF
+                desc['style'] = 'surface'
+
+        if shade is not None:
+            if shade == 0:
+                value |= wxnviz.DM_FLAT
+                desc['shading'] = 'flat'
+            else: # surface
+                value |= wxnviz.DM_GOURAUD
+                desc['shading'] = 'gouraud'
+        
+        return (value, desc)
+    
+    def SetSurfaceDefaultProp(self, data):
+        """Set default surface properties, add actions to update list"""
+        #
+        # attributes
+        #
+        for attrb in ('shine', ):
+            data['attribute'][attrb] = {}
+            for key, value in UserSettings.Get(group='nviz', key='volume',
+                                               subkey=attrb).iteritems():
+                data['attribute'][attrb][key] = value
+            self.update.append('surface:attribute:%s' % attrb)
+        
+        #
+        # draw
+        #
+        data['draw']['all'] = False # apply only for current surface
+        for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
+            if control[:3] == 'res':
+                if not data['draw'].has_key('resolution'):
+                    data['draw']['resolution'] = {}
+                if 'surface:draw:%s' % 'resolution' not in self.update:
+                    self.update.append('surface:draw:%s' % 'resolution')
+                data['draw']['resolution'][control[4:]] = value
+                continue
+            
+            elif control not in ('style', 'shading'):
+                self.update.append('surface:draw:%s' % control)
+
+            if control == 'wire-color':
+                value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
+            elif control in ('mode', 'style', 'shading'):
+                if not data['draw'].has_key('mode'):
+                    data['draw']['mode'] = {}
+                continue
+
+            data['draw'][control] = { 'value' : value }
+            
+        value, desc = self.GetDrawMode(UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'mode']),
+                                       UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'style']),
+                                       UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading']))
+
+        data['draw']['mode'] = { 'value' : value,
+                                 'desc' : desc, }
+
+    def SetVolumeDefaultProp(self, data):
+        """Set default volume properties and add actions to update list"""
+        #
+        # draw
+        #
+        for control, value in UserSettings.Get(group='nviz', key='volume', subkey='draw').iteritems():
+            if control == 'mode':
+                continue
+            if 'volume:draw:%s' % control not in self.update:
+                self.update.append('volume:draw:%s' % control)
+            if control == 'shading':
+                sel = UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading'])
+                value, desc = self.GetDrawMode(shade=sel, string=False)
+
+                data['draw']['shading'] = { 'value' : value,
+                                            'desc' : desc['shading'] }
+            elif control == 'mode':
+                sel = UserSettings.Get(group='nviz', key='volume', subkey=['draw', 'mode'])
+                if sel == 0:
+                    desc = 'isosurface'
+                else:
+                    desc = 'slice'
+                data['draw']['mode'] = { 'value' : sel,
+                                         'desc' : desc, }
+            else:
+                data['draw'][control] = { 'value' : value }
+        
+        #
+        # isosurface attributes
+        #
+        for attrb in ('shine', ):
+            data['attribute'][attrb] = {}
+            for key, value in UserSettings.Get(group='nviz', key='volume',
+                                               subkey=attrb).iteritems():
+                data['attribute'][attrb][key] = value
+        
+    def SetVectorDefaultProp(self, data):
+        """Set default vector properties, add actions to update list"""
+        self.SetVectorLinesDefaultProp(data['lines'])
+        self.SetVectorPointsDefaultProp(data['points'])
+
+    def SetVectorLinesDefaultProp(self, data):
+        """Set default vector properties -- lines"""
+        # width
+        data['width'] = UserSettings.Get(group='nviz', key='vector',
+                                                  subkey=['lines', 'width'])
+        
+        # color
+        value = UserSettings.Get(group='nviz', key='vector',
+                                 subkey=['lines', 'color'])
+        color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
+        data['color'] = color
+
+        # mode
+        if UserSettings.Get(group='nviz', key='vector',
+                            subkey=['lines', 'flat']):
+            type = 'flat'
+            map  = None
+        else:
+            if len(self.layers['raster']['name']) > 0:
+                type = 'surface'
+                map  = self.layers['raster']['name'][0]
+            else:
+                type = 'flat'
+                map = None
+
+        data['mode'] = {}
+        data['mode']['type'] = type
+        if map:
+            data['mode']['surface'] = map
+
+        # height
+        data['height'] = UserSettings.Get(group='nviz', key='vector',
+                                                   subkey=['lines', 'height'])
+
+        if data.has_key('object'):
+            self.update.append('vector:lines:color')
+            self.update.append('vector:lines:width')
+            self.update.append('vector:lines:mode')
+            self.update.append('vector:lines:height')
+
+    def SetVectorPointsDefaultProp(self, data):
+        """Set default vector properties -- points"""
+        # size
+        data['size'] = UserSettings.Get(group='nviz', key='vector',
+                                        subkey=['points', 'size'])
+
+        # width
+        data['width'] = UserSettings.Get(group='nviz', key='vector',
+                                         subkey=['points', 'width'])
+
+        # marker
+        data['marker'] = UserSettings.Get(group='nviz', key='vector',
+                                          subkey=['points', 'marker'])
+
+        # color
+        value = UserSettings.Get(group='nviz', key='vector',
+                                 subkey=['points', 'color'])
+        color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
+        data['color'] = color
+
+        # mode
+        data['mode'] = { 'type' : 'surface',
+                         'surface' : '' }
+        if len(self.layers['raster']['name']) > 0:
+            data['mode']['surface'] = self.layers['raster']['name'][0]
+        
+        # height
+        data['height'] = UserSettings.Get(group='nviz', key='vector',
+                                          subkey=['points', 'height'])
+
+        if data.has_key('object'):
+            self.update.append('vector:points:size')
+            self.update.append('vector:points:width')
+            self.update.append('vector:points:marker')
+            self.update.append('vector:points:color')
+            self.update.append('vector:points:surface')
+            self.update.append('vector:points:height')
+
+    def Reset(self):
+        """Reset (unload data)"""
+        self.nvizClass.Reset()
+        self.init = False
+
+    def OnZoomToMap(self, event):
+        """
+        Set display extents to match selected raster
+        or vector map or volume.
+
+        @todo vector, volume
+        """
+        layer = self.GetSelectedLayer()
+
+        if layer is None:
+            return
+
+        Debug.msg (3, "GLWindow.OnZoomToMap(): layer=%s, type=%s" % \
+                       (layer.name, layer.type))
+
+        self.nvizClass.SetViewportDefault()
+
+    def ResetView(self):
+        """Reset to default view"""
+        self.view['z-exag']['value'], \
+            self.iview['height']['value'], \
+            self.iview['height']['min'], \
+            self.iview['height']['max'] = self.nvizClass.SetViewDefault()
+        
+        self.view['pos']['x'] = UserSettings.Get(group='nviz', key='view',
+                                                 subkey=('pos', 'x'))
+        self.view['pos']['y'] = UserSettings.Get(group='nviz', key='view',
+                                                 subkey=('pos', 'x'))
+        self.view['persp']['value'] = UserSettings.Get(group='nviz', key='view',
+                                                       subkey=('persp', 'value'))
+
+        self.view['twist']['value'] = UserSettings.Get(group='nviz', key='view',
+                                                       subkey=('twist', 'value'))
+
+        self.update.append('view')
+
+    def UpdateLayerProperties(self, event):
+        """Update data layer properties"""
+        print self.update
+        if not hasattr(event, "layer"):
+            mapLayer = self.GetSelectedLayer()
+            data = self.GetSelectedLayer(type='nviz')
+        else:
+            mapLayer = self.tree.GetPyData(event.layer)[0]['maplayer']
+            data = self.tree.GetPyData(event.layer)[0]['nviz']
+
+        if mapLayer.type == 'raster':
+            id = data['surface']['object']['id']
+            self.UpdateSurfaceProperties(id, data['surface'])
+            # -> initialized
+            data['surface']['object']['init'] = True
+
+        elif mapLayer.type == '3d-raster':
+            id = data['volume']['object']['id']
+            if hasattr(event, "isoSurfId"):
+                self.UpdateVolumeProperties(id, data['volume'], isosurfId)
+            else:
+                self.UpdateVolumeProperties(id, data['volume'])
+            # -> initialized
+            data['volume']['object']['init'] = True
+
+        elif mapLayer.type == 'vector':
+            for type in ('lines', 'points'):
+                if data['vector'][type].has_key('object'):
+                    id = data['vector'][type]['object']['id']
+                    self.UpdateVectorProperties(id, data['vector'], type)
+                    # -> initialized
+                    data['vector'][type]['object']['init'] = True
+        print self.update
+    def UpdateSurfaceProperties(self, id, data):
+        """Update surface layer properties"""
+        # surface attributes
+        for attrb in ('topo', 'color', 'mask',
+                     'transp', 'shine', 'emit'):
+            attrb, 'surface:attribute:%s' % attrb in self.update
+            if 'surface:attribute:%s' % attrb in self.update:
+                map = data['attribute'][attrb]['map']
+                value = data['attribute'][attrb]['value']
+
+                if map is None: # unset
+                    # only optional attributes
+                    if attrb == 'mask':
+                        # TODO: invert mask
+                        # TODO: broken in NVIZ
+                        self.nvizClass.UnsetSurfaceMask(id)
+                    elif attrb == 'transp':
+                        self.nvizClass.UnsetSurfaceTransp(id)
+                    elif attrb == 'emit':
+                        self.nvizClass.UnsetSurfaceEmit(id) 
+                else:
+                    if type(value) == type('') and \
+                            len(value) <= 0: # ignore empty values (TODO: warning)
+                        continue
+                    if attrb == 'topo':
+                        self.nvizClass.SetSurfaceTopo(id, map, str(value)) 
+                    elif attrb == 'color':
+                        self.nvizClass.SetSurfaceColor(id, map, str(value))
+                    elif attrb == 'mask':
+                        # TODO: invert mask
+                        # TODO: broken in NVIZ
+                        self.nvizClass.SetSurfaceMask(id, False, str(value))
+                    elif attrb == 'transp':
+                        self.nvizClass.SetSurfaceTransp(id, map, str(value)) 
+                    elif attrb == 'shine':
+                        self.nvizClass.SetSurfaceShine(id, map, str(value)) 
+                    elif attrb == 'emit':
+                        self.nvizClass.SetSurfaceEmit(id, map, str(value)) 
+                self.update.remove('surface:attribute:%s' % attrb)
+
+        # draw res
+        if 'surface:draw:resolution' in self.update:
+            coarse = data['draw']['resolution']['coarse']
+            fine   = data['draw']['resolution']['fine']
+
+            if data['draw']['all']:
+                self.nvizClass.SetSurfaceRes(-1, fine, coarse)
+            else:
+                self.nvizClass.SetSurfaceRes(id, fine, coarse)
+            self.update.remove('surface:draw:resolution')
+
+        # draw style
+        if 'surface:draw:mode' in self.update:
+            if data['draw']['mode']['value'] < 0: # need to calculate
+                data['draw']['mode']['value'] = \
+                    self.GetDrawMode(mode=data['draw']['mode']['desc']['mode'],
+                                        style=data['draw']['mode']['desc']['style'],
+                                        shade=data['draw']['mode']['desc']['shading'],
+                                        string=True)
+            style = data['draw']['mode']['value']
+            if data['draw']['all']:
+                self.nvizClass.SetSurfaceStyle(-1, style)
+            else:
+                self.nvizClass.SetSurfaceStyle(id, style)
+            self.update.remove('surface:draw:mode')
+
+        # wire color
+        if 'surface:draw:wire-color' in self.update:
+            color = data['draw']['wire-color']['value']
+            if data['draw']['all']:
+                self.nvizClass.SetWireColor(-1, str(color))
+            else:
+                self.nvizClass.SetWireColor(id, str(color))
+                self.update.remove('surface:draw:wire-color')
+        
+        # position
+        if 'surface:position' in self.update:
+            x = data['position']['x']
+            y = data['position']['y']
+            z = data['position']['z']
+            self.nvizClass.SetSurfacePosition(id, x, y, z)
+            self.update.remove('surface:position')
+            
+    def UpdateVolumeProperties(self, id, data, isosurfId=None):
+        """Apply volume layer properties"""
+        #
+        # draw
+        #
+        if 'volume:draw:resolution' in self.update:
+            self.nvizClass.SetIsosurfaceRes(id, data['draw']['resolution']['value'])
+            self.update.remove('volume:draw:resolution')
+        
+        if 'volume:draw:shading' in self.update:
+            if data['draw']['shading']['value'] < 0: # need to calculate
+                data['draw']['shading']['value'] = \
+                    self.GetDrawMode(shade=data['draw']['shading'],
+                                     string=False)
+            self.update.remove('volume:draw:shading')
+            
+        #
+        # isosurface attributes
+        #
+        for attrb in ('color', 'mask',
+                      'transp', 'shine', 'emit'):
+            if 'volume:attribute:%s' % attrb in self.update:
+                map = data['attribute'][attrb]['map']
+                value = data['attribute'][attrb]['value']
+
+                if map is None: # unset
+                    # only optional attributes
+                    if attrb == 'mask':
+                        # TODO: invert mask
+                        # TODO: broken in NVIZ
+                        # self.nvizClass.UnsetSurfaceMask(id)
+                        pass
+                    elif attrb == 'transp':
+                        # self.nvizClass.UnsetSurfaceTransp(id)
+                        pass
+                    elif attrb == 'emit':
+                        # self.nvizClass.UnsetSurfaceEmit(id) 
+                        pass
+                else:
+                    if type(value) == type('') and \
+                            len(value) <= 0: # ignore empty values (TODO: warning)
+                        continue
+                    elif attrb == 'color' and isosurfId:
+                        self.nvizClass.SetIsosurfaceColor(id, isosurfId, map, str(value))
+                    elif attrb == 'mask':
+                        # TODO: invert mask
+                        # TODO: broken in NVIZ
+                        # self.nvizClass.SetSurfaceMask(id, False, str(value))
+                        pass
+                    elif attrb == 'transp':
+                        # self.nvizClass.SetSurfaceTransp(id, map, str(value)) 
+                        pass
+                    elif attrb == 'shine':
+                        # self.nvizClass.SetSurfaceShine(id, map, str(value)) 
+                        pass
+                    elif attrb == 'emit':
+                        # self.nvizClass.SetSurfaceEmit(id, map, str(value)) 
+                        pass
+                self.update.remove('volume:attribute:%s' % attrb)
+
+    def UpdateVectorProperties(self, id, data, type):
+        """Update vector layer properties
+
+        @param id layer id
+        @param data properties
+        @param type lines/points
+        """
+        if type == 'points':
+            self.UpdateVectorPointsProperties(id, data[type])
+        else:
+            self.UpdateVectorLinesProperties(id, data[type])
+    
+    def UpdateVectorLinesProperties(self, id, data):
+        """Apply changes for vector line layer"""
+        # mode
+        if 'vector:lines:color' in self.update or \
+                'vector:lines:width' in self.update or \
+                'vector:lines:mode' in self.update:
+            width = data['width']
+            color = data['color']
+            if data['mode']['type'] == 'flat':
+                flat = True
+                if data.has_key('surface'):
+                    data.pop('surface')
+            else:
+                flat = False
+                if not 'vector:lines:surface' in self.update:
+                    self.update.append('vector:lines:surface')
+
+            self.nvizClass.SetVectorLineMode(id, color,
+                                             width, flat)
+            if 'vector:lines:color' in self.update:
+                self.update.remove('vector:lines:color')
+            if 'vector:lines:width' in self.update:
+                self.update.remove('vector:lines:width')
+            if 'vector:lines:mode' in self.update:
+                self.update.remove('vector:lines:mode')
+        # height
+        if 'vector:lines:height' in self.update:
+            self.nvizClass.SetVectorLineHeight(id,
+                                               data['height'])
+            self.update.remove('vector:lines:height')
+
+        # surface
+        if 'vector:lines:surface' in self.update:
+            idx = self.layers['raster']['name'].index(data['mode']['surface'])
+            if idx > -1:
+                self.nvizClass.SetVectorLineSurface(id,
+                                                    self.layers['raster']['id'][idx])
+            self.update.remove('vector:lines:surface')
+
+    def UpdateVectorPointsProperties(self, id, data):
+        """Apply changes for vector point layer"""
+        if 'vector:points:size' in self.update or \
+                'vector:points:width' in self.update or \
+                'vector:points:marker' in self.update or \
+                'vector:points:color' in self.update:
+            ret = self.nvizClass.SetVectorPointMode(id, data['color'],
+                                                    data['width'], float(data['size']),
+                                                    data['marker'] + 1)
+
+            error = None
+            if ret == -1:
+                error = _("Vector point layer not found (id=%d)") % id
+            elif ret == -2:
+                error = _("Unable to set data layer properties (id=%d)") % id
+
+            if error:
+                raise gcmd.NvizError(parent=self.parent,
+                                     message=_("Setting data layer properties failed.\n\n%s") % error)
+
+            for prop in ('size', 'width', 'marker', 'color'):
+                if 'vector:points:%s' % prop in self.update:
+                    self.update.remove('vector:points:%s' % prop)
+        
+        # height
+        if 'vector:points:height' in self.update:
+            self.nvizClass.SetVectorPointHeight(id,
+                                                data['height'])
+            self.update.remove('vector:points:height')
+
+        # surface
+        if 'vector:points:surface' in self.update:
+            idx = self.layers['raster']['name'].index(data['mode']['surface'])
+            if idx > -1:
+                self.nvizClass.SetVectorPointSurface(id,
+                                                     self.layers['raster']['id'][idx])
+            self.update.remove('vector:points:surface')


Property changes on: grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_mapdisp.py
___________________________________________________________________
Name: svn:keywords
   + Author Date Id
Name: svn:eol-style
   + native

Added: grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_tools.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_tools.py	                        (rev 0)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_tools.py	2008-08-15 20:05:46 UTC (rev 32788)
@@ -0,0 +1,2618 @@
+"""
+ at package nviz_tools.py
+
+ at brief Nviz tools window
+
+Classes:
+ - NvizToolWindow
+ - ViewPositionWindow
+ - IsoSurfList
+
+(C) 2008 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> (Google SoC 2008)
+"""
+
+import os
+
+import wx
+import wx.lib.colourselect as csel
+
+import globalvar
+import gselect
+from preferences import globalSettings as UserSettings
+
+class NvizToolWindow(wx.Frame):
+    """Experimental window for Nviz tools
+
+    @todo integrate with Map display
+    """
+    def __init__(self, parent=None, id=wx.ID_ANY, title=_("Nviz tools"),
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_FRAME_STYLE, mapWindow=None):
+        
+        self.parent = parent # MapFrame
+        self.lmgr = self.parent.gismanager # GMFrame
+        self.mapWindow = mapWindow
+
+        wx.Frame.__init__(self, parent, id, title, pos, size, style)
+
+        #
+        # icon
+        #
+        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_nviz.ico'), wx.BITMAP_TYPE_ICO))
+
+        #
+        # dialog body
+        #
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+        self.win = {} # window ids
+
+        #
+        # notebook
+        #
+        self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
+
+        self.page = {}
+        # view page
+        self.__createViewPage()
+        self.page['view'] = { 'id' : 0 }
+        # surface page
+        size = self.__createSurfacePage()
+        size = (size[0] + 25, size[0] + 20)
+        # vector page
+        self.__createVectorPage()
+        # volume page
+        self.__createVolumePage()
+        # settings page
+        self.__createSettingsPage()
+        self.page['settings'] = { 'id' : 1 }
+        self.UpdatePage('settings')
+        self.pageChanging = False
+
+        mainSizer.Add(item=self.notebook, proportion=1,
+                      flag=wx.EXPAND | wx.ALL, border=5)
+
+        #
+        # bindings
+        #
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+        #
+        # layout
+        #
+        self.SetSizer(mainSizer)
+        mainSizer.Fit(self)
+
+        self.SetSize(size)
+
+    def __createViewPage(self):
+        """Create view settings page"""
+        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
+        self.notebook.AddPage(page=panel,
+                              text=" %s " % _("View"))
+        
+        pageSizer = wx.BoxSizer(wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
+
+        self.win['view'] = {}
+
+        # position
+        posSizer = wx.GridBagSizer(vgap=3, hgap=3)
+        posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("W")),
+                     pos=(1, 0), flag=wx.ALIGN_CENTER)
+        posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("N")),
+                     pos=(0, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM)
+        viewPos = ViewPositionWindow(panel, id=wx.ID_ANY, size=(175, 175),
+                                     mapwindow=self.mapWindow)
+        self.win['view']['pos'] = viewPos.GetId()
+        posSizer.Add(item=viewPos,
+                     pos=(1, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL)
+        posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("S")),
+                     pos=(2, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_TOP)
+        posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("E")),
+                     pos=(1, 2), flag=wx.ALIGN_CENTER)
+        gridSizer.Add(item=posSizer, pos=(0, 0))
+                  
+        # perspective
+        range = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
+        self.CreateControl(panel, dict=self.win['view'], name='persp',
+                           range=(range['min'], range['max']),
+                           bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
+        gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Perspective:")),
+                      pos=(1, 0), flag=wx.ALIGN_CENTER)
+        gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['slider']), pos=(2, 0))
+        gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['spin']), pos=(3, 0),
+                      flag=wx.ALIGN_CENTER)        
+
+        # twist
+        range = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
+        self.CreateControl(panel, dict=self.win['view'], name='twist',
+                           range=(range['min'], range['max']),
+                           bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
+        gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Twist:")),
+                      pos=(1, 1), flag=wx.ALIGN_CENTER)
+        gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['slider']), pos=(2, 1))
+        gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['spin']), pos=(3, 1),
+                      flag=wx.ALIGN_CENTER)        
+
+        # height + z-exag
+        self.CreateControl(panel, dict=self.win['view'], name='height', sliderHor=False,
+                           range=(0, 1),
+                           bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
+        self.CreateControl(panel, dict=self.win['view'], name='z-exag', sliderHor=False,
+                           range=(0, 1),
+                           bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
+        heightSizer = wx.GridBagSizer(vgap=3, hgap=3)
+        heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Height:")),
+                      pos=(0, 0), flag=wx.ALIGN_LEFT, span=(1, 2))
+        heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['slider']),
+                        flag=wx.ALIGN_RIGHT, pos=(1, 0))
+        heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['spin']),
+                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
+                        wx.BOTTOM | wx.RIGHT, pos=(1, 1))
+        heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Z-exag:")),
+                      pos=(0, 2), flag=wx.ALIGN_LEFT, span=(1, 2))
+        heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['slider']),
+                        flag=wx.ALIGN_RIGHT, pos=(1, 2))
+        heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['spin']),
+                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
+                        wx.BOTTOM | wx.RIGHT, pos=(1, 3))
+
+        gridSizer.Add(item=heightSizer, pos=(0, 1), flag=wx.ALIGN_RIGHT)
+
+        # view setup + reset
+        viewSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        viewSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY,
+                                         label=_("Look at:")),
+                      flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
+        
+        viewType = wx.Choice (parent=panel, id=wx.ID_ANY, size=(125, -1),
+                              choices = [_("top"),
+                                         _("north"),
+                                         _("south"),
+                                         _("east"),
+                                         _("west"),
+                                         _("north-west"),
+                                         _("north-east"),
+                                         _("south-east"),
+                                         _("south-west")])
+        viewType.SetSelection(0)
+        viewType.Bind(wx.EVT_CHOICE, self.OnLookAt)
+        # self.win['lookAt'] = viewType.GetId()
+        viewSizer.Add(item=viewType, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
+                      border=5)
+
+        reset = wx.Button(panel, id=wx.ID_ANY, label=_("Reset"))
+        reset.SetToolTipString(_("Reset to default view"))
+        # self.win['reset'] = reset.GetId()
+        reset.Bind(wx.EVT_BUTTON, self.OnResetView)
+
+        viewSizer.Add(item=reset, proportion=1,
+                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT,
+                      border=5)
+
+        gridSizer.AddGrowableCol(3)
+        gridSizer.Add(item=viewSizer, pos=(4, 0), span=(1, 2),
+                      flag=wx.EXPAND)
+
+        # body
+        pageSizer.Add(item=gridSizer, proportion=1,
+                      flag=wx.EXPAND | wx.ALL,
+                      border=5)
+
+        panel.SetSizer(pageSizer)
+
+        return panel.GetBestSize()
+
+    def __createSurfacePage(self):
+        """Create view settings page"""
+        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
+        self.page['surface'] = {}
+        self.page['surface']['id'] = -1
+        self.page['surface']['panel'] = panel.GetId()
+
+        # panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY)
+        # panel.SetupScrolling(scroll_x=True, scroll_y=True)
+
+        pageSizer = wx.BoxSizer(wx.VERTICAL)
+
+        self.win['surface'] = {}
+        #
+        # surface attributes
+        #
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Surface attributes")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
+
+        # type 
+        self.win['surface']['attr'] = {}
+        row = 0
+        for code, attrb in (('topo', _("Topography")),
+                           ('color', _("Color")),
+                           ('mask', _("Mask")),
+                           ('transp', _("Transparency")),
+                           ('shine', _("Shininess")),
+                           ('emit', _("Emission"))):
+            self.win['surface'][code] = {} 
+            gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                             label=attrb + ':'),
+                          pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+            use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                             choices = [_("map")])
+            if code not in ('topo', 'color', 'shine'):
+                use.Insert(item=_("unset"), pos=0)
+                self.win['surface'][code]['required'] = False
+            else:
+                self.win['surface'][code]['required'] = True
+            if code != 'mask':
+                use.Append(item=_('constant'))
+            self.win['surface'][code]['use'] = use.GetId()
+            use.Bind(wx.EVT_CHOICE, self.OnMapObjUse)
+            gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
+                          pos=(row, 1))
+
+            map = gselect.Select(parent=panel, id=wx.ID_ANY,
+                                 # size=globalvar.DIALOG_GSELECT_SIZE,
+                                 size=(200, -1),
+                                 type="raster")
+            self.win['surface'][code]['map'] = map.GetId() - 1 # FIXME
+            map.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
+            # changing map topography not allowed
+            if code == 'topo':
+                map.Enable(False)
+            gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
+                          pos=(row, 2))
+
+            if code == 'color':
+                value = csel.ColourSelect(panel, id=wx.ID_ANY,
+                                          colour=UserSettings.Get(group='nviz', key='surface',
+                                                                  subkey=['color', 'value']))
+                value.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceMap)
+            elif code == 'mask':
+                value = None
+            else:
+                value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                                    initial=0)
+                if code == 'topo':
+                    value.SetRange(minVal=-1e9, maxVal=1e9)
+                elif code in ('shine', 'transp', 'emit'):
+                    value.SetRange(minVal=0, maxVal=255)
+                else:
+                    value.SetRange(minVal=0, maxVal=100)
+                value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
+            
+            if value:
+                self.win['surface'][code]['const'] = value.GetId()
+                value.Enable(False)
+                gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
+                              pos=(row, 3))
+            else:
+                self.win['surface'][code]['const'] = None
+
+            self.SetMapObjUseMap(nvizType='surface',
+                                 attrb=code) # -> enable map / disable constant
+                
+            row += 1
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.ALL,
+                      border=5)
+
+        #
+        # draw
+        #
+        self.win['surface']['draw'] = {}
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Draw")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+        gridSizer.AddGrowableCol(4)
+
+        # mode
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Mode:")),
+                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                          choices = [_("coarse"),
+                                     _("fine"),
+                                     _("both")])
+        mode.SetSelection(0)
+        mode.SetName("selection")
+        mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
+        self.win['surface']['draw']['mode'] = mode.GetId()
+        gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(0, 1))
+
+        # resolution (mode)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Resolution:")),
+                      pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
+        resSizer = wx.BoxSizer(wx.HORIZONTAL)
+        resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                        label=_("coarse:")),
+                     flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
+        resC = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=1,
+                           min=1,
+                           max=100)
+        resC.SetName("value")
+        self.win['surface']['draw']['res-coarse'] = resC.GetId()
+        resC.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
+        resSizer.Add(item=resC, flag=wx.ALL, border=3)
+        
+        resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                        label=_("fine:")),
+                     flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
+        resF = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=1,
+                           min=1,
+                           max=100)
+        resF.SetName("value")
+        self.win['surface']['draw']['res-fine'] = resF.GetId()
+        resF.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
+        resSizer.Add(item=resF, flag=wx.ALL, border=3)
+
+        gridSizer.Add(item=resSizer, pos=(0, 3), span=(1, 2))
+
+        # style
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Coarse style:")),
+                      pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        style = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                          choices = [_("wire"),
+                                     _("surface")])
+        style.SetName("selection")
+        self.win['surface']['draw']['style'] = style.GetId()
+        style.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
+        gridSizer.Add(item=style, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(1, 1))
+
+        # shading
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Shading:")),
+                      pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
+        shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                           choices = [_("flat"),
+                                      _("gouraud")])
+        shade.SetName("selection")
+        self.win['surface']['draw']['shading'] = shade.GetId()
+        shade.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
+        gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(1, 3))
+
+        # color
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Wire color:")),
+                      pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        color = csel.ColourSelect(panel, id=wx.ID_ANY)
+        color.SetName("colour")
+        color.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceWireColor)
+        self.win['surface']['draw']['wire-color'] = color.GetId()
+        gridSizer.Add(item=color, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(2, 1))
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+
+        all = wx.Button(panel, id=wx.ID_ANY, label=_("All"))
+        all.SetToolTipString(_("Use for all loaded surfaces"))
+        # self.win['reset'] = reset.GetId()
+        all.Bind(wx.EVT_BUTTON, self.OnSurfaceModeAll)
+        gridSizer.Add(item=all, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
+                      pos=(2, 4))
+
+        #
+        # mask
+        #
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Mask")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Mask zeros:")),
+                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+
+        elev = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+                           label=_("by elevation"))
+        elev.Enable(False) # TODO: not implemented yet
+        gridSizer.Add(item=elev, pos=(0, 1))
+
+        color = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+                           label=_("by color"))
+        color.Enable(False) # TODO: not implemented yet
+        gridSizer.Add(item=color, pos=(0, 2))
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+
+        #
+        # position
+        #
+        self.win['surface']['position'] = {}
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Position")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+
+        # position
+        axis = wx.Choice (parent=panel, id=wx.ID_ANY, size=(75, -1),
+                          choices = ["X",
+                                     "Y",
+                                     "Z"])
+        axis.SetSelection(0)
+        self.win['surface']['position']['axis'] = axis.GetId()
+        axis.Bind(wx.EVT_CHOICE, self.OnSurfaceAxis)
+        gridSizer.Add(item=axis, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(0, 0))
+        value = wx.Slider(parent=panel, id=wx.ID_ANY,
+                          value=0,
+                          minValue=-1e4,
+                          maxValue=1e4,
+                          style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
+                              wx.SL_TOP | wx.SL_LABELS,
+                          size=(350, -1))
+        self.win['surface']['position']['pos'] = value.GetId()
+        value.Bind(wx.EVT_SCROLL, self.OnSurfacePosition)
+        gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(0, 1))
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+        
+        panel.SetSizer(pageSizer)
+        
+        return panel.GetBestSize()
+
+    def __createVectorPage(self):
+        """Create view settings page"""
+        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
+        self.page['vector'] = {}
+        self.page['vector']['id'] = -1
+        self.page['vector']['panel'] = panel.GetId()
+
+        pageSizer = wx.BoxSizer(wx.VERTICAL)
+
+        self.win['vector'] = {}
+
+        #
+        # desc
+        #
+        desc = wx.StaticText(parent=panel, id=wx.ID_ANY,
+                             label="")
+        self.win['vector']['desc'] = desc.GetId()
+        pageSizer.Add(item=desc, proportion=0,
+                      flag=wx.EXPAND | wx.ALL,
+                      border=10)
+
+        #
+        # vector lines
+        #
+        self.win['vector']['lines'] = {}
+
+        showLines = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+                                label=_("Show vector lines"))
+        self.win['vector']['lines']['show'] = showLines.GetId()
+        showLines.Bind(wx.EVT_CHECKBOX, self.OnVectorShow)
+
+        pageSizer.Add(item=showLines, proportion=0,
+                      flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Vector lines")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+
+        # width
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Width:")),
+                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+
+        width = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                            initial=1,
+                            min=1,
+                            max=100)
+        self.win['vector']['lines']['width'] = width.GetId()
+        width.Bind(wx.EVT_SPINCTRL, self.OnVectorLines)
+        gridSizer.Add(item=width, pos=(0, 1),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        gridSizer.AddGrowableCol(2)
+
+        # color
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Color:")),
+                      pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL)
+
+        color = csel.ColourSelect(panel, id=wx.ID_ANY,
+                                  colour=UserSettings.Get(group='nviz', key='vector',
+                                                          subkey=['lines', 'color']))
+        self.win['vector']['lines']['color'] = color.GetId()
+        color.Bind(csel.EVT_COLOURSELECT, self.OnVectorLines)
+
+        gridSizer.Add(item=color, pos=(0, 4))
+
+        gridSizer.AddGrowableCol(5)
+
+        # display
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Display:")),
+                      pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
+
+        display = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                             choices = [_("on surface"),
+                                        _("flat")])
+        self.win['vector']['lines']['flat'] = display.GetId()
+        display.Bind(wx.EVT_CHOICE, self.OnVectorDisplay)
+
+        gridSizer.Add(item=display, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(0, 7))
+
+        # hight
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Hight above surface:")),
+                      pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL,
+                      span=(1, 2))
+        
+        surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
+                              style=wx.CB_SIMPLE | wx.CB_READONLY,
+                              choices=[])
+        surface.Bind(wx.EVT_COMBOBOX, self.OnVectorSurface)
+        self.win['vector']['lines']['surface'] = surface.GetId()
+        gridSizer.Add(item=surface, 
+                      pos=(1, 2), span=(1, 6),
+                      flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+
+        self.CreateControl(panel, dict=self.win['vector']['lines'], name='height', size=300,
+                           range=(0, 1000),
+                           bind=(self.OnVectorHeight, self.OnVectorHeightFull, self.OnVectorHeightSpin))
+        gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['slider']),
+                      pos=(2, 2), span=(1, 6))
+        gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['spin']),
+                      pos=(3, 4),
+                      flag=wx.ALIGN_CENTER)
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                     flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+
+        #
+        # vector points
+        #
+        self.win['vector']['points'] = {}
+
+        showPoints = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+                                 label=_("Show vector points"))
+        self.win['vector']['points']['show'] = showPoints.GetId()
+        showPoints.Bind(wx.EVT_CHECKBOX, self.OnVectorShow)
+
+        pageSizer.Add(item=showPoints, proportion=0,
+                      flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Vector points")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+
+        # icon size
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Icon size:")),
+                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+
+        isize = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                            initial=1,
+                            min=1,
+                            max=1e6)
+        isize.SetName('value')
+        self.win['vector']['points']['size'] = isize.GetId()
+        isize.Bind(wx.EVT_SPINCTRL, self.OnVectorPoints)
+        gridSizer.Add(item=isize, pos=(0, 1),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        # icon width
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("width:")),
+                      pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
+
+        iwidth = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                             initial=1,
+                             min=1,
+                             max=1e6)
+        iwidth.SetName('value')
+        self.win['vector']['points']['width'] = iwidth.GetId()
+        iwidth.Bind(wx.EVT_SPINCTRL, self.OnVectorPoints)
+        gridSizer.Add(item=iwidth, pos=(0, 3),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        # icon symbol
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("symbol:")),
+                      pos=(0, 4), flag=wx.ALIGN_CENTER_VERTICAL)
+        isym = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                          choices=UserSettings.Get(group='nviz', key='vector',
+                                                   subkey=['points', 'marker'], internal=True))
+        isym.SetName("selection")
+        self.win['vector']['points']['marker'] = isym.GetId()
+        isym.Bind(wx.EVT_CHOICE, self.OnVectorPoints)
+        gridSizer.Add(item=isym, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(0, 5))
+
+        # icon color
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("color:")),
+                      pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
+        icolor = csel.ColourSelect(panel, id=wx.ID_ANY)
+        icolor.SetName("color")
+        self.win['vector']['points']['color'] = icolor.GetId()
+        icolor.Bind(csel.EVT_COLOURSELECT, self.OnVectorPoints)
+        gridSizer.Add(item=icolor, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(0, 7))
+
+        # high
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Hight above surface:")),
+                      pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL,
+                      span=(1, 2))
+        
+        surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
+                              style=wx.CB_SIMPLE | wx.CB_READONLY,
+                              choices=[])
+        surface.Bind(wx.EVT_COMBOBOX, self.OnVectorSurface)
+        self.win['vector']['points']['surface'] = surface.GetId()
+        gridSizer.Add(item=surface, 
+                      pos=(1, 2), span=(1, 6),
+                      flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        self.CreateControl(panel, dict=self.win['vector']['points'], name='height', size=300,
+                           range=(0, 1000),
+                           bind=(self.OnVectorHeight, self.OnVectorHeightFull, self.OnVectorHeightSpin))
+        gridSizer.Add(item=self.FindWindowById(self.win['vector']['points']['height']['slider']),
+                      pos=(2, 2), span=(1, 6))
+        gridSizer.Add(item=self.FindWindowById(self.win['vector']['points']['height']['spin']),
+                      pos=(3, 4),
+                      flag=wx.ALIGN_CENTER)
+
+        
+        boxSizer.Add(item=gridSizer, proportion=1,
+                     flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+
+
+        panel.SetSizer(pageSizer)
+
+        return panel.GetBestSize()
+
+    def __createVolumePage(self):
+        """Create view settings page"""
+        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
+        self.page['volume'] = {}
+        self.page['volume']['id'] = -1
+        self.page['volume']['panel'] = panel.GetId()
+        
+        pageSizer = wx.BoxSizer(wx.VERTICAL)
+        
+        self.win['volume'] = {}
+
+        #
+        # draw
+        #
+        self.win['volume']['draw'] = {}
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Draw")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+        gridSizer.AddGrowableCol(4)
+
+        # mode
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Mode:")),
+                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(150, -1),
+                          choices = [_("isosurfaces"),
+                                     _("slides")])
+        mode.SetSelection(0)
+        mode.SetName("selection")
+        # mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
+        self.win['volume']['draw']['mode'] = mode.GetId()
+        gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(0, 1))
+
+        # shading
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Shading:")),
+                      pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
+        shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                           choices = [_("flat"),
+                                      _("gouraud")])
+        shade.SetName("selection")
+        self.win['volume']['draw']['shading'] = shade.GetId()
+        shade.Bind(wx.EVT_CHOICE, self.OnVolumeIsosurfMode)
+        gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(0, 3))
+
+        # resolution (mode)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Resolution:")),
+                      pos=(0, 4), flag=wx.ALIGN_CENTER_VERTICAL)
+        resol = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                            initial=1,
+                            min=1,
+                            max=100)
+        resol.SetName("value")
+        self.win['volume']['draw']['resolution'] = resol.GetId()
+        resol.Bind(wx.EVT_SPINCTRL, self.OnVolumeIsosurfResolution)
+        gridSizer.Add(item=resol, pos=(0, 5))
+        
+        boxSizer.Add(item=gridSizer, proportion=1,
+                     flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.ALL,
+                      border=5)
+
+        #
+        # manage isosurfaces
+        #
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("List of isosurfaces")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
+
+        # list
+        isolevel = IsoSurfList(parent=panel, win=self.win['volume'],
+                               size=(300, 150))
+        self.win['volume']['isosurfs'] = isolevel.GetId()
+        gridSizer.Add(item=isolevel, pos=(0, 0), span=(4, 1))
+        
+        # buttons (add, delete, move up, move down)
+        btnAdd = wx.Button(parent=panel, id=wx.ID_ADD)
+        self.win['volume']['btnIsosurfAdd'] = btnAdd.GetId()
+        btnAdd.Bind(wx.EVT_BUTTON, self.OnVolumeIsosurfAdd)
+        gridSizer.Add(item=btnAdd,
+                      pos=(0, 1))
+        btnDelete = wx.Button(parent=panel, id=wx.ID_DELETE)
+        self.win['volume']['btnIsosurfDelete'] = btnDelete.GetId()
+        btnDelete.Bind(wx.EVT_BUTTON, self.OnVolumeIsosurfDelete)
+        btnDelete.Enable(False)
+        gridSizer.Add(item=btnDelete,
+                      pos=(1, 1))
+        btnMoveUp = wx.Button(parent=panel, id=wx.ID_UP)
+        self.win['volume']['btnIsosurfMoveUp'] = btnMoveUp.GetId()
+        btnMoveUp.Bind(wx.EVT_BUTTON, self.OnVolumeIsosurfMoveUp)
+        btnMoveUp.Enable(False)
+        gridSizer.Add(item=btnMoveUp,
+                      pos=(2, 1))
+        btnMoveDown = wx.Button(parent=panel, id=wx.ID_DOWN)
+        self.win['volume']['btnIsosurfMoveDown'] = btnMoveDown.GetId()
+        btnMoveDown.Bind(wx.EVT_BUTTON, self.OnVolumeIsosurfMoveDown)
+        btnMoveDown.Enable(False)
+        gridSizer.Add(item=btnMoveDown,
+                      pos=(3, 1))
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                     flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+        
+        #
+        # isosurface attributes
+        #
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Isosurface attributes")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
+
+        self.win['volume']['attr'] = {}
+        row = 0
+        for code, attrb in (('topo', _("Topography level")),
+                            ('color', _("Color")),
+                            ('mask', _("Mask")),
+                            ('transp', _("Transparency")),
+                            ('shine', _("Shininess")),
+                            ('emit', _("Emission"))):
+            self.win['volume'][code] = {} 
+            # label
+            gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                             label=attrb + ':'),
+                          pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+            if code != 'topo':
+                use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                                 choices = [_("map")])
+            else:
+                use = None
+            # check for required properties
+            if code not in ('topo', 'color', 'shine'):
+                use.Insert(item=_("unset"), pos=0)
+                self.win['volume'][code]['required'] = False
+            else:
+                self.win['volume'][code]['required'] = True
+            if use and code != 'mask':
+                use.Append(item=_('constant'))
+            if use:
+                self.win['volume'][code]['use'] = use.GetId()
+                use.Bind(wx.EVT_CHOICE, self.OnMapObjUse)
+                gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
+                              pos=(row, 1))
+            
+            if code != 'topo':
+                map = gselect.Select(parent=panel, id=wx.ID_ANY,
+                                     # size=globalvar.DIALOG_GSELECT_SIZE,
+                                     size=(200, -1),
+                                     type="grid3")
+                self.win['volume'][code]['map'] = map.GetId() - 1 # FIXME
+                map.Bind(wx.EVT_TEXT, self.OnVolumeIsosurfMap)
+                gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
+                              pos=(row, 2))
+            else:
+                map = None
+            
+            if code == 'color':
+                value = csel.ColourSelect(panel, id=wx.ID_ANY,
+                                          colour=UserSettings.Get(group='nviz', key='volume',
+                                                                  subkey=['color', 'value']))
+                value.Bind(csel.EVT_COLOURSELECT, self.OnVolumeIsosurfMap)
+            elif code == 'mask':
+                value = None
+            else:
+                if code == 'topo':
+                    size = (200, -1)
+                else:
+                    size = (65, -1)
+                value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=size,
+                                    initial=0)
+                if code == 'topo':
+                    value.SetRange(minVal=-1e9, maxVal=1e9)
+                elif code in ('shine', 'transp', 'emit'):
+                    value.SetRange(minVal=0, maxVal=255)
+                else:
+                    value.SetRange(minVal=0, maxVal=100)
+                value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
+            
+            if value:
+                self.win['volume'][code]['const'] = value.GetId()
+                if code == 'topo':
+                    gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
+                                  pos=(row, 2))
+                else:
+                    value.Enable(False)
+                    gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
+                                  pos=(row, 3))
+            else:
+                self.win['volume'][code]['const'] = None
+            
+            if code != 'topo':
+                self.SetMapObjUseMap(nvizType='volume',
+                                     attrb=code) # -> enable map / disable constant
+                
+            row += 1
+        
+        boxSizer.Add(item=gridSizer, proportion=1,
+                     flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+        
+        panel.SetSizer(pageSizer)
+        
+        return panel.GetBestSize()
+    
+    def __createSettingsPage(self):
+        """Create settings page"""
+        panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
+        self.notebook.AddPage(page=panel,
+                              text=" %s " % _("Settings"))
+        
+        pageSizer = wx.BoxSizer(wx.VERTICAL)
+
+        self.win['settings'] = {}
+
+        #
+        # general
+        #
+        self.win['settings']['general'] = {}
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("General")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
+
+        # background color
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Background color:")),
+                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+
+        color = csel.ColourSelect(panel, id=wx.ID_ANY,
+                                  colour=UserSettings.Get(group='nviz', key='settings',
+                                                          subkey=['general', 'bgcolor']))
+        self.win['settings']['general']['bgcolor'] = color.GetId()
+        color.Bind(csel.EVT_COLOURSELECT, self.OnBgColor)
+        gridSizer.Add(item=color, pos=(0, 1))
+
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.ALL,
+                      border=5)
+
+        #
+        # view
+        #
+        self.win['settings']['view'] = {}
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("View")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
+
+
+        # perspective
+        self.win['settings']['view']['persp'] = {}
+        pvals = UserSettings.Get(group='nviz', key='view', subkey='persp')
+        ipvals = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Perspective:")),
+                      pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("(value)")),
+                      pos=(0, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        pval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=pvals['value'],
+                           min=ipvals['min'],
+                           max=ipvals['max'])
+        self.win['settings']['view']['persp']['value'] = pval.GetId()
+        gridSizer.Add(item=pval, pos=(0, 2),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("(step)")),
+                      pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        pstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=pvals['step'],
+                           min=ipvals['min'],
+                           max=ipvals['max']-1)
+        self.win['settings']['view']['persp']['step'] = pstep.GetId()
+        gridSizer.Add(item=pstep, pos=(0, 4),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        # position
+        self.win['settings']['view']['pos'] = {}
+        posvals = UserSettings.Get(group='nviz', key='view', subkey='pos')
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Position:")),
+                      pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("(x)")),
+                      pos=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        px = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=posvals['x'] * 100,
+                           min=0,
+                           max=100)
+        self.win['settings']['view']['pos']['x'] = px.GetId()
+        gridSizer.Add(item=px, pos=(1, 2),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="(y)"),
+                      pos=(1, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        py = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=posvals['y'] * 100,
+                           min=0,
+                           max=100)
+        self.win['settings']['view']['pos']['y'] = py.GetId()
+        gridSizer.Add(item=py, pos=(1, 4),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        # height
+        self.win['settings']['view']['height'] = {}
+        hvals = UserSettings.Get(group='nviz', key='view', subkey='height')
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Height")),
+                      pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("(step)")),
+                      pos=(2, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        hstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=hvals['step'],
+                           min=1,
+                           max=1e6)
+        self.win['settings']['view']['height']['step'] = hstep.GetId()
+        gridSizer.Add(item=hstep, pos=(2, 2),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        # twist
+        self.win['settings']['view']['twist'] = {}
+        tvals = UserSettings.Get(group='nviz', key='view', subkey='twist')
+        itvals = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Twist")),
+                      pos=(3, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("(value)")),
+                      pos=(3, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        tval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=tvals['value'],
+                           min=itvals['min'],
+                           max=itvals['max'])
+        self.win['settings']['view']['twist']['value'] = tval.GetId()
+        gridSizer.Add(item=tval, pos=(3, 2),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("(step)")),
+                      pos=(3, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        tstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=tvals['step'],
+                           min=itvals['min'],
+                           max=itvals['max']-1)
+        self.win['settings']['view']['twist']['step'] = tstep.GetId()
+        gridSizer.Add(item=tstep, pos=(3, 4),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        # z-exag
+        self.win['settings']['view']['z-exag'] = {}
+        zvals = UserSettings.Get(group='nviz', key='view', subkey='z-exag')
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Z-exag")),
+                      pos=(4, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("(value)")),
+                      pos=(4, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        zval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=zvals['value'],
+                           min=-1e6,
+                           max=1e6)
+        self.win['settings']['view']['z-exag']['value'] = zval.GetId()
+        gridSizer.Add(item=zval, pos=(4, 2),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("(step):")),
+                      pos=(4, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
+
+        zstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                           initial=zvals['step'],
+                           min=-1e6,
+                           max=1e6)
+        self.win['settings']['view']['z-exag']['step'] = zstep.GetId()
+        gridSizer.Add(item=zstep, pos=(4, 4),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+
+        #
+        # surface
+        #
+        self.win['settings']['surface'] = {}
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Surface")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
+
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+
+        #
+        # vector lines
+        #
+        self.win['settings']['vector'] = {}
+        self.win['settings']['vector']['lines'] = {}
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Vector lines")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
+
+        # show
+        row = 0
+        showLines = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+                                label=_("Show lines"))
+        self.win['settings']['vector']['lines']['show'] = showLines.GetId()
+        showLines.SetValue(UserSettings.Get(group='nviz', key='vector',
+                                            subkey=['lines', 'show']))
+        gridSizer.Add(item=showLines, pos=(row, 0))
+
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+
+        #
+        # vector points
+        #
+        self.win['settings']['vector']['points'] = {}
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s " % (_("Vector points")))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap=3, hgap=5)
+
+        # show
+        row = 0
+        showPoints = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+                                 label=_("Show points"))
+        showPoints.SetValue(UserSettings.Get(group='nviz', key='vector',
+                                             subkey=['points', 'show']))
+        self.win['settings']['vector']['points']['show'] = showPoints.GetId()
+        gridSizer.Add(item=showPoints, pos=(row, 0), span=(1, 8))
+
+        # icon size
+        row += 1 
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Size:")),
+                      pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
+        
+        isize = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                            initial=100,
+                            min=1,
+                            max=1e6)
+        self.win['settings']['vector']['points']['size'] = isize.GetId()
+        isize.SetValue(UserSettings.Get(group='nviz', key='vector',
+                                        subkey=['points', 'size']))
+        gridSizer.Add(item=isize, pos=(row, 1),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+
+        # icon width
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Witdh:")),
+                      pos=(row, 2), flag=wx.ALIGN_CENTER_VERTICAL)
+        
+        iwidth = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
+                            initial=2,
+                            min=1,
+                            max=1e6)
+        self.win['settings']['vector']['points']['width'] = isize.GetId()
+        iwidth.SetValue(UserSettings.Get(group='nviz', key='vector',
+                                         subkey=['points', 'width']))
+        gridSizer.Add(item=iwidth, pos=(row, 3),
+                      flag=wx.ALIGN_CENTER_VERTICAL)
+
+        # icon symbol
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Marker:")),
+                      pos=(row, 4), flag=wx.ALIGN_CENTER_VERTICAL)
+        isym = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
+                          choices=UserSettings.Get(group='nviz', key='vector',
+                                                   subkey=['points', 'marker'], internal=True))
+        isym.SetName("selection")
+        self.win['settings']['vector']['points']['marker'] = isym.GetId()
+        isym.SetSelection(UserSettings.Get(group='nviz', key='vector',
+                                           subkey=['points', 'marker']))
+        gridSizer.Add(item=isym, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(row, 5))
+
+        # icon color
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=_("Color:")),
+                      pos=(row, 6), flag=wx.ALIGN_CENTER_VERTICAL)
+        icolor = csel.ColourSelect(panel, id=wx.ID_ANY)
+        icolor.SetName("color")
+        self.win['settings']['vector']['points']['color'] = icolor.GetId()
+        icolor.SetColour(UserSettings.Get(group='nviz', key='vector',
+                                          subkey=['points', 'color']))
+        gridSizer.Add(item=icolor, flag=wx.ALIGN_CENTER_VERTICAL,
+                      pos=(row, 7))
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.ALL | wx.EXPAND, border=3)
+        pageSizer.Add(item=boxSizer, proportion=0,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+                      border=5)
+
+        #
+        # buttons
+        #
+        btnDefault = wx.Button(panel, wx.ID_CANCEL, label=_("Default"))
+        btnSave = wx.Button(panel, wx.ID_SAVE)
+        btnApply = wx.Button(panel, wx.ID_APPLY)
+
+        btnDefault.Bind(wx.EVT_BUTTON, self.OnDefault)
+        btnDefault.SetToolTipString(_("Restore default settings"))
+        btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
+        btnApply.SetToolTipString(_("Apply changes for the current session"))
+        btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
+        btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
+        btnSave.SetDefault()
+
+        btnSizer = wx.StdDialogButtonSizer()
+        btnSizer.AddButton(btnDefault)
+        btnSizer.AddButton(btnApply)
+        btnSizer.AddButton(btnSave)
+        btnSizer.Realize()
+
+        pageSizer.Add(item=btnSizer, proportion=1,
+                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM,
+                      border=5)
+
+        panel.SetSizer(pageSizer)
+
+        return panel.GetBestSize()
+
+    def CreateControl(self, parent, dict, name, range, bind, sliderHor=True, size=200):
+        """Add control (Slider + SpinCtrl)"""
+        dict[name] = {}
+        if sliderHor:
+            style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
+                wx.SL_BOTTOM
+            sizeW = (size, -1)
+        else:
+            style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | \
+                wx.SL_BOTTOM | wx.SL_INVERSE
+            sizeW = (-1, size)
+        try:
+            val = self.mapWindow.view[name]['value']
+        except KeyError:
+            val=-1
+        slider = wx.Slider(parent=parent, id=wx.ID_ANY,
+                           value=val,
+                           minValue=range[0],
+                           maxValue=range[1],
+                           style=style,
+                           size=sizeW)
+        slider.SetName('slider')
+        slider.Bind(wx.EVT_SCROLL, bind[0])
+        slider.Bind(wx.EVT_SCROLL_CHANGED, bind[1])
+        dict[name]['slider'] = slider.GetId()
+
+        spin = wx.SpinCtrl(parent=parent, id=wx.ID_ANY, size=(65, -1),
+                           initial=val,
+                           min=range[0],
+                           max=range[1])
+        #         spin = wx.SpinButton(parent=parent, id=wx.ID_ANY)
+        #         spin.SetValue (self.mapWindow.view[name]['value'])
+        #         spin.SetRange(self.mapWindow.view[name]['min'],
+        #                      self.mapWindow.view[name]['max'])
+
+        # no 'changed' event ... (FIXME)
+        spin.SetName('spin')
+        spin.Bind(wx.EVT_SPINCTRL, bind[2])
+        dict[name]['spin'] = spin.GetId()
+
+    def UpdateSettings(self):
+        """Update dialog settings"""
+        for control in ('height',
+                        'persp',
+                        'twist',
+                        'z-exag'):
+            for win in self.win['view'][control].itervalues():
+                if control == 'height':
+                    value = UserSettings.Get(group='nviz', key='view',
+                                             subkey=['height', 'value'], internal=True)
+                else:
+                    value = self.mapWindow.view[control]['value']
+                self.FindWindowById(win).SetValue(value)
+
+        self.FindWindowById(self.win['view']['pos']).Draw()
+        self.FindWindowById(self.win['view']['pos']).Refresh(False)
+        
+        self.Refresh(False)
+
+    def __GetWindowName(self, dict, id):
+        for name in dict.iterkeys():
+            if type(dict[name]) is type({}):
+                for win in dict[name].itervalues():
+                    if win == id:
+                        return name
+            else:
+                if dict[name] == id:
+                    return name
+
+        return None
+
+    def OnViewChange(self, event):
+        """Change view, render in quick mode"""
+        # find control
+        winName = self.__GetWindowName(self.win['view'], event.GetId())
+        if not winName:
+            return
+
+        if winName == 'height':
+            view = self.mapWindow.iview # internal
+        else:
+            view = self.mapWindow.view
+
+        view[winName]['value'] = event.GetInt()
+
+        for win in self.win['view'][winName].itervalues():
+            self.FindWindowById(win).SetValue(view[winName]['value'])
+
+        self.mapWindow.update.append('view')
+        if winName == 'z-exag':
+            self.mapWindow.update.append('z-exag')
+        
+        self.mapWindow.render['quick'] = True
+        self.mapWindow.Refresh(False)
+
+    def OnViewChanged(self, event):
+        """View changed, render in full resolution"""
+        self.mapWindow.render['quick'] = False
+        self.mapWindow.Refresh(False)
+
+    def OnViewChangedSpin(self, event):
+        """View changed, render in full resolution"""
+        # TODO: use step value instead
+
+        self.OnViewChange(event)
+        self.OnViewChanged(None)
+
+    def OnResetView(self, event):
+        """Reset to default view (view page)"""
+        self.mapWindow.ResetView()
+        self.UpdateSettings()
+        self.mapWindow.Refresh(False)
+
+    def OnLookAt(self, event):
+        """Look at (view page)"""
+        sel = event.GetSelection()
+        if sel == 0: # top
+            self.mapWindow.view['pos']['x'] = 0.5
+            self.mapWindow.view['pos']['y'] = 0.5
+        elif sel == 1: # north
+            self.mapWindow.view['pos']['x'] = 0.5
+            self.mapWindow.view['pos']['y'] = 0.0
+        elif sel == 2: # south
+            self.mapWindow.view['pos']['x'] = 0.5
+            self.mapWindow.view['pos']['y'] = 1.0
+        elif sel == 3: # east
+            self.mapWindow.view['pos']['x'] = 1.0
+            self.mapWindow.view['pos']['y'] = 0.5
+        elif sel == 4: # west
+            self.mapWindow.view['pos']['x'] = 0.0
+            self.mapWindow.view['pos']['y'] = 0.5
+        elif sel == 5: # north-west
+            self.mapWindow.view['pos']['x'] = 0.0
+            self.mapWindow.view['pos']['y'] = 0.0
+        elif sel == 6: # north-east
+            self.mapWindow.view['pos']['x'] = 1.0
+            self.mapWindow.view['pos']['y'] = 0.0
+        elif sel == 7: # south-east
+            self.mapWindow.view['pos']['x'] = 1.0
+            self.mapWindow.view['pos']['y'] = 1.0
+        elif sel == 8: # south-west
+            self.mapWindow.view['pos']['x'] = 0.0
+            self.mapWindow.view['pos']['y'] = 1.0
+
+        self.mapWindow.update.append('view')
+
+        self.UpdateSettings()
+
+        self.mapWindow.Refresh(False)
+
+    def OnDefault(self, event):
+        """Restore default settings"""
+        settings = copy.deepcopy(UserSettings.GetDefaultSettings()['nviz'])
+        UserSettings.Set(group='nviz',
+                         value=settings)
+        
+        for subgroup, key in settings.iteritems(): # view, surface, vector...
+            if subgroup != 'view':
+                continue
+            for subkey, value in key.iteritems():
+                for subvalue in value.keys():
+                    win = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue])
+                    val = settings[subgroup][subkey][subvalue]
+                    if subkey == 'pos':
+                        val = int(val * 100)
+
+                    win.SetValue(val)
+        
+        event.Skip()
+
+    def OnApply(self, event):
+        """Apply button pressed"""
+        if self.notebook.GetSelection() == self.page['settings']['id']:
+            self.ApplySettings()
+        
+        if event:
+            event.Skip()
+
+    def ApplySettings(self):
+        """Apply Nviz settings for current session"""
+        settings = UserSettings.Get(group='nviz')
+        for subgroup, key in settings.iteritems(): # view, surface, vector...
+            for subkey, value in key.iteritems():
+                for subvalue in value.keys():
+                    try: # TODO
+                        win = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue])
+                    except:
+                        # print 'e', subgroup, subkey, subvalue
+                        continue
+                    
+                    if win.GetName() == "selection":
+                        value = win.GetSelection()
+                    elif win.GetName() == "color":
+                        value = tuple(win.GetColour())
+                    else:
+                        value = win.GetValue()
+                    if subkey == 'pos':
+                        value = float(value) / 100
+                    
+                    settings[subgroup][subkey][subvalue] = value
+                    
+    def OnSave(self, event):
+        """OK button pressed
+        
+        Apply changes, update map and save settings of selected layer
+        """
+        #
+        # apply changes
+        #
+        self.OnApply(None)
+
+        if self.notebook.GetSelection() == self.page['settings']['id']:
+            fileSettings = {}
+            UserSettings.ReadSettingsFile(settings=fileSettings)
+            fileSettings['nviz'] = UserSettings.Get(group='nviz')
+            file = UserSettings.SaveToFile(fileSettings)
+            self.lmgr.goutput.WriteLog(_('Nviz settings saved to file <%s>.') % file)
+
+    def OnBgColor(self, event):
+        """Background color changed"""
+        color = event.GetValue()
+        color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
+
+        self.mapWindow.nvizClass.SetBgColor(str(color))
+
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+        
+    def OnClose(self, event):
+        """Close button pressed
+        
+        Close dialog
+        """
+        self.Hide()
+
+    def OnMapObjUse(self, event):
+        """Surface attribute -- use -- map/constant"""
+        if not self.mapWindow.init:
+            return
+
+        wx.Yield()
+
+        # find attribute row
+        attrb = self.__GetWindowName(self.win['surface'], event.GetId())
+        if not attrb:
+            attrb = self.__GetWindowName(self.win['volume'], event.GetId())
+            nvizType = 'volume'
+        else:
+            nvizType = 'surface'
+        
+        selection = event.GetSelection()
+        if self.win[nvizType][attrb]['required']: # no 'unset'
+            selection += 1
+        if selection == 0: # unset
+            useMap = None
+            value = ''
+        elif selection == 1: # map
+            useMap = True
+            value = self.FindWindowById(self.win[nvizType][attrb]['map']).GetValue()
+        elif selection == 2: # constant
+            useMap = False
+            if attrb == 'color':
+                value = self.FindWindowById(self.win[nvizType][attrb]['const']).GetColour()
+                value = self._getColorString(value)
+            else:
+                value = self.FindWindowById(self.win[nvizType][attrb]['const']).GetValue()
+
+        self.SetMapObjUseMap(nvizType=nvizType,
+                             attrb=attrb, map=useMap)
+        
+        self.mapWindow.update.append('%s:attribute:%s' % (nvizType, attrb))
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        data[nvizType]['attribute'][attrb] = { 'map' : useMap,
+                                               'value' : str(value),
+                                               }
+
+        # update properties
+        event = wxUpdateProperties()
+        wx.PostEvent(self.mapWindow, event)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+    def SetMapObjUseMap(self, nvizType, attrb, map=None):
+        if attrb in ('topo', 'color', 'shine'):
+            incSel = -1 # decrement selection (no 'unset')
+        else:
+            incSel = 0
+
+        if map is True: # map
+            if attrb != 'topo': # changing map topography not allowed
+                # not sure why, but here must be disabled both ids, should be fixed!
+                self.FindWindowById(self.win[nvizType][attrb]['map'] + 1).Enable(True)
+            if self.win[nvizType][attrb]['const']:
+                self.FindWindowById(self.win[nvizType][attrb]['const']).Enable(False)
+            self.FindWindowById(self.win[nvizType][attrb]['use']).SetSelection(1 + incSel)
+        elif map is False: # const
+            self.FindWindowById(self.win[nvizType][attrb]['map'] + 1).Enable(False)
+            if self.win[nvizType][attrb]['const']:
+                self.FindWindowById(self.win[nvizType][attrb]['const']).Enable(True)
+            self.FindWindowById(self.win[nvizType][attrb]['use']).SetSelection(2 + incSel)
+        else: # unset
+            self.FindWindowById(self.win[nvizType][attrb]['map'] + 1).Enable(False)
+            if self.win[nvizType][attrb]['const']:
+                self.FindWindowById(self.win[nvizType][attrb]['const']).Enable(False)
+            self.FindWindowById(self.win[nvizType][attrb]['use']).SetSelection(0)
+
+    def OnSurfaceMap(self, event):
+        """Set surface attribute"""
+        self.SetMapObjAttrb(nvizType='surface', winId=event.GetId())
+        
+    def SetMapObjAttrb(self, nvizType, winId):
+        """Set map object attrbite"""
+        if not self.mapWindow.init:
+            return
+
+        attrb = self.__GetWindowName(self.win[nvizType], winId) 
+        if not attrb:
+            return
+
+        selection = self.FindWindowById(self.win[nvizType][attrb]['use']).GetSelection()
+        if self.win[nvizType][attrb]['required']:
+            selection += 1
+
+        if selection == 0: # unset
+            map = None
+            value = ''
+        elif selection == 1: # map
+            value = self.FindWindowById(self.win[nvizType][attrb]['map']).GetValue()
+            map = True
+        else: # constant
+            if attrb == 'color':
+                value = self.FindWindowById(self.win[nvizType][attrb]['const']).GetColour()
+                # tuple to string
+                value = self._getColorString(value)
+            else:
+                value = self.FindWindowById(self.win[nvizType][attrb]['const']).GetValue()
+            map = False
+        
+        if not self.pageChanging:
+            self.mapWindow.update.append('%s:attribute:%s' % (nvizType, attrb))
+            data = self.mapWindow.GetSelectedLayer(type='nviz')
+            data[nvizType]['attribute'][attrb] = { 'map' : map,
+                                                   'value' : str(value),
+                                                   }
+            
+            # update properties
+            event = wxUpdateProperties()
+            wx.PostEvent(self.mapWindow, event)
+            
+            if self.parent.autoRender.IsChecked():
+                self.mapWindow.Refresh(False)
+
+    def OnSurfaceResolution(self, event):
+        """Draw resolution changed"""
+        self.SetSurfaceResolution()
+
+        if apply and self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+    def SetSurfaceResolution(self):
+        """Set draw resolution"""
+        coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
+        fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
+            
+        self.mapWindow.update.append('surface:draw:resolution')
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        data['surface']['draw']['resolution'] = { 'coarse' : coarse,
+                                                  'fine' : fine }
+        
+        # update properties
+        event = wxUpdateProperties(layer=item)
+        wx.PostEvent(self.mapWindow, event)
+        
+    def SetSurfaceMode(self):
+        """Set draw mode
+
+        @param apply allow auto-rendering
+        """
+        mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
+        if mode == 0: # coarse
+            self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
+            self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
+        elif mode == 1: # fine
+            self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
+            self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
+        else: # both
+            self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
+            self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
+
+        style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
+
+        shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
+
+        value, desc = self.mapWindow.GetDrawMode(mode, style, shade)
+
+        return value, desc
+
+    def OnSurfaceMode(self, event):
+        """Set draw mode"""
+        value, desc = self.SetSurfaceMode()
+
+        self.mapWindow.update.append('surface:draw:mode')
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        data['surface']['draw']['mode'] = { 'value' : value,
+                                            'desc' : desc }
+        
+        # update properties
+        event = wxUpdateProperties()
+        wx.PostEvent(self.mapWindow, event)
+        
+        if apply and self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+    def OnSurfaceModeAll(self, event):
+        """Set draw mode (including wire color) for all loaded surfaces"""
+        self.SetSurfaceMode(all=True)
+        self.SetSurfaceResolution(all=True)
+        ### color = self.FindWindowById(self.win['surface']['draw']['wire-color']).GetColour()
+
+        if apply and self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+    def _getColorString(self, color):
+        """Set wire color"""
+        return str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
+
+    def OnSurfaceWireColor(self, event):
+        """Set wire color"""
+        self.mapWindow.update.append('surface:draw:wire-color')
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        value = self._getColorString(event.GetValue())
+        data['surface']['draw']['wire-color'] = { 'value' : value }
+        
+        
+        # update properties
+        event = wxUpdateProperties()
+        wx.PostEvent(self.mapWindow, event)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+    def OnSurfaceAxis(self, event):
+        """Surface position, axis changed"""
+        mapLayer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        id = data['object']['id']
+
+        axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
+        win = self.FindWindowById(self.win['surface']['position']['pos'])
+
+        x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
+
+        if axis == 0: # x
+            win.SetRange(-1e4, 1e4)
+            win.SetValue(x)
+        elif axis == 1: # y
+            win.SetRange(-1e4, 1e4)
+            win.SetValue(y)
+        else: # z
+            win.SetRange(-1e3, 1e3)
+            win.SetValue(z)
+
+    def OnSurfacePosition(self, event):
+        """Surface position"""
+        axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
+        value = event.GetInt()
+
+        mapLayer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        id = data['object']['id']
+        x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
+
+        if axis == 0: # x
+            x = value
+        elif axis == 1: # y
+            y = value
+        else: # z
+            z = value
+        
+        self.mapWindow.update.append('surface:position')
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        data['surface']['position']['x'] = x
+        data['surface']['position']['y'] = y
+        data['surface']['position']['z'] = z
+        
+        # update properties
+        event = wxUpdateProperties(layer=item)
+        wx.PostEvent(self.mapWindow, event)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+    def UpdateVectorShow(self, vecType, enabled):
+        """Enable/disable lines/points widgets
+
+        @param vecType vector type (lines, points)
+        """
+        if vecType != 'lines' and vecType != 'points':
+            return False
+
+        for win in self.win['vector'][vecType].keys():
+            if win == 'show':
+                continue
+            if type(self.win['vector'][vecType][win]) == type({}):
+                for swin in self.win['vector'][vecType][win].keys():
+                    if enabled:
+                        self.FindWindowById(self.win['vector'][vecType][win][swin]).Enable(True)
+                    else:
+                        self.FindWindowById(self.win['vector'][vecType][win][swin]).Enable(False)
+            else:
+                if enabled:
+                    self.FindWindowById(self.win['vector'][vecType][win]).Enable(True)
+                else:
+                    self.FindWindowById(self.win['vector'][vecType][win]).Enable(False)
+
+        return True
+    
+    def OnVectorShow(self, event):
+        """Show vector lines/points"""
+        winId = event.GetId()
+        if winId == self.win['vector']['lines']['show']:
+            vecType = 'lines'
+        else: # points
+            vecType = 'points'
+
+        checked = event.IsChecked()
+        item = self.mapWindow.GetSelectedLayer(type='item')
+        data = self.mapWindow.GetSelectedLayer(type='nviz')['vector']
+        
+        if checked:
+            self.mapWindow.LoadVector(item, (vecType,))
+        else:
+            self.mapWindow.UnloadVector(item, (vecType,))
+        
+        self.UpdateVectorShow(vecType, checked)
+        
+        if checked:
+            try:
+                id = data[vecType]['object']['id']
+            except KeyError:
+                id = -1
+
+            if id > 0:
+                self.mapWindow.SetLayerData(item, id, vecType)
+        
+                # update properties
+                event = wxUpdateProperties(layer=item)
+                wx.PostEvent(self.mapWindow, event)
+                
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+        
+        event.Skip()
+    
+    def OnVectorDisplay(self, event):
+        """Display vector lines on surface/flat"""
+        if event.GetSelection() == 0: # surface
+            if len(self.mapWindow.layers['raster']['name']) < 1:
+                event.Veto()
+                return
+
+            self.FindWindowById(self.win['vector']['lines']['surface']).Enable(True)
+            # set first found surface
+            data = self.mapWindow.GetSelectedLayer(type='nviz')
+            data['vector']['lines']['mode']['surface'] = self.mapWindow.layers['raster']['name'][0]
+            self.FindWindowById(self.win['vector']['lines']['surface']).SetStringSelection( \
+                self.mapWindow.layers['raster']['name'][0])
+        else: # flat
+            self.FindWindowById(self.win['vector']['lines']['surface']).Enable(False)
+
+        self.OnVectorLines(event)
+
+        event.Skip()
+
+    def OnVectorLines(self, event):
+        """Set vector lines mode, apply changes if auto-rendering is enabled"""
+        width = self.FindWindowById(self.win['vector']['lines']['width']).GetValue()
+
+        color = self.FindWindowById(self.win['vector']['lines']['color']).GetColour()
+        color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
+
+        mode = {}
+        if self.FindWindowById(self.win['vector']['lines']['flat']).GetSelection() == 0:
+            mode['type'] = 'surface'
+            mode['surface'] = self.FindWindowById(self.win['vector']['lines']['surface']).GetValue()
+            self.mapWindow.update.append('vector:lines:surface')
+        else:
+            mode['type'] = 'flat'
+
+        self.mapWindow.update.append('vector:lines:width')
+        self.mapWindow.update.append('vector:lines:color')
+        self.mapWindow.update.append('vector:lines:mode')
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        data['vector']['lines']['width'] = width
+        data['vector']['lines']['color'] = color
+        data['vector']['lines']['mode'] = mode
+        
+        # update properties
+        event = wxUpdateProperties()
+        wx.PostEvent(self.mapWindow, event)
+                        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+        
+    def OnVectorHeight(self, event):
+        value = event.GetInt()
+        id = event.GetId()
+        if id == self.win['vector']['lines']['height']['spin'] or \
+                id == self.win['vector']['lines']['height']['slider']:
+            vtype = 'lines'
+        else:
+            vtype = 'points'
+        
+        if type(event) == type(wx.ScrollEvent()):
+            # slider
+            win = self.FindWindowById(self.win['vector'][vtype]['height']['spin'])
+        else:
+            # spin
+            win = self.FindWindowById(self.win['vector'][vtype]['height']['slider'])
+        win.SetValue(value)
+
+        self.mapWindow.update.append('vector:%s:height' % vtype)
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        
+        data['vector'][vtype]['height'] = value
+
+        # update properties
+        event = wxUpdateProperties()
+        wx.PostEvent(self.mapWindow, event)
+        
+        self.mapWindow.render['quick'] = True
+        self.mapWindow.render['v' + vtype] = True
+        self.mapWindow.Refresh(False)
+    
+    def OnVectorHeightFull(self, event):
+        """Vector height changed, render in full resolution"""
+        id = event.GetId()
+        if id == self.win['vector']['lines']['height']['spin'] or \
+                id == self.win['vector']['lines']['height']['slider']:
+            vtype = 'lines'
+        else:
+            vtype = 'points'
+
+        self.mapWindow.render['quick'] = False
+        self.mapWindow.render['v' + vtype] = False
+        self.mapWindow.Refresh(False)
+
+    def OnVectorHeightSpin(self, event):
+        """Vector height changed, render in full resolution"""
+        # TODO: use step value instead
+
+        self.OnVectorHeight(event)
+        self.OnVectorHeightFull(event)
+
+    def OnVectorSurface(self, event):
+        """Reference surface for vector map (lines/points)"""
+        id = event.GetId()
+        if id == self.win['vector']['lines']['surface']:
+            vtype = 'lines'
+        else:
+            vtype = 'points'
+
+        self.mapWindow.update.append('vector:%s:surface' % vtype)
+        
+        data['vector'][vtype]['mode']['surface'] = event.GetValue()
+        
+        # update properties
+        event = wxUpdateProperties()
+        wx.PostEvent(self.mapWindow, event)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+        
+    def OnVectorPoints(self, event):
+        """Set vector points mode, apply changes if auto-rendering is enabled"""
+        size  = self.FindWindowById(self.win['vector']['points']['size']).GetValue()
+        width = self.FindWindowById(self.win['vector']['points']['width']).GetValue()
+
+        color = self.FindWindowById(self.win['vector']['points']['color']).GetColour()
+        color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
+
+        marker = self.FindWindowById(self.win['vector']['points']['marker']).GetSelection()
+
+        self.mapWindow.update.append('vector:points:size')
+        self.mapWindow.update.append('vector:points:width')
+        self.mapWindow.update.append('vector:points:color')
+        self.mapWindow.update.append('vector:points:marker')
+        data = self.mapWindow.GetSelectedLayer(type='nviz')['vector']['points']
+        data['size'] = size
+        data['width'] = width
+        data['color'] = color
+        data['marker'] = marker
+
+        # update properties
+        event = wxUpdateProperties()
+        wx.PostEvent(self.mapWindow, event)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+    def UpdateIsosurfButtons(self, list):
+        """Enable/disable buttons 'add', 'delete',
+        'move up', 'move down'"""
+        nitems = list.GetCount()
+        add = self.parent.FindWindowById(self.win['volume']['btnIsosurfAdd'])
+        delete = self.parent.FindWindowById(self.win['volume']['btnIsosurfDelete'])
+        moveDown = self.parent.FindWindowById(self.win['volume']['btnIsosurfMoveDown'])
+        moveUp = self.parent.FindWindowById(self.win['volume']['btnIsosurfMoveUp'])
+        if nitems >= wxnviz.MAX_ISOSURFS:
+            # disable add button on max
+            add.Enable(False)
+        else:
+            add.Enable(True)
+
+        if nitems < 1:
+            # disable 'delete' if only one item in the lis
+            delete.Enable(False)
+        else:
+            delete.Enable(True)
+
+        if list.GetSelection() >= nitems - 1:
+            # disable 'move-down' if last
+            moveDown.Enable(False)
+        else:
+            moveDown.Enable(True)
+
+        if list.GetSelection() < 1:
+            # disable 'move-up' if first
+            moveUp.Enable(False)
+        else:
+            moveUp.Enable(True)
+        
+    def OnVolumeIsosurfMode(self, event):
+        """Set isosurface draw mode"""
+        self.SetIsosurfaceMode(event.GetSelection())
+    
+    def SetIsosurfaceMode(self, selection):
+        """Set isosurface draw mode"""
+        layer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
+        id = data['object']['id']
+
+        mode = 0
+        if selection == 0:
+            mode |= wxnviz.DM_FLAT
+        else:
+            mode |= wxnviz.DM_GOURAUD
+        
+        self.mapWindow.nvizClass.SetIsosurfaceMode(id, mode)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+        
+    def OnVolumeIsosurfResolution(self, event):
+        """Set isosurface draw resolution"""
+        self.SetIsosurfaceResolution(event.GetInt())
+    
+    def SetIsosurfaceResolution(self, res):
+        """Set isosurface draw resolution"""
+        layer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
+        id = data['object']['id']
+        self.mapWindow.nvizClass.SetIsosurfaceRes(id, res)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+    def OnVolumeIsosurfMap(self, event):
+        """Set surface attribute"""
+        self.SetMapObjAttrb(nvizType='surface', winId=event.GetId())
+                
+    def OnVolumeIsosurfAdd(self, event):
+        """Add new isosurface to the list"""
+        list = self.FindWindowById(self.win['volume']['isosurfs'])
+        level = self.FindWindowById(self.win['volume']['topo']['const']).GetValue()
+        
+        sel = list.GetSelection()
+        if sel < 0 or sel >= list.GetCount() - 1:
+            item = list.Append(item="%s %s" % (_("Level"), str(level)))
+        else:
+            list.Insert(item="%s %s" % (_("Level"), str(level)),
+                        pos=sel+1) # append
+            item = sel + 1
+        print item
+        list.Check(item)
+        list.SetSelection(item)
+        
+        layer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
+        id = data['object']['id']
+        
+        # collect properties
+        isosurfData = {}
+        for attrb in ('topo', 'color', 'mask',
+                      'transp', 'shine', 'emit'):
+            if attrb == 'topo':
+                isosurfData[attrb] = {}
+                win = self.FindWindowById(self.win['volume'][attrb]['const'])
+                isosurfData[attrb]['value'] = win.GetValue()
+            else:
+                uwin = self.FindWindowById(self.win['volume'][attrb]['use'])
+                sel = uwin.GetSelection()
+                if self.win['volume'][attrb]['required']:
+                    sel += 1
+                if sel == 0: # unset
+                    continue
+
+                isosurfData[attrb] = {}
+                if sel == 1: # map
+                    isosurfData[attrb]['map'] = True
+                    vwin = self.FindWindowById(self.win['volume'][attrb]['map'])
+                    value = vwin.GetValue()
+                else: # const
+                    isosurfData[attrb]['map'] = False
+                    vwin = self.FindWindowById(self.win['volume'][attrb]['const'])
+                    if vwin.GetName() == "color":
+                        value = self._getColorString(vwin.GetValue())
+                    else:
+                        value = vwin.GetValue()
+                isosurfData[attrb]['value'] = value
+
+        data['isosurface'].insert(item, isosurfData)
+        print '#', data
+
+        # add isosurface        
+        self.mapWindow.nvizClass.AddIsosurface(id, level)
+        self.mapWindow.nvizClass.SetIsosurfaceColor(id, 0, True, str(layer.name))
+
+        # update buttons
+        self.UpdateIsosurfButtons(list)
+
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+
+        event.Skip()
+        
+    def OnVolumeIsosurfDelete(self, event):
+        """Remove isosurface from list"""
+        list = self.FindWindowById(self.win['volume']['isosurfs'])
+        
+        # remove item from list
+        isosurfId = list.GetSelection()
+        list.Delete(isosurfId)
+        # select last item
+        if list.GetCount() > 0:
+            list.SetSelection(list.GetCount()-1)
+        
+        layer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
+        id = data['object']['id']
+
+        # delete isosurface
+        del data['isosurface'][isosurfId]
+        print '#', data
+        self.mapWindow.nvizClass.DeleteIsosurface(id, isosurfId)
+
+        # update buttons
+        self.UpdateIsosurfButtons(list)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+        
+        event.Skip()
+        
+    def OnVolumeIsosurfMoveUp(self, event):
+        """Move isosurface up in the list"""
+        list = self.FindWindowById(self.win['volume']['isosurfs'])
+        sel = list.GetSelection()
+
+        if sel < 1:
+            return # this should not happen
+
+        layer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
+        id = data['object']['id']
+
+        # move item up
+        text = list.GetStringSelection()
+        list.Insert(item=text, pos=sel-1)
+        list.Check(sel-1)
+        list.SetSelection(sel-1)
+        list.Delete(sel+1)
+        data['isosurface'].insert(sel-1, data['isosurface'][sel])
+        del data['isosurface'][sel+1]
+        self.mapWindow.nvizClass.MoveIsosurface(id, sel, True)
+
+        print '#', data
+        
+        # update buttons
+        self.UpdateIsosurfButtons(list)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+        
+        event.Skip()
+        
+    def OnVolumeIsosurfMoveDown(self, event):
+        """Move isosurface dowm in the list"""
+        list = self.FindWindowById(self.win['volume']['isosurfs'])
+        sel = list.GetSelection()
+
+        if sel >= list.GetCount() - 1:
+            return # this should not happen
+
+        layer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')['volume']
+        id = data['object']['id']
+
+        # move item up
+        text = list.GetStringSelection()
+        list.Insert(item=text, pos=sel+2)
+        list.Check(sel+2)
+        list.SetSelection(sel+2)
+        list.Delete(sel)
+        data['isosurface'].insert(sel+2, data['isosurface'][sel])
+        del data['isosurface'][sel]
+        self.mapWindow.nvizClass.MoveIsosurface(id, sel, False)
+
+        print '#', data
+        
+        # update buttons
+        self.UpdateIsosurfButtons(list)
+        
+        if self.parent.autoRender.IsChecked():
+            self.mapWindow.Refresh(False)
+        
+        event.Skip()
+        
+    def UpdatePage(self, pageId):
+        """Update dialog (selected page)"""
+        self.pageChanging = True
+        layer = self.mapWindow.GetSelectedLayer()
+        data = self.mapWindow.GetSelectedLayer(type='nviz')
+        
+        if pageId == 'view':
+            max = self.mapWindow.view['z-exag']['value'] * 10
+            hmin = self.mapWindow.iview['height']['min']
+            hmax = self.mapWindow.iview['height']['max']
+            for control in ('spin', 'slider'):
+                self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(1,
+                                                                                  max)
+                self.FindWindowById(self.win['view']['height'][control]).SetRange(hmin,
+                                                                                  hmax)
+        elif pageId == 'surface':
+            if self.notebook.GetSelection() != self.page['surface']['id']:
+                for page in ('vector', 'volume'):
+                    if self.page[page]['id'] > -1:
+                        self.notebook.RemovePage(self.page[page]['id'])
+                        self.page[page]['id'] = -1
+
+                self.page['surface']['id'] = 1
+                self.page['settings']['id'] = 2
+
+                panel = wx.FindWindowById(self.page['surface']['panel'])
+                self.notebook.InsertPage(n=self.page['surface']['id'],
+                                         page=panel,
+                                         text=" %s " % _("Layer properties"),
+                                         select=True)
+            
+            self.UpdateSurfacePage(layer, data['surface'])
+        
+        elif pageId == 'vector':
+            if self.notebook.GetSelection() != self.page['vector']['id']:
+                for page in ('surface', 'volume'):
+                    if self.page[page]['id'] > -1:
+                        self.notebook.RemovePage(self.page[page]['id'])
+                        self.page[page]['id'] = -1
+                    
+                self.page['vector']['id'] = 1
+                self.page['settings']['id'] = 2
+                
+                panel = wx.FindWindowById(self.page['vector']['panel'])
+                self.notebook.InsertPage(n=self.page['vector']['id'],
+                                         page=panel,
+                                         text=" %s " % _("Layer properties"),
+                                         select=True)
+                
+            self.UpdateVectorPage(layer, data['vector'])
+            
+        elif pageId == 'volume':
+            if self.notebook.GetSelection() != self.page['volume']['id']:
+                for page in ('surface', 'vector'):
+                    if self.page[page]['id'] > -1:
+                        self.notebook.RemovePage(self.page[page]['id'])
+                        self.page[page]['id'] = -1
+                    
+                self.page['volume']['id'] = 1
+                self.page['settings']['id'] = 2
+
+                panel = wx.FindWindowById(self.page['volume']['panel'])
+                self.notebook.InsertPage(n=self.page['volume']['id'],
+                                         page=panel,
+                                         text=" %s " % _("Layer properties"),
+                                         select=True)
+                
+            self.UpdateVolumePage(layer, data['volume'])
+            
+        self.pageChanging = False
+        
+    def UpdateSurfacePage(self, layer, data):
+        #
+        # attributes
+        #
+        for attr in ('topo', 'color'): # required
+            if layer and layer.type == 'raster':
+                self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
+            else:
+                self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
+            self.SetMapObjUseMap(nvizType='surface',
+                                 attrb=attr, map=True) # -> map
+
+        if data['attribute'].has_key('color'):
+            value = data['attribute']['color']['value']
+            if data['attribute']['color']['map']:
+                self.FindWindowById(self.win['surface']['color']['map']).SetValue(value)
+            else: # constant
+                color = map(int, value.split(':'))
+                self.FindWindowById(self.win['surface']['color']['const']).SetColour(color)
+            self.SetMapObjUseMap(nvizType='surface',
+                                 attrb=attr, map=data['attribute']['color']['map'])
+
+        self.SetMapObjUseMap(nvizType='surface',
+                             attrb='shine', map=data['attribute']['shine']['map'])
+        value = data['attribute']['shine']['value']
+        if data['attribute']['shine']['map']:
+            self.FindWindowById(self.win['surface']['shine']['map']).SetValue(value)
+        else:
+            self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
+
+        #
+        # draw
+        #
+        for control, dict in data['draw'].iteritems():
+            if control == 'all': # skip 'all' property
+                continue
+            if control == 'resolution':
+                self.FindWindowById(self.win['surface']['draw']['res-coarse']).SetValue(dict['coarse'])
+                self.FindWindowById(self.win['surface']['draw']['res-fine']).SetValue(dict['fine'])
+                continue
+
+            if control == 'mode':
+                if dict['desc']['mode'] == 'coarse':
+                    self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(0)
+                elif dict['desc']['mode'] == 'fine':
+                    self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(1)
+                else: # both
+                    self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(2)
+                    
+                if dict['desc']['style'] == 'wire':
+                    self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(0)
+                else: # surface
+                    self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(1)
+
+                if dict['desc']['shading'] == 'flat':
+                    self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(0)
+                else: # gouraud
+                    self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(1)
+                
+                continue
+
+            value = dict['value']
+            win = self.FindWindowById(self.win['surface']['draw'][control])
+            
+            name = win.GetName()
+
+            if name == "selection":
+                win.SetSelection(value)
+            elif name == "colour":
+                color = map(int, value.split(':'))
+                win.SetColour(color)
+            else:
+                win.SetValue(value)
+        # enable/disable res widget + set draw mode
+        self.SetSurfaceMode()
+        color = self.FindWindowById(self.win['surface']['draw']['wire-color'])
+        
+    def UpdateVectorPage(self, layer, data):
+        vInfo = gcmd.Command(['v.info',
+                              'map=%s' % layer.name])
+        npoints = nprimitives = 0
+        for line in vInfo.ReadStdOutput():
+            if 'Map is 3D' in line:
+                mapIs3D = int(line.replace('|', '').split(':')[1].strip())
+            elif 'Number of points' in line:
+                npoints = int(line.replace('|', '').split(':')[1].strip().split(' ')[0])
+                nprimitives = npoints
+            elif 'Number of lines' in line:
+                nprimitives += int(line.replace('|', '').split(':')[1].strip().split(' ')[0])
+            elif 'Number of boundaries' in line:
+                nprimitives += int(line.replace('|', '').split(':')[1].strip().split(' ')[0]) # boundaries
+                nprimitives += int(line.replace('|', '').split(':')[2].strip()) # faces
+            elif 'Number of centroids' in line:
+                nprimitives += int(line.replace('|', '').split(':')[1].strip().split(' ')[0]) # centroids
+                nprimitives += int(line.replace('|', '').split(':')[2].strip()) # kernels
+
+        if mapIs3D:
+            desc = _("Vector map <%s> is 3D") % layer.name
+            enable = False
+        else:
+            desc = _("Vector map <%s> is 2D") % layer.name
+            enable = True
+        desc += " - " + _("%d primitives (%d points)") % (nprimitives, npoints)
+
+        self.FindWindowById(self.win['vector']['lines']['flat']).Enable(enable)
+        for v in ('lines', 'points'):
+            self.FindWindowById(self.win['vector'][v]['surface']).Enable(enable)
+            self.FindWindowById(self.win['vector'][v]['height']['slider']).Enable(enable)
+            self.FindWindowById(self.win['vector'][v]['height']['spin']).Enable(enable)
+            
+        self.FindWindowById(self.win['vector']['desc']).SetLabel(desc)
+        #
+        # lines
+        #
+        showLines = self.FindWindowById(self.win['vector']['lines']['show'])
+        if data['lines'].has_key('object'):
+            showLines.SetValue(True)
+        else:
+            showLines.SetValue(False)
+            if nprimitives - npoints > 0:
+                showLines.Enable(True)
+            else:
+                showLines.Enable(False)
+
+        self.UpdateVectorShow('lines',
+                              showLines.IsChecked())
+
+        width = self.FindWindowById(self.win['vector']['lines']['width'])
+        width.SetValue(data['lines']['width'])
+
+        color = self.FindWindowById(self.win['vector']['lines']['color'])
+        color.SetValue(map(int, data['lines']['color'].split(':')))
+
+        for vtype in ('lines', 'points'):
+            if vtype == 'lines':
+                display = self.FindWindowById(self.win['vector']['lines']['flat'])
+                if data[vtype]['mode']['type'] == 'flat':
+                    display.SetSelection(1)
+                else:
+                    display.SetSelection(0)
+
+            if data[vtype]['mode']['type'] == 'surface' and \
+                    len(self.mapWindow.layers['raster']['name']) > 0:
+                surface = self.FindWindowById(self.win['vector'][vtype]['surface'])
+                surface.SetItems(self.mapWindow.layers['raster']['name'])
+                surface.SetStringSelection(data[vtype]['mode']['surface'])
+                
+        for type in ('slider', 'spin'):
+            win = self.FindWindowById(self.win['vector']['lines']['height'][type])
+            win.SetValue(data['lines']['height'])
+
+        #
+        # points
+        #
+        showPoints = self.FindWindowById(self.win['vector']['points']['show'])
+        
+        if data['points'].has_key('object'):
+            showPoints.SetValue(True)
+        else:
+            showPoints.SetValue(False)
+            if npoints > 0:
+                showPoints.Enable(True)
+            else:
+                showPoints.Enable(False)
+        
+        self.UpdateVectorShow('points',
+                              showPoints.IsChecked())
+        # size, width, marker, color
+        for prop in ('size', 'width', 'marker', 'color'):
+            win = self.FindWindowById(self.win['vector']['points'][prop])
+            name = win.GetName()
+            if name == 'selection':
+                win.SetSelection(data['points'][prop])
+            elif name == 'color':
+                color = map(int, data['points'][prop].split(':'))
+                win.SetValue(color)
+            else:
+                win.SetValue(data['points'][prop])
+        # height
+        for type in ('slider', 'spin'):
+            win = self.FindWindowById(self.win['vector']['points']['height'][type])
+            win.SetValue(data['points']['height'])
+
+    def UpdateVolumePage(self, layer, data):
+        """Update volume layer properties page"""
+        list = self.FindWindowById(self.win['volume']['isosurfs'])
+
+        #
+        # draw
+        #
+        for control, dict in data['draw'].iteritems():
+            if control == 'all': # skip 'all' property
+                continue
+
+            win = self.FindWindowById(self.win['volume']['draw'][control])
+
+            if control == 'shading':
+                if data['draw']['shading']['desc'] == 'flat':
+                    value = 0
+                else:
+                    value = 1
+            else:
+                value = dict['value']
+
+            if win.GetName() == "selection":
+                win.SetSelection(value)
+            else:
+                win.SetValue(value)
+
+        self.SetIsosurfaceMode(data['draw']['shading']['value'])
+        self.SetIsosurfaceResolution(data['draw']['resolution']['value'])
+                
+        #
+        # isosurface attributes
+        #
+        for attr in ('color', ): # required
+            if layer and layer.type == '3d-raster':
+                self.FindWindowById(self.win['volume'][attr]['map']).SetValue(layer.name)
+            else:
+                self.FindWindowById(self.win['volume'][attr]['map']).SetValue('')
+            self.SetMapObjUseMap(nvizType='volume',
+                                 attrb=attr, map=True) # -> map
+        
+        if data['attribute'].has_key('color'):
+            value = data['attribute']['color']['value']
+            if data['attribute']['color']['map']:
+                self.FindWindowById(self.win['volume']['color']['map']).SetValue(value)
+            else: # constant
+                color = map(int, value.split(':'))
+                self.FindWindowById(self.win['volume']['color']['const']).SetColour(color)
+            self.SetMapObjUseMap(nvizType='volume',
+                                 attrb=attr, map=data['attribute']['color']['map'])
+
+        self.SetMapObjUseMap(nvizType='volume',
+                             attrb='shine', map=data['attribute']['shine']['map'])
+        value = data['attribute']['shine']['value']
+        if data['attribute']['shine']['map']:
+            self.FindWindowById(self.win['volume']['shine']['map']).SetValue(value)
+        else:
+            self.FindWindowById(self.win['volume']['shine']['const']).SetValue(value)
+        
+    def SetPage(self, name):
+        """Get named page"""
+        self.notebook.SetSelection(self.page[name]['id'])
+
+class ViewPositionWindow(wx.Window):
+    """Position control window (for NvizToolWindow)"""
+    def __init__(self, parent, id, mapwindow,
+                 pos=wx.DefaultPosition,
+                 size=wx.DefaultSize):
+        self.mapWindow = mapwindow
+
+        wx.Window.__init__(self, parent, id, pos, size)
+
+        self.SetBackgroundColour("WHITE")
+
+        self.pdc = wx.PseudoDC()
+
+        self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
+        self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
+
+        self.Draw()
+
+        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        # self.Bind(wx.EVT_MOTION,       self.OnMouse)
+        self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+
+    def Draw(self, pos=None):
+        w, h = self.GetClientSize()
+
+        if pos is None:
+            x = self.mapWindow.view['pos']['x']
+            y = self.mapWindow.view['pos']['y']
+            x = x * w
+            y = y * h
+        else:
+            x, y = pos
+
+        self.pdc.Clear()
+        self.pdc.BeginDrawing()
+        self.pdc.DrawLine(w / 2, h / 2, x, y)
+        self.pdc.DrawCircle(x, y, 5)
+        self.pdc.EndDrawing()
+
+    def OnPaint(self, event):
+        dc = wx.BufferedPaintDC(self)
+        dc.SetBackground(wx.Brush("White"))
+        dc.Clear()
+
+        self.PrepareDC(dc)
+        self.pdc.DrawToDC(dc)
+
+    def OnMouse(self, event):
+        if event.LeftIsDown():
+            x, y = event.GetPosition()
+            self.Draw(pos=(x, y))
+            self.Refresh(False)
+            w, h = self.GetClientSize()
+            x = float(x) / w
+            y = float(y) / h
+            if x >= 0 and x <= 1.0:
+                self.mapWindow.view['pos']['x'] = x
+            if y >= 0 and y <= 1.0:
+                self.mapWindow.view['pos']['y'] = y
+            self.mapWindow.update.append('view')
+
+            self.mapWindow.render['quick'] = True
+            self.mapWindow.Refresh(eraseBackground=False)
+
+        elif event.LeftUp():
+            self.mapWindow.render['quick'] = False
+            self.mapWindow.Refresh(eraseBackground=False)
+        
+        event.Skip()
+
+class IsoSurfList(wx.CheckListBox):
+    """List of loaded volume isosurfaces (volume properties page)"""
+    def __init__(self, parent, win, id=wx.ID_ANY, size=wx.DefaultSize):
+        self.parent = parent
+        self.win = win
+        
+        wx.CheckListBox.__init__(self, parent, id, size=size)
+    
+        self.Bind(wx.EVT_CHECKLISTBOX, self.OnCheck)
+        self.Bind(wx.EVT_LISTBOX, self.OnSelect)
+    
+    def OnCheck(self, event):
+        """Item checked/unchecked -> load/delete surface"""
+        print event.IsChecked()
+        
+    def OnSelect(self, event):
+        """Item selected"""
+        winUp = self.parent.FindWindowById(self.win['btnIsosurfMoveUp'])
+        winDown = self.parent.FindWindowById(self.win['btnIsosurfMoveDown'])
+        selection = event.GetSelection()
+        if selection == 0:
+            winUp.Enable(False)
+            if not winDown.IsEnabled():
+                winDown.Enable()
+        elif selection == self.GetCount() - 1:
+            winDown.Enable(False)
+            if not winUp.IsEnabled():
+                winUp.Enable()
+        else:
+            if not winDown.IsEnabled():
+                winDown.Enable()
+            if not winUp.IsEnabled():
+                winUp.Enable()


Property changes on: grass/branches/develbranch_6/gui/wxpython/gui_modules/nviz_tools.py
___________________________________________________________________
Name: svn:keywords
   + Author Date Id
Name: svn:eol-style
   + native



More information about the grass-commit mailing list