[GRASS-SVN] r45659 - in grass-addons/gui/wxpython/psmap: . docs gui_modules images xml

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Mar 14 03:15:14 EDT 2011


Author: annakrat
Date: 2011-03-14 00:15:14 -0700 (Mon, 14 Mar 2011)
New Revision: 45659

Added:
   grass-addons/gui/wxpython/psmap/docs/
   grass-addons/gui/wxpython/psmap/docs/wxGUI.PsMap.html
   grass-addons/gui/wxpython/psmap/gui_modules/
   grass-addons/gui/wxpython/psmap/gui_modules/psmap.py
   grass-addons/gui/wxpython/psmap/gui_modules/psmap_dialogs.py
   grass-addons/gui/wxpython/psmap/images/
   grass-addons/gui/wxpython/psmap/images/scalebar-fancy.png
   grass-addons/gui/wxpython/psmap/images/scalebar-simple.png
   grass-addons/gui/wxpython/psmap/xml/
   grass-addons/gui/wxpython/psmap/xml/menudata_psmap.xml
Log:
ps.map gui added

Added: grass-addons/gui/wxpython/psmap/docs/wxGUI.PsMap.html
===================================================================
--- grass-addons/gui/wxpython/psmap/docs/wxGUI.PsMap.html	                        (rev 0)
+++ grass-addons/gui/wxpython/psmap/docs/wxGUI.PsMap.html	2011-03-14 07:15:14 UTC (rev 45659)
@@ -0,0 +1,31 @@
+<h2>DESCRIPTION</h2>
+
+<b>Note:</b> <em>wxGUI Hardcopy Map Utility is currently under
+development.</em>
+
+<p>
+<b>Hardcopy Map Utility</b> is
+a <em><a href="wxGUI.html">wxGUI</a></em> extension which allows the
+user ...
+
+<h2>SEE ALSO</h2>
+
+<em>
+  <a href="wxGUI.html">wxGUI</a>
+</em>
+
+<p>
+Other wxGUI components:<br>
+<em>
+  <a href="wxGUI.Vector_Digitizer.html">Vector Digitizer</a><br>
+  <a href="wxGUI.Attribute_Table_Manager.html">Attribute Table Manager</a><br>
+  <a href="wxGUI.Nviz.html">3D Viewer</a><br>
+  <a href="wxGUI.GCP_Manager.html">Manage Ground Control Points</a><br>
+</em>
+
+<h2>AUTHORS</h2>
+
+Anna Kratochvilova, CTU in Prague, Czech Republic (bachelor's final project 2011, mentor: Martin Landa)
+
+<p>
+<i>$Date$</i>

Added: grass-addons/gui/wxpython/psmap/gui_modules/psmap.py
===================================================================
--- grass-addons/gui/wxpython/psmap/gui_modules/psmap.py	                        (rev 0)
+++ grass-addons/gui/wxpython/psmap/gui_modules/psmap.py	2011-03-14 07:15:14 UTC (rev 45659)
@@ -0,0 +1,1535 @@
+"""!
+ at package psmap
+
+ at brief GUI for ps.map
+
+Classes:
+ - PsMapData    (to be moved - menudata.py)
+ - PsMapToolbar (to be moved - toolbars.py)
+ - PsMapFrame
+ - PsMapBufferedWindow
+
+(C) 2011 by Anna Kratochvilova, and 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 Anna Kratochvilova <anna.kratochvilova fsv.cvut.cz> (bachelor's project)
+ at author Martin Landa <landa.martin gmail.com> (mentor)
+"""
+
+import os
+import sys
+import tempfile
+import textwrap
+import Queue
+try:
+    import Image
+except ImportError:
+    sys.exit("Python Imaging Library is not available")
+from math import ceil, sin, cos, pi
+from collections import namedtuple
+
+import grass.script as grass
+if int(grass.version()['version'].split('.')[0]) > 6:
+    sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'gui', 'wxpython',
+                                 'gui_modules'))
+else:
+    sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'wxpython',
+                                 'gui_modules'))
+import globalvar
+import menu
+from   goutput    import CmdThread, EVT_CMD_DONE
+from   menudata   import MenuData, etcwxdir
+from   gselect    import Select
+from   toolbars   import AbstractToolbar
+from   icon       import Icons, MetaIcon, iconSet
+from   gcmd       import RunCommand, GError, GMessage
+from psmap_dialogs import *
+
+import wx
+import wx.lib.scrolledpanel as scrolled
+
+try:
+    from agw import flatnotebook as fnb
+except ImportError: # if it's not there locally, try the wxPython lib.
+    import wx.lib.agw.flatnotebook as fnb
+
+Icons['psMap'] = {
+    'script'     : MetaIcon(img = iconSet['ps-script'],
+                            label = _('Generate instruction file')),
+    'export'     : MetaIcon(img = iconSet['ps-export'],
+                            label = _('Generate PostScript output')),
+    'pageSetup'  : MetaIcon(img = iconSet['settings'],
+                            label = _('Page setup'),
+                            desc = _('Specify paper size, margins and orientation')),
+    'fullExtent' : MetaIcon(img = iconSet['zoom-extent'],
+                            label = _("Full extent"),
+                            desc = _("Zoom to full extent")),
+    'addMap'    : MetaIcon(img = iconSet['layer-add'],
+                            label = _("Map frame"),
+                            desc = _("Click and drag to place map frame")),
+    'addRast'    : MetaIcon(img = iconSet['layer-raster-add'],
+                            label = _("Raster map"),
+                            desc = _("Add raster map")),
+    'addVect'   : MetaIcon(img = iconSet['layer-vector-add'],
+                           label = _("Vector map"),
+                           desc = _("Add vector map")),
+    'deleteObj' : MetaIcon(img = iconSet['layer-remove'],
+                           label = _("Delete selected object")),
+    'preview'   : MetaIcon(img = iconSet['execute'],
+                           label = _("Show preview")),
+    'quit'      : MetaIcon(img = iconSet['quit'],
+                           label = _('Quit Hardcopy Map Utility')),
+    'addText'   : MetaIcon(img = iconSet['text-add'],
+                            label = _('Add text')),
+    'addMapinfo': MetaIcon(img = iconSet['legend-add'],
+                            label = _('Add map info')),
+    'addLegend' : MetaIcon(img = iconSet['legend-add'],
+                            label = _('Add legend')),
+    'addScalebar' : MetaIcon(img = iconSet['scalebar-add'],
+                            label = _('Add scale bar')),
+    }
+    
+class PsMapData(MenuData):
+    def __init__(self, path = None):
+        """!Menu for Hardcopy Map Output Utility (psmap.py)
+        
+        @path path to XML to be read (None for menudata_psmap.xml)
+        """
+        if not path:
+            gisbase = os.getenv('GISBASE')
+            global etcwxdir
+        path = os.path.join(etcwxdir, 'xml', 'menudata_psmap.xml')
+        
+        MenuData.__init__(self, path)
+
+class PsMapToolbar(AbstractToolbar):
+    def __init__(self, parent):
+        """!Toolbar Hardcopy Map Output Utility (psmap.py)
+        
+        @param parent parent window
+        """
+        AbstractToolbar.__init__(self, parent)
+        
+        self.InitToolbar(self._toolbarData())
+        
+        self.Realize()
+        
+        self.action = { 'id' : self.pointer }
+        self.defaultAction = { 'id' : self.pointer,
+                               'bind' : self.parent.OnPointer }
+        self.OnTool(None)
+
+        
+    def _toolbarData(self):
+        """!Toolbar data
+        """
+        self.quit = wx.NewId()
+        self.pagesetup = wx.NewId()
+        self.pointer = wx.NewId()
+        self.zoomIn = wx.NewId()
+        self.zoomOut = wx.NewId()
+        self.zoomAll = wx.NewId()
+        self.addMap = wx.NewId()
+        self.addRaster = wx.NewId()
+        self.addVector = wx.NewId()
+        self.dec = wx.NewId()
+        self.delete = wx.NewId()
+        self.preview = wx.NewId()
+        self.instructionFile = wx.NewId()
+        self.generatePS = wx.NewId()
+        self.pan = wx.NewId()
+
+        icons = Icons['psMap']
+        return self._getToolbarData(((self.pagesetup, 'page setup', icons['pageSetup'],
+                                      self.parent.OnPageSetup),
+                                     (None, ),
+                                     (self.pointer, "pointer", Icons["displayWindow"]["pointer"],
+                                      self.parent.OnPointer, wx.ITEM_CHECK),
+                                     (self.pan, 'pan', Icons["displayWindow"]['pan'],
+                                      self.parent.OnPan, wx.ITEM_CHECK),
+                                     (self.zoomIn, "zoomin", Icons["displayWindow"]["zoomIn"],
+                                      self.parent.OnZoomIn, wx.ITEM_CHECK),
+                                     (self.zoomOut, "zoomout", Icons["displayWindow"]["zoomOut"],
+                                      self.parent.OnZoomOut, wx.ITEM_CHECK),
+                                     (self.zoomAll, 'full extent', icons['fullExtent'],
+                                      self.parent.OnZoomAll),
+                                     (None, ),
+                                     (self.addMap, 'add map', icons['addMap'],
+                                      self.parent.OnAddMap, wx.ITEM_CHECK),
+                                     (self.addRaster, 'add raster', icons['addRast'],
+                                      self.parent.OnAddRaster),
+                                     (self.addVector, 'add vect', icons['addVect'],
+                                      self.parent.OnAddVect),
+                                     (self.dec, "overlay", Icons["displayWindow"]["overlay"],
+                                      self.parent.OnDecoration),
+                                     (self.delete, "delete", icons["deleteObj"],
+                                      self.parent.OnDelete),
+                                     (None, ),
+                                     (self.preview, "preview", icons["preview"],
+                                      self.parent.OnPreview),
+                                     (self.instructionFile, 'psScript', icons['script'],
+                                      self.parent.OnInstructionFile),
+                                     (self.generatePS, 'generatePS', icons['export'],
+                                      self.parent.OnPSFile),
+                                     (None, ),
+                                     (self.quit, 'quit', icons['quit'],
+                                      self.parent.OnCloseWindow))
+                                    )
+
+                
+class PsMapFrame(wx.Frame):
+    def __init__(self, parent = None, id = wx.ID_ANY,
+                 title = _("GRASS GIS Hardcopy Map Output Utility"), **kwargs):
+        """!Main window of ps.map GUI
+        
+        @param parent parent window
+        @param id window id
+        @param title window title
+        
+        @param kwargs wx.Frames' arguments
+        """
+        self.parent = parent
+
+        wx.Frame.__init__(self, parent = parent, id = id, title = title, name = "PsMap", **kwargs)
+        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
+        #menubar
+        self.menubar = menu.Menu(parent = self, data = PsMapData())
+        self.SetMenuBar(self.menubar)
+        #toolbar
+
+        self.toolbar = PsMapToolbar(parent = self)
+        self.SetToolBar(self.toolbar)
+        
+        self.actionOld = self.toolbar.action['id']
+        self.iconsize = (16, 16)
+        #satusbar
+        self.statusbar = self.CreateStatusBar(number = 1)
+        
+        # mouse attributes -- position on the screen, begin and end of
+        # dragging, and type of drawing
+        self.mouse = {
+            'begin': [0, 0], # screen coordinates
+            'end'  : [0, 0],
+            'use'  : "pointer",
+            }
+        # available cursors
+        self.cursors = {
+            "default" : wx.StockCursor(wx.CURSOR_ARROW),
+            "cross"   : wx.StockCursor(wx.CURSOR_CROSS),
+            "hand"    : wx.StockCursor(wx.CURSOR_HAND),
+            "sizenwse": wx.StockCursor(wx.CURSOR_SIZENWSE)
+            }
+        # pen and brush
+        self.pen = {
+            'paper': wx.Pen(colour = "BLACK", width = 1),
+            'margins': wx.Pen(colour = "GREY", width = 1),
+            'map': wx.Pen(colour = wx.Color(86, 122, 17), width = 2),
+            'rasterLegend': wx.Pen(colour = wx.Color(219, 216, 4), width = 2),
+            'vectorLegend': wx.Pen(colour = wx.Color(219, 216, 4), width = 2),
+            'mapinfo': wx.Pen(colour = wx.Color(5, 184, 249), width = 2),
+            'scalebar': wx.Pen(colour = wx.Color(150, 150, 150), width = 2),
+            'box': wx.Pen(colour = 'RED', width = 2, style = wx.SHORT_DASH),
+            'select': wx.Pen(colour = 'BLACK', width = 1, style = wx.SHORT_DASH),
+            'resize': wx.Pen(colour = 'BLACK', width = 1)
+            }
+        self.brush = {
+            'paper': wx.WHITE_BRUSH,
+            'margins': wx.TRANSPARENT_BRUSH,            
+            'map': wx.Brush(wx.Color(151, 214, 90)),
+            'rasterLegend': wx.Brush(wx.Color(250, 247, 112)),
+            'vectorLegend': wx.Brush(wx.Color(250, 247, 112)),
+            'mapinfo': wx.Brush(wx.Color(127, 222, 252)),
+            'scalebar': wx.Brush(wx.Color(200, 200, 200)),
+            'box': wx.TRANSPARENT_BRUSH,
+            'select':wx.TRANSPARENT_BRUSH,
+            'resize': wx.BLACK_BRUSH
+            } 
+          
+
+        # list of objects to draw
+        self.objectId = []
+        
+        # instructions
+        self.instruction = Instruction(parent = self, objectsToDraw = self.objectId)
+        
+        self.pageId = wx.NewId()
+        #current page of flatnotebook
+        self.currentPage = 0
+        #canvas for draft mode
+        self.canvas = PsMapBufferedWindow(parent = self, mouse = self.mouse, pen = self.pen,
+                                            brush = self.brush, cursors = self.cursors, 
+                                            instruction = self.instruction,
+                                            pageId = self.pageId, objectId = self.objectId,
+                                            preview = False)
+                                        
+        self.canvas.SetCursor(self.cursors["default"])
+        self.getInitMap()
+        
+        
+        # image path
+        env = grass.gisenv()
+        self.imgName = os.path.join( env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], '.tmp', 'tmpImage.png')
+        
+        #canvas for preview
+        self.previewCanvas = PsMapBufferedWindow(parent = self, mouse = self.mouse, cursors = self.cursors,
+                                                    pen = self.pen, brush = self.brush, preview = True)
+        
+        
+
+        
+        # set WIND_OVERRIDE
+        grass.use_temp_region()
+        
+        # create queues
+        self.requestQ = Queue.Queue()
+        self.resultQ = Queue.Queue()
+        # thread
+        self.cmdThread = CmdThread(self, self.requestQ, self.resultQ)
+        
+        self._layout()
+        self.SetMinSize(wx.Size(700, 600))
+        
+        self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CHANGING, self.OnPageChanging)
+        self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
+        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+        self.Bind(EVT_CMD_DONE, self.OnCmdDone)
+        
+##        # load instructions
+##        self.readObjectId = []
+##        self.readInstruction = Instruction(parent = self, objectsToDraw = self.readObjectId)
+##        self.readInstruction.Read('/home/anna/Desktop/reading.txt')
+##        print '%%%%%%%%%%%%%%%%%%%\n',self.readInstruction
+    
+    def _layout(self):
+        """!Do layout
+        """
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        if globalvar.hasAgw:
+            self.book = fnb.FlatNotebook(parent = self, id = wx.ID_ANY,
+                                            agwStyle = fnb.FNB_FANCY_TABS | fnb.FNB_BOTTOM |
+                                            fnb.FNB_NO_NAV_BUTTONS | fnb.FNB_NO_X_BUTTON)
+        else:
+            self.book = fnb.FlatNotebook(parent = self, id = wx.ID_ANY,
+                                            style = fnb.FNB_FANCY_TABS | fnb.FNB_BOTTOM |
+                                            fnb.FNB_NO_NAV_BUTTONS | fnb.FNB_NO_X_BUTTON)
+        #self.book = fnb.FlatNotebook(self, wx.ID_ANY, style = fnb.FNB_BOTTOM)
+        self.book.AddPage(self.canvas, "Draft mode")
+        self.book.AddPage(self.previewCanvas, "Preview")
+        self.book.SetSelection(0)
+        
+        mainSizer.Add(self.book,1, wx.EXPAND)
+        
+        self.SetSizer(mainSizer)
+        mainSizer.Fit(self)
+
+            
+    def InstructionFile(self):
+        """!Creates mapping instructions"""
+        
+        return str(self.instruction)
+
+    def OnPSFile(self, event):
+        filename = self.getFile(wildcard = "PostScript (*.ps)|*.ps|Encapsulated PostScript (*.eps)|*.eps")
+        if filename:
+            self.PSFile(filename)
+            
+    def OnPreview(self, event):
+        """!Run ps.map and show result"""
+        self.PSFile()
+
+
+        
+    def PSFile(self, filename = None):
+        """!Create temporary instructions file and run ps.map with output = filename"""
+        instrFile = grass.tempfile()
+        instrFileFd = open(instrFile, mode = 'w')
+        instrFileFd.write(self.InstructionFile())
+        instrFileFd.flush()
+        instrFileFd.close()
+        
+        temp = False
+        if not filename:
+            temp = True
+            filename = grass.tempfile()
+        
+        cmd = ['ps.map', '--overwrite']
+        if os.path.splitext(filename)[1] == '.eps':
+            cmd.append('-e')
+        if self.instruction[self.pageId]['Orientation'] == 'Landscape':
+            cmd.append('-r')
+        cmd.append('input=%s' % instrFile)
+        cmd.append('output=%s' % filename)
+        self.SetStatusText(_('Generating preview...'), 0)
+         
+        self.cmdThread.RunCmd(cmd, userData = {'instrFile' : instrFile, 'filename' : filename, 'temp' : temp })
+        
+    def OnCmdDone(self, event):
+        """!ps.map process finished"""
+        
+        if event.returncode != 0:
+            GMessage(parent = self,
+                   message = _("Ps.map exited with return code %s") % event.returncode)
+            return 
+        
+        try:
+            im = Image.open(event.userData['filename'])
+            if self.instruction[self.pageId]['Orientation'] == 'Landscape':
+                im = im.rotate(270)
+            im.save(self.imgName)
+            
+        except IOError, e:
+            GError(parent = self,
+                   message = _("Unable to generate preview. %s") % e)
+        
+        
+        rect = self.previewCanvas.ImageRect()
+        self.previewCanvas.image = wx.Image(self.imgName, wx.BITMAP_TYPE_PNG)
+        self.previewCanvas.DrawImage(rect = rect)
+        
+        self.SetStatusText(_('Preview generated'), 0)
+        self.book.SetSelection(1)
+        self.currentPage = 1
+
+        grass.try_remove(event.userData['instrFile'])
+        if event.userData['temp']:
+            grass.try_remove(event.userData['filename'])
+        
+    def getFile(self, wildcard):
+        suffix = []
+        for filter in wildcard.split('|')[1::2]:
+            s = filter.strip('*').split('.')[1]
+            if s:
+                s = '.' + s
+            suffix.append(s)
+        raster = self.instruction.FindInstructionByType('raster')
+        rasterId = raster.id if raster else None
+
+        if rasterId and self.instruction[rasterId]['raster']:
+            mapName = self.instruction[rasterId]['raster'].split('@')[0] + suffix[0]
+        else:
+            mapName = ''
+            
+        filename = ''
+        dlg = wx.FileDialog(self, message = "Save file as", defaultDir = "", 
+                            defaultFile = mapName, wildcard = wildcard,
+                            style = wx.CHANGE_DIR|wx.SAVE|wx.OVERWRITE_PROMPT)
+        if dlg.ShowModal() == wx.ID_OK:
+            filename = dlg.GetPath()
+            suffix = suffix[dlg.GetFilterIndex()]
+            if not os.path.splitext(filename)[1]:
+                filename = filename + suffix
+            elif os.path.splitext(filename)[1] != suffix and suffix != '':
+                filename = os.path.splitext(filename)[0] + suffix
+            
+        dlg.Destroy()
+        return filename
+                        
+    def OnInstructionFile(self, event):
+        filename = self.getFile(wildcard = "All files(*.*)|*.*|Text file|*.txt")        
+        if filename:    
+            instrFile = open(filename, "w")
+            instrFile.write(self.InstructionFile())
+            instrFile.close()            
+        
+    def OnPageSetup(self, event = None):
+        """!Specify paper size, margins and orientation"""
+        id = self.instruction.FindInstructionByType('page').id
+        dlg = PageSetupDialog(self, id = id, settings = self.instruction) 
+        dlg.CenterOnScreen()
+        val = dlg.ShowModal()
+        if val == wx.ID_OK:
+            self.canvas.SetPage()
+            self.canvas.RecalculatePosition(ids = self.objectId)
+        dlg.Destroy()
+        
+    def OnPointer(self, event):
+        self.toolbar.OnTool(event)
+        self.mouse["use"] = "pointer"
+        self.canvas.SetCursor(self.cursors["default"])
+        self.previewCanvas.SetCursor(self.cursors["default"])
+        
+    def OnPan(self, event):
+        self.toolbar.OnTool(event)
+        self.mouse["use"] = "pan"
+        self.canvas.SetCursor(self.cursors["hand"])
+        self.previewCanvas.SetCursor(self.cursors["hand"])
+            
+    def OnZoomIn(self, event):
+        self.toolbar.OnTool(event)
+        self.mouse["use"] = "zoomin"
+        self.canvas.SetCursor(self.cursors["cross"])
+        self.previewCanvas.SetCursor(self.cursors["cross"])
+        
+    def OnZoomOut(self, event):
+        self.toolbar.OnTool(event)
+        self.mouse["use"] = "zoomout"
+        self.canvas.SetCursor(self.cursors["cross"])
+        self.previewCanvas.SetCursor(self.cursors["cross"])
+        
+    def OnZoomAll(self, event):
+        self.mouseOld = self.mouse['use']
+        self.cursorOld = self.canvas.GetCursor() if self.currentPage == 0 else self.previewCanvas.GetCursor()
+        self.mouse["use"] = "zoomin"
+        self.canvas.ZoomAll() if self.currentPage == 0 else self.previewCanvas.ZoomAll()
+        self.mouse["use"] = self.mouseOld 
+        self.canvas.SetCursor(self.cursorOld)  if self.currentPage == 0 else self.previewCanvas.SetCursor(self.cursorOld)
+        
+        
+    def OnAddMap(self, event, notebook = False):
+        if event is not None:
+            if event.GetId() != self.toolbar.action['id']:
+                self.actionOld = self.toolbar.action['id']
+                self.mouseOld = self.mouse['use']
+                self.cursorOld = self.canvas.GetCursor()
+            self.toolbar.OnTool(event)
+        
+        if self.instruction.FindInstructionByType('map'):
+            mapId = self.instruction.FindInstructionByType('map').id
+        else: mapId = None
+        id = [mapId, None, None]
+        if notebook:
+            if self.instruction.FindInstructionByType('vector'):
+                vectorId = self.instruction.FindInstructionByType('vector').id
+            else: vectorId = None
+            if self.instruction.FindInstructionByType('raster'):
+                rasterId = self.instruction.FindInstructionByType('raster').id
+            else: rasterId = None
+            id[1] = rasterId
+            id[2] = vectorId
+        
+        
+        if mapId: # map exists
+             
+            self.toolbar.ToggleTool(self.actionOld, True)
+            self.toolbar.ToggleTool(self.toolbar.action['id'], False)
+            self.toolbar.action['id'] = self.actionOld
+            self.canvas.SetCursor(self.cursorOld) 
+   
+            dlg = MapDialog(parent = self, id  = id, settings = self.instruction,
+                            notebook = notebook)
+            dlg.ShowModal()  
+
+
+        else:    # sofar no map
+            self.mouse["use"] = "addMap"
+            self.canvas.SetCursor(self.cursors["cross"])
+            if self.currentPage == 1:
+                self.book.SetSelection(0)
+                self.currentPage = 0
+                
+    def OnAddRaster(self, event):
+        if self.instruction.FindInstructionByType('raster'):
+            id = self.instruction.FindInstructionByType('raster').id
+        else: id = None
+        if self.instruction.FindInstructionByType('map'):
+            mapId = self.instruction.FindInstructionByType('map').id
+        else: mapId = None
+
+        if not id:
+            if not mapId:
+                GMessage(message = _("Please, create map frame first."))
+                return
+            
+        dlg = RasterDialog(self, id = id, settings = self.instruction)
+        dlg.ShowModal()
+        
+        
+                
+    def OnAddVect(self, event):
+        if self.instruction.FindInstructionByType('vector'):
+            id = self.instruction.FindInstructionByType('vector').id
+        else: id = None
+        if self.instruction.FindInstructionByType('map'):
+            mapId = self.instruction.FindInstructionByType('map').id
+        else: mapId = None
+        if not id:
+            if not mapId:
+                GMessage(message = _("Please, create map frame first."))
+                return
+            
+        dlg = MainVectorDialog(self, id = id, settings = self.instruction)
+        dlg.ShowModal()
+        
+    def OnDecoration(self, event):
+        """!Decorations overlay menu
+        """
+        decmenu = wx.Menu()
+        # legend
+        AddLegend = wx.MenuItem(decmenu, wx.ID_ANY, Icons['psMap']["addLegend"].GetLabel())
+        AddLegend.SetBitmap(Icons['psMap']["addLegend"].GetBitmap(self.iconsize))
+        decmenu.AppendItem(AddLegend)
+        self.Bind(wx.EVT_MENU, self.OnAddLegend, AddLegend)
+        # mapinfo
+        AddMapinfo = wx.MenuItem(decmenu, wx.ID_ANY, Icons['psMap']["addMapinfo"].GetLabel())
+        AddMapinfo.SetBitmap(Icons['psMap']["addMapinfo"].GetBitmap(self.iconsize))
+        decmenu.AppendItem(AddMapinfo)
+        self.Bind(wx.EVT_MENU, self.OnAddMapinfo, AddMapinfo) 
+        # scalebar
+        AddScalebar = wx.MenuItem(decmenu, wx.ID_ANY, Icons['psMap']["addScalebar"].GetLabel())
+        AddScalebar.SetBitmap(Icons['psMap']["addScalebar"].GetBitmap(self.iconsize))
+        decmenu.AppendItem(AddScalebar)
+        self.Bind(wx.EVT_MENU, self.OnAddScalebar, AddScalebar) 
+        # text
+        AddText = wx.MenuItem(decmenu, wx.ID_ANY, Icons['psMap']["addText"].GetLabel())
+        AddText.SetBitmap(Icons['psMap']["addText"].GetBitmap(self.iconsize))
+        decmenu.AppendItem(AddText)
+        self.Bind(wx.EVT_MENU, self.OnAddText, AddText) 
+        # Popup the menu.  If an item is selected then its handler
+        # will be called before PopupMenu returns.
+        self.PopupMenu(decmenu)
+        decmenu.Destroy()
+        
+    def OnAddScalebar(self, event):
+        """!Add scalebar"""
+        if projInfo()['proj'] == 'll':
+            GMessage(message = _("Scalebar is not appropriate for this projection"))
+            return
+        if self.instruction.FindInstructionByType('scalebar'):
+            id = self.instruction.FindInstructionByType('scalebar').id
+        else: id = None
+
+        dlg = ScalebarDialog(self, id = id, settings = self.instruction)
+        dlg.ShowModal()  
+        
+        
+    def OnAddLegend(self, event, page = 0):
+        """!Add raster or vector legend"""
+        if self.instruction.FindInstructionByType('rasterLegend'):
+            idR = self.instruction.FindInstructionByType('rasterLegend').id
+        else: idR = None
+        if self.instruction.FindInstructionByType('vectorLegend'):
+            idV = self.instruction.FindInstructionByType('vectorLegend').id
+        else: idV = None
+
+        dlg = LegendDialog(self, id = [idR, idV], settings = self.instruction, page = page)
+        dlg.ShowModal()
+        
+
+
+    def OnAddMapinfo(self, event):
+        if self.instruction.FindInstructionByType('mapinfo'):
+            id = self.instruction.FindInstructionByType('mapinfo').id
+        else: id = None
+
+        dlg = MapinfoDialog(self, id = id, settings = self.instruction)
+        dlg.ShowModal()
+
+        
+    def OnAddText(self, event, id = None):            
+        dlg = TextDialog(self, id = id, settings = self.instruction) 
+        dlg.ShowModal()
+        
+    def getModifiedTextBounds(self, x, y, textExtent, rotation):
+        """!computes bounding box of rotated text, not very precisely"""
+        w, h = textExtent
+        rotation = float(rotation)/180*pi
+        H = float(w) * sin(rotation)
+        W = float(w) * cos(rotation)
+        X, Y = x, y
+        if pi/2 < rotation <= 3*pi/2:
+            X = x + W 
+        if 0 < rotation < pi:
+            Y = y - H
+        if rotation == 0:
+            return wx.Rect(x,y, *textExtent)
+        else:
+            return wx.Rect(X, Y, abs(W), abs(H)).Inflate(h,h) 
+       
+    def getTextExtent(self, textDict):
+        fontsize = str(textDict['fontsize'] * self.canvas.currScale)
+        #fontsize = str(fontsize if fontsize >= 4 else 4)
+        dc = wx.PaintDC(self) # dc created because of method GetTextExtent, which pseudoDC lacks
+        dc.SetFont(wx.FontFromNativeInfoString(textDict['font'] + " " + fontsize))
+        return dc.GetTextExtent(textDict['text'])
+    
+    def getInitMap(self):
+        """!Create default map frame when no map is selected, needed for coordinates in map units"""
+        instrFile = grass.tempfile()
+        instrFileFd = open(instrFile, mode = 'w')
+        instrFileFd.write(self.InstructionFile())
+        instrFileFd.flush()
+        instrFileFd.close()
+        
+        mapInitRect = GetMapBounds(instrFile)
+        grass.try_remove(instrFile)
+        
+        region = grass.region()
+        units = UnitConversion(self)
+        realWidth = units.convert(value = abs(region['w'] - region['e']), fromUnit = 'meter', toUnit = 'inch')
+        scale = mapInitRect.Get()[2]/realWidth  
+        
+        initMap = self.instruction.FindInstructionByType('initMap')
+        id = initMap.id if initMap else None
+        
+        if not id:
+            id = wx.NewId()
+            initMap = InitMap(id)
+            self.instruction.AddInstruction(initMap)
+        self.instruction[id].SetInstruction(dict(rect = mapInitRect, scale = scale))
+
+    def OnDelete(self, event):
+        if self.canvas.dragId != -1 and self.currentPage == 0:
+            if self.instruction[self.canvas.dragId].type == 'map':
+                self.deleteObject(self.canvas.dragId)
+                self.getInitMap()
+                self.canvas.RecalculateEN()
+            else:
+                self.deleteObject(self.canvas.dragId)
+            
+    
+    def deleteObject(self, id):
+        """!Deletes object, his id and redraws"""
+        #delete from canvas
+        self.canvas.pdcObj.RemoveId(id)
+        if id == self.canvas.dragId:
+            self.canvas.pdcTmp.RemoveAll()
+            self.canvas.dragId = -1
+        self.canvas.Refresh()
+        
+        # delete from instructions
+        del self.instruction[id]
+
+            
+
+        
+
+        
+
+    def DialogDataChanged(self, id):
+        ids = id
+        if type(id) == int:
+            ids = [id]
+        for id in ids:
+            itype = self.instruction[id].type
+            if itype in ('scalebar', 'mapinfo'):
+                drawRectangle = self.canvas.CanvasPaperCoordinates(
+                                    rect = self.instruction[id]['rect'], canvasToPaper = False)
+                self.canvas.Draw( pen = self.pen[itype], brush = self.brush[itype],
+                                pdc = self.canvas.pdcObj, drawid = id, pdctype = 'rectText', bb = drawRectangle)
+                self.canvas.RedrawSelectBox(id)
+                
+                
+            if itype == 'text':
+                
+                rot = float(self.instruction[id]['rotate']) if self.instruction[id]['rotate'] else 0
+                
+                extent = self.getTextExtent(textDict = self.instruction[id].GetInstruction())
+                rect = wx.Rect2D(self.instruction[id]['where'][0], self.instruction[id]['where'][1], 0, 0)
+                self.instruction[id]['coords'] = list(self.canvas.CanvasPaperCoordinates(rect = rect, canvasToPaper = False)[:2])
+                
+                #computes text coordinates according to reference point, not precisely
+                if self.instruction[id]['ref'].split()[0] == 'lower':
+                    self.instruction[id]['coords'][1] -= extent[1]
+                elif self.instruction[id]['ref'].split()[0] == 'center':
+                    self.instruction[id]['coords'][1] -= extent[1]/2
+                if self.instruction[id]['ref'].split()[1] == 'right':
+                    self.instruction[id]['coords'][0] -= extent[0] * cos(rot/180*pi)
+                    self.instruction[id]['coords'][1] += extent[0] * sin(rot/180*pi)
+                elif self.instruction[id]['ref'].split()[1] == 'center':
+                    self.instruction[id]['coords'][0] -= extent[0]/2 * cos(rot/180*pi)
+                    self.instruction[id]['coords'][1] += extent[0]/2 * sin(rot/180*pi)
+                    
+                self.instruction[id]['coords'][0] += self.instruction[id]['xoffset']
+                self.instruction[id]['coords'][1] += self.instruction[id]['yoffset']
+                coords = self.instruction[id]['coords']
+                self.instruction[id]['rect'] = bounds = self.getModifiedTextBounds(coords[0], coords[1], extent, rot)
+                self.canvas.DrawRotText(pdc = self.canvas.pdcObj, drawId = id,
+                                        textDict = self.instruction[id].GetInstruction(),
+                                        coords = coords, bounds = bounds)
+                self.canvas.RedrawSelectBox(id)
+                
+            if itype in ('map', 'vector', 'raster'):
+                    
+                if itype == 'raster':#set resolution
+                    resol = RunCommand('r.info', read = True, flags = 's', map = self.instruction[id]['raster'])
+                    resol = grass.parse_key_val(resol, val_type = float)
+                    RunCommand('g.region', nsres = resol['nsres'], ewres = resol['ewres'])
+                id = self.instruction.FindInstructionByType('map').id
+                   
+                rectCanvas = self.canvas.CanvasPaperCoordinates(rect = self.instruction[id]['rect'],
+                                                                    canvasToPaper = False)
+                self.canvas.RecalculateEN()
+                self.canvas.UpdateMapLabel()
+                
+                self.canvas.Draw( pen = self.pen['map'], brush = self.brush['map'],
+                                pdc = self.canvas.pdcObj, drawid = id, pdctype = 'rectText', bb = rectCanvas)
+                # redraw select box  
+                self.canvas.RedrawSelectBox(id)
+                self.canvas.pdcTmp.RemoveId(self.canvas.idZoomBoxTmp)
+                
+            if itype == 'rasterLegend':
+                if self.instruction[id]['rLegend']:
+                    drawRectangle = self.canvas.CanvasPaperCoordinates(rect = self.instruction[id]['rect'], canvasToPaper = False)
+                    self.canvas.Draw( pen = self.pen[itype], brush = self.brush[itype],
+                                        pdc = self.canvas.pdcObj, drawid = id, pdctype = 'rectText', bb = drawRectangle)
+                    self.canvas.RedrawSelectBox(id)
+                else:
+                    self.deleteObject(id)
+                    
+            if itype == 'vectorLegend':
+                if not self.instruction.FindInstructionByType('vector'):
+                    self.deleteObject(id)
+                elif self.instruction[id]['vLegend']:
+                    drawRectangle = self.canvas.CanvasPaperCoordinates(rect = self.instruction[id]['rect'], canvasToPaper = False)
+                    self.canvas.Draw( pen = self.pen[itype], brush = self.brush[itype],
+                                        pdc = self.canvas.pdcObj, drawid = id, pdctype = 'rectText', bb = drawRectangle)
+                    self.canvas.RedrawSelectBox(id)
+
+                else:
+                    self.deleteObject(id)
+                
+    def OnPageChanged(self, event):
+        """!Flatnotebook page has changed"""
+        self.currentPage = self.book.GetPageIndex(self.book.GetCurrentPage())
+        
+                
+    def OnPageChanging(self, event):
+        """!Flatnotebook page is changing"""
+        if self.currentPage == 0 and self.mouse['use'] == 'addMap':
+            event.Veto()
+
+    def OnHelp(self, event):
+        """!Show help"""
+        if self.parent and self.parent.GetName() == 'LayerManager':
+            log = self.parent.GetLogWindow()
+            log.RunCmd(['g.manual',
+                        'entry=wxGUI.PsMap'])
+        else:
+            RunCommand('g.manual',
+                       quiet = True,
+                       entry = 'wxGUI.PsMap')
+        
+    def OnAbout(self, event):
+        """!Display About window"""
+        info = wx.AboutDialogInfo()
+        
+        info.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
+        info.SetName(_('wxGUI Hardcopy Map Utility'))
+        info.SetWebSite('http://grass.osgeo.org')
+        info.SetDescription(_('(C) 2011 by the GRASS Development Team\n\n') + 
+                            '\n'.join(textwrap.wrap(_('This program is free software under the GNU General Public License'
+                                                      '(>=v2). Read the file COPYING that comes with GRASS for details.'), 75)))
+        
+        wx.AboutBox(info)
+
+    def OnCloseWindow(self, event):
+        """!Close window"""
+        try:
+            os.remove(self.imgName)
+        except OSError:
+            pass
+        self.Destroy()
+
+
+
+class PsMapBufferedWindow(wx.Window):
+    """!A buffered window class.
+    
+    @param parent parent window
+    @param kwargs other wx.Window parameters
+    """
+    def __init__(self, parent, id =  wx.ID_ANY,
+                 style = wx.NO_FULL_REPAINT_ON_RESIZE,
+                 **kwargs):
+        wx.Window.__init__(self, parent, id = id, style = style)
+        self.parent = parent
+    
+        self.FitInside()
+        
+        # store an off screen empty bitmap for saving to file
+        self._buffer = None
+        # indicates whether or not a resize event has taken place
+        self.resize = False 
+        
+        self.mouse = kwargs['mouse']
+        self.cursors = kwargs['cursors']
+        self.preview = kwargs['preview']
+        self.pen = kwargs['pen']
+        self.brush = kwargs['brush']
+        
+        if kwargs.has_key('instruction'):
+            self.instruction = kwargs['instruction']
+        if kwargs.has_key('pageId'):
+            self.pageId = kwargs['pageId']
+        if kwargs.has_key('objectId'):
+            self.objectId = kwargs['objectId']
+        
+        
+        #labels
+        self.itemLabels = { 'map': ['MAP FRAME'],
+                            'rasterLegend': ['RASTER LEGEND'],
+                            'vectorLegend': ['VECTOR LEGEND'],
+                            'mapinfo': ['MAP INFO'],
+                            'scalebar': ['SCALE BAR']}
+        
+        # define PseudoDC
+        self.pdc = wx.PseudoDC()
+        self.pdcObj = wx.PseudoDC()
+        self.pdcPaper = wx.PseudoDC()
+        self.pdcTmp = wx.PseudoDC()
+        self.pdcImage = wx.PseudoDC()
+        dc = wx.PaintDC(self)
+        self.font = dc.GetFont()
+        
+        self.SetClientSize((700,510))#?
+        self._buffer = wx.EmptyBitmap(*self.GetClientSize())
+        
+        self.idBoxTmp = wx.NewId()
+        self.idZoomBoxTmp = wx.NewId()
+        self.idResizeBoxTmp = wx.NewId()
+        
+        
+
+        self.dragId = -1
+        
+        if self.preview:
+            self.image = None
+            self.imageId = 2000
+            self.imgName = self.parent.imgName
+            
+            
+ 
+        self.currScale = None
+  
+        self.Clear()
+        
+        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+        
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_SIZE,  self.OnSize)
+        self.Bind(wx.EVT_IDLE,  self.OnIdle)
+        self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+
+
+    def Clear(self):
+        """!Clear canvas and set paper
+        """
+        bg = wx.LIGHT_GREY_BRUSH
+        self.pdcPaper.BeginDrawing()
+        self.pdcPaper.SetBackground(bg)
+        self.pdcPaper.Clear()
+        self.pdcPaper.EndDrawing()
+        if not self.preview:
+            self.SetPage()
+        
+
+    
+    def CanvasPaperCoordinates(self, rect, canvasToPaper = True):
+        """!Converts canvas (pixel) -> paper (inch) coordinates and size and vice versa"""
+        
+        units = UnitConversion(self)
+        
+        fromU = 'pixel'
+        toU = 'inch'
+        pRect = self.pdcPaper.GetIdBounds(self.pageId)
+        pRectx, pRecty = pRect.x, pRect.y 
+        scale = 1/self.currScale
+        if not canvasToPaper: # paper -> canvas
+            fromU = 'inch'
+            toU = 'pixel'
+            scale = self.currScale
+            pRectx = units.convert(value =  - pRect.x, fromUnit = 'pixel', toUnit = 'inch' ) /scale #inch, real, negative
+            pRecty = units.convert(value =  - pRect.y, fromUnit = 'pixel', toUnit = 'inch' ) /scale 
+        Width = units.convert(value = rect.width, fromUnit = fromU, toUnit = toU) * scale
+        Height = units.convert(value = rect.height, fromUnit = fromU, toUnit = toU) * scale
+        X = units.convert(value = (rect.x - pRectx), fromUnit = fromU, toUnit = toU) * scale
+        Y = units.convert(value = (rect.y - pRecty), fromUnit = fromU, toUnit = toU) * scale
+
+        return wx.Rect2D(X, Y, Width, Height)
+
+        
+        
+    def SetPage(self):
+        """!Sets and changes page, redraws paper"""
+        
+        page = self.instruction[self.pageId]
+        if not page:
+            page = PageSetup(id = self.pageId)
+            self.instruction.AddInstruction(page)
+        
+        ppi = wx.PaintDC(self).GetPPI()
+        cW, cH = self.GetClientSize()
+        pW, pH = page['Width']*ppi[0], page['Height']*ppi[1]
+
+        if self.currScale is None:
+            self.currScale = min(cW/pW, cH/pH)
+        pW = pW * self.currScale
+        pH = pH * self.currScale
+        
+        x = cW/2 - pW/2
+        y = cH/2 - pH/2
+        self.DrawPaper(wx.Rect(x, y, pW, pH))
+
+
+    def modifyRectangle(self, r):
+        """! Recalculates rectangle not to have negative size"""
+        if r.GetWidth() < 0:
+            r.SetX(r.GetX() + r.GetWidth())
+        if r.GetHeight() < 0:
+            r.SetY(r.GetY() + r.GetHeight())
+        r.SetWidth(abs(r.GetWidth()))
+        r.SetHeight(abs(r.GetHeight()))
+        return r 
+          
+    def RecalculateEN(self):
+        """!Recalculate east and north for texts (eps, points) after their or map's movement"""
+        try:
+            mapId = self.instruction.FindInstructionByType('map').id
+        except AttributeError:
+            mapId = self.instruction.FindInstructionByType('initMap').id
+            
+        texts = self.instruction.FindInstructionByType('text', list = True)
+        for text in texts:
+            e, n = PaperMapCoordinates(self, mapId = mapId, x = self.instruction[text.id]['where'][0],
+                                                y = self.instruction[text.id]['where'][1], paperToMap = True)
+            self.instruction[text.id]['east'], self.instruction[text.id]['north'] = e, n
+            
+    def OnPaint(self, event):
+        """!Draw pseudo DC to buffer
+        """
+        if not self._buffer:
+            return
+        dc = wx.BufferedPaintDC(self, self._buffer)
+        # use PrepareDC to set position correctly
+        self.PrepareDC(dc)
+        
+        dc.SetBackground(wx.LIGHT_GREY_BRUSH)
+        dc.Clear()
+        
+        # draw paper
+        if not self.preview:
+            self.pdcPaper.DrawToDC(dc)
+        # draw to the DC using the calculated clipping rect
+
+        rgn = self.GetUpdateRegion()
+        
+        if not self.preview:
+            self.pdcObj.DrawToDCClipped(dc, rgn.GetBox())
+        else: 
+            self.pdcImage.DrawToDCClipped(dc, rgn.GetBox())
+        self.pdcTmp.DrawToDCClipped(dc, rgn.GetBox())
+        
+    def OnMouse(self, event):
+
+        if event.GetWheelRotation():
+            zoom = event.GetWheelRotation()
+            use = self.mouse['use']
+            self.mouse['begin'] = event.GetPosition()
+            if zoom > 0:
+                self.mouse['use'] = 'zoomin'
+            else:
+                self.mouse['use'] = 'zoomout'
+                
+            zoomFactor, view = self.ComputeZoom(wx.Rect(0,0,0,0))
+            self.Zoom(zoomFactor, view)
+            self.mouse['use'] = use
+            
+        if event.Moving():
+            if self.mouse['use'] in ('pointer', 'resize'):
+                pos = event.GetPosition()
+                foundResize = self.pdcTmp.FindObjects(pos[0], pos[1])
+                if foundResize and foundResize[0] == self.idResizeBoxTmp:
+                    self.SetCursor(self.cursors["sizenwse"])
+                    self.parent.SetStatusText(_('Click and drag to resize object'), 0)
+                else:
+                    self.parent.SetStatusText(_(''), 0)
+                    self.SetCursor(self.cursors["default"])
+        elif event.LeftDown():
+            self.mouse['begin'] = event.GetPosition()
+            self.begin = self.mouse['begin']
+            if self.mouse['use'] in ('pan', 'zoomin', 'zoomout', 'addMap'):
+                pass
+                
+            #select
+            if self.mouse['use'] == 'pointer':
+                found = self.pdcObj.FindObjects(self.mouse['begin'][0], self.mouse['begin'][1])
+                foundResize = self.pdcTmp.FindObjects(self.mouse['begin'][0], self.mouse['begin'][1])
+
+                if foundResize and foundResize[0] == self.idResizeBoxTmp:
+                    self.mouse['use'] = 'resize'
+                elif found:
+                    self.dragId = found[0]  
+                    self.RedrawSelectBox(self.dragId)
+                    if self.instruction[self.dragId].type != 'map':
+                        self.pdcTmp.RemoveId(self.idResizeBoxTmp)
+                        self.Refresh()
+
+                else:
+                    self.dragId = -1
+                    self.pdcTmp.RemoveId(self.idBoxTmp)
+                    self.pdcTmp.RemoveId(self.idResizeBoxTmp)
+                    self.Refresh()           
+          
+                   
+        elif event.Dragging() and event.LeftIsDown():
+            #draw box when zooming, creating map 
+            if self.mouse['use'] in ('zoomin', 'zoomout', 'addMap'):
+                self.mouse['end'] = event.GetPosition()
+                r = wx.Rect(self.mouse['begin'][0], self.mouse['begin'][1],
+                            self.mouse['end'][0]-self.mouse['begin'][0], self.mouse['end'][1]-self.mouse['begin'][1])
+                r = self.modifyRectangle(r)
+                self.Draw(pen = self.pen['box'], brush = self.brush['box'], pdc = self.pdcTmp, drawid = self.idZoomBoxTmp,
+                            pdctype = 'rect', bb = r)
+                            
+            # panning                
+            if self.mouse["use"] == 'pan':
+                self.mouse['end'] = event.GetPosition()
+                view = self.mouse['begin'][0] - self.mouse['end'][0], self.mouse['begin'][1] - self.mouse['end'][1]
+                zoomFactor = 1
+                self.Zoom(zoomFactor, view)
+                self.mouse['begin'] = event.GetPosition()
+                
+            #move object
+            if self.mouse['use'] == 'pointer' and self.dragId != -1:
+                
+                self.mouse['end'] = event.GetPosition()
+                dx, dy = self.mouse['end'][0] - self.begin[0], self.mouse['end'][1] - self.begin[1]
+                self.pdcObj.TranslateId(self.dragId, dx, dy)
+                self.pdcTmp.TranslateId(self.idBoxTmp, dx, dy)
+                self.pdcTmp.TranslateId(self.idResizeBoxTmp, dx, dy)
+                if self.instruction[self.dragId].type == 'text': 
+                    self.instruction[self.dragId]['coords'] = self.instruction[self.dragId]['coords'][0] + dx,\
+                                                            self.instruction[self.dragId]['coords'][1] + dy
+                self.begin = event.GetPosition()
+                self.Refresh()
+                
+            # resize object
+            if self.mouse['use'] == 'resize':
+                bounds = self.pdcObj.GetIdBounds(self.dragId)
+                type = self.instruction[self.dragId].type
+                self.mouse['end'] = event.GetPosition()
+                diffX = self.mouse['end'][0] - self.begin[0]
+                diffY = self.mouse['end'][1] - self.begin[1]
+                bounds.Inflate(diffX, diffY)
+                
+                self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcObj, drawid = self.dragId,
+                            pdctype = 'rectText', bb = bounds)
+                self.RedrawSelectBox(self.dragId)
+                self.begin = event.GetPosition()
+                
+        elif event.LeftUp():
+            # zoom in, zoom out
+            if self.mouse['use'] in ('zoomin','zoomout'):
+                zoomR = self.pdcTmp.GetIdBounds(self.idZoomBoxTmp)
+                self.pdcTmp.RemoveId(self.idZoomBoxTmp)
+                self.Refresh()
+                zoomFactor, view = self.ComputeZoom(zoomR)
+                self.Zoom(zoomFactor, view)
+
+                
+            # draw map frame    
+            if self.mouse['use'] == 'addMap':
+                rectTmp = self.pdcTmp.GetIdBounds(self.idZoomBoxTmp)
+                rectPaper = self.CanvasPaperCoordinates(rect = rectTmp, canvasToPaper = True)                
+                
+                dlg = MapDialog(parent = self.parent, id = [None, None, None], settings = self.instruction, 
+                                         rect = rectPaper)
+                dlg.ShowModal()
+                if  self.instruction.FindInstructionByType('map'):
+                    #redraw objects to lower map to the bottom
+                    self.Zoom(zoomFactor = 1, view = (0, 0))
+
+                    self.mouse['use'] = self.parent.mouseOld
+
+                    self.SetCursor(self.parent.cursorOld)
+                    self.parent.toolbar.ToggleTool(self.parent.actionOld, True)
+                    self.parent.toolbar.ToggleTool(self.parent.toolbar.action['id'], False)
+                    self.parent.toolbar.action['id'] = self.parent.actionOld
+                    
+                self.pdcTmp.RemoveId(self.idZoomBoxTmp)
+                self.Refresh() 
+
+
+            # resize resizable objects (only map sofar)
+            if self.mouse['use'] == 'resize':
+                mapId = self.instruction.FindInstructionByType('map').id
+                
+                if self.dragId == mapId:
+                    # necessary to change either map frame (scaleType 0,1,2) or region (scaletype 3)
+                    newRectCanvas = self.pdcObj.GetIdBounds(mapId)
+                    newRectPaper = self.CanvasPaperCoordinates(rect = newRectCanvas, canvasToPaper = True)
+                    self.instruction[mapId]['rect'] = newRectPaper
+                    
+                    if self.instruction[mapId]['scaleType'] in (0, 1, 2):
+                        if self.instruction[mapId]['scaleType'] == 0:
+                            
+                            scale, foo, rect = AutoAdjust(self, scaleType = 0,
+                                                        map = self.instruction[mapId]['map'],
+                                                        mapType = self.instruction[mapId]['mapType'], 
+                                                        rect = self.instruction[mapId]['rect'])
+                        if self.instruction[mapId]['scaleType'] == 1:
+                            scale, foo, rect = AutoAdjust(self, scaleType = 1,
+                                                        region = self.instruction[mapId]['region'],
+                                                        rect = self.instruction[mapId]['rect'])
+                        else:
+                            scale, foo, rect = AutoAdjust(self, scaleType = 2,
+                                                        rect = self.instruction[mapId]['rect'])
+                        self.instruction[mapId]['rect'] = rect
+                        self.instruction[mapId]['scale'] = scale
+                        
+                        rectCanvas = self.CanvasPaperCoordinates(rect = rect, canvasToPaper = False)
+                        self.Draw(pen = self.pen['map'], brush = self.brush['map'],
+                                    pdc = self.pdcObj, drawid = mapId, pdctype = 'rectText', bb = rectCanvas)
+                                    
+                    elif self.instruction[mapId]['scaleType'] == 3:
+                        ComputeSetRegion(self, mapDict = self.instruction[mapId].GetInstruction())
+                        
+                    self.RedrawSelectBox(mapId)
+                self.mouse['use'] = 'pointer'
+                
+            # recalculate the position of objects after dragging    
+            if self.mouse['use'] in ('pointer', 'resize') and self.dragId != -1:
+                if self.mouse['begin'] != event.GetPosition(): #for double click
+                    
+                    self.RecalculatePosition(ids = [self.dragId])
+
+        # double click launches dialogs
+        elif event.LeftDClick():
+            if self.mouse['use'] == 'pointer' and self.dragId != -1:
+                itemCall = {    'text':self.parent.OnAddText, 'mapinfo': self.parent.OnAddMapinfo,
+                                'scalebar': self.parent.OnAddScalebar,
+                                'rasterLegend': self.parent.OnAddLegend, 'vectorLegend': self.parent.OnAddLegend,  
+                                'map': self.parent.OnAddMap}
+                itemArg = { 'text': dict(event = None, id = self.dragId), 'mapinfo': dict(event = None),
+                            'scalebar': dict(event = None),
+                            'rasterLegend': dict(event = None), 'vectorLegend': dict(event = None, page = 1),
+                            'map': dict(event = None, notebook = True)}
+                type = self.instruction[self.dragId].type
+                itemCall[type](**itemArg[type])
+
+                    
+                    
+                
+    def RecalculatePosition(self, ids):
+        for id in ids:
+            itype = self.instruction[id].type
+            if itype == 'map':
+                        self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = self.pdcObj.GetIdBounds(id),
+                                                                    canvasToPaper = True)
+                        self.RecalculateEN()
+                        
+            elif itype in ('mapinfo' ,'rasterLegend', 'vectorLegend'):
+                self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = self.pdcObj.GetIdBounds(id),
+                                                            canvasToPaper = True)
+                self.instruction[id]['where'] = self.CanvasPaperCoordinates(rect = self.pdcObj.GetIdBounds(id),
+                                                            canvasToPaper = True)[:2]            
+            elif  itype == 'scalebar':
+                self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = self.pdcObj.GetIdBounds(id),
+                                                            canvasToPaper = True)
+
+                
+                self.instruction[id]['where'] = self.instruction[id]['rect'].GetCentre()
+                                                             
+            elif  itype == 'text':
+                x, y = self.instruction[id]['coords'][0] - self.instruction[id]['xoffset'],\
+                        self.instruction[id]['coords'][1] - self.instruction[id]['yoffset']
+                extent = self.parent.getTextExtent(textDict = self.instruction[id])
+                rot = float(self.instruction[id]['rotate'])/180*pi if self.instruction[id]['rotate'] is not None else 0
+                if self.instruction[id]['ref'].split()[0] == 'lower':
+                    y += extent[1]
+                elif self.instruction[id]['ref'].split()[0] == 'center':
+                    y += extent[1]/2
+                if self.instruction[id]['ref'].split()[1] == 'right':
+                    x += extent[0] * cos(rot)
+                    y -= extent[0] * sin(rot)
+                elif self.instruction[id]['ref'].split()[1] == 'center':
+                    x += extent[0]/2 * cos(rot)
+                    y -= extent[0]/2 * sin(rot)
+                
+                self.instruction[id]['where'] = self.CanvasPaperCoordinates(rect = wx.Rect2D(x, y, 0, 0),
+                                                            canvasToPaper = True)[:2]
+                self.RecalculateEN()
+        
+    def ComputeZoom(self, rect):
+        """!Computes zoom factor and scroll view"""
+        zoomFactor = 1
+        cW, cH = self.GetClientSize()
+        cW = float(cW)
+        if rect.IsEmpty(): # clicked on canvas
+            zoomFactor = 1.5
+            if self.mouse['use'] == 'zoomout':
+                zoomFactor = 1./zoomFactor
+            x,y = self.mouse['begin']
+            xView = x - cW/(zoomFactor * 2)
+            yView = y - cH/(zoomFactor * 2)
+
+        else:   #dragging    
+            rW, rH = float(rect.GetWidth()), float(rect.GetHeight())
+            zoomFactor = 1/max(rW/cW, rH/cH)
+            # when zooming to full extent, in some cases, there was zoom 1.01..., which causes problem
+            zoomFactor = zoomFactor if abs(zoomFactor - 1) > 0.01 else 1.
+
+            if self.mouse['use'] == 'zoomout':
+                zoomFactor = min(rW/cW, rH/cH) 
+            if rW/rH > cW/cH:
+                yView = rect.GetY() - (rW*(cH/cW) - rH)/2
+                xView = rect.GetX()
+                
+                if self.mouse['use'] == 'zoomout':
+                    x,y = rect.GetX() + (rW-(cW/cH)*rH)/2, rect.GetY()
+                    xView, yView = -x, -y
+            else:
+                xView = rect.GetX() - (rH*(cW/cH) - rW)/2
+                yView = rect.GetY()
+                if self.mouse['use'] == 'zoomout':
+                    x,y = rect.GetX(), rect.GetY() + (rH-(cH/cW)*rW)/2
+                    xView, yView = -x, -y
+        return zoomFactor, (int(xView), int(yView))
+               
+                
+    def Zoom(self, zoomFactor, view):
+        """! Zoom to specified region, scroll view, redraw"""
+        if not self.currScale:
+            return
+        self.currScale = self.currScale*zoomFactor
+        
+        if self.currScale > 10 or self.currScale < 0.1:
+            self.currScale = self.currScale/zoomFactor
+            return 
+        if not self.preview:
+            # redraw paper
+            pRect = self.pdcPaper.GetIdBounds(self.pageId)
+            pRect.OffsetXY(-view[0], -view[1])
+            pRect = self.ScaleRect(rect = pRect, scale = zoomFactor)
+            self.DrawPaper(pRect)
+            
+            #redraw objects
+            for id in self.objectId:
+                oRect = self.CanvasPaperCoordinates(
+                                    rect = self.instruction[id]['rect'], canvasToPaper = False)
+                    
+                type = self.instruction[id].type
+                if type == 'text':
+                    coords = self.instruction[id]['coords']# recalculate coordinates, they are not equal to BB
+                    self.instruction[id]['coords'] = coords = [(int(coord) - view[i]) * zoomFactor
+                                                                        for i, coord in enumerate(coords)]
+                    self.DrawRotText(pdc = self.pdcObj, drawId = id, textDict = self.instruction[id],
+                     coords = coords, bounds = oRect )
+                    extent = self.parent.getTextExtent(textDict = self.instruction[id])
+                    rot = float(self.instruction[id]['rotate']) if self.instruction[id]['rotate'] else 0
+                    self.instruction[id]['rect'] = bounds = self.parent.getModifiedTextBounds(coords[0], coords[1], extent, rot)
+                    self.pdcObj.SetIdBounds(id, bounds)
+                else:
+                    self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcObj,
+                            drawid = id, pdctype = 'rectText', bb = oRect)
+            #redraw tmp objects
+            if self.dragId != -1:
+                self.RedrawSelectBox(self.dragId)
+                
+        #redraw preview
+        else: # preview mode    
+            imageRect = self.pdcImage.GetIdBounds(self.imageId)
+            imageRect.OffsetXY(-view[0], -view[1])
+            imageRect = self.ScaleRect(rect = imageRect, scale = zoomFactor)
+            self.DrawImage(imageRect)
+            
+            
+        
+    def ZoomAll(self):
+        """! Zoom to full extent"""  
+        if not self.preview:
+            bounds = self.pdcPaper.GetIdBounds(self.pageId)
+        else:
+            bounds = self.pdcImage.GetIdBounds(self.imageId)
+        zoomP = bounds.Inflate(bounds.width/20, bounds.height/20)
+        zoomFactor, view = self.ComputeZoom(zoomP)
+        self.Zoom(zoomFactor, view)
+                    
+    def Draw(self, pen, brush, pdc, drawid = None, pdctype = 'rect', bb = wx.Rect(0,0,0,0)): 
+        """! Draw object"""    
+        if drawid is None:
+            drawid = wx.NewId()
+        bb = bb.Get()
+        pdc.BeginDrawing()
+        pdc.RemoveId(drawid)
+        pdc.SetId(drawid)
+        pdc.SetPen(pen)
+        pdc.SetBrush(brush)
+        if pdctype in ('rect', 'rectText'):
+            pdc.DrawRectangle(*bb)
+        if pdctype == 'rectText':
+            dc = wx.PaintDC(self) # dc created because of method GetTextExtent, which pseudoDC lacks
+            font = self.font
+            size = 10
+            font.SetPointSize(size)
+            font.SetStyle(wx.ITALIC)
+            dc.SetFont(font)
+            pdc.SetFont(font)
+            text = '\n'.join(self.itemLabels[self.instruction[drawid].type])
+            textExtent = dc.GetTextExtent(text)
+            textRect = wx.Rect(0, 0, *textExtent).CenterIn(bb)
+            r = map(int, bb)
+            while not wx.Rect(*r).ContainsRect(textRect) and size >= 8:
+                size -= 2
+                font.SetPointSize(size)
+                dc.SetFont(font)
+                pdc.SetFont(font)
+                textExtent = dc.GetTextExtent(text)
+                textRect = wx.Rect(0, 0, *textExtent).CenterIn(bb)
+            pdc.SetTextForeground(wx.Color(100,100,100,200)) 
+            pdc.SetBackgroundMode(wx.TRANSPARENT)
+
+            pdc.DrawText(text = text, x = textRect.x, y = textRect.y)
+            
+        pdc.SetIdBounds(drawid, bb)
+        pdc.EndDrawing()
+        self.Refresh()
+
+        return drawid
+    
+    def DrawRotText(self, pdc, drawId, textDict, coords, bounds):
+        rot = float(textDict['rotate']) if textDict['rotate'] else 0
+        fontsize = str(textDict['fontsize'] * self.currScale)
+        background = textDict['background'] if textDict['background'] != 'none' else None
+        
+        dc = wx.PaintDC(self) # dc created because of method GetTextExtent, which pseudoDC lacks
+        dc.SetFont(wx.FontFromNativeInfoString(textDict['font'] + " " + fontsize))
+        textExtent = dc.GetTextExtent(textDict['text'])
+        
+        pdc.RemoveId(drawId)
+        pdc.SetId(drawId)
+        pdc.BeginDrawing()
+        # doesn't work
+        if background:
+            pdc.SetBackground(wx.Brush(convertRGB(background)))
+            pdc.SetBackgroundMode(wx.SOLID)
+        else:
+            pdc.SetBackground(wx.TRANSPARENT_BRUSH)
+            pdc.SetBackgroundMode(wx.TRANSPARENT)
+        pdc.SetFont(wx.FontFromNativeInfoString(textDict['font'] + " " + fontsize))    
+##        pdc.SetTextForeground(convertRGB(textDict['color']))        
+        pdc.SetTextForeground(textDict['color'])        
+        pdc.DrawRotatedText(textDict['text'], coords[0], coords[1], rot)
+
+        pdc.SetIdBounds(drawId, wx.Rect(*bounds))
+        self.Refresh()
+        pdc.EndDrawing()
+        
+    def DrawImage(self, rect):
+        """!Draw preview image to pseudoDC"""
+        self.pdcImage.ClearId(self.imageId)
+        self.pdcImage.SetId(self.imageId)
+        img = self.image
+        
+
+        if img.GetWidth() != rect.width or img.GetHeight() != rect.height:
+            img = img.Scale(rect.width, rect.height)
+        bitmap = img.ConvertToBitmap()
+        
+        self.pdcImage.BeginDrawing()
+        self.pdcImage.DrawBitmap(bitmap, rect.x, rect.y)
+        self.pdcImage.SetIdBounds(self.imageId, rect)
+        self.pdcImage.EndDrawing()
+        self.Refresh()
+        
+    def DrawPaper(self, rect):
+        """!Draw paper and margins"""
+        page = self.instruction[self.pageId]
+        scale = page['Width'] / rect.GetWidth()
+        w = (page['Width'] - page['Right'] - page['Left']) / scale
+        h = (page['Height'] - page['Top'] - page['Bottom']) / scale
+        x = page['Left'] / scale + rect.GetX()
+        y = page['Top'] / scale + rect.GetY()
+        
+        self.pdcPaper.BeginDrawing()
+        self.pdcPaper.RemoveId(self.pageId)
+        self.pdcPaper.SetId(self.pageId)
+        self.pdcPaper.SetPen(self.pen['paper'])
+        self.pdcPaper.SetBrush(self.brush['paper'])
+        self.pdcPaper.DrawRectangleRect(rect)
+        
+        self.pdcPaper.SetPen(self.pen['margins'])
+        self.pdcPaper.SetBrush(self.brush['margins'])
+        self.pdcPaper.DrawRectangle(x, y, w, h)
+        
+        self.pdcPaper.SetIdBounds(self.pageId, rect)
+        self.pdcPaper.EndDrawing()
+        self.Refresh()
+
+        
+    def ImageRect(self):
+        """!Returns image centered in canvas, computes scale"""
+        img = wx.Image(self.imgName, wx.BITMAP_TYPE_PNG)
+        cW, cH = self.GetClientSize()
+        iW, iH = img.GetWidth(), img.GetHeight()
+
+        self.currScale = min(float(cW)/iW, float(cH)/iH)
+        iW = iW * self.currScale
+        iH = iH * self.currScale
+        x = cW/2 - iW/2
+        y = cH/2 - iH/2
+        imageRect = wx.Rect(x, y, iW, iH)
+
+        return imageRect 
+    
+    def RedrawSelectBox(self, id):
+        """!Redraws select box when selected object changes its size"""
+        if self.dragId == id:
+            rect = [self.pdcObj.GetIdBounds(id).Inflate(3,3)]
+            type = ['select']
+            ids = [self.idBoxTmp]
+            if self.instruction[id].type == 'map':
+                controlP = self.pdcObj.GetIdBounds(id).GetBottomRight()
+                rect.append(wx.Rect(controlP.x, controlP.y, 10,10))
+                type.append('resize')
+                ids.append(self.idResizeBoxTmp)
+            for id, type, rect in zip(ids, type, rect):
+                self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcTmp,
+                            drawid = id, pdctype = 'rect', bb = rect)
+        
+    def UpdateMapLabel(self):
+        """!Updates map frame label"""
+        mapId = self.instruction.FindInstructionByType('map').id
+        vector = self.instruction.FindInstructionByType('vector')
+        vectorId = vector.id if vector else None
+        raster = self.instruction.FindInstructionByType('raster')
+        rasterId = raster.id if raster else None
+        rasterName = 'None'
+        if rasterId:
+            rasterName = self.instruction[rasterId]['raster'].split('@')[0]
+                            
+        self.itemLabels['map'] = self.itemLabels['map'][0:1]
+        self.itemLabels['map'].append("raster: " + rasterName)
+        if vectorId: 
+            for map in self.instruction[vectorId]['list']:
+                self.itemLabels['map'].append('vector: ' + map[0].split('@')[0])
+            
+    def OnSize(self, event):
+        """!Init image size to match window size
+        """
+        # not zoom all when notebook page is changed
+        if self.preview and self.parent.currentPage == 1 or not self.preview and self.parent.currentPage == 0:
+            self.ZoomAll()
+        self.OnIdle(None)
+        event.Skip()
+        
+    def OnIdle(self, event):
+        """!Only re-render a image during idle time instead of
+        multiple times during resizing.
+        """ 
+        
+        width, height = self.GetClientSize()
+        # Make new off screen bitmap: this bitmap will always have the
+        # current drawing in it, so it can be used to save the image
+        # to a file, or whatever.
+        self._buffer = wx.EmptyBitmap(width, height)
+        # re-render image on idle
+        self.resize = True
+
+            
+    def ScaleRect(self, rect, scale):
+        """! Scale rectangle"""
+        return wx.Rect(rect.GetLeft()*scale, rect.GetTop()*scale,
+                    rect.GetSize()[0]*scale, rect.GetSize()[1]*scale)   
+                     
+def main():
+    app = wx.PySimpleApp()
+    wx.InitAllImageHandlers()
+    frame = PsMapFrame()
+    frame.Show()
+    
+    app.MainLoop()
+
+if __name__ == "__main__":
+    main()

Added: grass-addons/gui/wxpython/psmap/gui_modules/psmap_dialogs.py
===================================================================
--- grass-addons/gui/wxpython/psmap/gui_modules/psmap_dialogs.py	                        (rev 0)
+++ grass-addons/gui/wxpython/psmap/gui_modules/psmap_dialogs.py	2011-03-14 07:15:14 UTC (rev 45659)
@@ -0,0 +1,4488 @@
+"""!
+ at package psmap_dialogs
+
+ at brief dialogs for ps.map
+
+Classes:
+ - UnitConversion
+ - PageSetupDialog
+ - MapDialog 
+ - LegendDialog
+
+(C) 2011 by Anna Kratochvilova, and 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 Anna Kratochvilova <anna.kratochvilova fsv.cvut.cz> (bachelor's project)
+ at author Martin Landa <landa.martin gmail.com> (mentor)
+"""
+
+import os
+import sys
+import string
+from math import ceil, floor
+from copy import deepcopy
+
+import grass.script as grass
+if int(grass.version()['version'].split('.')[0]) > 6:
+    sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'gui', 'wxpython',
+                                 'gui_modules'))
+else:
+    sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'wxpython',
+                                 'gui_modules'))
+import globalvar
+import dbm_base
+from   utils      import CmdToTuple
+from   gselect    import Select
+from   gcmd       import RunCommand, GError, GMessage
+
+import wx
+import wx.lib.scrolledpanel as scrolled
+import  wx.lib.filebrowsebutton as filebrowse
+from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
+from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED
+
+try:
+    from agw import flatnotebook as fnb
+except ImportError: # if it's not there locally, try the wxPython lib.
+    import wx.lib.agw.flatnotebook as fnb
+
+grass.set_raise_on_error(True)
+
+class UnitConversion():
+    """! Class for converting units"""
+    def __init__(self, parent):
+        self.parent = parent
+        ppi = wx.PaintDC(self.parent).GetPPI()
+        self._unitsPage = { 'inch' : 1.0,
+                            'point' : 72.0,
+                            'centimeter' : 2.54,
+                            'milimeter' : 25.4}
+        self._unitsMap = {  'meters' : 0.0254,
+                            'kilometers' : 2.54e-5,
+                            'feet' : 1./12,
+                            'miles' : 1./63360,
+                            'nautical miles' : 1/72913.44}
+
+        self._units = { 'pixel': ppi[0],
+                        'meter': 0.0254,
+                        'degrees' : 0.0254  #like 1 meter, incorrect
+                        }
+        self._units.update(self._unitsPage)
+        self._units.update(self._unitsMap)
+
+    def getPageUnits(self):
+        return sorted(self._unitsPage.keys())
+    
+    def getMapUnits(self):
+        return sorted(self._unitsMap.keys())
+    
+    def getAllUnits(self):
+        return sorted(self._units.keys())
+    
+    def convert(self, value, fromUnit = None, toUnit = None):
+        return float(value)/self._units[fromUnit]*self._units[toUnit]
+    
+    
+class TCValidator(wx.PyValidator):
+    """!validates input in textctrls, combobox, taken from wxpython demo"""
+    def __init__(self, flag = None):
+        wx.PyValidator.__init__(self)
+        self.flag = flag
+        self.Bind(wx.EVT_CHAR, self.OnChar)
+
+    def Clone(self):
+        return TCValidator(self.flag)
+
+    def Validate(self, win):
+       
+        tc = self.GetWindow()
+        val = tc.GetValue()
+
+        if self.flag == 'DIGIT_ONLY':
+            for x in val:
+                if x not in string.digits:
+                    return False
+        return True
+
+    def OnChar(self, event):
+        key = event.GetKeyCode()
+        if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255:
+            event.Skip()
+            return
+        if self.flag == 'DIGIT_ONLY' and chr(key) in string.digits + '.':
+            event.Skip()
+            return
+##        if self.flag == 'SCALE' and chr(key) in string.digits + ':':
+##            event.Skip()
+##            return
+        if self.flag == 'ZERO_AND_ONE_ONLY' and chr(key) in '01':
+            event.Skip()
+            return
+        if not wx.Validator_IsSilent():
+            wx.Bell()
+        # Returning without calling even.Skip eats the event before it
+        # gets to the text control
+        return  
+
+
+class PenStyleComboBox(wx.combo.OwnerDrawnComboBox):
+    """!Combo for selecting line style, taken from wxpython demo"""
+
+    # Overridden from OwnerDrawnComboBox, called to draw each
+    # item in the list
+    def OnDrawItem(self, dc, rect, item, flags):
+        if item == wx.NOT_FOUND:
+            # painting the control, but there is no valid item selected yet
+            return
+
+        r = wx.Rect(*rect)  # make a copy
+        r.Deflate(3, 5)
+
+        penStyle = wx.SOLID
+        if item == 1:
+            penStyle = wx.LONG_DASH
+        elif item == 2:
+            penStyle = wx.DOT
+        elif item == 3:
+            penStyle = wx.DOT_DASH
+
+        pen = wx.Pen(dc.GetTextForeground(), 3, penStyle)
+        dc.SetPen(pen)
+
+        # for painting the items in the popup
+        dc.DrawText(self.GetString( item ),
+                    r.x + 3,
+                    (r.y + 0) + ( (r.height/2) - dc.GetCharHeight() )/2
+                    )
+        dc.DrawLine( r.x+5, r.y+((r.height/4)*3)+1, r.x+r.width - 5, r.y+((r.height/4)*3)+1 )
+
+           
+    def OnDrawBackground(self, dc, rect, item, flags):
+        """!Overridden from OwnerDrawnComboBox, called for drawing the
+            background area of each item."""
+        # If the item is selected, or its item # iseven, or we are painting the
+        # combo control itself, then use the default rendering.
+        if (item & 1 == 0 or flags & (wx.combo.ODCB_PAINTING_CONTROL |
+                                      wx.combo.ODCB_PAINTING_SELECTED)):
+            wx.combo.OwnerDrawnComboBox.OnDrawBackground(self, dc, rect, item, flags)
+            return
+
+        # Otherwise, draw every other background with different colour.
+        bgCol = wx.Colour(240,240,250)
+        dc.SetBrush(wx.Brush(bgCol))
+        dc.SetPen(wx.Pen(bgCol))
+        dc.DrawRectangleRect(rect);
+
+    def OnMeasureItem(self, item):
+        """!Overridden from OwnerDrawnComboBox, should return the height
+            needed to display an item in the popup, or -1 for default"""
+        return 30
+
+    def OnMeasureItemWidth(self, item):
+        """!Overridden from OwnerDrawnComboBox.  Callback for item width, or
+            -1 for default/undetermined"""
+        return -1; # default - will be measured from text width  
+    
+    
+class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
+    """!List control for managing order and labels of vector maps in legend"""
+    def __init__(self, parent):
+        wx.ListCtrl.__init__(self, parent, id = wx.ID_ANY, 
+                style = wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.BORDER_SUNKEN|wx.LC_VRULES|wx.LC_HRULES)
+        CheckListCtrlMixin.__init__(self) 
+        ListCtrlAutoWidthMixin.__init__(self)
+        
+class Instruction:
+    """!Class which represents instruction file"""
+    def __init__(self, parent, objectsToDraw):
+        
+        self.parent = parent
+        self.objectsToDraw = objectsToDraw
+        #here are kept objects like mapinfo, rasterlegend, etc.
+        self.instruction = list()
+        
+    def __str__(self):
+        """!Returns text for instruction file"""
+        border = ''
+        if not self.FindInstructionByType('map'):
+            border = 'border n\n'
+        text = [str(each) for each in self.instruction]
+        return border + '\n'.join(text) + '\nend'
+    
+    def __getitem__(self, id):
+        for each in self.instruction:
+            if each.id == id:
+                return each
+        return None
+    
+    def __contains__(self, id):
+        """!Test if instruction is included"""
+        for each in self.instruction:
+            if each.id == id:
+                return True
+        return False
+        
+    def __delitem__(self, id):
+        """!Delete instruction"""
+        for each in self.instruction:
+            if each.id == id:
+                if each.type == 'map':
+                    #must remove raster, vector layers too
+                    vektor = self.FindInstructionByType('vector', list = True)
+                    vProperties = self.FindInstructionByType('vProperties', list = True)
+                    raster = self.FindInstructionByType('raster', list = True)
+                    for item in vektor + vProperties + raster:
+                        if item in self.instruction:
+                            self.instruction.remove(item)
+                            
+                self.instruction.remove(each)
+                if id in self.objectsToDraw:
+                    self.objectsToDraw.remove(id)
+                return
+            
+    def AddInstruction(self, instruction):
+        """!Add instruction"""
+        self.instruction.append(instruction)
+        if instruction.type not in ('page', 'raster', 'vector', 'vProperties', 'initMap'):
+            self.objectsToDraw.append(instruction.id)    
+                
+
+            
+    def FindInstructionByType(self, type, list = False):
+        """!Find instruction(s) with the given type"""
+        inst = []
+        for each in self.instruction:
+            if each.type == type:
+                inst.append(each)
+        if len(inst) == 1 and not list:
+            return inst[0]
+        return inst
+        
+    def Read(self, filename):
+        """!Reads instruction file and creates instruction objects"""
+        print 'Starts to read...'
+        # open file
+        try:
+            file = open(filename, 'r')
+        except IOError:
+            GError(message = _("Unable to open file\n{0}").format(filename))
+            return
+        # read lines
+        isBuffer = False
+        buffer = []
+        instruction = None
+        isRegionComment = False
+        for line in file:
+            line = line.strip()
+            if isBuffer:
+                buffer.append(line)
+                if line.startswith('end'):
+                    isBuffer = False
+                    self.SendToRead(instruction, buffer)
+                    buffer = []
+                continue
+
+            if line.startswith('#'):
+                if 'g.region' in line:
+                    instruction = 'gregion'
+                    self.SendToRead(instruction, line)
+                    isRegionComment = True
+                else:
+                    continue  
+            
+            if line.startswith('paper'):
+                instruction = 'paper'
+                isBuffer = True
+                buffer.append(line)
+                continue
+            
+            if line.startswith('border'):
+                if line == 'border n':
+                    self.SendToRead('border', [line])
+                    continue
+                elif line == 'border y':
+                    instruction = 'border'
+                    isBuffer = True
+                    buffer.append(line)
+                    continue
+            
+            if line.startswith('scale'):
+                self.SendToRead('scale', line)
+                continue
+            
+            if line.startswith('maploc'):
+                self.SendToRead(instruction = 'maploc', text = line, filename = filename)
+                continue
+                
+            if line.startswith('raster'):
+                self.SendToRead(instruction = 'raster', text = line)
+                continue
+            
+            if line.startswith('mapinfo'):
+                instruction = 'mapinfo'
+                isBuffer = True
+                buffer.append(line)
+                continue
+            
+        
+        # check at the end
+        if not isRegionComment:
+            map = self.FindInstructionByType('map')
+            if map:
+                map['scaleType'] = 2 # current region
+                if not map['rect']:
+                    map['rect'] = GetMapBounds(filename)
+                    if map['rect']:
+                        region = grass.region()
+                        units = UnitConversion(self.parent)
+                        realWidth = units.convert(value = abs(region['w'] - region['e']), fromUnit = 'meter', toUnit = 'inch')
+                        scale = map['rect'].Get()[2]/realWidth
+                        map['scale'] = scale
+                        
+                    
+            else:
+                rect = GetMapBounds(filename)
+                if rect:
+                    initMap = InitMap(wx.NewId())
+                    self.instruction.AddInstruction(initMap)
+                    initMap['rect'] = rect
+                    region = grass.region()
+                    units = UnitConversion(self.parent)
+                    realWidth = units.convert(value = abs(region['w'] - region['e']), fromUnit = 'meter', toUnit = 'inch')
+                    scale = rect.Get()[2]/realWidth 
+                    initMap['scale'] = scale 
+                
+        print 'end of reading'
+        
+        
+    def SendToRead(self, instruction, text, **kwargs):
+        #print 'send to read', instruction, text
+        psmapInstrDict = dict(  paper = ['page'],
+                                maploc = ['map'],
+                                scale = ['map'],
+                                border = ['map'],
+                                raster = ['raster'],
+                                mapinfo = ['mapinfo'],
+                                scalebar = ['scalebar'],
+                                text = ['text'],
+                                vpoints = ['vector', 'vProperties'],
+                                vlines = ['vector', 'vProperties'],
+                                vareas = ['vector', 'vProperties'],
+                                colortable = ['rasterLegend'],
+                                vlegend = ['vectorLegend'],
+                                # not a real instruction, just help in commentary
+                                gregion = ['map']
+                            )
+        
+        myInstrDict = dict( page = PageSetup,
+                            map = MapFrame,
+                            raster = Raster,
+                            mapinfo = Mapinfo,
+                            scalebar = Scalebar,
+                            text = Text,
+                            rasterLegend = RasterLegend,
+                            vectorLegend = VectorLegend,
+                            vector = Vector,
+                            vProperties = VProperties
+                        )
+         
+        myInstruction = psmapInstrDict[instruction]
+        
+        for i in myInstruction:
+            instr = self.FindInstructionByType(i)
+            if i in ('text', 'vProperties') or not instr:
+                id = wx.NewId() #!vProperties expect subtype
+                newInstr = myInstrDict[i](id)
+                ok = newInstr.Read(instruction, text, **kwargs)
+                if ok:
+                    self.AddInstruction(newInstr)
+                else:
+                    GMessage(_("Failed to read"))
+                    
+            else:
+                ok = instr.Read(instruction, text, **kwargs)
+
+                if not ok:
+                    GMessage(_("Failed to read"))
+            
+              
+                            
+        
+class InstructionObject:
+    """!Abtract class representing single instruction"""
+    def __init__(self, id): 
+        self.id = id
+        
+        # default values
+        self.defaultInstruction = dict()
+        # current values
+        self.instruction = self.defaultInstruction    
+    
+    def __str__(self):
+        """!Returns particular part of text instruction"""
+        return ''
+        
+    def __getitem__(self, key):
+        for each in self.instruction.keys():
+            if each == key:
+                return self.instruction[key]
+        return None
+               
+    def __setitem__(self, key, value):
+        self.instruction[key] = value
+    
+    def GetInstruction(self):
+        """!Get current values"""
+        return self.instruction
+    
+    def SetInstruction(self, instruction):
+        """!Set default values"""
+        self.instruction = instruction
+        
+    def Read(self, instruction, text, **kwargs):
+        """!Read instruction and save them"""
+        pass
+        
+class InitMap(InstructionObject):
+    """!Class representing virtual map"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'initMap'
+        
+        # default values
+        self.defaultInstruction = dict(rect = None, scale =  None)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+            
+    
+class MapFrame(InstructionObject):
+    """!Class representing map (instructions maploc, scale, border)"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'map'
+        # default values
+        self.defaultInstruction = dict( map = None, mapType = None, region = None,
+                                        rect = wx.Rect2D(), scaleType = 0, scale = None, center = None,
+                                        border = 'y', width = 1, color = '0:0:0') 
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = ''
+        comment = ''
+        #region settings
+        if self.instruction['scaleType'] == 0: #match map
+            map = self.instruction['map']
+            mapType = 'rast' if self.instruction['mapType'] == 'raster' else 'vect'
+            comment = "# set region: g.region {0}={1}\n".format(mapType, map)
+        elif self.instruction['scaleType'] == 1:# saved region
+            region = self.instruction['region']
+            comment = "# set region: g.region region={0}\n".format(region)                
+        elif self.instruction['scaleType'] == 3: #fixed scale
+            region = grass.region()
+            comment = "# set region: g.region n={n} s={s} e={e} w={w}\n".format(**region)
+        instr += comment
+        instr += '\n'
+        # maploc
+        maplocInstruction = "maploc {rect.x} {rect.y}".format(**self.instruction)
+        if self.instruction['scaleType'] != 3:
+            maplocInstruction += "  {rect.width} {rect.height}".format(**self.instruction)
+        instr += maplocInstruction
+        instr += '\n'
+        
+        # scale
+        if self.instruction['scaleType'] == 3: #fixed scale
+            scaleInstruction = "scale 1:{0:.0f}".format(1/self.instruction['scale'])
+            instr += scaleInstruction
+            instr += '\n'
+        # border
+        borderInstruction = ''
+        if self.instruction['border'] == 'n':
+            borderInstruction = "border n"
+        else:
+            borderInstruction = "border y\n"
+            borderInstruction += "    width {width}\n    color {color}\n".format(**self.instruction)
+            borderInstruction += "end"
+        instr += borderInstruction
+        instr += '\n'
+
+        return instr  
+     
+    def Read(self, instruction, text, **kwargs):
+        """!Read instruction and save information"""
+        
+        instr = {}
+        if instruction == 'gregion':
+            start = text.find('g.region')
+            cmd = text[start:].split()
+            if len(cmd) == 2:
+                if cmd[1].split('=')[0] == 'rast':
+                    instr['scaleType'] = 0
+                    instr['mapType'] = 'raster'   
+                    instr['map'] = cmd[1].split('=')[1]  
+                elif cmd[1].split('=')[0] == 'vect':
+                    instr['scaleType'] = 0
+                    instr['mapType'] = 'vector' 
+                    instr['map'] = cmd[1].split('=')[1]  
+                elif cmd[1].split('=')[0] == 'region':
+                    instr['scaleType'] = 1  
+                    instr['region'] = cmd[1].split('=')[1]
+                    
+            elif len(text[start:].split()[1:]) == 4:
+                instr['scaleType'] = 3  
+                region = grass.parse_key_val(text[start:].split(' ',1)[1], val_type = float, vsep = ' ')
+                instr['center'] = (region['n'] + region['s']) / 2, (region['w'] + region['e']) / 2
+
+            cmd = CmdToTuple(cmd)
+            RunCommand(cmd[0], **cmd[1])
+
+            
+        elif instruction == 'border':
+            for line in text:
+                try:
+                    if line == 'border n':
+                        instr['border'] = 'n'
+                        break
+                    elif line == 'border y':
+                        instr['border'] = 'y'
+                    elif line.startswith('width'):
+                        instr['width'] = line.split()[1]
+                    elif line.startswith('color'):
+                        instr['color'] = line.split()[1]
+                except IndexError:
+                    GError(_("Failed to read instruction {0}").format(instruction))
+                    return False
+                    
+        elif instruction == 'scale':
+            try:
+                scale = text.strip('scale ').split(':')[1]
+                instr['scale'] = 1/float(scale)
+            except (ValueError, IndexError):
+                GError(_("Failed to read instruction {0}.\nUse 1:25000 notation.").format(instruction))
+                return False
+        
+        elif instruction == 'maploc':
+            #TODO: run psmap -b always?
+            instr['rect'] = GetMapBounds(kwargs['filename'])
+            
+
+        self.instruction.update(instr)   
+        return True 
+    
+class PageSetup(InstructionObject):
+    """!Class representing page instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'page'
+        # default values
+        self.defaultInstruction = dict(Units = 'inch', Format = 'a4', Orientation = 'Portrait',
+                                        Width = 8.268, Height = 11.693, Left = 0.5, Right = 0.5, Top = 1, Bottom = 1)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        if self.instruction['Format'] == 'custom':
+            instr = "paper\n    width {Width}\n    height {Height}\n".format(**self.instruction)
+        else:
+            instr = "paper {Format}\n".format(**self.instruction)
+        instr += "    left {Left}\n    right {Right}\n"    \
+                            "    bottom {Bottom}\n    top {Top}\nend".format(**self.instruction)
+
+        return instr
+    
+    def Read(self, instruction, text):
+        """!Read instruction and save information"""
+        instr = {}
+        self.cats = ['Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
+        self.subInstr = dict(zip(['width', 'height', 'left', 'right', 'top', 'bottom'], self.cats))
+
+        if instruction == 'paper': # just for sure
+            for line in text:
+                if line.startswith('paper'): 
+                    if len(line.split()) > 1:
+                        format = line.split()[1]
+                        availableFormats = self._toDict(grass.read_command('ps.map', flags = 'p'))
+                        # e.g. paper a3 
+                        try:
+                            instr['Format'] = format
+                            for key, value in availableFormats[format].iteritems():
+                                instr[key] = float(value)
+                            break
+                        except KeyError:
+                            GError(_("Failed to read instruction '{0}'.\nUnknown format {1}").format(instruction, format))
+                            return False
+                        
+                    else:
+                        # paper
+                        # width ...
+                        instr['Format'] = 'custom'
+                # read subinstructions
+                elif instr['Format'] == 'custom' and not line.startswith('end'):
+                    text = line.split()
+                    try:
+                        instr[self.subInstr[text[0]]] = float(text[1])
+                    except  (IndexError, KeyError):
+                        GError(_("Failed to read instruction '{0}'.").format(instruction))
+                        return False
+
+            self.instruction.update(instr)
+        return True  
+    
+    def _toDict(self, paperStr):    
+        sizeDict = dict()
+#     cats = self.subInstr[ 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
+        for line in paperStr.strip().split('\n'):
+            d = dict(zip(self.cats, line.split()[1:]))
+            sizeDict[line.split()[0]] = d
+       
+        return sizeDict    
+    
+class Mapinfo(InstructionObject):
+    """!Class representing mapinfo instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'mapinfo'
+        # default values
+        self.defaultInstruction = dict( unit = 'inch', where = (0, 0),
+                                            font = 'Helvetica', fontsize = 10, color = 'black', background = 'none', 
+                                            #font = 'Sans', fontsize = 10, color = '0:0:0', background = 'none', 
+                                            border = 'none', rect = None)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = "mapinfo\n"
+        instr += "    where {where[0]} {where[1]}\n".format(**self.instruction)
+        instr += "    font {font}\n    fontsize {fontsize}\n    color {color}\n".format(**self.instruction)            
+        instr += "    background {background}\n    border {border}\n".format(**self.instruction)  
+        instr += "end"
+        return instr
+    
+    def Read(self, instruction, text):
+        """!Read instruction and save information"""
+        instr = {}
+        try:
+            for line in text:
+                sub = line.split(' ',1)
+                if sub[0] == 'font':
+                    instr['font'] = sub[1]
+                elif sub[0] == 'fontsize':
+                    instr['fontsize'] = int(sub[1])
+                elif sub[0] == 'color':
+                    instr['color'] = sub[1]
+                elif sub[0] == 'background':
+                    instr['background'] = sub[1]
+                elif sub[0] == 'border':
+                    instr['border'] = sub[1]
+                elif sub[0] == 'where':
+                    instr['where'] = tuple(sub[2].split())
+        except (ValueError, IndexError):
+            GError(_("Failed to read instruction {0}").format(instruction))
+        
+        self.instruction.update(instr)
+        return True
+    
+class Text(InstructionObject):
+    """!Class representing text instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'text'
+        # default values
+        self.defaultInstruction = dict(text = "", font = "Helvetica", fontsize = 10, color = 'black', background = 'none',
+                                        hcolor = 'none', hwidth = 1, border = 'none', width = '1', XY = True,
+                                        where = (0,0), unit = 'inch', rotate = None, 
+                                        ref = "center center", xoffset = 0, yoffset = 0, east = None, north = None)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        text = self.instruction['text'].replace('\n','\\n')
+        instr = "text {east} {north}".format(**self.instruction)
+        instr += " {0}\n".format(text)
+        instr += "    font {font}\n    fontsize {fontsize}\n    color {color}\n".format(**self.instruction)
+        instr += "    hcolor {hcolor}\n".format(**self.instruction)
+        if self.instruction['hcolor'] != 'none':
+            instr += "    hwidth {hwidth}\n".format(**self.instruction)
+        instr += "    border {border}\n".format(**self.instruction)
+        if self.instruction['border'] != 'none':
+            instr += "    width {width}\n".format(**self.instruction)
+        instr += "    background {background}\n".format(**self.instruction)
+        if self.instruction["ref"] != '0':
+            instr += "    ref {ref}\n".format(**self.instruction)
+        if self.instruction["rotate"]:
+            instr += "    rotate {rotate}\n".format(**self.instruction)
+        if float(self.instruction["xoffset"]) or float(self.instruction["yoffset"]):
+            instr += "    xoffset {xoffset}\n    yoffset {yoffset}\n".format(**self.instruction)
+        instr += "end"
+        return instr
+    
+    
+class Scalebar(InstructionObject):
+    """!Class representing scalebar instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'scalebar'
+        # default values
+        self.defaultInstruction = dict( unit = 'inch', where = (0,0),
+                                            unitsLength = 'auto', unitsHeight = 'inch',
+                                            length = None, height = 0.1, rect = None,
+                                            fontsize = 10, background = 'y',
+                                            scalebar = 'f', segment = 4, numbers = 1)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = "scalebar {scalebar}\n".format(**self.instruction)
+        instr += "    where {where[0]} {where[1]}\n".format(**self.instruction)
+        instr += "    length {length}\n    units {unitsLength}\n".format(**self.instruction)
+        instr += "    height {height}\n".format(**self.instruction)
+        instr += "    segment {segment}\n    numbers {numbers}\n".format(**self.instruction)
+        instr += "    fontsize {fontsize}\n    background {background}\n".format(**self.instruction)
+        instr += "end"
+        return instr
+        
+class RasterLegend(InstructionObject):
+    """!Class representing colortable instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'rasterLegend'
+        # default values
+        self.defaultInstruction = dict(rLegend = False, unit = 'inch', rasterDefault = True, raster = None,
+                                                discrete = None, type = None,
+                                                where = (0, 0), defaultSize = True,
+                                                width = 0, height = 0, cols = 1, font = "Serif", fontsize = 10,
+                                                #color = '0:0:0', tickbar = False, range = False, min = 0, max = 0,
+                                                color = 'black', tickbar = False, range = False, min = 0, max = 0,
+                                                nodata = False)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = "colortable y\n"
+        instr += "    raster {raster}\n".format(**self.instruction)
+        instr += "    where {where[0]} {where[1]}\n".format(**self.instruction)
+        if not self.instruction['defaultSize']:
+            instr += "    width {width}\n".format(**self.instruction)
+        instr += "    discrete {discrete}\n".format(**self.instruction)
+        if self.instruction['discrete'] == 'n':
+            if not self.instruction['defaultSize']:
+                instr += "    height {height}\n".format(**self.instruction)
+            instr += "    tickbar {tickbar}\n".format(**self.instruction)
+            if self.instruction['range']:
+                instr += "    range {min} {max}\n".format(**self.instruction)
+        else:
+            instr += "    cols {cols}\n".format(**self.instruction)
+            instr += "    nodata {nodata}\n".format(**self.instruction)
+        instr += "    font {font}\n    fontsize {fontsize}\n    color {color}\n"\
+                                .format(**self.instruction)
+        instr += "end"
+        return instr    
+  
+
+class VectorLegend(InstructionObject):
+    """!Class representing colortable instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'vectorLegend'
+        # default values
+        self.defaultInstruction = dict(vLegend = False, unit = 'inch', where = (0, 0),
+                                                defaultSize = True, width = 0.4, cols = 1, span = None, font = "Serif", fontsize = 10,
+                                                border = 'none')
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = "vlegend\n"
+        instr += "    where {where[0]} {where[1]}\n".format(**self.instruction)
+        instr += "    font {font}\n    fontsize {fontsize}\n".format(**self.instruction)
+        instr += "    width {width}\n    cols {cols}\n".format(**self.instruction)
+        if self.instruction['span']:
+            instr += "    span {span}\n".format(**self.instruction)
+        instr += "    border {border}\n".format(**self.instruction)  
+        instr += "end"  
+        return instr
+          
+class Raster(InstructionObject):
+    """!Class representing raster instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'raster'
+        # default values
+        self.defaultInstruction = dict(isRaster = False, raster = None)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = "raster {raster}".format(**self.instruction)
+        return instr
+    
+    def Read(self, instruction, text):
+        """!Read instruction and save information"""
+        instr = {}
+        instr['isRaster'] = True
+        try:
+            map = text.split()[1]
+        except IndexError:
+            GError(_("Failed to read instruction {0}").format(instruction))
+            return False
+        try:
+            info = grass.find_file(map, element = 'cell')
+        except grass.ScriptError, e:
+            GError(message = e.value)
+            return False
+        instr['raster'] = info['fullname']
+
+        
+        self.instruction.update(instr)
+        return True
+    
+class Vector(InstructionObject):
+    """!Class keeps vector layers"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'vector'
+        # default values
+        self.defaultInstruction = dict(list = None)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+    def __str__(self):
+        return ''
+        
+class VProperties(InstructionObject):
+    """!Class represents instructions vareas, vlines, vpoints"""
+    def __init__(self, id, subType):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'vProperties'
+        self.subType = subType
+        # default values
+        if self.subType == 'points':
+            dd = dict(subType  = 'points', name = None, type = 'point or centroid', connection = False, layer = '1', masked = 'n', color = '0:0:0', width = 1,
+                        fcolor = '255:0:0', rgbcolumn = None, symbol = os.path.join('basic', 'x'), eps = None,
+                        size = 5, sizecolumn = None, scale = None,
+                        rotation = False, rotate = 0, rotatecolumn = None, label = None, lpos = None)
+        elif self.subType == 'lines':
+            dd = dict(subType = 'lines', name = None, type = 'line or boundary', connection = False, layer = '1', masked = 'n', color = '0:0:0', hwidth = 1,
+                        hcolor = 'none', rgbcolumn = None,
+                        width = 1, cwidth = None,
+                        style = 'solid', linecap = 'butt', label = None, lpos = None)
+        else: # areas
+            dd = dict(subType = 'areas', name = None, type = 'point or centroid', connection = False, layer = '1', masked = 'n', color = '0:0:0', width = 1,
+                        fcolor = 'none', rgbcolumn = None,
+                        pat = None, pwidth = 1, scale = 1, label = None, lpos = None)
+        self.defaultInstruction = dd
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        dic = self.instruction
+        vInstruction = "v{subType} {name}\n".format(**dic)
+        #data selection
+        if self.subType in ('points', 'lines'):
+           vInstruction += "    type {type}\n".format(**dic) 
+        if dic['connection']:
+            vInstruction += "    layer {layer}\n".format(**dic)
+            if dic.has_key('cats'):
+                vInstruction += "    cats {cats}\n".format(**dic)
+            elif dic.has_key('where'):
+                    vInstruction += "    where {where}\n".format(**dic)
+        vInstruction += "    masked {masked}\n".format(**dic)
+        #colors
+        vInstruction += "    color {color}\n".format(**dic)
+        if self.subType in ('points', 'areas'):
+            if dic['color'] != 'none':
+                vInstruction += "    width {width}\n".format(**dic)
+            if dic['rgbcolumn']:
+                vInstruction += "    rgbcolumn {rgbcolumn}\n".format(**dic)
+            vInstruction += "    fcolor {fcolor}\n".format(**dic)
+        else:
+            if dic['rgbcolumn']:
+                vInstruction += "    rgbcolumn {rgbcolumn}\n".format(**dic)
+            elif dic['hcolor'] != 'none':
+                vInstruction += "    hwidth {hwidth}\n".format(**dic)
+                vInstruction += "    hcolor {hcolor}\n".format(**dic)
+        
+        # size and style
+        if self.subType == 'points':
+            if dic['symbol']:
+                vInstruction += "    symbol {symbol}\n".format(**dic)
+            else: #eps
+                vInstruction += "    eps {eps}\n".format(**dic)
+            if dic['size']:
+                vInstruction += "    size {size}\n".format(**dic)            
+            else: # sizecolumn
+                vInstruction += "    sizecolumn {sizecolumn}\n".format(**dic)
+                vInstruction += "    scale {scale}\n".format(**dic)
+            if dic['rotation']:
+                if dic['rotate'] is not None:
+                    vInstruction += "    rotate {rotate}\n".format(**dic)
+                else:
+                    vInstruction += "    rotatecolumn {rotatecolumn}\n".format(**dic)
+                    
+        if self.subType == 'areas':
+            if dic['pat'] is not None:
+                vInstruction += "    pat {pat}\n".format(**dic)
+                vInstruction += "    pwidth {pwidth}\n".format(**dic)
+                vInstruction += "    scale {scale}\n".format(**dic)
+                
+        if self.subType == 'lines':
+            if dic['width'] is not None:
+                vInstruction += "    width {width}\n".format(**dic)
+            else:
+                vInstruction += "    cwidth {cwidth}\n".format(**dic)
+            vInstruction += "    style {style}\n".format(**dic)
+            vInstruction += "    linecap {linecap}\n".format(**dic)
+        #position and label in vlegend
+        vInstruction += "    label {label}\n    lpos {lpos}\n".format(**dic)
+        
+        vInstruction += "end"
+        return vInstruction
+    
+class PsmapDialog(wx.Dialog):
+    def __init__(self, parent, id,  title, settings, apply = True):
+        wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, 
+                            title = title, size = wx.DefaultSize, style = wx.DEFAULT_DIALOG_STYLE)
+        self.apply = apply
+        self.id = id
+        self.parent = parent
+        self.instruction = settings
+
+        self.unitConv = UnitConversion(self)
+        self.spinCtrlSize = (50, -1)
+
+        
+    def AddUnits(self, parent, dialogDict):
+        parent.units = dict()
+        parent.units['unitsLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Units:"))
+        choices = self.unitConv.getPageUnits()
+        parent.units['unitsCtrl'] = wx.Choice(parent, id = wx.ID_ANY, choices = choices)  
+        parent.units['unitsCtrl'].SetStringSelection(dialogDict['unit'])
+          
+    def AddPosition(self, parent, dialogDict):
+        parent.position = dict()
+        parent.position['comment'] = wx.StaticText(parent, id = wx.ID_ANY,\
+                    label = _("Position of the top left corner\nfrom the top left edge of the paper"))
+        parent.position['xLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("X:"))
+        parent.position['yLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Y:"))
+        parent.position['xCtrl'] = wx.TextCtrl(parent, id = wx.ID_ANY, value = str(dialogDict['where'][0]), validator = TCValidator(flag = 'DIGIT_ONLY'))
+        parent.position['yCtrl'] = wx.TextCtrl(parent, id = wx.ID_ANY, value = str(dialogDict['where'][1]), validator = TCValidator(flag = 'DIGIT_ONLY'))
+        if dialogDict.has_key('unit'):
+            x = self.unitConv.convert(value = dialogDict['where'][0], fromUnit = 'inch', toUnit = dialogDict['unit'])
+            y = self.unitConv.convert(value = dialogDict['where'][1], fromUnit = 'inch', toUnit = dialogDict['unit'])
+            parent.position['xCtrl'].SetValue("{0:5.3f}".format(x))
+            parent.position['yCtrl'].SetValue("{0:5.3f}".format(y))
+        
+    def AddFont(self, parent, dialogDict, color = True):
+        parent.font = dict()
+##        parent.font['fontLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose font:"))
+##        parent.font['fontCtrl'] = wx.FontPickerCtrl(parent, id = wx.ID_ANY)
+##        
+##        parent.font['fontCtrl'].SetSelectedFont(
+##                        wx.FontFromNativeInfoString(dialogDict['font'] + " " + str(dialogDict['fontsize'])))
+##        parent.font['fontCtrl'].SetMaxPointSize(50)
+##        
+##        if color:
+##            parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose color:"))
+##            parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY, style=wx.FNTP_FONTDESC_AS_LABEL)
+##            parent.font['colorCtrl'].SetColour(dialogDict['color'])
+           
+##        parent.font['colorCtrl'].SetColour(convertRGB(dialogDict['color'])) 
+           
+        parent.font['fontLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Font:"))
+        parent.font['fontSizeLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Font size:"))
+        fontChoices = [ 'Times-Roman', 'Times-Italic', 'Times-Bold', 'Times-BoldItalic', 'Helvetica',\
+                        'Helvetica-Oblique', 'Helvetica-Bold', 'Helvetica-BoldOblique', 'Courier',\
+                        'Courier-Oblique', 'Courier-Bold', 'Courier-BoldOblique'] 
+        parent.font['fontCtrl'] = wx.Choice(parent, id = wx.ID_ANY, choices = fontChoices)
+        parent.font['fontCtrl'].SetStringSelection(dialogDict['font'])
+        parent.font['fontSizeCtrl']= wx.SpinCtrl(parent, id = wx.ID_ANY, min = 4, max = 50, initial = 10)
+        parent.font['fontSizeCtrl'].SetValue(dialogDict['fontsize'])
+         
+        if color:
+            parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose color:"))
+            parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY, style=wx.FNTP_FONTDESC_AS_LABEL)
+            parent.font['colorCtrl'].SetColour(dialogDict['color'])
+##            parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Color:"))
+##            colorChoices = [  'aqua', 'black', 'blue', 'brown', 'cyan', 'gray', 'green', 'indigo', 'magenta',\
+##                                'orange', 'purple', 'red', 'violet', 'white', 'yellow']
+##            parent.colorCtrl = wx.Choice(parent, id = wx.ID_ANY, choices = colorChoices)
+##            parent.colorCtrl.SetStringSelection(parent.rLegendDict['color'])
+##            parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY)
+##            parent.font['colorCtrl'].SetColour(dialogDict['color'])   
+    def OnApply(self, event):
+        ok = self.update()
+        if ok:
+            self.parent.DialogDataChanged(id = self.id)
+            return True 
+        else:
+            return False
+        
+    def OnOK(self, event):
+        ok = self.OnApply(event)
+        if ok:
+            event.Skip()
+        
+    def OnCancel(self, event):
+        event.Skip()
+        
+        
+    def _layout(self, panel):
+        #buttons
+        btnCancel = wx.Button(self, wx.ID_CANCEL)
+        btnOK = wx.Button(self, wx.ID_OK)
+        btnOK.SetDefault()
+        if self.apply:
+            btnApply = wx.Button(self, wx.ID_APPLY)
+        
+
+        # bindigs
+        btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
+        btnOK.SetToolTipString(_("Close dialog and apply changes"))
+        btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
+        btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
+        if self.apply:
+            btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
+            btnApply.SetToolTipString(_("Apply changes"))
+        
+        # sizers
+        btnSizer = wx.StdDialogButtonSizer()
+        btnSizer.AddButton(btnCancel)
+        if self.apply:
+            btnSizer.AddButton(btnApply)
+        btnSizer.AddButton(btnOK)
+        btnSizer.Realize()
+        
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        mainSizer.Add(item = panel, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
+        
+        self.Bind(wx.EVT_CLOSE, self.OnCancel)
+        
+        self.SetSizer(mainSizer)
+        mainSizer.Layout()
+        mainSizer.Fit(self) 
+            
+class PageSetupDialog(PsmapDialog):
+    def __init__(self, parent, id, settings):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "Page setup",  settings = settings)
+        
+        self.cat = ['Units', 'Format', 'Orientation', 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
+        paperString = RunCommand('ps.map', flags = 'p', read = True)
+        self.paperTable = self._toList(paperString) 
+        self.unitsList = self.unitConv.getPageUnits()
+        pageId = id
+        self.pageSetupDict = settings[id].GetInstruction()
+
+        self._layout()
+        
+        if self.pageSetupDict:
+            for item in self.cat[:3]:
+                self.getCtrl(item).SetSelection(self.getCtrl(item).FindString(self.pageSetupDict[item]))
+            for item in self.cat[3:]:
+                self.getCtrl(item).SetValue("{0:4.3f}".format(self.pageSetupDict[item]))
+
+       
+        if self.getCtrl('Format').GetString(self.getCtrl('Format').GetSelection()) != 'custom':
+            self.getCtrl('Width').Disable()
+            self.getCtrl('Height').Disable()
+        else:
+            self.getCtrl('Orientation').Disable()
+        # events
+        self.getCtrl('Units').Bind(wx.EVT_CHOICE, self.OnChoice)
+        self.getCtrl('Format').Bind(wx.EVT_CHOICE, self.OnChoice)
+        self.getCtrl('Orientation').Bind(wx.EVT_CHOICE, self.OnChoice)
+        self.btnOk.Bind(wx.EVT_BUTTON, self.OnOK)
+
+    
+    def update(self):
+        self.pageSetupDict['Units'] = self.getCtrl('Units').GetString(self.getCtrl('Units').GetSelection())
+        self.pageSetupDict['Format'] = self.paperTable[self.getCtrl('Format').GetSelection()]['Format']
+        self.pageSetupDict['Orientation'] = self.getCtrl('Orientation').GetString(self.getCtrl('Orientation').GetSelection())
+        for item in self.cat[3:]:
+            self.pageSetupDict[item] = self.unitConv.convert(value = float(self.getCtrl(item).GetValue()),
+                                        fromUnit = self.pageSetupDict['Units'], toUnit = 'inch')
+            
+
+            
+    def OnOK(self, event):
+        try:
+            self.update()
+        except ValueError:
+                wx.MessageBox(message = _("Literal is not allowed!"), caption = _('Invalid input'),
+                                    style = wx.OK|wx.ICON_ERROR)
+        else:
+            event.Skip()
+        
+    def _layout(self):
+        size = (110,-1)
+        #sizers
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        pageBox = wx.StaticBox(self, id = wx.ID_ANY, label ="  Page size ")
+        pageSizer = wx.StaticBoxSizer(pageBox, wx.VERTICAL)
+        marginBox = wx.StaticBox(self, id = wx.ID_ANY, label = " Margins ")
+        marginSizer = wx.StaticBoxSizer(marginBox, wx.VERTICAL)
+        horSizer = wx.BoxSizer(wx.HORIZONTAL) 
+        #staticText + choice
+        choices = [self.unitsList, [item['Format'] for item in self.paperTable], ['Portrait', 'Landscape']]
+        propor = [0,1,1]
+        border = [5,3,3]
+        self.hBoxDict={}
+        for i, item in enumerate(self.cat[:3]):
+            hBox = wx.BoxSizer(wx.HORIZONTAL)
+            stText = wx.StaticText(self, id = wx.ID_ANY, label = item + ':')
+            choice = wx.Choice(self, id = wx.ID_ANY, choices = choices[i], size = size)
+            hBox.Add(stText, proportion = propor[i], flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = border[i])
+            hBox.Add(choice, proportion = 0, flag = wx.ALL, border = border[i])
+            if item == 'Units':
+                hBox.Add(size,1) 
+            self.hBoxDict[item] = hBox    
+
+        #staticText + TextCtrl
+        for item in self.cat[3:]:
+            hBox = wx.BoxSizer(wx.HORIZONTAL)
+            label = wx.StaticText(self, id = wx.ID_ANY, label = item + ':')
+            textctrl = wx.TextCtrl(self, id = wx.ID_ANY, size = size, value = '')
+            hBox.Add(label, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 3)
+            hBox.Add(textctrl, proportion = 0, flag = wx.ALIGN_CENTRE|wx.ALL, border = 3)
+            self.hBoxDict[item] = hBox
+         
+        sizer = list([mainSizer] + [pageSizer]*4 + [marginSizer]*4)
+        for i, item in enumerate(self.cat):
+                sizer[i].Add(self.hBoxDict[item], 0, wx.GROW|wx.RIGHT|wx.LEFT,5)
+        # OK button
+        btnSizer = wx.StdDialogButtonSizer()
+        self.btnOk = wx.Button(self, wx.ID_OK)
+        self.btnOk.SetDefault()
+        btnSizer.AddButton(self.btnOk)
+        btn = wx.Button(self, wx.ID_CANCEL)
+        btnSizer.AddButton(btn)
+        btnSizer.Realize()
+    
+    
+        horSizer.Add(pageSizer, proportion = 0, flag = wx.LEFT|wx.RIGHT|wx.BOTTOM, border = 10)
+        horSizer.Add(marginSizer, proportion = 0, flag = wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, border = 10)
+        mainSizer.Add(horSizer, proportion = 0, border = 10)  
+        mainSizer.Add(btnSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL,  border = 10)      
+        self.SetSizer(mainSizer)
+        mainSizer.Fit(self)
+    
+    def OnChoice(self, event):
+        currPaper = self.paperTable[self.getCtrl('Format').GetSelection()]
+        currUnit = self.getCtrl('Units').GetString(self.getCtrl('Units').GetSelection())
+        currOrient = self.getCtrl('Orientation').GetString(self.getCtrl('Orientation').GetSelection())
+        newSize = dict()
+        for item in self.cat[3:]:
+            newSize[item] = self.unitConv.convert(float(currPaper[item]), fromUnit = 'inch', toUnit = currUnit)
+
+        enable = True
+        if currPaper['Format'] != 'custom':
+            if currOrient == 'Landscape':
+                newSize['Width'], newSize['Height'] = newSize['Height'], newSize['Width']
+            for item in self.cat[3:]:
+                self.getCtrl(item).ChangeValue("{0:4.3f}".format(newSize[item]))
+            enable = False
+        self.getCtrl('Width').Enable(enable)
+        self.getCtrl('Height').Enable(enable)
+        self.getCtrl('Orientation').Enable(not enable)
+
+
+    def getCtrl(self, item):
+         return self.hBoxDict[item].GetItem(1).GetWindow()
+        
+    def _toList(self, paperStr):
+        
+        sizeList = list()
+        for line in paperStr.strip().split('\n'):
+            d = dict(zip([self.cat[1]]+ self.cat[3:],line.split()))
+            sizeList.append(d)
+        d = {}.fromkeys([self.cat[1]]+ self.cat[3:], 100)
+        d.update(Format = 'custom')
+        sizeList.append(d)
+        return sizeList
+    
+class MapDialog(PsmapDialog):
+    """!Dialog for map frame settings and optionally  raster and vector map selection"""
+    def __init__(self, parent, id, settings,  rect = None, notebook = False):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "", settings = settings)
+ 
+        self.instruction = settings
+        self.isNotebook = notebook
+        #notebook
+        if self.isNotebook:
+            notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
+            self.mPanel = MapFramePanel(parent = notebook, id = self.id[0], settings = self.instruction, 
+                                        rect = rect, notebook = True)
+            self.id[0] = self.mPanel.getId()
+            self.rPanel = RasterPanel(parent = notebook, id = self.id[1], settings = self.instruction, 
+                                        notebook = True)
+            self.id[1] = self.rPanel.getId()
+            self.vPanel = VectorPanel(parent = notebook, id = self.id[2], settings = self.instruction,
+                                        notebook = True)
+            self.id[2] = self.vPanel.getId()
+            self._layout(notebook)
+            self.SetTitle(_("Map settings"))
+        else:
+            self.mPanel = MapFramePanel(parent = self, id = self.id[0], settings = self.instruction, 
+                                        rect = rect, notebook = False)
+            self.id[0] = self.mPanel.getId()
+            self._layout(self.mPanel)
+            self.SetTitle(_("Map frame settings"))
+        
+        
+    def OnApply(self, event):
+        """!Apply changes"""
+        if self.isNotebook:
+            okV = self.vPanel.update()
+            okR = self.rPanel.update()
+            if okV and self.id[2] in self.instruction:
+                self.parent.DialogDataChanged(id = self.id[2])
+            if okR and self.id[1] in self.instruction:
+                self.parent.DialogDataChanged(id = self.id[1])
+            if not okR or not okV:
+                return False
+
+        ok = self.mPanel.update()
+        if ok:
+            self.parent.DialogDataChanged(id = self.id[0])
+            return True 
+        
+        return False
+
+class MapFramePanel(wx.Panel):
+    """!wx.Panel with map (scale, region, border) settings"""
+    def __init__(self, parent, id, settings, rect, notebook = True):
+        wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
+
+        self.id = id
+        self.instruction = settings
+        
+        if notebook:
+            self.book = parent
+            self.book.AddPage(page = self, text = _("Map frame"))
+            self.mapDialog = self.book.GetParent()
+        else:
+            self.mapDialog = parent
+            
+        if self.id is not None:
+            self.mapFrameDict = self.instruction[self.id].GetInstruction() 
+        else:
+            self.id = wx.NewId()
+            mapFrame = MapFrame(self.id)
+            self.mapFrameDict = mapFrame.GetInstruction()
+            self.mapFrameDict['rect'] = rect
+
+            
+        self._layout()
+
+        self.scale = [None]*4
+        self.center = [None]*4
+        
+        
+        
+        self.selectedMap = self.mapFrameDict['map']
+        self.selectedRegion = self.mapFrameDict['region']
+        self.scaleType = self.mapFrameDict['scaleType']
+        self.mapType = self.mapFrameDict['mapType']
+        self.scaleChoice.SetSelection(self.mapFrameDict['scaleType'])
+        if self.mapFrameDict['scaleType'] == 0 and self.mapFrameDict['map']:
+            
+            self.select.SetValue(self.mapFrameDict['map'])
+            if self.mapFrameDict['mapType'] == 'raster':
+                self.rasterTypeRadio.SetValue(True)
+                self.vectorTypeRadio.SetValue(False)
+            else:
+                self.rasterTypeRadio.SetValue(False)
+                self.vectorTypeRadio.SetValue(True)
+        elif self.mapFrameDict['scaleType'] == 1 and self.mapFrameDict['region']:
+            self.select.SetValue(self.mapFrameDict['region'])
+        
+        
+        self.OnMap(None)
+        self.scale[self.mapFrameDict['scaleType']] = self.mapFrameDict['scale']
+        self.center[self.mapFrameDict['scaleType']] = self.mapFrameDict['center']
+        self.OnScaleChoice(None)
+        self.OnElementType(None)
+        self.OnBorder(None)
+        
+        
+        
+    def _layout(self):
+        """!Do layout"""
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        box   = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " {0} ".format(_("Map frame")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+
+
+        #scale options
+        frameText = wx.StaticText(self, id = wx.ID_ANY, label = _("Map frame options:"))
+        scaleChoices = [_("fit frame to match selected map"),
+                        _("fit frame to match saved region"),
+                        _("fit frame to match current computational region"),
+                        _("fixed scale and map center")]
+        self.scaleChoice = wx.Choice(self, id = wx.ID_ANY, choices = scaleChoices)
+        
+        
+        gridBagSizer.Add(frameText, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.scaleChoice, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+        #map and region selection
+        self.staticBox = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " {0} ".format(_("Map selection")))        
+        sizerM = wx.StaticBoxSizer(self.staticBox, wx.HORIZONTAL)
+        self.mapSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+
+        self.rasterTypeRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " {0} ".format(_("raster")), style = wx.RB_GROUP)
+        self.vectorTypeRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " {0} ".format(_("vector")))
+        
+        self.mapOrRegionText = [_("Map:"), _("Region:")] 
+        dc = wx.PaintDC(self)# determine size of labels
+        width = max(dc.GetTextExtent(self.mapOrRegionText[0])[0], dc.GetTextExtent(self.mapOrRegionText[1])[0])
+        self.mapText = wx.StaticText(self, id = wx.ID_ANY, label = self.mapOrRegionText[0], size = (width, -1))
+        self.select = Select(self, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
+                             type = 'raster', multiple = False,
+                             updateOnPopup = True, onPopup = None)
+                            
+        self.mapSizer.Add(self.rasterTypeRadio, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.mapSizer.Add(self.vectorTypeRadio, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.mapSizer.Add(self.mapText, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.mapSizer.Add(self.select, pos = (1, 1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+                 
+        sizerM.Add(self.mapSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        gridBagSizer.Add(sizerM, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+
+        #map scale and center
+        boxC   = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " {0} ".format(_("Map scale and center")))        
+        sizerC = wx.StaticBoxSizer(boxC, wx.HORIZONTAL)
+        self.centerSizer = wx.FlexGridSizer(rows = 2, cols = 5, hgap = 5, vgap = 5)        
+                
+                           
+        centerText = wx.StaticText(self, id = wx.ID_ANY, label = _("Center:"))
+        self.eastingText = wx.StaticText(self, id = wx.ID_ANY, label = _("E:"))
+        self.northingText = wx.StaticText(self, id = wx.ID_ANY, label = _("N:"))
+        self.eastingTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, style = wx.TE_RIGHT, validator = TCValidator(flag = 'DIGIT_ONLY'))
+        self.northingTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, style = wx.TE_RIGHT, validator = TCValidator(flag = 'DIGIT_ONLY'))
+        scaleText = wx.StaticText(self, id = wx.ID_ANY, label = _("Scale:"))
+        scalePrefixText = wx.StaticText(self, id = wx.ID_ANY, label = _("1 :"))
+        self.scaleTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, value = "", style = wx.TE_RIGHT, validator = TCValidator('DIGIT_ONLY'))
+        
+        self.centerSizer.Add(centerText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border = 10)
+        self.centerSizer.Add(self.eastingText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
+        self.centerSizer.Add(self.eastingTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.centerSizer.Add(self.northingText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
+        self.centerSizer.Add(self.northingTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        self.centerSizer.Add(scaleText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border = 10)
+        self.centerSizer.Add(scalePrefixText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
+        self.centerSizer.Add(self.scaleTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizerC.Add(self.centerSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        gridBagSizer.Add(sizerC, pos = (3, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        # border
+        box   = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " {0} ".format(_("Border")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        
+        self.borderCheck = wx.CheckBox(self, id = wx.ID_ANY, label = (_("draw border around map frame")))
+        self.borderCheck.SetValue(True if self.mapFrameDict['border'] == 'y' else False)
+        
+        self.borderColorText = wx.StaticText(self, id = wx.ID_ANY, label = _("border color:"))
+        self.borderWidthText = wx.StaticText(self, id = wx.ID_ANY, label = _("border width (pts):"))
+        self.borderColourPicker = wx.ColourPickerCtrl(self, id = wx.ID_ANY)
+        self.borderWidthCtrl = wx.SpinCtrl(self, id = wx.ID_ANY, min = 1, max = 100, initial = 1)
+        
+        if self.mapFrameDict['border'] == 'y':
+            self.borderWidthCtrl.SetValue(int(self.mapFrameDict['width']))
+            self.borderColourPicker.SetColour(convertRGB(self.mapFrameDict['color']))
+        
+        
+        gridBagSizer.Add(self.borderCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(self.borderColorText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.borderWidthText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.borderColourPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(self.borderWidthCtrl, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.SetSizer(border)
+        self.Fit()
+        
+        
+        if projInfo()['proj'] == 'll':
+            self.scaleChoice.SetItems(self.scaleChoice.GetItems()[0:2])
+            boxC.Hide()
+            for each in self.centerSizer.GetChildren():
+                each.GetWindow().Hide()
+
+            
+        # bindings
+        self.scaleChoice.Bind(wx.EVT_CHOICE, self.OnScaleChoice)
+        self.select.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnMap)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnElementType, self.vectorTypeRadio)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnElementType, self.rasterTypeRadio)
+        self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.borderCheck)
+        
+        
+     
+    def OnMap(self, event):
+        """!Selected map or region changing"""
+        
+        self.selected = self.select.GetValue() if self.select.GetValue() else None
+        if self.scaleChoice.GetSelection() == 0:
+            self.selectedMap = self.selected
+            mapType = 'raster' if self.rasterTypeRadio.GetValue() else 'vector'
+            self.scale[0], self.center[0], foo = AutoAdjust(self, scaleType = 0, map = self.selected,
+                                                mapType = mapType, rect = self.mapFrameDict['rect'])
+            #self.center[0] = self.RegionCenter(self.RegionDict(scaleType = 0))
+
+        elif self.scaleChoice.GetSelection() == 1:
+            self.selectedRegion = self.selected
+            self.scale[1], self.center[1],  foo = AutoAdjust(self, scaleType = 1, region = self.selected, rect = self.mapFrameDict['rect'])
+            #self.center[1] = self.RegionCenter(self.RegionDict(scaleType = 1))
+        elif self.scaleChoice.GetSelection() == 2:
+            self.scale[2], self.center[2], foo = AutoAdjust(self, scaleType = 2, rect = self.mapFrameDict['rect'])
+            #self.center[2] = self.RegionCenter(self.RegionDict(scaleType = 2))
+            
+        else:
+            self.scale[3] = None        
+            self.center[3] = None
+            
+        self.OnScaleChoice(None)
+        
+            
+    def OnScaleChoice(self, event):
+        """!Selected scale type changing"""
+        
+        scaleType = self.scaleChoice.GetSelection()
+        if self.scaleType != scaleType:
+            self.scaleType = scaleType
+            self.select.SetValue("")
+        
+        if scaleType in (0, 1): # automatic - region from raster map, saved region
+            if scaleType == 0:
+                # set map selection
+                self.rasterTypeRadio.Show()
+                self.vectorTypeRadio.Show()
+                self.staticBox.SetLabel(" {0} ".format(_("Map selection")))
+                type = 'raster' if self.rasterTypeRadio.GetValue() else 'vector'
+                self.select.SetElementList(type = type)
+                self.mapText.SetLabel(self.mapOrRegionText[0])
+                self.select.SetToolTipString(_("Region is set to match this map,\nraster or vector map must be added later"))
+                    
+            if scaleType == 1:
+                # set region selection
+                self.rasterTypeRadio.Hide()
+                self.vectorTypeRadio.Hide()
+                self.staticBox.SetLabel(" {0} ".format(_("Region selection")))
+                type = 'region'
+                self.select.SetElementList(type = type)
+                self.mapText.SetLabel(self.mapOrRegionText[1])
+                self.select.SetToolTipString(_(""))
+                
+            for each in self.mapSizer.GetChildren():
+                each.GetWindow().Enable()
+            for each in self.centerSizer.GetChildren():
+                each.GetWindow().Disable()
+                    
+            if self.scale[scaleType]:
+                self.scaleTextCtrl.SetValue("{0:.0f}".format(1/self.scale[scaleType]))
+            if self.center[scaleType]:
+                self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
+                self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
+        elif scaleType == 2:
+            for each in self.mapSizer.GetChildren():
+                each.GetWindow().Disable()
+            for each in self.centerSizer.GetChildren():
+                each.GetWindow().Disable()
+                
+            if self.scale[scaleType]:
+                self.scaleTextCtrl.SetValue("{0:.0f}".format(1/self.scale[scaleType]))
+            if self.center[scaleType]:
+                self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
+                self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
+        else: # fixed
+            for each in self.mapSizer.GetChildren():
+                each.GetWindow().Disable()
+            for each in self.centerSizer.GetChildren():
+                each.GetWindow().Enable()
+                    
+            if self.scale[scaleType]:
+                self.scaleTextCtrl.SetValue("{0:.0f}".format(1/self.scale[scaleType]))
+            if self.center[scaleType]:
+                self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
+                self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
+                
+    def OnElementType(self, event):
+        """!Changes data in map selection tree ctrl popup"""
+        if self.rasterTypeRadio.GetValue():
+            mapType = 'raster'
+        else:
+            mapType = 'vector'
+        self.select.SetElementList(type  = mapType)
+        if self.mapType != mapType and event is not None:
+            self.mapType = mapType
+            self.select.SetValue('')
+        self.mapType = mapType    
+        
+    def OnBorder(self, event):
+        """!Enables/disable the part relating to border of map frame"""
+        for each in (self.borderColorText, self.borderWidthText, self.borderColourPicker, self.borderWidthCtrl):
+            each.Enable(self.borderCheck.GetValue())
+            
+    def getId(self):
+        """!Returns id of raster map"""
+        return self.id
+            
+    def update(self):
+        """!Save changes"""
+        mapFrameDict = dict(self.mapFrameDict)
+        
+        #scale
+        scaleType = self.scaleType
+        mapFrameDict['scaleType'] = scaleType
+        
+        if mapFrameDict['scaleType'] == 0:
+            if self.select.GetValue():
+                mapFrameDict['map'] = self.select.GetValue()
+                mapFrameDict['mapType'] = self.mapType
+                mapFrameDict['region'] = None
+
+                self.scale[0], self.center[0], self.rectAdjusted = AutoAdjust(self, scaleType = 0, map = mapFrameDict['map'],
+                                                                   mapType = self.mapType, rect = self.mapFrameDict['rect'])
+                                               
+                mapFrameDict['rect'] = self.rectAdjusted if self.rectAdjusted else self.mapFrameDict['rect']
+                mapFrameDict['scale'] = self.scale[0]
+                
+                mapFrameDict['center'] = self.center[0]
+                # set region
+                if self.mapType == 'raster':
+                    RunCommand('g.region', rast = mapFrameDict['map'])
+                if self.mapType == 'vector':
+                    raster = self.instruction.FindInstructionByType('raster')
+                    rasterId = raster.id if raster else None
+                    if rasterId:
+                        
+                        RunCommand('g.region', vect = mapFrameDict['map'], rast = self.instruction[rasterId]['raster'])
+                    else:
+                        RunCommand('g.region', vect = mapFrameDict['map'])
+            else:
+                wx.MessageBox(message = _("No map selected!"),
+                                    caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR)
+                return False    
+            
+        elif mapFrameDict['scaleType'] == 1:
+            if self.select.GetValue():
+                mapFrameDict['map'] = None
+                mapFrameDict['mapType'] = None
+                mapFrameDict['region'] = self.select.GetValue()
+                self.scale[1], self.center[1], self.rectAdjusted = AutoAdjust(self, scaleType = 1, region = mapFrameDict['region'],
+                                                                                rect = self.mapFrameDict['rect'])
+                mapFrameDict['rect'] = self.rectAdjusted if self.rectAdjusted else self.mapFrameDict['rect']
+                mapFrameDict['scale'] = self.scale[1]
+                mapFrameDict['center'] = self.center[1]
+                # set region
+                RunCommand('g.region', region = mapFrameDict['region'])
+            else:
+                wx.MessageBox(message = _("No region selected!"),
+                                    caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR)
+                return False 
+                               
+        elif scaleType == 2:
+            mapFrameDict['map'] = None
+            mapFrameDict['mapType'] = None
+            mapFrameDict['region'] = None
+            self.scale[2], self.center[2], self.rectAdjusted = AutoAdjust(self, scaleType = 2, rect = self.mapFrameDict['rect'])
+            mapFrameDict['rect'] = self.rectAdjusted if self.rectAdjusted else self.mapFrameDict['rect']
+            mapFrameDict['scale'] = self.scale[2]
+            mapFrameDict['center'] = self.center[2]
+            
+            env = grass.gisenv()
+            windFilePath = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], 'WIND')
+            try:
+                windFile = open(windFilePath, 'r').read()
+                region = grass.parse_key_val(windFile, sep = ':', val_type = float)
+            except IOError:
+                region = grass.region()
+            
+            raster = self.instruction.FindInstructionByType('raster')
+            rasterId = raster.id if raster else None
+            if rasterId: # because of resolution
+                RunCommand('g.region', n = region['north'], s = region['south'],
+                            e = region['east'], w = region['west'], rast = self.instruction[rasterId]['raster'])
+            else:
+                RunCommand('g.region',  n = region['north'], s = region['south'],
+                                        e = region['east'], w = region['west'])
+            
+        elif scaleType == 3:
+            mapFrameDict['map'] = None
+            mapFrameDict['mapType'] = None
+            mapFrameDict['region'] = None
+            mapFrameDict['rect'] = self.mapFrameDict['rect']
+            try:
+                scaleNumber = float(self.scaleTextCtrl.GetValue())
+                centerE = float(self.eastingTextCtrl.GetValue()) 
+                centerN = float(self.northingTextCtrl.GetValue())
+            except (ValueError, SyntaxError):
+                wx.MessageBox(message = _("Invalid scale or map center!"),
+                                    caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR)
+                return False  
+            mapFrameDict['scale'] = 1/scaleNumber
+            mapFrameDict['center'] = centerE, centerN
+        
+            ComputeSetRegion(self, mapDict = mapFrameDict)
+        
+        # border
+        mapFrameDict['border'] = 'y' if self.borderCheck.GetValue() else 'n'
+        if mapFrameDict['border'] == 'y':
+            mapFrameDict['width'] = self.borderWidthCtrl.GetValue()
+            mapFrameDict['color'] = convertRGB(self.borderColourPicker.GetColour())
+            
+        if self.id not in self.instruction:
+            mapFrame = MapFrame(self.id)
+            self.instruction.AddInstruction(mapFrame)
+        self.instruction[self.id].SetInstruction(mapFrameDict)
+
+        if self.id not in self.mapDialog.parent.objectId:
+            self.mapDialog.parent.objectId.insert(0, self.id)# map frame is drawn first
+        return True
+        
+class RasterPanel(wx.Panel):
+    """!Panel for raster map settings"""
+    def __init__(self, parent, id, settings,  notebook = True):
+        wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
+        self.instruction = settings
+        
+        if notebook:
+            self.book = parent
+            self.book.AddPage(page = self, text = _("Raster map"))
+            self.mainDialog = self.book.GetParent()
+        else:
+            self.mainDialog = parent
+        if id:
+            self.id = id
+            self.rasterDict = self.instruction[self.id].GetInstruction()
+        else:
+            self.id = wx.NewId()
+            raster = Raster(self.id)
+            self.rasterDict = raster.GetInstruction()
+            
+            
+        self._layout()
+        self.OnRaster(None)
+            
+    def _layout(self):
+        """!Do layout"""
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        # choose raster map
+        
+        box   = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " {0} ".format(_("Choose raster map")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        
+        self.rasterNoRadio = wx.RadioButton(self, id = wx.ID_ANY, label = _("no raster map"), style = wx.RB_GROUP)
+        self.rasterYesRadio = wx.RadioButton(self, id = wx.ID_ANY, label = _("raster:"))
+        
+        self.rasterSelect = Select(self, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
+                             type = 'raster', multiple = False,
+                             updateOnPopup = True, onPopup = None)
+        if self.rasterDict['isRaster']:
+            self.rasterYesRadio.SetValue(True)
+            self.rasterNoRadio.SetValue(False)
+            self.rasterSelect.SetValue(self.rasterDict['raster'])
+        else:
+            self.rasterYesRadio.SetValue(False)
+            self.rasterNoRadio.SetValue(True)
+            mapId = self.instruction.FindInstructionByType('map').id
+
+            if self.instruction[mapId]['map'] and self.instruction[mapId]['mapType'] == 'raster':
+                self.rasterSelect.SetValue(self.instruction[mapId]['map'])# raster map from map frame dialog if possible
+            else:
+                self.rasterSelect.SetValue('')                
+        gridBagSizer.Add(self.rasterNoRadio, pos = (0, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)            
+        gridBagSizer.Add(self.rasterYesRadio, pos = (1, 0),  flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.rasterSelect, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        #self.rasterSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnRaster)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterNoRadio)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterYesRadio)
+        
+        self.SetSizer(border)
+        self.Fit()
+        
+    def OnRaster(self, event):
+        """!Enable/disable raster selection"""
+        self.rasterSelect.Enable(self.rasterYesRadio.GetValue())
+        
+    def update(self):
+        #draw raster
+        if self.rasterNoRadio.GetValue() or not self.rasterSelect.GetValue():
+            self.rasterDict['isRaster'] = False
+            self.rasterDict['raster'] = None
+            if self.id in self.instruction:
+                del self.instruction[self.id]
+
+        else:
+            self.rasterDict['isRaster'] = True
+            self.rasterDict['raster'] = self.rasterSelect.GetValue()
+            
+            if self.id not in self.instruction:
+                raster = Raster(self.id)
+                self.instruction.AddInstruction(raster)
+            self.instruction[self.id].SetInstruction(self.rasterDict)
+            
+        
+        return True
+        
+    def getId(self):
+        return self.id
+  
+class VectorPanel(wx.Panel):
+    """!Panel for vector maps settings"""
+    def __init__(self, parent, id, settings, notebook = True):
+        wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
+        
+        self.parent = parent
+        self.instruction = settings
+        self.tmpDialogDict = {}
+        vectors = self.instruction.FindInstructionByType('vProperties', list = True)
+        for vector in vectors:
+            self.tmpDialogDict[vector.id] = dict(self.instruction[vector.id].GetInstruction())
+        
+        if id:
+            self.id = id
+            self.vectorList = deepcopy(self.instruction[id]['list'])
+        else:
+            self.id = wx.NewId()
+            self.vectorList = []
+
+        vLegend = self.instruction.FindInstructionByType('vectorLegend')
+        self.vLegendId = vLegend.id if vLegend else None
+         
+        self._layout()
+        
+        if notebook:
+            self.parent.AddPage(page = self, text = _("Vector maps"))
+            
+    def _layout(self):
+        """!Do layout"""
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        # choose vector map
+        
+        box   = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " {0} ".format(_("Choose map")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        
+        text = wx.StaticText(self, id = wx.ID_ANY, label = _("Map:"))
+        self.select = Select(self, id = wx.ID_ANY,# size = globalvar.DIALOG_GSELECT_SIZE,
+                             type = 'vector', multiple = False,
+                             updateOnPopup = True, onPopup = None)
+        topologyType = [_("points"), _("lines"), _("areas")]
+        self.vectorType = wx.RadioBox(self, id = wx.ID_ANY, label = " {0} ".format(_("Data Type")), choices = topologyType,
+                                        majorDimension = 3, style = wx.RA_SPECIFY_COLS)
+        self.AddVector = wx.Button(self, id = wx.ID_ANY, label = _("Add"))
+        
+        gridBagSizer.Add(text, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.select, pos = (0,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.vectorType, pos = (1,1), flag = wx.ALIGN_CENTER, border = 0)
+        gridBagSizer.Add(self.AddVector, pos = (1,2), flag = wx.ALIGN_BOTTOM|wx.ALIGN_RIGHT, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        # manage vector layers
+        
+        box   = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " {0} ".format(_("Vector maps order")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(0,2)
+        gridBagSizer.AddGrowableCol(1,1)
+
+        
+        
+        text = wx.StaticText(self, id = wx.ID_ANY, label = _("The topmost vector map overlaps the others"))
+        self.listbox = wx.ListBox(self, id = wx.ID_ANY, choices = [], style = wx.LB_SINGLE|wx.LB_NEEDED_SB)
+        self.btnUp = wx.Button(self, id = wx.ID_ANY, label = _("Up"))
+        self.btnDown = wx.Button(self, id = wx.ID_ANY, label = _("Down"))
+        self.btnDel = wx.Button(self, id = wx.ID_ANY, label = _("Delete"))
+        self.btnProp = wx.Button(self, id = wx.ID_ANY, label = _("Properties"))
+        
+        self.updateListBox()
+        
+        
+        gridBagSizer.Add(text, pos = (0,0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.listbox, pos = (1,0), span = (4, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(self.btnUp, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.btnDown, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.btnDel, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.btnProp, pos = (4,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.Bind(wx.EVT_BUTTON, self.OnAddVector, self.AddVector)
+        self.Bind(wx.EVT_BUTTON, self.OnDelete, self.btnDel)
+        self.Bind(wx.EVT_BUTTON, self.OnUp, self.btnUp)
+        self.Bind(wx.EVT_BUTTON, self.OnDown, self.btnDown)
+        self.Bind(wx.EVT_BUTTON, self.OnProperties, self.btnProp)
+        self.select.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnVector)
+        
+        self.SetSizer(border)
+        self.Fit()
+
+    def OnVector(self, event):
+        """!Gets info about toplogy and enables/disables choices point/line/area"""
+        vmap = self.select.GetValue()   
+        try:     
+            topoInfo = grass.vector_info_topo(map = vmap)
+        except grass.ScriptError, e:
+            GError(parent = self,
+                   message = e.value)
+            return
+        
+        self.vectorType.EnableItem(2, bool(topoInfo['areas']))
+        self.vectorType.EnableItem(1, bool(topoInfo['boundaries']) or bool(topoInfo['lines']))
+        self.vectorType.EnableItem(0, bool(topoInfo['centroids'] or bool(topoInfo['points']) ))
+        for item in range(2,-1,-1):
+            if self.vectorType.IsItemEnabled(item):
+                self.vectorType.SetSelection(item)
+                break
+        
+        self.AddVector.SetFocus()        
+            
+    def OnAddVector(self, event):
+        """!Adds vector map to list"""
+        vmap = self.select.GetValue()
+        if vmap:
+            mapname = vmap.split('@')[0]
+            try:
+                mapset = '(' + vmap.split('@')[1] + ')'
+            except IndexError:
+                mapset = ''
+            type = self.vectorType.GetStringSelection()
+            record = "{0} - {1}".format(vmap,type)
+            id = wx.NewId()
+            lpos = 1
+            label = mapname + mapset 
+            self.vectorList.insert(0, [vmap, type, id, lpos, label])
+            self.reposition()
+            self.listbox.InsertItems([record], 0)
+            
+            vector = VProperties(id, type)
+            #self.instruction.AddInstruction(vector)
+            self.tmpDialogDict[id] = vector.GetInstruction()
+            self.tmpDialogDict[id]['name'] = vmap
+
+            
+            self.listbox.SetSelection(0)  
+            self.listbox.EnsureVisible(0)
+            self.btnProp.SetFocus()
+            
+    def OnDelete(self, event):
+        """!Deletes vector map from the list"""
+        if self.listbox.GetSelections():
+            pos = self.listbox.GetSelection()
+            id = self.vectorList[pos][2]
+            del self.vectorList[pos]
+            del self.tmpDialogDict[id]
+            
+            for i in range(pos, len(self.vectorList)):
+                if self.vectorList[i][3]:# can be 0
+                    self.vectorList[i][3] -= 1
+            self.updateListBox(selected = pos if pos < len(self.vectorList) -1 else len(self.vectorList) -1)
+            
+            
+    def OnUp(self, event):
+        """!Moves selected map to top"""
+        if self.listbox.GetSelections():
+            pos = self.listbox.GetSelection()
+            if pos:
+                self.vectorList.insert(pos - 1, self.vectorList.pop(pos))
+            if not self.vLegendId:
+                self.reposition()
+            self.updateListBox(selected = (pos - 1) if pos > 0 else 0)
+            
+    def OnDown(self, event):
+        """!Moves selected map to bottom"""
+        if self.listbox.GetSelections():
+            pos = self.listbox.GetSelection()
+            if pos != len(self.vectorList) - 1:
+                self.vectorList.insert(pos + 1, self.vectorList.pop(pos))
+                if not self.vLegendId:
+                    self.reposition()
+            self.updateListBox(selected = (pos + 1) if pos < len(self.vectorList) -1 else len(self.vectorList) -1)
+    
+    def OnProperties(self, event):
+        """!Opens vector map properties dialog"""
+        if self.listbox.GetSelections():
+            pos = self.listbox.GetSelection()
+            id = self.vectorList[pos][2]
+
+            dlg = VPropertiesDialog(self, id = id, settings = self.instruction, 
+                                    vectors = self.vectorList, tmpSettings = self.tmpDialogDict[id])
+            dlg.ShowModal()
+            
+            self.parent.FindWindowById(wx.ID_OK).SetFocus()
+           
+
+    
+    def updateListBox(self, selected = None):
+        mapList = ["{0} - {1}".format(*item) for item in self.vectorList]
+        self.listbox.Set(mapList)
+        if selected is not None:
+            self.listbox.SetSelection(selected)  
+            self.listbox.EnsureVisible(selected)  
+              
+    def reposition(self):
+        """!Update position in legend, used only if there is no vlegend yet"""
+        for i in range(len(self.vectorList)):
+            if self.vectorList[i][3]:
+                self.vectorList[i][3] = i + 1
+                
+    def getId(self):
+        return self.id
+        
+    def update(self):
+        vectors = self.instruction.FindInstructionByType('vProperties', list = True)
+        
+        for vector in vectors:
+            del self.instruction[vector.id]
+        if self.id in self.instruction:
+            del self.instruction[self.id] 
+
+        if len(self.vectorList) > 0:
+            vector = Vector(self.id)
+            self.instruction.AddInstruction(vector)
+
+            vector.SetInstruction({'list': deepcopy(self.vectorList)})
+            
+
+            # save new vectors
+            for item in self.vectorList:
+                id = item[2]
+
+                vLayer = VProperties(id, item[1])
+                self.instruction.AddInstruction(vLayer)
+                vLayer.SetInstruction(self.tmpDialogDict[id])
+                vLayer['name'] = item[0]
+                vLayer['label'] = item[4]
+                vLayer['lpos'] = item[3]
+            
+        else:
+            if self.id in self.instruction:
+                del self.instruction[self.id]
+
+        return True
+    
+class RasterDialog(PsmapDialog):
+    def __init__(self, parent, id, settings):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "Choose raster map", settings = settings)
+        self.instruction = settings
+        self.rPanel = RasterPanel(parent = self, id = self.id, settings = self.instruction, notebook = False)
+
+        self.id = self.rPanel.getId()
+        self._layout(self.rPanel)
+    
+    def update(self):
+        ok = self.rPanel.update()
+        if ok:
+            return True
+        return False
+    
+    def OnApply(self, event):
+        ok = self.update()
+        if not ok:
+            return False
+
+        if self.id in self.instruction:
+            self.parent.DialogDataChanged(id = self.id)
+        else:
+            mapId = self.instruction.FindInstructionByType('map').id
+            self.parent.DialogDataChanged(id = mapId)
+        return True
+ 
+class MainVectorDialog(PsmapDialog):
+    def __init__(self, parent, id, settings):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "Choose vector maps", settings = settings)
+        self.instruction = settings
+        self.vPanel = VectorPanel(parent = self, id = self.id, settings = self.instruction, notebook = False)
+
+        self.id = self.vPanel.getId()
+        self._layout(self.vPanel)
+    
+    def update(self):
+        self.vPanel.update()
+        
+    def OnApply(self, event):
+        self.update()
+        if self.id in self.instruction:
+            self.parent.DialogDataChanged(id = self.id)
+        else:
+            mapId = self.instruction.FindInstructionByType('map').id
+            self.parent.DialogDataChanged(id = mapId)
+        return True
+        
+
+class VPropertiesDialog(PsmapDialog):
+    def __init__(self, parent, id, settings, vectors, tmpSettings):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "", settings = settings, apply = False)
+        
+        vectorList = vectors
+        self.vPropertiesDict = tmpSettings
+        
+        # determine map and its type
+        for item in vectorList:
+            if id == item[2]:
+                self.vectorName = item[0]
+                self.type = item[1]
+        self.SetTitle(self.vectorName + " "+ _("properties"))
+        
+        #vector map info
+        self.connection = True
+        try:
+            self.mapDBInfo = dbm_base.VectorDBInfo(self.vectorName)
+            self.layers = self.mapDBInfo.layers.keys()
+        except grass.ScriptError:
+            self.connection = False
+            self.layers = []
+
+            
+        self.currLayer = self.vPropertiesDict['layer']
+        
+        #path to symbols, patterns
+        gisbase = os.getenv("GISBASE")
+        self.symbolPath = os.path.join(gisbase, 'etc', 'symbol')
+        self.symbols = []
+        for dir in os.listdir(self.symbolPath):
+            for symbol in os.listdir(os.path.join(self.symbolPath, dir)):
+                self.symbols.append(os.path.join(dir, symbol))
+        self.patternPath = os.path.join(gisbase, 'etc', 'paint', 'patterns')
+
+        #notebook
+        notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
+        self.DSpanel = self._DataSelectionPanel(notebook)
+        self.EnableLayerSelection(enable = self.connection)
+        selectPanel = { 'points': [self._ColorsPointAreaPanel, self._StylePointPanel], 
+                        'lines': [self._ColorsLinePanel, self._StyleLinePanel], 
+                        'areas': [self._ColorsPointAreaPanel, self._StyleAreaPanel]}
+        self.ColorsPanel = selectPanel[self.type][0](notebook)
+        
+        self.OnOutline(None)
+        if self.type in ('points', 'areas'):
+            self.OnFill(None)
+        self.OnColor(None)
+        
+        self.StylePanel = selectPanel[self.type][1](notebook)
+        if self.type == 'points':
+            self.OnSize(None)
+            self.OnRotation(None)
+        if self.type == 'areas':
+            self.OnPattern(None)
+        
+        self._layout(notebook)
+        
+    def _DataSelectionPanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Data selection"))
+        
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        # data type
+        self.checkType1 = self.checkType2 = None
+        if self.type in ('lines', 'points'):
+            box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Feature type")))        
+            sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+            gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+            
+            label = (_("points"), _("centroids")) if self.type == 'points' else (_("lines"), _("boundaries"))
+            name = ("point", "centroid") if self.type == 'points' else ("line", "boundary")
+            self.checkType1 = wx.CheckBox(panel, id = wx.ID_ANY, label = label[0], name = name[0])
+            self.checkType2 = wx.CheckBox(panel, id = wx.ID_ANY, label = label[1], name = name[1])
+            self.checkType1.SetValue(self.vPropertiesDict['type'].find(name[0]) >= 0)
+            self.checkType2.SetValue(self.vPropertiesDict['type'].find(name[1]) >= 0)
+            
+            gridBagSizer.Add(self.checkType1, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            gridBagSizer.Add(self.checkType2, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+            border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        # layer selection
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Layer selection")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        self.gridBagSizerL = wx.GridBagSizer(hgap = 5, vgap = 5)
+        
+        
+        self.warning =  wx.StaticText(panel, id = wx.ID_ANY, label = "")
+        if not self.connection:
+            self.warning = wx.StaticText(panel, id = wx.ID_ANY, label = _("Database connection is not defined in DB file."))
+        text = wx.StaticText(panel, id = wx.ID_ANY, label = _("Select layer:"))
+        self.layerChoice = wx.Choice(panel, id = wx.ID_ANY, choices = map(str, self.layers), size = self.spinCtrlSize)
+        self.layerChoice.SetStringSelection(self.currLayer)
+                
+        table = self.mapDBInfo.layers[int(self.currLayer)]['table'] if self.connection else ""
+        self.radioWhere = wx.RadioButton(panel, id = wx.ID_ANY, label = "SELECT * FROM {0} WHERE".format(table), style = wx.RB_GROUP)
+        self.textCtrlWhere = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
+        
+        
+        cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table']) if self.connection else []
+        self.choiceColumns = wx.Choice(panel, id = wx.ID_ANY, choices = cols)
+        
+        self.radioCats = wx.RadioButton(panel, id = wx.ID_ANY, label = "Choose categories ".format(table))
+        self.textCtrlCats = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
+        self.textCtrlCats.SetToolTipString(_("list of categories (e.g. 1,3,5-7)"))
+        
+        if self.vPropertiesDict.has_key('cats'):
+            self.radioCats.SetValue(True)
+            self.textCtrlCats.SetValue(self.vPropertiesDict['cats'])
+        if self.vPropertiesDict.has_key('where'):
+            self.radioWhere.SetValue(True)
+            where = self.vPropertiesDict['where'].strip().split(" ",1)
+            self.choiceColumns.SetStringSelection(where[0])
+            self.textCtrlWhere.SetValue(where[1])
+            
+        row = 0
+        if not self.connection:
+            self.gridBagSizerL.Add(self.warning, pos = (0,0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            row = 1
+        self.gridBagSizerL.Add(text, pos = (0 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerL.Add(self.layerChoice, pos = (0 + row,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        self.gridBagSizerL.Add(self.radioWhere, pos = (1 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerL.Add(self.choiceColumns, pos = (1 + row,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerL.Add(self.textCtrlWhere, pos = (1 + row,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerL.Add(self.radioCats, pos = (2 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerL.Add(self.textCtrlCats, pos = (2 + row,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+        sizer.Add(self.gridBagSizerL, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        #mask
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Mask")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        
+        self.mask = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Use current mask"))
+        self.mask.SetValue(True if self.vPropertiesDict['masked'] == 'y' else False)
+        
+        sizer.Add(self.mask, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+        self.Bind(wx.EVT_CHOICE, self.OnLayer, self.layerChoice)
+        
+        panel.SetSizer(border)
+        panel.Fit()
+        return panel
+    
+    def _ColorsPointAreaPanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Colors"))
+        
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        #colors - outline
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Outline")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        self.gridBagSizerO = wx.GridBagSizer(hgap = 5, vgap = 2)
+        
+        
+        self.outlineCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw outline"))
+        self.outlineCheck.SetValue(self.vPropertiesDict['color'] != 'none')
+        
+        widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):"))
+        self.widthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1, size = self.spinCtrlSize)
+        self.widthSpin.SetValue(self.vPropertiesDict['width'] if self.vPropertiesDict['color'] != 'none' else 1)
+        
+        colorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color:"))
+        self.colorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.colorPicker.SetColour(convertRGB(self.vPropertiesDict['color']) if self.vPropertiesDict['color'] != 'none' else 'black')
+        
+        
+        self.gridBagSizerO.Add(self.outlineCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerO.Add(widthText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerO.Add(self.widthSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)        
+        self.gridBagSizerO.Add(colorText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)                
+        self.gridBagSizerO.Add(self.colorPicker, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        
+        
+        sizer.Add(self.gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.Bind(wx.EVT_CHECKBOX, self.OnOutline, self.outlineCheck)
+        
+        #colors - fill
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Fill")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        self.gridBagSizerF = wx.GridBagSizer(hgap = 5, vgap = 2)
+       
+        self.fillCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("fill color"))
+        self.fillCheck.SetValue(self.vPropertiesDict['fcolor'] != 'none' or self.vPropertiesDict['rgbcolumn'] is not None)
+        
+
+        self.colorPickerRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("choose color:"), style = wx.RB_GROUP)
+        #set choose color option if there is no db connection
+        if self.connection:
+            self.colorPickerRadio.SetValue(not self.vPropertiesDict['rgbcolumn'])
+        else:
+            self.colorPickerRadio.SetValue(False)            
+        self.fillColorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.fillColorPicker.SetColour(convertRGB(self.vPropertiesDict['fcolor']) if self.vPropertiesDict['fcolor'] != 'none' else 'red')
+        
+        
+        self.colorColRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("color from map table column:"))
+        self.colorColChoice = self.getColsChoice(parent = panel)
+        if self.connection:
+            if self.vPropertiesDict['rgbcolumn']:
+                self.colorColRadio.SetValue(True)
+                self.colorColChoice.SetStringSelection(self.vPropertiesDict['rgbcolumn'])
+            else:
+                self.colorColRadio.SetValue(False)
+                self.colorColChoice.SetSelection(0)
+        self.colorColChoice.Enable(self.connection)
+        self.colorColRadio.Enable(self.connection)
+        
+        self.gridBagSizerF.Add(self.fillCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerF.Add(self.colorPickerRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerF.Add(self.fillColorPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerF.Add(self.colorColRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerF.Add(self.colorColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)        
+        
+        sizer.Add(self.gridBagSizerF, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+        self.Bind(wx.EVT_CHECKBOX, self.OnFill, self.fillCheck)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorColRadio)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorPickerRadio)
+        
+        panel.SetSizer(border)
+        panel.Fit()
+        return panel
+    
+    def _ColorsLinePanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Colors"))
+        
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        #colors - outline
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Outline")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        self.gridBagSizerO = wx.GridBagSizer(hgap = 5, vgap = 2)
+        
+        
+        self.outlineCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw outline"))
+        self.outlineCheck.SetValue(self.vPropertiesDict['hcolor'] != 'none')
+        self.outlineCheck.SetToolTipString(_("No effect for fill color from table column"))
+        
+        widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):"))
+        self.widthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1, size = self.spinCtrlSize)
+        self.widthSpin.SetValue(self.vPropertiesDict['hwidth'] if self.vPropertiesDict['hcolor'] != 'none' else 1)
+        
+        colorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color:"))
+        self.colorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.colorPicker.SetColour(convertRGB(self.vPropertiesDict['hcolor']) if self.vPropertiesDict['hcolor'] != 'none' else 'black')
+        
+        
+        self.gridBagSizerO.Add(self.outlineCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerO.Add(widthText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerO.Add(self.widthSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)        
+        self.gridBagSizerO.Add(colorText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)                
+        self.gridBagSizerO.Add(self.colorPicker, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        
+        
+        sizer.Add(self.gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.Bind(wx.EVT_CHECKBOX, self.OnOutline, self.outlineCheck)
+        
+        #colors - fill
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Fill")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        self.gridBagSizerF = wx.GridBagSizer(hgap = 5, vgap = 2)
+       
+        fillText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color of lines:"))
+        
+
+        self.colorPickerRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("choose color:"), style = wx.RB_GROUP)
+        #set choose color option if there is no db connection
+        if self.connection:
+            self.colorPickerRadio.SetValue(not self.vPropertiesDict['rgbcolumn'])
+        else:
+            self.colorPickerRadio.SetValue(False)            
+        self.fillColorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.fillColorPicker.SetColour(convertRGB(self.vPropertiesDict['color']) if self.vPropertiesDict['color'] != 'none' else 'black')
+        
+        
+        self.colorColRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("color from map table column:"))
+        self.colorColChoice = self.getColsChoice(parent = panel)
+        if self.connection:
+            if self.vPropertiesDict['rgbcolumn']:
+                self.colorColRadio.SetValue(True)
+                self.colorColChoice.SetStringSelection(self.vPropertiesDict['rgbcolumn'])
+            else:
+                self.colorColRadio.SetValue(False)
+                self.colorColChoice.SetSelection(0)
+        self.colorColChoice.Enable(self.connection)
+        self.colorColRadio.Enable(self.connection)
+        
+        self.gridBagSizerF.Add(fillText, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerF.Add(self.colorPickerRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerF.Add(self.fillColorPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerF.Add(self.colorColRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        self.gridBagSizerF.Add(self.colorColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)        
+        
+        sizer.Add(self.gridBagSizerF, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorColRadio)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorPickerRadio)
+        panel.SetSizer(border)
+        panel.Fit()
+        return panel
+    
+    def _StylePointPanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Size and style"))
+        
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        #symbology
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Symbology")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(1)
+    
+        self.symbolRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("symbol:"), style = wx.RB_GROUP)
+        self.symbolRadio.SetValue(bool(self.vPropertiesDict['symbol']))
+            
+         
+        self.symbolChoice = wx.Choice(panel, id = wx.ID_ANY, choices = self.symbols)
+            
+        self.epsRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("eps file:"))
+        self.epsRadio.SetValue(bool(self.vPropertiesDict['eps']))
+        
+        self.epsFileCtrl = filebrowse.FileBrowseButton(panel, id = wx.ID_ANY, labelText = '',
+                                buttonText =  _("Browse"), toolTip = _("Type filename or click browse to choose file"), 
+                                dialogTitle = _("Choose a file"), startDirectory = '', initialValue = '',
+                                fileMask = "Encapsulated PostScript (*.eps)|*.eps|All files (*.*)|*.*", fileMode = wx.OPEN)
+        if self.vPropertiesDict['symbol']:
+            self.symbolChoice.SetStringSelection(self.vPropertiesDict['symbol'])
+            self.epsFileCtrl.SetValue('')
+        else: #eps chosen
+            self.epsFileCtrl.SetValue(self.vPropertiesDict['eps'])
+            self.symbolChoice.SetSelection(0)
+            
+        gridBagSizer.Add(self.symbolRadio, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.symbolChoice, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.epsRadio, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.epsFileCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        #size
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Size")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(0)
+        
+        self.sizeRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("size:"), style = wx.RB_GROUP)
+        self.sizeSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 50, initial = 1)
+        self.sizecolumnRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("size from map table column:"))
+        self.sizeColChoice = self.getColsChoice(panel)
+        self.scaleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("scale:"))
+        self.scaleSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1)
+        
+        self.sizeRadio.SetValue(self.vPropertiesDict['size'] is not None)
+        self.sizecolumnRadio.SetValue(bool(self.vPropertiesDict['sizecolumn']))
+        self.sizeSpin.SetValue(self.vPropertiesDict['size'] if self.vPropertiesDict['size'] else 5)
+        if self.vPropertiesDict['sizecolumn']:
+            self.scaleSpin.SetValue(self.vPropertiesDict['scale'])
+            self.sizeColChoice.SetStringSelection(self.vPropertiesDict['sizecolumn'])
+        else:
+            self.scaleSpin.SetValue(1)
+            self.sizeColChoice.SetSelection(0)
+        if not self.connection:   
+            for each in (self.sizecolumnRadio, self.sizeColChoice, self.scaleSpin, self.scaleText):
+                each.Disable()
+            
+        gridBagSizer.Add(self.sizeRadio, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.sizeSpin, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.sizecolumnRadio, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.sizeColChoice, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(self.scaleText, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
+        gridBagSizer.Add(self.scaleSpin, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnSize, self.sizeRadio)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnSize, self.sizecolumnRadio)
+        
+        #rotation
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Rotation")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(1)
+
+        
+        self.rotateCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("rotate symbols:"))
+        self.rotateRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("counterclockwise in degrees:"), style = wx.RB_GROUP)
+        self.rotateSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 0, max = 360, initial = 0)
+        self.rotatecolumnRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("from map table column:"))
+        self.rotateColChoice = self.getColsChoice(panel)
+        
+        self.rotateCheck.SetValue(self.vPropertiesDict['rotation'])
+        self.rotateRadio.SetValue(self.vPropertiesDict['rotate'] is not None)
+        self.rotatecolumnRadio.SetValue(bool(self.vPropertiesDict['rotatecolumn']))
+        self.rotateSpin.SetValue(self.vPropertiesDict['rotate'] if self.vPropertiesDict['rotate'] else 0)
+        if self.vPropertiesDict['rotatecolumn']:
+            self.rotateColChoice.SetStringSelection(self.vPropertiesDict['rotatecolumn'])
+        else:
+            self.rotateColChoice.SetSelection(0)
+            
+        gridBagSizer.Add(self.rotateCheck, pos = (0, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.rotateRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.rotateSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.rotatecolumnRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.rotateColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.Bind(wx.EVT_CHECKBOX, self.OnRotation, self.rotateCheck)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnRotationType, self.rotateRadio)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnRotationType, self.rotatecolumnRadio)
+        
+        panel.SetSizer(border)
+        panel.Fit()
+        return panel
+    
+    def _StyleLinePanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Size and style"))
+        
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        #width
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Width")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        
+        widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Set width (pts):"))
+        self.widthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1)
+        self.cwidthCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("multiply width by category value"))
+        
+        if self.vPropertiesDict['width']:
+            self.widthSpin.SetValue(self.vPropertiesDict['width'])
+            self.cwidthCheck.SetValue(False)
+        else:
+            self.widthSpin.SetValue(self.vPropertiesDict['cwidth'])
+            self.cwidthCheck.SetValue(True)
+        
+        gridBagSizer.Add(widthText, pos = (0, 0),  flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.widthSpin, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.cwidthCheck, pos = (1, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        #style
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Line style")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        
+        styleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose line style:"))
+        penStyles = ["solid", "dashed", "dotted", "dashdotted"]
+        self.styleCombo = PenStyleComboBox(panel, choices = penStyles, validator = TCValidator(flag = 'ZERO_AND_ONE_ONLY'))
+##        self.styleCombo = wx.ComboBox(panel, id = wx.ID_ANY,
+##                            choices = ["solid", "dashed", "dotted", "dashdotted"],
+##                            validator = TCValidator(flag = 'ZERO_AND_ONE_ONLY'))
+##        self.styleCombo.SetToolTipString(_("It's possible to enter a series of 0's and 1's too. "\
+##                                    "The first block of repeated zeros or ones represents 'draw', "\
+##                                    "the second block represents 'blank'. An even number of blocks "\
+##                                    "will repeat the pattern, an odd number of blocks will alternate the pattern."))
+        linecapText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose linecap:"))
+        self.linecapChoice = wx.Choice(panel, id = wx.ID_ANY, choices = ["butt", "round", "extended_butt"])
+        
+        self.styleCombo.SetValue(self.vPropertiesDict['style'])
+        self.linecapChoice.SetStringSelection(self.vPropertiesDict['linecap'])
+        
+        gridBagSizer.Add(styleText, pos = (0, 0),  flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.styleCombo, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(linecapText, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.linecapChoice, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        panel.SetSizer(border)
+        panel.Fit()
+        return panel
+        
+    def _StyleAreaPanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Size and style"))
+        
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        #pattern
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Pattern")))        
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(1)
+        
+        self.patternCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use pattern:"))
+        self.patFileCtrl = filebrowse.FileBrowseButton(panel, id = wx.ID_ANY, labelText = _("Choose pattern file:"),
+                                buttonText =  _("Browse"), toolTip = _("Type filename or click browse to choose file"), 
+                                dialogTitle = _("Choose a file"), startDirectory = self.patternPath, initialValue = '',
+                                fileMask = "Encapsulated PostScript (*.eps)|*.eps|All files (*.*)|*.*", fileMode = wx.OPEN)
+        self.patWidthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("pattern line width (pts):"))
+        self.patWidthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1)
+        self.patScaleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("pattern scale factor:"))
+        self.patScaleSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1)
+        
+        self.patternCheck.SetValue(bool(self.vPropertiesDict['pat']))
+        if self.patternCheck.GetValue():
+            self.patFileCtrl.SetValue(self.vPropertiesDict['pat'])
+            self.patWidthSpin.SetValue(self.vPropertiesDict['pwidth'])
+            self.patScaleSpin.SetValue(self.vPropertiesDict['scale'])
+        
+        gridBagSizer.Add(self.patternCheck, pos = (0, 0),  flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.patFileCtrl, pos = (1, 0), span = (1, 2),flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(self.patWidthText, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.patWidthSpin, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.patScaleText, pos = (3, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.patScaleSpin, pos = (3, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.Bind(wx.EVT_CHECKBOX, self.OnPattern, self.patternCheck)
+        
+        panel.SetSizer(border)
+        panel.Fit()
+        return panel
+        
+
+    def OnLayer(self, event):
+        """!Change columns on layer change """
+        if self.layerChoice.GetStringSelection() == self.currLayer:
+            return
+        self.currLayer = self.layerChoice.GetStringSelection()
+        cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table']) if self.connection else []
+        self.choiceColumns.SetItems(cols)
+
+        self.choiceColumns.SetSelection(0)
+        if self.type in ('points', 'lines'):
+            self.colorColChoice.SetItems(cols)
+            self.colorColChoice.SetSelection(0)
+            
+    def OnOutline(self, event):
+        for widget in self.gridBagSizerO.GetChildren():
+            if widget.GetWindow() != self.outlineCheck:
+                widget.GetWindow().Enable(self.outlineCheck.GetValue())
+                
+    def OnFill(self, event):
+        enable = self.fillCheck.GetValue()
+        
+        self.colorColChoice.Enable(enable)
+        self.colorColRadio.Enable(enable)
+        self.fillColorPicker.Enable(enable)
+        self.colorPickerRadio.Enable(enable)
+        if enable:
+            self.OnColor(None)
+        if not self.connection:
+            self.colorColChoice.Disable()
+            self.colorColRadio.Disable()
+            
+    def OnColor(self, event):
+        self.colorColChoice.Enable(self.colorColRadio.GetValue())
+        self.fillColorPicker.Enable(self.colorPickerRadio.GetValue())
+            
+    def OnSize(self, event):
+        self.sizeSpin.Enable(self.sizeRadio.GetValue())
+        self.sizeColChoice.Enable(self.sizecolumnRadio.GetValue())
+        self.scaleText.Enable(self.sizecolumnRadio.GetValue())
+        self.scaleSpin.Enable(self.sizecolumnRadio.GetValue())
+        
+    def OnRotation(self, event):
+        for each in (self.rotateRadio, self.rotatecolumnRadio, self.rotateColChoice, self.rotateSpin):
+            if self.rotateCheck.GetValue():
+                each.Enable()
+                self.OnRotationType(event = None)     
+            else:
+                each.Disable()
+           
+        
+    def OnRotationType(self, event):
+        self.rotateSpin.Enable(self.rotateRadio.GetValue())
+        self.rotateColChoice.Enable(self.rotatecolumnRadio.GetValue())
+        
+    def OnPattern(self, event):
+        for each in (self.patFileCtrl, self.patWidthText, self.patWidthSpin, self.patScaleText, self.patScaleSpin):
+            each.Enable(self.patternCheck.GetValue())
+            
+    def EnableLayerSelection(self, enable = True):
+        for widget in self.gridBagSizerL.GetChildren():
+            if widget.GetWindow() != self.warning:
+                widget.GetWindow().Enable(enable)
+                
+    def getColsChoice(self, parent):
+        """!Returns a wx.Choice with table columns"""
+        cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table']) if self.connection else []
+        choice = wx.Choice(parent = parent, id = wx.ID_ANY, choices = cols)
+        return choice
+        
+    def update(self):
+        #feature type
+        if self.type in ('lines', 'points'):
+            featureType = None
+            if self.checkType1.GetValue():
+                featureType = self.checkType1.GetName()
+                if self.checkType2.GetValue():
+                    featureType += " or " + self.checkType2.GetName()
+            elif self.checkType2.GetValue():
+                featureType = self.checkType2.GetName()
+            if featureType:
+                self.vPropertiesDict['type'] = featureType
+            
+        # is connection
+        self.vPropertiesDict['connection'] = self.connection
+        if self.connection:
+            self.vPropertiesDict['layer'] = self.layerChoice.GetStringSelection()
+            if self.radioCats.GetValue() and not self.textCtrlCats.IsEmpty():
+                self.vPropertiesDict['cats'] = self.textCtrlCats.GetValue()
+            elif self.radioWhere.GetValue() and not self.textCtrlWhere.IsEmpty():
+                self.vPropertiesDict['where'] = self.choiceColumns.GetStringSelection() + " " \
+                                                                + self.textCtrlWhere.GetValue()
+        #mask
+        self.vPropertiesDict['masked'] = 'y' if self.mask.GetValue() else 'n'
+        
+        #colors
+        if self.type in ('points', 'areas'):
+            if self.outlineCheck.GetValue():
+                self.vPropertiesDict['color'] = convertRGB(self.colorPicker.GetColour())
+                self.vPropertiesDict['width'] = self.widthSpin.GetValue()
+            else:
+                self.vPropertiesDict['color'] = 'none'
+                
+            if self.fillCheck.GetValue():
+                if self.colorPickerRadio.GetValue():
+                    self.vPropertiesDict['fcolor'] = convertRGB(self.fillColorPicker.GetColour())
+                    self.vPropertiesDict['rgbcolumn'] = None
+                if self.colorColRadio.GetValue():
+                    self.vPropertiesDict['fcolor'] = 'none'# this color is taken in case of no record in rgb column
+                    self.vPropertiesDict['rgbcolumn'] = self.colorColChoice.GetStringSelection()
+            else:
+                self.vPropertiesDict['fcolor'] = 'none'    
+                
+        if self.type == 'lines':
+                #hcolor only when no rgbcolumn
+            if self.outlineCheck.GetValue():# and self.fillCheck.GetValue() and self.colorColRadio.GetValue():
+                self.vPropertiesDict['hcolor'] = convertRGB(self.colorPicker.GetColour())
+                self.vPropertiesDict['hwidth'] = self.widthSpin.GetValue()
+            else:
+                self.vPropertiesDict['hcolor'] = 'none'
+                
+            if self.colorPickerRadio.GetValue():
+                self.vPropertiesDict['color'] = convertRGB(self.fillColorPicker.GetColour())
+                self.vPropertiesDict['rgbcolumn'] = None
+            if self.colorColRadio.GetValue():
+                self.vPropertiesDict['color'] = 'none'# this color is taken in case of no record in rgb column
+                self.vPropertiesDict['rgbcolumn'] = self.colorColChoice.GetStringSelection()
+        #
+        #size and style
+        #
+        
+        if self.type == 'points':
+            #symbols
+            if self.symbolRadio.GetValue():
+                self.vPropertiesDict['symbol'] = self.symbolChoice.GetStringSelection()
+                self.vPropertiesDict['eps'] = None
+            else:
+                self.vPropertiesDict['eps'] = self.epsFileCtrl.GetValue()
+                self.vPropertiesDict['symbol'] = None
+            #size
+            if self.sizeRadio.GetValue():
+                self.vPropertiesDict['size'] = self.sizeSpin.GetValue()
+                self.vPropertiesDict['sizecolumn'] = None
+                self.vPropertiesDict['scale'] = None
+            else:
+                self.vPropertiesDict['sizecolumn'] = self.sizeColChoice.GetStringSelection()
+                self.vPropertiesDict['scale'] = self.scaleSpin.GetValue()
+                self.vPropertiesDict['size'] = None
+            
+            #rotation
+            self.vPropertiesDict['rotate'] = None
+            self.vPropertiesDict['rotatecolumn'] = None
+            self.vPropertiesDict['rotation'] = False
+            if self.rotateCheck.GetValue():
+                self.vPropertiesDict['rotation'] = True
+            if self.rotateRadio.GetValue():
+                self.vPropertiesDict['rotate'] = self.rotateSpin.GetValue()
+            else:
+                self.vPropertiesDict['rotatecolumn'] = self.rotateColChoice.GetStringSelection()
+                
+        if self.type == 'areas':
+            #pattern
+            self.vPropertiesDict['pat'] = None 
+            if self.patternCheck.GetValue() and bool(self.patFileCtrl.GetValue()):
+                self.vPropertiesDict['pat'] = self.patFileCtrl.GetValue()
+                self.vPropertiesDict['pwidth'] = self.patWidthSpin.GetValue()
+                self.vPropertiesDict['scale'] = self.patScaleSpin.GetValue()
+                
+        if self.type == 'lines':
+            #width
+            if self.cwidthCheck.GetValue():
+                self.vPropertiesDict['cwidth'] = self.widthSpin.GetValue()
+                self.vPropertiesDict['width'] = None
+            else:
+                self.vPropertiesDict['width'] = self.widthSpin.GetValue()
+                self.vPropertiesDict['cwidth'] = None
+            #line style
+            self.vPropertiesDict['style'] = self.styleCombo.GetValue() if self.styleCombo.GetValue() else 'solid'
+            self.vPropertiesDict['linecap'] = self.linecapChoice.GetStringSelection()
+            
+    
+    def OnOK(self, event):
+        self.update()
+        event.Skip()
+        
+class LegendDialog(PsmapDialog):
+    def __init__(self, parent, id, settings, page):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "Legend settings", settings = settings)
+        
+        self.instruction = settings
+        map = self.instruction.FindInstructionByType('map')
+        self.mapId = map.id if map else None
+        vector = self.instruction.FindInstructionByType('vector')
+        self.vectorId = vector.id if vector else None
+        raster = self.instruction.FindInstructionByType('raster')
+        self.rasterId = raster.id if raster else None
+
+
+        self.pageId = self.instruction.FindInstructionByType('page').id
+        currPage = self.instruction[self.pageId].GetInstruction()
+        #raster legend
+        if self.id[0] is not None:
+            self.rLegendDict = self.instruction[self.id[0]].GetInstruction()
+        else:
+            self.id[0] = wx.NewId()
+            rasterLegend = RasterLegend(self.id[0])
+            self.rLegendDict = rasterLegend.GetInstruction()
+            self.rLegendDict['where'] = currPage['Left'], currPage['Top']
+            
+            
+        #vector legend    
+        if self.id[1] is not None:
+            self.vLegendDict = self.instruction[self.id[1]].GetInstruction()
+        else:
+            self.id[1] = wx.NewId()
+            vectorLegend = VectorLegend(self.id[1])
+            self.vLegendDict = vectorLegend.GetInstruction()
+            self.vLegendDict['where'] = currPage['Left'], currPage['Top']
+            
+
+        
+        self.currRaster = self.instruction[self.rasterId]['raster'] if self.rasterId else None
+        
+        #notebook
+        self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
+        self.panelRaster = self._rasterLegend(self.notebook)
+        self.panelVector = self._vectorLegend(self.notebook)  
+        self.OnDefaultSize(None)
+        self.OnRaster(None)
+        self.OnRange(None)
+        self.OnIsLegend(None)
+        self.OnSpan(None)
+        self.OnBorder(None)
+        
+        
+        self._layout(self.notebook)
+        self.notebook.ChangeSelection(page)
+        
+    def _rasterLegend(self, notebook):
+        panel = scrolled.ScrolledPanel(parent = notebook, id = wx.ID_ANY, size = (-1, 500), style = wx.TAB_TRAVERSAL)
+        panel.SetupScrolling(scroll_x = False, scroll_y = True)
+        notebook.AddPage(page = panel, text = _("Raster legend"))
+
+        border = wx.BoxSizer(wx.VERTICAL)
+        # is legend
+        self.isRLegend = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Show raster legend"))
+        self.isRLegend.SetValue(self.rLegendDict['rLegend'])
+        border.Add(item = self.isRLegend, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+        # choose raster
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Source raster")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
+        flexSizer.AddGrowableCol(1)
+        
+        self.rasterDefault = wx.RadioButton(panel, id = wx.ID_ANY, label = _("current raster"), style = wx.RB_GROUP)
+        self.rasterOther = wx.RadioButton(panel, id = wx.ID_ANY, label = _("select raster"))
+        self.rasterDefault.SetValue(self.rLegendDict['rasterDefault'])#
+        self.rasterOther.SetValue(not self.rLegendDict['rasterDefault'])#
+
+        rasterType = self.getRasterType(map = self.currRaster)
+
+        self.rasterCurrent = wx.StaticText(panel, id = wx.ID_ANY, label = _("{0}: type {1}").format(self.currRaster, str(rasterType)))
+        self.rasterSelect = Select( panel, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
+                                    type = 'raster', multiple = False,
+                                    updateOnPopup = True, onPopup = None)
+        self.rasterSelect.SetValue(self.rLegendDict['raster'] if not self.rLegendDict['rasterDefault'] else '')
+        flexSizer.Add(self.rasterDefault, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexSizer.Add(self.rasterCurrent, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border = 10)
+        flexSizer.Add(self.rasterOther, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexSizer.Add(self.rasterSelect, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
+        
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        # type of legend
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Type of legend")))        
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        vbox = wx.BoxSizer(wx.VERTICAL)
+        self.discrete = wx.RadioButton(parent = panel, id = wx.ID_ANY, 
+                        label = " {0} ".format(_("discrete legend (categorical maps)")), style = wx.RB_GROUP)
+        self.continuous = wx.RadioButton(parent = panel, id = wx.ID_ANY, 
+                        label = " {0} ".format(_("continuous color gradient legend (floating point map)")))
+        
+        vbox.Add(self.discrete, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 0)
+        vbox.Add(self.continuous, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 0)
+        sizer.Add(item = vbox, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        # size, position and font
+        self.sizePositionFont(legendType = 'raster', parent = panel, mainSizer = border)
+        
+        # advanced settings
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Advanced legend settings")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        # no data
+        self.nodata = wx.CheckBox(panel, id = wx.ID_ANY, label = _('draw "no data" box'))
+        self.nodata.SetValue(True if self.rLegendDict['nodata'] == 'y' else False)
+        #tickbar
+        self.ticks = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw ticks across color table"))
+        self.ticks.SetValue(True if self.rLegendDict['tickbar'] == 'y' else False)
+        # range
+        if self.rasterId and self.instruction[self.rasterId]['raster']:
+            range = RunCommand('r.info', flags = 'r', read = True, map = self.instruction[self.rasterId]['raster']).strip().split('\n')
+            self.minim, self.maxim = range[0].split('=')[1], range[1].split('=')[1]
+        else:
+            self.minim, self.maxim = 0,0
+        self.range = wx.CheckBox(panel, id = wx.ID_ANY, label = _("range"))
+        self.range.SetValue(self.rLegendDict['range'])
+        self.minText =  wx.StaticText(panel, id = wx.ID_ANY, label = "{0} ({1})".format(_("min:"),self.minim))
+        self.maxText =  wx.StaticText(panel, id = wx.ID_ANY, label = "{0} ({1})".format(_("max:"),self.maxim))
+       
+        self.min = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(self.rLegendDict['min']))
+        self.max = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(self.rLegendDict['max']))
+        
+        gridBagSizer.Add(self.nodata, pos = (0,0), span = (1,5), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.ticks, pos = (1,0), span = (1,5), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.range, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.minText, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
+        gridBagSizer.Add(self.min, pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.maxText, pos = (2,3), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
+        gridBagSizer.Add(self.max, pos = (2,4), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+   
+        panel.SetSizer(border)
+        panel.Fit()
+        
+        # bindings
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterDefault)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterOther)
+        self.Bind(wx.EVT_CHECKBOX, self.OnIsLegend, self.isRLegend)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnDiscrete, self.discrete)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnDiscrete, self.continuous)
+        self.Bind(wx.EVT_CHECKBOX, self.OnDefaultSize, panel.defaultSize)
+        self.Bind(wx.EVT_CHECKBOX, self.OnRange, self.range)
+        self.rasterSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnRaster)
+        
+        return panel
+    
+    def _vectorLegend(self, notebook):
+        panel = scrolled.ScrolledPanel(parent = notebook, id = wx.ID_ANY, size = (-1, 500), style = wx.TAB_TRAVERSAL)
+        panel.SetupScrolling(scroll_x = False, scroll_y = True)
+        notebook.AddPage(page = panel, text = _("Vector legend"))
+
+        border = wx.BoxSizer(wx.VERTICAL)
+        # is legend
+        self.isVLegend = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Show vector legend"))
+        self.isVLegend.SetValue(self.vLegendDict['vLegend'])
+        border.Add(item = self.isVLegend, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        #vector maps, their order, labels
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Source vector maps")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(0,3)
+        gridBagSizer.AddGrowableCol(1,1)
+        
+        vectorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose vector maps and their order in legend"))
+
+        self.vectorListCtrl = CheckListCtrl(panel)
+        
+        self.vectorListCtrl.InsertColumn(0, _("Vector map"))
+        self.vectorListCtrl.InsertColumn(1, _("Label"))
+        if self.vectorId:
+            vectors = sorted(self.instruction[self.vectorId]['list'], key = lambda x: x[3])
+            for vector in vectors:
+                index = self.vectorListCtrl.InsertStringItem(sys.maxint, vector[0].split('@')[0])
+                self.vectorListCtrl.SetStringItem(index, 1, vector[4])
+                self.vectorListCtrl.SetItemData(index, index)
+                self.vectorListCtrl.CheckItem(index, True)
+                if vector[3] == 0:
+                    self.vectorListCtrl.CheckItem(index, False)
+        if not self.vectorId:
+            self.vectorListCtrl.SetColumnWidth(0, 100)
+        else:
+            self.vectorListCtrl.SetColumnWidth(0, wx.LIST_AUTOSIZE)
+        self.vectorListCtrl.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+        
+        self.btnUp = wx.Button(panel, id = wx.ID_ANY, label = _("Up"))
+        self.btnDown = wx.Button(panel, id = wx.ID_ANY, label = _("Down"))
+        self.btnLabel = wx.Button(panel, id = wx.ID_ANY, label = _("Edit label"))
+
+        
+        gridBagSizer.Add(vectorText, pos = (0,0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.vectorListCtrl, pos = (1,0), span = (3,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(self.btnUp, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.btnDown, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.btnLabel, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        # size, position and font
+        self.sizePositionFont(legendType = 'vector', parent = panel, mainSizer = border)
+         
+        # border
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Border")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        flexGridSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
+        
+        self.borderCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw border around legend"))
+        self.borderColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY, style = wx.FNTP_FONTDESC_AS_LABEL)
+        if self.vLegendDict['border'] == 'none':
+            self.borderColorCtrl.SetColour('black')
+            self.borderCheck.SetValue(False)
+        else:
+            self.borderColorCtrl.SetColour(self.vLegendDict['border'])
+            self.borderCheck.SetValue(True)
+            
+        flexGridSizer.Add(self.borderCheck, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)    
+        flexGridSizer.Add(self.borderColorCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        sizer.Add(item = flexGridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.Bind(wx.EVT_BUTTON, self.OnUp, self.btnUp)
+        self.Bind(wx.EVT_BUTTON, self.OnDown, self.btnDown)  
+        self.Bind(wx.EVT_BUTTON, self.OnEditLabel, self.btnLabel)
+        self.Bind(wx.EVT_CHECKBOX, self.OnIsLegend, self.isVLegend)    
+        self.Bind(wx.EVT_CHECKBOX, self.OnSpan, panel.spanRadio)  
+        self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.borderCheck)
+        self.Bind(wx.EVT_FONTPICKER_CHANGED, self.OnFont, panel.font['fontCtrl']) 
+        
+        panel.SetSizer(border)
+        
+        panel.Fit()
+        return panel
+    
+    def sizePositionFont(self, legendType, parent, mainSizer):
+        """!Insert widgets for size, position and font control"""
+        legendDict = self.rLegendDict if legendType == 'raster' else self.vLegendDict
+        panel = parent
+        border = mainSizer
+        
+        # size and position
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Size and position")))        
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        #unit
+        self.AddUnits(parent = panel, dialogDict = legendDict)
+        unitBox = wx.BoxSizer(wx.HORIZONTAL)
+        unitBox.Add(panel.units['unitsLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border = 10)
+        unitBox.Add(panel.units['unitsCtrl'], proportion = 1, flag = wx.ALL, border = 5)
+        sizer.Add(unitBox, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        hBox = wx.BoxSizer(wx.HORIZONTAL)
+        posBox = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Position"))) 
+        posSizer = wx.StaticBoxSizer(posBox, wx.VERTICAL)       
+        sizeBox = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Size"))) 
+        sizeSizer = wx.StaticBoxSizer(sizeBox, wx.VERTICAL) 
+        posGridBagSizer = wx.GridBagSizer(hgap = 10, vgap = 5)
+        posGridBagSizer.AddGrowableRow(2)
+        
+        #position
+        self.AddPosition(parent = panel, dialogDict = legendDict)
+        
+        posGridBagSizer.Add(panel.position['xLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        posGridBagSizer.Add(panel.position['xCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        posGridBagSizer.Add(panel.position['yLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        posGridBagSizer.Add(panel.position['yCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        posGridBagSizer.Add(panel.position['comment'], pos = (2,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0)
+        posSizer.Add(posGridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        
+        #size
+        width = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width:"))
+        w = self.unitConv.convert(value = float(legendDict['width']), fromUnit = 'inch', toUnit = legendDict['unit'])
+        panel.widthCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(w), validator = TCValidator("DIGIT_ONLY"))
+        
+        if legendType == 'raster':
+            panel.defaultSize = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Use default size"))
+            panel.defaultSize.SetValue(legendDict['defaultSize'])
+            
+            panel.heightOrColumnsLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Height:"))
+            h = self.unitConv.convert(value = float(legendDict['height']), fromUnit = 'inch', toUnit = legendDict['unit'])
+            panel.heightOrColumnsCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(h), validator = TCValidator("DIGIT_ONLY"))
+            
+            self.rSizeGBSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+            self.rSizeGBSizer.Add(panel.defaultSize, pos = (0,0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.rSizeGBSizer.Add(width, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.rSizeGBSizer.Add(panel.widthCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.rSizeGBSizer.Add(panel.heightOrColumnsLabel, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.rSizeGBSizer.Add(panel.heightOrColumnsCtrl, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            sizeSizer.Add(self.rSizeGBSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+            
+        if legendType == 'vector':
+            panel.widthCtrl.SetToolTipString(_("Width of the color symbol (for lines)\nin front of the legend text")) 
+            #columns
+            minVect, maxVect = 0, 0
+            if self.vectorId:
+                minVect = 1
+                maxVect = min(10, len(self.instruction[self.vectorId]['list']))
+            cols = wx.StaticText(panel, id = wx.ID_ANY, label = _("Columns:"))
+            panel.colsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, value = "",
+                                        min = minVect, max = maxVect, initial = legendDict['cols'])
+            #span
+            panel.spanRadio = wx.CheckBox(panel, id = wx.ID_ANY, label = _("column span:"))
+            panel.spanTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = '')
+            panel.spanTextCtrl.SetToolTipString(_("Column separation distance between the left edges\n"\
+                                                "of two columns in a multicolumn legend"))
+            if legendDict['span']:
+                panel.spanRadio.SetValue(True)
+                s = self.unitConv.convert(value = float(legendDict['span']), fromUnit = 'inch', toUnit = legendDict['unit'])    
+                panel.spanTextCtrl.SetValue(str(s))
+            else:
+                panel.spanRadio.SetValue(False)
+                
+            self.vSizeGBSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+            self.vSizeGBSizer.AddGrowableCol(1)
+            self.vSizeGBSizer.Add(width, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.vSizeGBSizer.Add(panel.widthCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.vSizeGBSizer.Add(cols, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.vSizeGBSizer.Add(panel.colsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.vSizeGBSizer.Add(panel.spanRadio, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            self.vSizeGBSizer.Add(panel.spanTextCtrl, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+            sizeSizer.Add(self.vSizeGBSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)        
+        
+        hBox.Add(posSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 3)
+        hBox.Add(sizeSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 3)
+        sizer.Add(hBox, proportion = 0, flag = wx.EXPAND, border = 0)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        
+        # font
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Font settings")))
+        fontSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
+        flexSizer.AddGrowableCol(1)
+        
+        if legendType == 'raster':
+            self.AddFont(parent = panel, dialogDict = legendDict, color = True)
+        else:
+            self.AddFont(parent = panel, dialogDict = legendDict, color = False)            
+        flexSizer.Add(panel.font['fontLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexSizer.Add(panel.font['fontCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexSizer.Add(panel.font['fontSizeLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexSizer.Add(panel.font['fontSizeCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        if legendType == 'raster':
+            flexSizer.Add(panel.font['colorLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+            flexSizer.Add(panel.font['colorCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        fontSizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = fontSizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)    
+            
+
+
+
+    #   some enable/disable methods  
+        
+    def OnIsLegend(self, event):
+        """!Enables and disables controls, it depends if raster or vector legend is checked"""
+        page = self.notebook.GetSelection()
+        if page == 0 or event is None:
+            children = self.panelRaster.GetChildren()
+            if self.isRLegend.GetValue():
+                for i,widget in enumerate(children):
+                        widget.Enable()
+                self.OnRaster(None)
+                self.OnDefaultSize(None)
+                self.OnRange(None)
+                self.OnDiscrete(None)
+            else:
+                for i,widget in enumerate(children):
+                    if i != 0:
+                        widget.Disable()
+        if page == 1 or event is None:
+            children = self.panelVector.GetChildren()
+            if self.isVLegend.GetValue():
+                for i, widget in enumerate(children):
+                        widget.Enable()
+                self.OnSpan(None)
+                self.OnBorder(None)
+            else:
+                for i, widget in enumerate(children):
+                    if i != 0:
+                        widget.Disable()
+                    
+    def OnRaster(self, event):
+        if self.rasterDefault.GetValue():#default
+            self.rasterSelect.Disable()
+            type = self.getRasterType(self.currRaster)
+        else:#select raster
+            self.rasterSelect.Enable()
+            map = self.rasterSelect.GetValue()
+            type = self.getRasterType(map)
+  
+        if type == 'CELL':
+            self.discrete.SetValue(True)
+        elif type in ('FCELL', 'DCELL'):
+            self.continuous.SetValue(True)
+        if event is None:
+            if self.rLegendDict['discrete'] == 'y':
+                self.discrete.SetValue(True)
+            elif self.rLegendDict['discrete'] == 'n':
+                self.continuous.SetValue(True)
+        self.OnDiscrete(None)
+        
+    def OnDiscrete(self, event):
+        """! Change control according to the type of legend"""
+        enabledSize = self.panelRaster.heightOrColumnsCtrl.IsEnabled()
+        self.panelRaster.heightOrColumnsCtrl.Destroy()
+        if self.discrete.GetValue():
+            self.panelRaster.heightOrColumnsLabel.SetLabel(_("Columns:"))
+            self.panelRaster.heightOrColumnsCtrl = wx.SpinCtrl(self.panelRaster, id = wx.ID_ANY, value = "", min = 1, max = 10, initial = self.rLegendDict['cols'])
+            self.panelRaster.heightOrColumnsCtrl.Enable(enabledSize)
+            self.nodata.Enable()
+            self.range.Disable()
+            self.min.Disable()
+            self.max.Disable()
+            self.minText.Disable()
+            self.maxText.Disable()
+            self.ticks.Disable()
+        else:
+            self.panelRaster.heightOrColumnsLabel.SetLabel(_("Height:"))
+            h = self.unitConv.convert(value = float(self.rLegendDict['height']), fromUnit = 'inch', toUnit = self.rLegendDict['unit'])
+            self.panelRaster.heightOrColumnsCtrl = wx.TextCtrl(self.panelRaster, id = wx.ID_ANY,
+                                                    value = str(h), validator = TCValidator("DIGIT_ONLY"))
+            self.panelRaster.heightOrColumnsCtrl.Enable(enabledSize)
+            self.nodata.Disable()
+            self.range.Enable()
+            if self.range.GetValue():
+                self.minText.Enable()
+                self.maxText.Enable()
+                self.min.Enable()
+                self.max.Enable()
+            self.ticks.Enable()
+        
+        self.rSizeGBSizer.Add(self.panelRaster.heightOrColumnsCtrl, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.panelRaster.Layout()
+        self.panelRaster.Fit()
+        
+        
+    def OnDefaultSize(self, event):
+        if self.panelRaster.defaultSize.GetValue():
+            self.panelRaster.widthCtrl.Disable()
+            self.panelRaster.heightOrColumnsCtrl.Disable()        
+        else:    
+            self.panelRaster.widthCtrl.Enable()
+            self.panelRaster.heightOrColumnsCtrl.Enable()
+        
+    def OnRange(self, event):
+        if not self.range.GetValue():
+            self.min.Disable()        
+            self.max.Disable()
+            self.minText.Disable()
+            self.maxText.Disable()
+        else:
+            self.min.Enable()        
+            self.max.Enable() 
+            self.minText.Enable()
+            self.maxText.Enable()           
+     
+    def OnUp(self, event):
+        """!Moves selected map up, changes order in vector legend"""
+        if self.vectorListCtrl.GetFirstSelected() != -1:
+            pos = self.vectorListCtrl.GetFirstSelected()
+            if pos:
+                idx1 = self.vectorListCtrl.GetItemData(pos) - 1
+                idx2 = self.vectorListCtrl.GetItemData(pos - 1) + 1
+                self.vectorListCtrl.SetItemData(pos, idx1) 
+                self.vectorListCtrl.SetItemData(pos - 1, idx2) 
+                self.vectorListCtrl.SortItems(cmp)
+                selected = (pos - 1) if pos > 0 else 0
+                self.vectorListCtrl.Select(selected)
+       
+    def OnDown(self, event):
+        """!Moves selected map down, changes order in vector legend"""
+        if self.vectorListCtrl.GetFirstSelected() != -1:
+            pos = self.vectorListCtrl.GetFirstSelected()
+            if pos != self.vectorListCtrl.GetItemCount() - 1:
+                idx1 = self.vectorListCtrl.GetItemData(pos) + 1
+                idx2 = self.vectorListCtrl.GetItemData(pos + 1) - 1
+                self.vectorListCtrl.SetItemData(pos, idx1) 
+                self.vectorListCtrl.SetItemData(pos + 1, idx2) 
+                self.vectorListCtrl.SortItems(cmp)
+                selected = (pos + 1) if pos < self.vectorListCtrl.GetItemCount() -1 else self.vectorListCtrl.GetItemCount() -1
+                self.vectorListCtrl.Select(selected)
+                
+    def OnEditLabel(self, event):
+        """!Change legend label of vector map"""
+        if self.vectorListCtrl.GetFirstSelected() != -1:
+            idx = self.vectorListCtrl.GetFirstSelected()
+            default = self.vectorListCtrl.GetItem(idx, 1).GetText()
+            dlg = wx.TextEntryDialog(self, message = _("Edit legend label:"), caption = _("Edit label"),
+                                    defaultValue = default, style = wx.OK|wx.CANCEL|wx.CENTRE)
+            if dlg.ShowModal() == wx.ID_OK:
+                new = dlg.GetValue()
+                self.vectorListCtrl.SetStringItem(idx, 1, new)
+            dlg.Destroy()
+        
+    def OnSpan(self, event):
+        self.panelVector.spanTextCtrl.Enable(self.panelVector.spanRadio.GetValue())
+    def OnFont(self, event):
+        """!Changes default width according to fontsize, width [inch] = fontsize[pt]/24"""   
+##        fontsize = self.panelVector.font['fontCtrl'].GetSelectedFont().GetPointSize() 
+        fontsize = self.panelVector.font['fontSizeCtrl'].GetValue()
+        unit = self.panelVector.units['unitsCtrl'].GetStringSelection()
+        w = fontsize/24.
+        width = self.unitConv.convert(value = w, fromUnit = 'inch', toUnit = unit)
+        self.panelVector.widthCtrl.SetValue("{0:3.2f}".format(width))
+        
+    def OnBorder(self, event):
+        """!Enables/disables colorPickerCtrl for border"""    
+        self.borderColorCtrl.Enable(self.borderCheck.GetValue())
+        
+    def updateRasterLegend(self):
+        """!Save information from raster legend dialog to dictionary"""
+
+        #is raster legend
+        if not self.isRLegend.GetValue():
+            self.rLegendDict['rLegend'] = False
+        else:
+            self.rLegendDict['rLegend'] = True
+        #units
+        currUnit = self.panelRaster.units['unitsCtrl'].GetStringSelection()
+        self.rLegendDict['unit'] = currUnit
+        # raster
+        if self.rasterDefault.GetValue():
+            self.rLegendDict['rasterDefault'] = True
+            self.rLegendDict['raster'] = self.currRaster
+        else:
+            self.rLegendDict['rasterDefault'] = False
+            self.rLegendDict['raster'] = self.rasterSelect.GetValue()
+        if self.rLegendDict['rLegend'] and not self.rLegendDict['raster']:
+            wx.MessageBox(message = _("No raster map selected!"),
+                                    caption = _('No raster'), style = wx.OK|wx.ICON_ERROR)
+            return False
+            
+        if self.rLegendDict['raster']:
+            # type and range of map
+            rasterType = self.getRasterType(self.rLegendDict['raster'])
+            self.rLegendDict['type'] = rasterType
+            
+            range = RunCommand('r.info', flags = 'r', read = True, map = self.rLegendDict['raster']).strip().split('\n')
+            minim, maxim = range[0].split('=')[1], range[1].split('=')[1]
+            
+            #discrete
+            if self.discrete.GetValue():
+                self.rLegendDict['discrete'] = 'y'
+            else:
+                self.rLegendDict['discrete'] = 'n'   
+                    
+            # font 
+            self.rLegendDict['font'] = self.panelRaster.font['fontCtrl'].GetStringSelection()
+            self.rLegendDict['fontsize'] = self.panelRaster.font['fontSizeCtrl'].GetValue()
+##            font = self.panelRaster.font['fontCtrl'].GetSelectedFont()
+##            self.rLegendDict['font'] = font.GetFaceName()
+##            self.rLegendDict['fontsize'] = font.GetPointSize()
+            self.rLegendDict['color'] = self.panelRaster.font['colorCtrl'].GetColour().GetAsString(wx.C2S_NAME)
+            dc = wx.PaintDC(self)
+            font = dc.GetFont()
+            dc.SetFont(wx.Font(   pointSize = self.rLegendDict['fontsize'], family = font.GetFamily(),
+                                                style = font.GetStyle(), weight = wx.FONTWEIGHT_NORMAL))
+            # position
+            x = self.unitConv.convert(value = float(self.panelRaster.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
+            y = self.unitConv.convert(value = float(self.panelRaster.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
+            self.rLegendDict['where'] = (x, y)
+            # estimated size
+            if not self.panelRaster.defaultSize.GetValue():
+                self.rLegendDict['defaultSize'] = False
+            
+                width = self.unitConv.convert(value = float(self.panelRaster.widthCtrl.GetValue()), fromUnit = currUnit, toUnit = 'inch')
+                height = self.unitConv.convert(value = float(self.panelRaster.heightOrColumnsCtrl.GetValue()), fromUnit = currUnit, toUnit = 'inch')
+            
+                if self.rLegendDict['discrete'] == 'n':  #rasterType in ('FCELL', 'DCELL'):
+                    self.rLegendDict['width'] = width 
+                    self.rLegendDict['height'] = height
+                    textPart = self.unitConv.convert(value = dc.GetTextExtent(maxim)[0], fromUnit = 'pixel', toUnit = 'inch')
+                    drawWidth = width + textPart
+                    drawHeight = height
+                    self.rLegendDict['rect'] = wx.Rect2D(x = x, y = y, w = drawWidth, h = drawHeight)
+                else: #categorical map
+                    self.rLegendDict['width'] = width 
+                    self.rLegendDict['cols'] = self.panelRaster.heightOrColumnsCtrl.GetValue() 
+                    cat = RunCommand(   'r.category', read = True, map = self.rLegendDict['raster'],
+                                        fs = ':').strip().split('\n')
+                    rows = ceil(float(len(cat))/self.rLegendDict['cols'])
+
+                    drawHeight = self.unitConv.convert(value =  1.5 *rows * self.rLegendDict['fontsize'], fromUnit = 'point', toUnit = 'inch')
+                    self.rLegendDict['rect'] = wx.Rect2D(x = x, y = y, w = width, h = drawHeight)
+
+            else:
+                self.rLegendDict['defaultSize'] = True
+                if self.rLegendDict['discrete'] == 'n':  #rasterType in ('FCELL', 'DCELL'):
+                    textPart = self.unitConv.convert(value = dc.GetTextExtent(maxim)[0], fromUnit = 'pixel', toUnit = 'inch')
+                    drawWidth = self.unitConv.convert( value = self.rLegendDict['fontsize'] * 2, 
+                                                    fromUnit = 'point', toUnit = 'inch') + textPart
+                                
+                    drawHeight = self.unitConv.convert(value = self.rLegendDict['fontsize'] * 10,
+                                                    fromUnit = 'point', toUnit = 'inch')
+                    self.rLegendDict['rect'] = wx.Rect2D(x = x, y = y, w = drawWidth, h = drawHeight)
+                else:#categorical map
+                    self.rLegendDict['cols'] = self.panelRaster.heightOrColumnsCtrl.GetValue()
+                    cat = RunCommand(   'r.category', read = True, map = self.rLegendDict['raster'],
+                                        fs = ':').strip().split('\n')
+                    if len(cat) == 1:# for discrete FCELL
+                        rows = float(maxim)
+                    else:
+                        rows = ceil(float(len(cat))/self.rLegendDict['cols'])
+                    drawHeight = self.unitConv.convert(value =  1.5 *rows * self.rLegendDict['fontsize'],
+                                                    fromUnit = 'point', toUnit = 'inch')
+                    paperWidth = self.instruction[self.pageId]['Width']- self.instruction[self.pageId]['Right']\
+                                                                        - self.instruction[self.pageId]['Left']
+                    drawWidth = (paperWidth / self.rLegendDict['cols']) * (self.rLegendDict['cols'] - 1) + 1
+                    self.rLegendDict['rect'] = wx.Rect2D(x = x, y = y, w = drawWidth, h = drawHeight)
+
+
+                         
+            # no data
+            if self.rLegendDict['discrete'] == 'y':
+                if self.nodata.GetValue():
+                    self.rLegendDict['nodata'] = 'y'
+                else:
+                    self.rLegendDict['nodata'] = 'n'
+            # tickbar
+            elif self.rLegendDict['discrete'] == 'n':
+                if self.ticks.GetValue():
+                    self.rLegendDict['tickbar'] = 'y'
+                else:
+                    self.rLegendDict['tickbar'] = 'n'
+            # range
+                if self.range.GetValue():
+                    self.rLegendDict['range'] = True
+                    self.rLegendDict['min'] = self.min.GetValue()
+                    self.rLegendDict['max'] = self.max.GetValue()
+                else:
+                    self.rLegendDict['range'] = False
+         
+        if not self.id[0] in self.instruction:
+            rasterLegend = RasterLegend(self.id[0])
+            self.instruction.AddInstruction(rasterLegend)
+        self.instruction[self.id[0]].SetInstruction(self.rLegendDict)
+
+        if self.id[0] not in self.parent.objectId:
+            self.parent.objectId.append(self.id[0])
+        return True
+                    
+    def updateVectorLegend(self):
+        """!Save information from vector legend dialog to dictionary"""
+
+        #is vector legend
+        if not self.isVLegend.GetValue():
+            self.vLegendDict['vLegend'] = False
+        else:
+            self.vLegendDict['vLegend'] = True   
+        if self.vLegendDict['vLegend'] == True and self.vectorId is not None:
+            # labels
+            #reindex order
+            idx = 1
+            for item in range(self.vectorListCtrl.GetItemCount()):
+                if self.vectorListCtrl.IsChecked(item):
+                    self.vectorListCtrl.SetItemData(item, idx)
+                    idx += 1
+                else:
+                    self.vectorListCtrl.SetItemData(item, 0)
+            if idx == 1: 
+                self.vLegendDict['vLegend'] = False     
+            else:
+                vList = self.instruction[self.vectorId]['list']
+                for i, vector in enumerate(vList):
+                    item = self.vectorListCtrl.FindItem(start = -1, str = vector[0].split('@')[0])
+                    vList[i][3] = self.vectorListCtrl.GetItemData(item)
+                    vList[i][4] = self.vectorListCtrl.GetItem(item, 1).GetText()
+                vmaps = self.instruction.FindInstructionByType('vProperties', list = True)
+                for vmap, vector in zip(vmaps, vList):
+                    self.instruction[vmap.id]['lpos'] = vector[3]
+                    self.instruction[vmap.id]['label'] = vector[4]
+                #units
+                currUnit = self.panelVector.units['unitsCtrl'].GetStringSelection()
+                self.vLegendDict['unit'] = currUnit
+                # position
+                x = self.unitConv.convert(value = float(self.panelVector.position['xCtrl'].GetValue()),
+                                                                fromUnit = currUnit, toUnit = 'inch')
+                y = self.unitConv.convert(value = float(self.panelVector.position['yCtrl'].GetValue()),
+                                                                fromUnit = currUnit, toUnit = 'inch')
+                self.vLegendDict['where'] = (x, y)
+                
+                # font 
+                self.vLegendDict['font'] = self.panelVector.font['fontCtrl'].GetStringSelection()
+                self.vLegendDict['fontsize'] = self.panelVector.font['fontSizeCtrl'].GetValue()
+##                self.vLegendDict['font'] = font.GetFaceName()
+##                self.vLegendDict['fontsize'] = font.GetPointSize()
+                dc = wx.PaintDC(self)
+                font = dc.GetFont()
+                dc.SetFont(wx.Font(   pointSize = self.vLegendDict['fontsize'], family = font.GetFamily(),
+                                                style = font.GetStyle(), weight = wx.FONTWEIGHT_NORMAL))
+                #size
+                width = self.unitConv.convert(value = float(self.panelVector.widthCtrl.GetValue()),
+                                                        fromUnit = currUnit, toUnit = 'inch')
+                self.vLegendDict['width'] = width
+                self.vLegendDict['cols'] = self.panelVector.colsCtrl.GetValue()
+                if self.panelVector.spanRadio.GetValue() and self.panelVector.spanTextCtrl.GetValue():
+                    self.vLegendDict['span'] = self.panelVector.spanTextCtrl.GetValue()
+                else:
+                    self.vLegendDict['span'] = None
+                    
+                # size estimation
+                vectors = self.instruction[self.vectorId]['list']
+                labels = [vector[4] for vector in vectors if vector[3] != 0]
+                extent = dc.GetTextExtent(max(labels, key = len))
+                wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'pixel', toUnit = 'inch')
+                hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'pixel', toUnit = 'inch')
+                w = (width + wExtent) * self.vLegendDict['cols']
+                h = len(labels) * hExtent / self.vLegendDict['cols']
+                h *= 1.1
+                self.vLegendDict['rect'] = wx.Rect2D(x, y, w, h)
+                
+                #border
+                if self.borderCheck.GetValue():
+                    self.vLegendDict['border'] = self.borderColorCtrl.GetColour().GetAsString(flags=wx.C2S_NAME)
+                else:
+                    self.vLegendDict['border'] = 'none'
+             
+        if not self.id[1] in self.instruction:
+            vectorLegend = VectorLegend(self.id[1])
+            self.instruction.AddInstruction(vectorLegend)
+        self.instruction[self.id[1]].SetInstruction(self.vLegendDict)
+        if self.id[1] not in self.parent.objectId:
+            self.parent.objectId.append(self.id[1])
+        return True
+    
+    def update(self):
+        okR = self.updateRasterLegend()
+        okV = self.updateVectorLegend()
+        if okR and okV:
+            return True
+        return False
+        
+    def getRasterType(self, map):
+        rasterType = RunCommand('r.info', flags = 't', read = True, 
+                                map = map).strip().split('=')
+        return (rasterType[1] if rasterType[0] else None)
+        
+
+             
+class MapinfoDialog(PsmapDialog):
+    def __init__(self, parent, id, settings):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "Mapinfo settings", settings = settings)
+        self.instruction = settings
+        if self.id is not None:
+            self.mapinfoDict = self.instruction[id].GetInstruction()
+        else:
+            self.id = wx.NewId()
+            mapinfo = Mapinfo(self.id)
+
+            self.mapinfoDict = mapinfo.GetInstruction()
+            page = self.instruction.FindInstructionByType('page').GetInstruction()
+            self.mapinfoDict['where'] = page['Left'], page['Top']
+
+        self.panel = self._mapinfoPanel()
+        
+        self._layout(self.panel)
+        self.OnIsBackground(None)
+        self.OnIsBorder(None)
+
+
+    def _mapinfoPanel(self):
+        panel = wx.Panel(parent = self, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        #panel.SetupScrolling(scroll_x = False, scroll_y = True)
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        
+        # position
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Position")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(1)
+        
+        self.AddPosition(parent = panel, dialogDict = self.mapinfoDict)
+        self.AddUnits(parent = panel, dialogDict = self.mapinfoDict)
+        gridBagSizer.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        # font
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Font settings")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(1)
+        
+        self.AddFont(parent = panel, dialogDict = self.mapinfoDict)#creates font color too, used below
+        
+##        gridBagSizer.Add(panel.font['fontLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+##        gridBagSizer.Add(panel.font['fontCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+##        gridBagSizer.Add(panel.font['colorLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+##        gridBagSizer.Add(panel.font['colorCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+
+        gridBagSizer.Add(panel.font['fontLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.font['fontCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.font['fontSizeLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.font['fontSizeCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.font['colorLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        gridBagSizer.Add(panel.font['colorCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(item = gridBagSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        # colors
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Color settings")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
+        flexSizer.AddGrowableCol(1)
+        
+        self.colors = {}
+        self.colors['borderCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use border color:"))
+        self.colors['backgroundCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use background color:"))
+        self.colors['borderColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.colors['backgroundColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        
+        self.colors['borderCtrl'].SetValue(True if self.mapinfoDict['border'] != 'none' else False)
+        self.colors['backgroundCtrl'].SetValue(True if self.mapinfoDict['background'] != 'none' else False)
+        self.colors['borderColor'].SetColour(self.mapinfoDict['border']
+                                            if self.mapinfoDict['border'] != 'none' else 'black')
+##        self.colors['borderColor'].SetColour(convertRGB(self.mapinfoDict['border']) 
+##                                            if self.mapinfoDict['border'] != 'none' else 'black')
+        self.colors['backgroundColor'].SetColour(self.mapinfoDict['background']
+                                            if self.mapinfoDict['background'] != 'none' else 'black')
+##        self.colors['backgroundColor'].SetColour(convertRGB(self.mapinfoDict['background']) 
+##                                            if self.mapinfoDict['background'] != 'none' else 'black')
+        
+        flexSizer.Add(self.colors['borderCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexSizer.Add(self.colors['borderColor'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexSizer.Add(self.colors['backgroundCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexSizer.Add(self.colors['backgroundColor'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        panel.SetSizer(border)
+        
+
+        self.Bind(wx.EVT_CHECKBOX, self.OnIsBorder, self.colors['borderCtrl'])
+        self.Bind(wx.EVT_CHECKBOX, self.OnIsBackground, self.colors['backgroundCtrl'])
+        
+        return panel
+    
+    def OnIsBackground(self, event):
+        if self.colors['backgroundCtrl'].GetValue():
+            self.colors['backgroundColor'].Enable()
+        else:
+            self.colors['backgroundColor'].Disable()
+                        
+    def OnIsBorder(self, event):
+        if self.colors['borderCtrl'].GetValue():
+            self.colors['borderColor'].Enable()
+        else:
+            self.colors['borderColor'].Disable() 
+                           
+                    
+    def update(self):
+
+        #units
+        currUnit = self.panel.units['unitsCtrl'].GetStringSelection()
+        self.mapinfoDict['unit'] = currUnit
+        # position
+        x = self.panel.position['xCtrl'].GetValue() if self.panel.position['xCtrl'].GetValue() else self.mapinfoDict['where'][0]
+        y = self.panel.position['yCtrl'].GetValue() if self.panel.position['yCtrl'].GetValue() else self.mapinfoDict['where'][1]
+        x = self.unitConv.convert(value = float(self.panel.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
+        y = self.unitConv.convert(value = float(self.panel.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
+        self.mapinfoDict['where'] = (x, y)
+        # font
+        self.mapinfoDict['font'] = font = self.panel.font['fontCtrl'].GetStringSelection()
+        self.mapinfoDict['fontsize'] = self.panel.font['fontSizeCtrl'].GetValue()
+##        font = self.panel.font['fontCtrl'].GetSelectedFont()
+##        self.mapinfoDict['font'] = font.GetFaceName()
+##        self.mapinfoDict['fontsize'] = font.GetPointSize()
+        #colors
+        self.mapinfoDict['color'] = self.panel.font['colorCtrl'].GetColour().GetAsString(flags=wx.C2S_NAME)
+        self.mapinfoDict['background'] = self.colors['backgroundColor'].GetColour().GetAsString(flags=wx.C2S_NAME)\
+                                        if self.colors['backgroundCtrl'].GetValue() else 'none'
+##        self.mapinfoDict['background'] = (convertRGB(self.colors['backgroundColor'].GetColour())
+##                                        if self.colors['backgroundCtrl'].GetValue() else 'none') 
+        self.mapinfoDict['border'] = self.colors['borderColor'].GetColour().GetAsString(flags=wx.C2S_NAME)\
+                                        if self.colors['borderCtrl'].GetValue() else 'none'
+##        self.mapinfoDict['border'] = (convertRGB(self.colors['borderColor'].GetColour())
+##                                        if self.colors['borderCtrl'].GetValue() else 'none')
+        
+        # estimation of size
+        w = self.mapinfoDict['fontsize'] * 20 # any better estimation? 
+        h = self.mapinfoDict['fontsize'] * 7
+        width = self.unitConv.convert(value = w, fromUnit = 'point', toUnit = 'inch')
+        height = self.unitConv.convert(value = h, fromUnit = 'point', toUnit = 'inch')
+        self.mapinfoDict['rect'] = wx.Rect2D(x = x, y = y, w = width, h = height)
+        
+        if self.id not in self.instruction:
+            mapinfo = Mapinfo(self.id)
+            self.instruction.AddInstruction(mapinfo)
+        self.instruction[self.id].SetInstruction(self.mapinfoDict)
+
+        if self.id not in self.parent.objectId:
+            self.parent.objectId.append(self.id)
+            
+        return True
+      
+    
+class ScalebarDialog(PsmapDialog):
+    """!Dialog for scale bar"""
+    def __init__(self, parent, id, settings):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "Scale bar settings", settings = settings)
+        self.instruction = settings
+        if self.id is not None:
+            self.scalebarDict = self.instruction[id].GetInstruction()
+        else:
+            self.id = wx.NewId()
+            scalebar = Scalebar(self.id)
+            self.scalebarDict = scalebar.GetInstruction()
+            page = self.instruction.FindInstructionByType('page').GetInstruction()
+            self.scalebarDict['where'] = page['Left'], page['Top']
+
+
+            
+        self.panel = self._scalebarPanel()
+        
+        self._layout(self.panel)
+        
+        self.mapUnit = projInfo()['units']
+        if projInfo()['proj'] == 'xy':
+            self.mapUnit = 'meters'
+        if self.mapUnit not in self.unitConv.getAllUnits():
+            wx.MessageBox(message = _("Units of current projection are not supported,\n meters will be used!"),
+                            caption = _('Unsupported units'),
+                                    style = wx.OK|wx.ICON_ERROR)
+            self.mapUnit = 'meters'
+            
+    def _scalebarPanel(self):
+        panel = wx.Panel(parent = self, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
+        border = wx.BoxSizer(wx.VERTICAL)
+        #        
+        # position
+        #
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Position")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(1)
+        
+        self.AddUnits(parent = panel, dialogDict = self.scalebarDict)
+        self.AddPosition(parent = panel, dialogDict = self.scalebarDict)
+        
+        if self.scalebarDict['rect']: # set position, ref point is center and not left top corner
+            
+            x = self.unitConv.convert(value = self.scalebarDict['where'][0] - self.scalebarDict['rect'].Get()[2]/2,
+                                                    fromUnit = 'inch', toUnit = self.scalebarDict['unit'])
+            y = self.unitConv.convert(value = self.scalebarDict['where'][1] - self.scalebarDict['rect'].Get()[3]/2,
+                                                    fromUnit = 'inch', toUnit = self.scalebarDict['unit'])
+            panel.position['xCtrl'].SetValue("{0:5.3f}".format(x))
+            panel.position['yCtrl'].SetValue("{0:5.3f}".format(y))
+        
+        gridBagSizer.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        #
+        # size
+        #
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Size")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(1)
+        
+        lengthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Length:"))
+        heightText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Height:"))
+        
+        self.lengthTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, validator = TCValidator('DIGIT_ONLY'))
+        self.lengthTextCtrl.SetToolTipString(_("Scalebar length is given in map units"))
+        
+        self.heightTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, validator = TCValidator('DIGIT_ONLY'))
+        self.heightTextCtrl.SetToolTipString(_("Scalebar height is real height on paper"))
+        
+        choices = ['default'] + self.unitConv.getMapUnits()
+        self.unitsLength = wx.Choice(panel, id = wx.ID_ANY, choices = choices)
+        choices = self.unitConv.getPageUnits()
+        self.unitsHeight = wx.Choice(panel, id = wx.ID_ANY, choices = choices)
+        
+        # set values
+        ok = self.unitsLength.SetStringSelection(self.scalebarDict['unitsLength'])
+        if not ok:
+            if self.scalebarDict['unitsLength'] == 'auto':
+                 self.unitsLength.SetSelection(0)
+            elif self.scalebarDict['unitsLength'] == 'nautmiles':
+                 self.unitsLength.SetStringSelection("nautical miles")                
+        self.unitsHeight.SetStringSelection(self.scalebarDict['unitsHeight'])
+        if self.scalebarDict['length']:
+            self.lengthTextCtrl.SetValue(str(self.scalebarDict['length']))
+        else: #estimate default
+            reg = grass.region()
+            w = int((reg['e'] - reg['w'])/3)
+            w = round(w, -len(str(w)) + 2) #12345 -> 12000
+            self.lengthTextCtrl.SetValue(str(w))
+            
+        h = self.unitConv.convert(value = self.scalebarDict['height'], fromUnit = 'inch',
+                                                toUnit =  self.scalebarDict['unitsHeight']) 
+        self.heightTextCtrl.SetValue(str(h))
+        
+        gridBagSizer.Add(lengthText, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.lengthTextCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.unitsLength, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(heightText, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.heightTextCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.unitsHeight, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        #
+        #style
+        #
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Style")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        
+        
+        sbTypeText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Type:"))
+        self.sbCombo = wx.combo.BitmapComboBox(panel, style = wx.CB_READONLY)
+        # only temporary, images must be moved away
+        imagePath = os.path.join(globalvar.ETCIMGDIR, "scalebar-fancy.png"), os.path.join(globalvar.ETCIMGDIR, "scalebar-simple.png") 
+        for item, path in zip(['fancy', 'simple'], imagePath):
+            if not os.path.exists(path):
+                bitmap = wx.EmptyBitmap(0,0)
+            else:
+                bitmap = wx.Bitmap(path)
+            self.sbCombo.Append(item = item, bitmap = bitmap, clientData = item[0])
+        #self.sbCombo.Append(item = 'simple', bitmap = wx.Bitmap("./images/scalebar-simple.png"), clientData = 's')
+        if self.scalebarDict['scalebar'] == 'f':
+            self.sbCombo.SetSelection(0)
+        elif self.scalebarDict['scalebar'] == 's':
+            self.sbCombo.SetSelection(1)
+            
+        sbSegmentsText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Number of segments:"))
+        self.sbSegmentsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 4)
+        self.sbSegmentsCtrl.SetValue(self.scalebarDict['segment'])
+        
+        sbLabelsText1 = wx.StaticText(panel, id = wx.ID_ANY, label = _("Label every "))
+        sbLabelsText2 = wx.StaticText(panel, id = wx.ID_ANY, label = _("segments"))
+        self.sbLabelsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 1)
+        self.sbLabelsCtrl.SetValue(self.scalebarDict['numbers'])
+        
+        #font
+        fontsizeText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Font size:"))
+        self.fontsizeCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 4, max = 30, initial = 10)
+        self.fontsizeCtrl.SetValue(self.scalebarDict['fontsize'])
+        
+        self.backgroundCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent text background"))
+        self.backgroundCheck.SetValue(False if self.scalebarDict['background'] == 'y' else True)
+
+            
+        gridBagSizer.Add(sbTypeText, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.sbCombo, pos = (0,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+        gridBagSizer.Add(sbSegmentsText, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.sbSegmentsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(sbLabelsText1, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.sbLabelsCtrl, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(sbLabelsText2, pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(fontsizeText, pos = (3,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.fontsizeCtrl, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.backgroundCheck, pos = (4, 0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        panel.SetSizer(border)
+        
+        return panel
+
+                           
+                    
+    def update(self):
+        """!Save information from dialog"""
+
+        #units
+        currUnit = self.panel.units['unitsCtrl'].GetStringSelection()
+        self.scalebarDict['unit'] = currUnit
+        # position
+        x = self.panel.position['xCtrl'].GetValue() if self.panel.position['xCtrl'].GetValue() else self.scalebarDict['where'][0]
+        y = self.panel.position['yCtrl'].GetValue() if self.panel.position['yCtrl'].GetValue() else self.scalebarDict['where'][1]
+        x = self.unitConv.convert(value = float(self.panel.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
+        y = self.unitConv.convert(value = float(self.panel.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
+        
+        
+        # size
+        
+        # height
+        self.scalebarDict['unitsHeight'] = self.unitsHeight.GetStringSelection()
+        try:
+            height = float(self.heightTextCtrl.GetValue())  
+            height = self.unitConv.convert(value = height, fromUnit = self.scalebarDict['unitsHeight'], toUnit = 'inch') 
+        except (ValueError, SyntaxError):
+            height = 0.1 #default in inch
+        self.scalebarDict['height'] = height    
+        
+        #length
+        selected = self.unitsLength.GetStringSelection()
+        if selected == 'default':
+            selected = 'auto'
+        elif selected == 'nautical miles':
+            selected = 'nautmiles'
+        self.scalebarDict['unitsLength'] = selected
+        try:
+            length = float(self.lengthTextCtrl.GetValue())
+        except (ValueError, SyntaxError):
+            wx.MessageBox(message = _("Length of scale bar is not defined"),
+                                    caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR)
+            return False
+        self.scalebarDict['length'] = length
+        
+        if self.scalebarDict['unitsLength'] != 'auto':
+            length = self.unitConv.convert(value = length, fromUnit = self.unitsLength.GetStringSelection(), toUnit = 'inch')
+        else:
+            length = self.unitConv.convert(value = length, fromUnit = self.mapUnit, toUnit = 'inch')
+        # estimation of size
+        map = self.instruction.FindInstructionByType('map')
+        if not map:
+            map = self.instruction.FindInstructionByType('initMap')
+        mapId = map.id
+
+        length *= self.instruction[mapId]['scale']
+        length *= 1.1 #for numbers on the edge
+        fontsize = 10
+        height = height + 2 * self.unitConv.convert(value = fontsize, fromUnit = 'point', toUnit = 'inch') 
+        self.scalebarDict['rect'] = wx.Rect2D(x, y, length, height)
+          
+        
+        self.scalebarDict['where'] = self.scalebarDict['rect'].GetCentre()  
+
+        #style
+        self.scalebarDict['scalebar'] = self.sbCombo.GetClientData(self.sbCombo.GetSelection())
+        self.scalebarDict['segment'] = self.sbSegmentsCtrl.GetValue()
+        self.scalebarDict['numbers'] = self.sbLabelsCtrl.GetValue()
+        self.scalebarDict['fontsize'] = self.fontsizeCtrl.GetValue()
+        self.scalebarDict['background'] = 'n' if self.backgroundCheck.GetValue() else 'y'
+
+
+        if self.id not in self.instruction:
+            scalebar = Scalebar(self.id)
+            self.instruction.AddInstruction(scalebar)
+        self.instruction[self.id].SetInstruction(self.scalebarDict)
+        if self.id not in self.parent.objectId:
+            self.parent.objectId.append(self.id)
+            
+        return True
+    
+      
+class TextDialog(PsmapDialog):
+    def __init__(self, parent, id, settings):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "Text settings", settings = settings)
+        
+        if self.id is not None:
+            self.textDict = self.instruction[id].GetInstruction()
+        else:
+            self.id = wx.NewId()  
+            text = Text(self.id)
+            self.textDict = text.GetInstruction()
+            page = self.instruction.FindInstructionByType('page').GetInstruction()
+            self.textDict['where'] = page['Left'], page['Top'] 
+                
+        map = self.instruction.FindInstructionByType('map')
+        if not map:
+            map = self.instruction.FindInstructionByType('initMap')
+        self.mapId = map.id
+
+
+        self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(self, mapId = self.mapId, x = self.textDict['where'][0], y = self.textDict['where'][1], paperToMap = True)
+        
+        notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)     
+        self.textPanel = self._textPanel(notebook)
+        self.positionPanel = self._positionPanel(notebook)
+        self.OnBackground(None)
+        self.OnHighlight(None)
+        self.OnBorder(None)
+        self.OnPositionType(None)
+        self.OnRotation(None)
+     
+        self._layout(notebook)
+
+    def _textPanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Text"))
+        
+        border = wx.BoxSizer(wx.VERTICAL)
+        
+        # text entry
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Text")))
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        
+        textLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Enter text:"))
+        self.textCtrl = ExpandoTextCtrl(panel, id = wx.ID_ANY, value = self.textDict['text'])
+        
+        sizer.Add(textLabel, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
+        sizer.Add(self.textCtrl, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)        
+        
+
+        #font
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Font settings")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        flexGridSizer = wx.FlexGridSizer (rows = 3, cols = 2, hgap = 5, vgap = 5)
+        flexGridSizer.AddGrowableCol(1)
+        
+        self.AddFont(parent = panel, dialogDict = self.textDict)
+        
+        flexGridSizer.Add(panel.font['fontLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexGridSizer.Add(panel.font['fontCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexGridSizer.Add(panel.font['fontSizeLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexGridSizer.Add(panel.font['fontSizeCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        flexGridSizer.Add(panel.font['colorLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)        
+        flexGridSizer.Add(panel.font['colorCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(item = flexGridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        #text effects
+        
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Text effects")))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        
+        self.effect = {}
+        self.effect['backgroundCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("text background"))
+        self.effect['backgroundColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        
+        self.effect['highlightCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("highlight"))
+        self.effect['highlightColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.effect['highlightWidth'] = wx.SpinCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize, value = 'pts',min = 0, max = 5, initial = 1)
+        self.effect['highlightWidthLabel'] = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):"))
+        
+        self.effect['borderCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("text border"))
+        self.effect['borderColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.effect['borderWidth'] = wx.SpinCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize, value = 'pts',min = 1, max = 25, initial = 1)
+        self.effect['borderWidthLabel'] = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):"))
+        #set values
+        self.effect['backgroundCtrl'].SetValue(True if self.textDict['background'] != 'none' else False)
+        self.effect['backgroundColor'].SetColour(convertRGB(self.textDict['background']) 
+                                            if self.textDict['background'] != 'none' else 'white')
+        self.effect['highlightCtrl'].SetValue(True if self.textDict['hcolor'] != 'none' else False)
+        self.effect['highlightColor'].SetColour(convertRGB(self.textDict['hcolor']) 
+                                            if self.textDict['hcolor'] != 'none' else 'grey')
+        self.effect['highlightWidth'].SetValue(float(self.textDict['hwidth']))
+        self.effect['borderCtrl'].SetValue(True if self.textDict['border'] != 'none' else False)
+        self.effect['borderColor'].SetColour(convertRGB(self.textDict['border']) 
+                                            if self.textDict['border'] != 'none' else 'black')
+        self.effect['borderWidth'].SetValue(float(self.textDict['width']))
+        
+        gridBagSizer.Add(self.effect['backgroundCtrl'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['backgroundColor'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['highlightCtrl'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['highlightColor'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['highlightWidthLabel'], pos = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['highlightWidth'], pos = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['borderCtrl'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['borderColor'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['borderWidthLabel'], pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizer.Add(self.effect['borderWidth'], pos = (2,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizer.Add(item = gridBagSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        self.Bind(EVT_ETC_LAYOUT_NEEDED, self.OnRefit, self.textCtrl)
+        self.Bind(wx.EVT_CHECKBOX, self.OnBackground, self.effect['backgroundCtrl'])
+        self.Bind(wx.EVT_CHECKBOX, self.OnHighlight, self.effect['highlightCtrl'])
+        self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.effect['borderCtrl'])
+        
+        panel.SetSizer(border)
+        panel.Fit()
+        return panel 
+    
+    def _positionPanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Position"))
+
+        border = wx.BoxSizer(wx.VERTICAL) 
+
+        #Position
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Position")))
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(0)
+        gridBagSizer.AddGrowableCol(1)
+        
+        self.positionLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Position is given:"))
+        self.paperPositionCtrl = wx.RadioButton(panel, id = wx.ID_ANY, label = _("relatively to paper"), style = wx.RB_GROUP)
+        self.mapPositionCtrl = wx.RadioButton(panel, id = wx.ID_ANY, label = _("by map coordinates"))
+        self.paperPositionCtrl.SetValue(self.textDict['XY'])
+        self.mapPositionCtrl.SetValue(not self.textDict['XY'])
+        
+        gridBagSizer.Add(self.positionLabel, pos = (0,0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0)
+        gridBagSizer.Add(self.paperPositionCtrl, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0)
+        gridBagSizer.Add(self.mapPositionCtrl, pos = (1,1),flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0)
+        
+        # first box - paper coordinates
+        box1   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = "")
+        sizerP = wx.StaticBoxSizer(box1, wx.VERTICAL)
+        self.gridBagSizerP = wx.GridBagSizer (hgap = 5, vgap = 5)
+        self.gridBagSizerP.AddGrowableCol(1)
+        self.gridBagSizerP.AddGrowableRow(3)
+        
+        self.AddPosition(parent = panel, dialogDict = self.textDict)
+        panel.position['comment'].SetLabel(_("Position from the top left\nedge of the paper"))
+        self.AddUnits(parent = panel, dialogDict = self.textDict)
+        self.gridBagSizerP.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerP.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerP.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerP.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerP.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerP.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerP.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag = wx.ALIGN_BOTTOM, border = 0)
+        
+        
+        sizerP.Add(self.gridBagSizerP, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        gridBagSizer.Add(sizerP, pos = (2,0),span = (1,1), flag = wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND, border = 0)
+        
+        
+        # second box - map coordinates
+        box2   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = "")
+        sizerM = wx.StaticBoxSizer(box2, wx.VERTICAL)
+        self.gridBagSizerM = wx.GridBagSizer (hgap = 5, vgap = 5)
+        self.gridBagSizerM.AddGrowableCol(0)
+        self.gridBagSizerM.AddGrowableCol(1)
+        
+        self.eastingLabel  = wx.StaticText(panel, id = wx.ID_ANY, label = "E:")
+        self.northingLabel  = wx.StaticText(panel, id = wx.ID_ANY, label = "N:")
+        self.eastingCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
+        self.northingCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
+        east, north = PaperMapCoordinates(self, mapId = self.mapId, x = self.textDict['where'][0], y = self.textDict['where'][1], paperToMap = True)
+        self.eastingCtrl.SetValue(str(east))
+        self.northingCtrl.SetValue(str(north))
+        
+
+        self.gridBagSizerM.Add(self.eastingLabel, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerM.Add(self.northingLabel, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerM.Add(self.eastingCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        self.gridBagSizerM.Add(self.northingCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizerM.Add(self.gridBagSizerM, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        gridBagSizer.Add(sizerM, pos = (2,1), flag = wx.ALIGN_LEFT|wx.EXPAND, border = 0)
+        
+        #offset
+        box3   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Offset")))
+        sizerO = wx.StaticBoxSizer(box3, wx.VERTICAL)
+        gridBagSizerO = wx.GridBagSizer (hgap = 5, vgap = 5)
+        self.xoffLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("horizontal (pts):"))
+        self.yoffLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("vertical (pts):"))
+        self.xoffCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, size = (50, -1), min = -50, max = 50, initial = 0)
+        self.yoffCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, size = (50, -1), min = -50, max = 50, initial = 0) 
+        self.xoffCtrl.SetValue(self.textDict['xoffset'])       
+        self.yoffCtrl.SetValue(self.textDict['yoffset'])
+        gridBagSizerO.Add(self.xoffLabel, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizerO.Add(self.yoffLabel, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizerO.Add(self.xoffCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridBagSizerO.Add(self.yoffCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        
+        sizerO.Add(gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        gridBagSizer.Add(sizerO, pos = (3,0), flag = wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND, border = 0)
+        # reference point
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_(" Reference point")))
+        sizerR = wx.StaticBoxSizer(box, wx.VERTICAL)
+        flexSizer = wx.FlexGridSizer(rows = 3, cols = 3, hgap = 5, vgap = 5)
+        flexSizer.AddGrowableCol(0)
+        flexSizer.AddGrowableCol(1)
+        flexSizer.AddGrowableCol(2)
+        ref = []
+        for row in ["upper", "center", "lower"]:
+            for col in ["left", "center", "right"]:
+                ref.append(row + " " + col)
+        self.radio = [wx.RadioButton(panel, id = wx.ID_ANY, label = '', style = wx.RB_GROUP, name = ref[0])]
+        self.radio[0].SetValue(False)
+        flexSizer.Add(self.radio[0], proportion = 0, flag = wx.ALIGN_CENTER, border = 0)
+        for i in range(1,9):
+            self.radio.append(wx.RadioButton(panel, id = wx.ID_ANY, label = '', name = ref[i]))
+            self.radio[-1].SetValue(False)
+            flexSizer.Add(self.radio[-1], proportion = 0, flag = wx.ALIGN_CENTER, border = 0)
+        self.FindWindowByName(self.textDict['ref']).SetValue(True)
+
+        
+        sizerR.Add(flexSizer, proportion = 1, flag = wx.EXPAND, border = 0)
+        gridBagSizer.Add(sizerR, pos = (3,1), flag = wx.ALIGN_LEFT|wx.EXPAND, border = 0)
+        
+        sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+                
+        #rotation
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " {0} ".format(_("Text rotation")))
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+
+        self.rotCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("rotate text (counterclockwise)"))
+        self.rotValue = wx.SpinCtrl(panel, wx.ID_ANY, size = (50, -1), min = 0, max = 360, initial = 0)
+        if self.textDict['rotate']:
+            self.rotValue.SetValue(int(self.textDict['rotate']))
+            self.rotCtrl.SetValue(True)
+        else:
+            self.rotValue.SetValue(0)
+            self.rotCtrl.SetValue(False)
+        sizer.Add(self.rotCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.ALL, border = 5)
+        sizer.Add(self.rotValue, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.ALL, border = 5)
+        
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        panel.SetSizer(border)
+        panel.Fit()
+          
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, self.paperPositionCtrl) 
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, self.mapPositionCtrl)
+        self.Bind(wx.EVT_CHECKBOX, self.OnRotation, self.rotCtrl)
+        
+        return panel
+     
+    def OnRefit(self, event):
+        self.Fit()
+        
+    def OnRotation(self, event):
+        if self.rotCtrl.GetValue():
+            self.rotValue.Enable()
+        else: 
+            self.rotValue.Disable()
+            
+    def OnPositionType(self, event):
+        if self.paperPositionCtrl.GetValue():
+            for widget in self.gridBagSizerP.GetChildren():
+                widget.GetWindow().Enable()
+            for widget in self.gridBagSizerM.GetChildren():
+                widget.GetWindow().Disable()
+        else:
+            for widget in self.gridBagSizerM.GetChildren():
+                widget.GetWindow().Enable()
+            for widget in self.gridBagSizerP.GetChildren():
+                widget.GetWindow().Disable()
+    def OnBackground(self, event):
+        if self.effect['backgroundCtrl'].GetValue():
+            self.effect['backgroundColor'].Enable()
+        else:
+            self.effect['backgroundColor'].Disable()
+    
+    def OnHighlight(self, event):
+        if self.effect['highlightCtrl'].GetValue():
+            self.effect['highlightColor'].Enable()
+            self.effect['highlightWidth'].Enable()
+            self.effect['highlightWidthLabel'].Enable()
+        else:
+            self.effect['highlightColor'].Disable()
+            self.effect['highlightWidth'].Disable()
+            self.effect['highlightWidthLabel'].Disable()
+            
+    def OnBorder(self, event):
+        if self.effect['borderCtrl'].GetValue():
+            self.effect['borderColor'].Enable()
+            self.effect['borderWidth'].Enable()
+            self.effect['borderWidthLabel'].Enable()
+        else:
+            self.effect['borderColor'].Disable()
+            self.effect['borderWidth'].Disable()
+            self.effect['borderWidthLabel'].Disable()
+            
+    def update(self): 
+
+        #text
+        self.textDict['text'] = self.textCtrl.GetValue()
+        if not self.textDict['text']:
+            wx.MessageBox(_("No text entered!"), _("Error"))
+            return False
+            
+        #font
+        self.textDict['font'] = font = self.textPanel.font['fontCtrl'].GetStringSelection()
+        self.textDict['fontsize'] = self.textPanel.font['fontSizeCtrl'].GetValue()
+##        font = self.textPanel.font['fontCtrl'].GetSelectedFont()
+##        self.textDict['font'] = font.GetFaceName()
+##        self.textDict['fontsize'] = font.GetPointSize()
+        self.textDict['color'] = self.textPanel.font['colorCtrl'].GetColour().GetAsString(flags=wx.C2S_NAME)
+        #effects
+        self.textDict['background'] = (convertRGB(self.effect['backgroundColor'].GetColour())
+                                        if self.effect['backgroundCtrl'].GetValue() else 'none') 
+        self.textDict['border'] = (convertRGB(self.effect['borderColor'].GetColour())
+                                        if self.effect['borderCtrl'].GetValue() else 'none')
+        self.textDict['width'] = self.effect['borderWidth'].GetValue()
+        self.textDict['hcolor'] = (convertRGB(self.effect['highlightColor'].GetColour())
+                                        if self.effect['highlightCtrl'].GetValue() else 'none')
+        self.textDict['hwidth'] = self.effect['highlightWidth'].GetValue()
+        
+        #offset
+        self.textDict['xoffset'] = self.xoffCtrl.GetValue()
+        self.textDict['yoffset'] = self.yoffCtrl.GetValue()
+        #position
+        if self.paperPositionCtrl.GetValue():
+            self.textDict['XY'] = True
+            currUnit = self.positionPanel.units['unitsCtrl'].GetStringSelection()
+            self.textDict['unit'] = currUnit
+            x = self.positionPanel.position['xCtrl'].GetValue() if self.positionPanel.position['xCtrl'].GetValue() else self.textDict['where'][0]
+            y = self.positionPanel.position['yCtrl'].GetValue() if self.positionPanel.position['yCtrl'].GetValue() else self.textDict['where'][1]
+            x = self.unitConv.convert(value = float(x), fromUnit = currUnit, toUnit = 'inch')
+            y = self.unitConv.convert(value = float(y), fromUnit = currUnit, toUnit = 'inch')
+            self.textDict['where'] = x, y
+            self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(self, self.mapId, x, y, paperToMap = True)
+        else:
+            self.textDict['XY'] = False
+            self.textDict['east'] = self.eastingCtrl.GetValue() if self.eastingCtrl.GetValue() else self.textDict['east']
+            self.textDict['north'] = self.northingCtrl.GetValue() if self.northingCtrl.GetValue() else self.textDict['north']
+            self.textDict['where'] = PaperMapCoordinates(self, mapId = self.mapId, x = float(self.textDict['east']),
+                                                            y = float(self.textDict['north']), paperToMap = False)
+        #rotation
+        if self.rotCtrl.GetValue():
+            self.textDict['rotate'] = self.rotValue.GetValue()
+        else:
+            self.textDict['rotate'] = None
+        #reference point
+        for radio in self.radio:
+            if radio.GetValue() == True:
+                self.textDict['ref'] = radio.GetName()
+                
+        if self.id not in self.instruction:
+            text = Text(self.id)
+            self.instruction.AddInstruction(text)
+        self.instruction[self.id].SetInstruction(self.textDict)
+        
+        if self.id not in self.parent.objectId:
+            self.parent.objectId.append(self.id)
+
+        return True
+    
+    
+    
+def find_key(dic, val, multiple = False):
+    """!Return the key of dictionary given the value"""
+    result = [k for k, v in dic.iteritems() if v == val]
+    if len(result) == 0 and not multiple:
+        return None
+    return sorted(result) if multiple else result[0]
+
+def convertRGB(rgb):
+    """!Converts wx.Colour(255,255,255,255) and string '255:255:255',
+            depends on input"""    
+    if type(rgb) == wx.Colour:
+        return str(rgb.Red()) + ':' + str(rgb.Green()) + ':' + str(rgb.Blue())
+    elif type(rgb) == str:
+        return wx.Colour(*map(int, rgb.split(':')))
+        
+        
+def PaperMapCoordinates(self, mapId, x, y, paperToMap = True):
+    """!Converts paper (inch) coordinates -> map coordinates"""
+    unitConv = UnitConversion(self)
+    currRegionDict = grass.region()
+    cornerEasting, cornerNorthing = currRegionDict['w'], currRegionDict['n']
+    xMap = self.instruction[mapId]['rect'][0]
+    yMap = self.instruction[mapId]['rect'][1]
+    widthMap = self.instruction[mapId]['rect'][2] * 0.0254 # to meter
+    heightMap = self.instruction[mapId]['rect'][3] * 0.0254
+    xScale = widthMap / abs(currRegionDict['w'] - currRegionDict['e'])
+    yScale = heightMap / abs(currRegionDict['n'] - currRegionDict['s'])
+    currScale = (xScale + yScale) / 2
+
+    
+    if not paperToMap:
+        textEasting, textNorthing = x, y
+        eastingDiff = textEasting - cornerEasting 
+        eastingDiff = - eastingDiff if currRegionDict['w'] > currRegionDict['e'] else eastingDiff
+        northingDiff = textNorthing - cornerNorthing
+        northingDiff = - northingDiff if currRegionDict['n'] > currRegionDict['s'] else northingDiff
+        xPaper = xMap + unitConv.convert(value = eastingDiff, fromUnit = 'meter', toUnit = 'inch') * currScale
+        yPaper = yMap + unitConv.convert(value = northingDiff, fromUnit = 'meter', toUnit = 'inch') * currScale
+        return xPaper, yPaper
+    else:
+        eastingDiff = (x - xMap) if currRegionDict['w'] < currRegionDict['e'] else (xMap - x)
+        northingDiff = (y - yMap) if currRegionDict['n'] < currRegionDict['s'] else (yMap - y)
+        textEasting = cornerEasting + unitConv.convert(value = eastingDiff, fromUnit = 'inch', toUnit = 'meter') / currScale
+        textNorthing = cornerNorthing + unitConv.convert(value = northingDiff, fromUnit = 'inch', toUnit = 'meter') / currScale
+        return int(textEasting), int(textNorthing)
+    
+    
+def AutoAdjust(self, scaleType,  rect, map = None, mapType = None, region = None):
+    """!Computes map scale, center and map frame rectangle to fit region (scale is not fixed)"""
+    currRegionDict = {}
+    if scaleType == 0 and map:# automatic, region from raster or vector
+        res = ''
+        if mapType == 'raster': 
+            res = grass.read_command("g.region", flags = 'gu', rast = map)
+        elif mapType == 'vector':
+            res = grass.read_command("g.region", flags = 'gu', vect = map)
+        currRegionDict = grass.parse_key_val(res, val_type = float)
+    elif scaleType == 1 and region: # saved region
+        res = grass.read_command("g.region", flags = 'gu', region = region)
+        currRegionDict = grass.parse_key_val(res, val_type = float)
+    elif scaleType == 2: # current region
+        env = grass.gisenv()
+        windFilePath = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], 'WIND')
+        try:
+            windFile = open(windFilePath, 'r').read()
+        except IOError:
+            currRegionDict = grass.region()
+        regionDict = grass.parse_key_val(windFile, sep = ':', val_type = float)
+        region = grass.read_command("g.region", flags = 'gu', n = regionDict['north'], s = regionDict['south'],
+                                                                e = regionDict['east'], w = regionDict['west'])
+        currRegionDict = grass.parse_key_val(region, val_type = float)
+                                                                
+    else:
+        return None, None, None
+    
+    if not currRegionDict:
+        return None, None
+    rX = rect.x
+    rY = rect.y
+    rW = rect.width
+    rH = rect.height
+    if not hasattr(self, 'unitConv'):
+        self.unitConv = UnitConversion(self)
+    toM = 1
+    if projInfo()['proj'] != 'xy':
+        toM = float(projInfo()['meters'])
+
+    mW = self.unitConv.convert(value = (currRegionDict['e'] - currRegionDict['w']) * toM, fromUnit = 'meter', toUnit = 'inch')
+    mH = self.unitConv.convert(value = (currRegionDict['n'] - currRegionDict['s']) * toM, fromUnit = 'meter', toUnit = 'inch')
+    scale = min(rW/mW, rH/mH)
+    
+
+    if rW/rH > mW/mH:
+        x = rX - (rH*(mW/mH) - rW)/2
+        y = rY
+        rWNew = rH*(mW/mH)
+        rHNew = rH
+    else:
+        x = rX
+        y = rY - (rW*(mH/mW) - rH)/2
+        rHNew = rW*(mH/mW)
+        rWNew = rW
+
+    # center
+    cE = (currRegionDict['w'] + currRegionDict['e'])/2
+    cN = (currRegionDict['n'] + currRegionDict['s'])/2
+    return scale, (cE, cN), wx.Rect2D(x, y, rWNew, rHNew) #inch
+
+def ComputeSetRegion(self, mapDict):
+    """!Computes and sets region from current scale, map center coordinates and map rectangle"""
+
+    if mapDict['scaleType'] == 3: # fixed scale
+        scale = mapDict['scale']
+            
+        if not hasattr(self, 'unitConv'):
+            self.unitConv = UnitConversion(self)
+        
+        fromM = 1
+        if projInfo()['proj'] != 'xy':
+            fromM = float(projInfo()['meters'])
+        rectHalfInch = ( mapDict['rect'].width/2, mapDict['rect'].height/2)
+        rectHalfMeter = ( self.unitConv.convert(value = rectHalfInch[0], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale,
+                                self.unitConv.convert(value = rectHalfInch[1], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale) 
+        
+        centerE = mapDict['center'][0]
+        centerN = mapDict['center'][1]
+        
+        raster = self.instruction.FindInstructionByType('raster')
+        rasterId = raster.id if raster else None
+
+        if rasterId:
+            RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]),
+                           s = floor(centerN - rectHalfMeter[1]),
+                           e = ceil(centerE + rectHalfMeter[0]),
+                           w = floor(centerE - rectHalfMeter[0]),
+                           rast = self.instruction[rasterId]['raster'])
+        else:
+            RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]),
+                           s = floor(centerN - rectHalfMeter[1]),
+                           e = ceil(centerE + rectHalfMeter[0]),
+                           w = floor(centerE - rectHalfMeter[0]))
+                    
+def projInfo():
+    """!Return region projection and map units information,
+    taken from render.py"""
+    
+    projinfo = dict()
+    
+    ret = RunCommand('g.proj', read = True, flags = 'p')
+    
+    if not ret:
+        return projinfo
+    
+    for line in ret.splitlines():
+        if ':' in line:
+            key, val = line.split(':')
+            projinfo[key.strip()] = val.strip()
+        elif "XY location (unprojected)" in line:
+            projinfo['proj'] = 'xy'
+            projinfo['units'] = ''
+            break
+    
+    return projinfo
+
+def GetMapBounds(filename):
+    """!Run ps.map -b to get information about map bounding box"""
+    try:
+        bb = map(float, RunCommand('ps.map', read = True,
+                                        flags = 'b',
+                                        input = filename).strip().split('=')[1].split(','))
+    except (grass.ScriptError, IndexError):
+        GError(message = _("Unable to run ps.map -b "))
+        return None
+    return wx.Rect2D(bb[0], bb[3], bb[2] - bb[0], bb[1] - bb[3])

Added: grass-addons/gui/wxpython/psmap/images/scalebar-fancy.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/gui/wxpython/psmap/images/scalebar-fancy.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: grass-addons/gui/wxpython/psmap/images/scalebar-simple.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/gui/wxpython/psmap/images/scalebar-simple.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: grass-addons/gui/wxpython/psmap/xml/menudata_psmap.xml
===================================================================
--- grass-addons/gui/wxpython/psmap/xml/menudata_psmap.xml	                        (rev 0)
+++ grass-addons/gui/wxpython/psmap/xml/menudata_psmap.xml	2011-03-14 07:15:14 UTC (rev 45659)
@@ -0,0 +1,104 @@
+<menudata>
+  <menubar>
+    <menu>
+      <label>&amp;File</label>
+      <items>
+      	<menuitem>
+		  <label>Page setup</label>
+		  <help>Specify paper size, margins and orientation</help>
+		  <handler>OnPageSetup</handler>
+		  <shortcut>Ctrl+P</shortcut>
+		</menuitem>
+		<menuitem>
+		  <label>Export to text file</label>
+		  <help>Generate text file with mapping instructions</help>
+		  <handler>OnInstructionFile</handler>
+		  <shortcut>Ctrl+Shift+E</shortcut>
+		</menuitem>
+		<menuitem>
+		  <label>Export to PostScript</label>
+		  <help>Generate PostScript file</help>
+		  <handler>OnPSFile</handler>
+		  <shortcut>Ctrl+E</shortcut>
+		</menuitem>
+		<separator/>
+		<menuitem>
+		  <label>Quit</label>
+		  <help>Close Hardcopy Map Output Utility</help>
+		  <handler>OnCloseWindow</handler>
+		  <shortcut>Ctrl+W</shortcut>
+		</menuitem>
+      </items>
+    </menu>
+    <menu>
+      <label>&amp;Insert</label>
+      <items>
+         <menuitem>
+		  <label>Map frame</label>
+		  <help>Add or edit map frame</help>
+		  <handler>OnAddMap</handler>
+		  <shortcut>Ctrl+M</shortcut>
+		</menuitem>
+		<menuitem>
+		  <label>Raster map</label>
+		  <help>Add or edit raster map</help>
+		  <handler>OnAddRaster</handler>
+		  <shortcut>Ctrl+R</shortcut>
+		</menuitem>
+		<menuitem>
+		  <label>Vector map</label>
+		  <help>Add or edit vector map</help>
+		  <handler>OnAddVect</handler>
+		  <shortcut>Ctrl+V</shortcut>
+		</menuitem>
+    <menuitem>
+		  <label>Map legend</label>
+		  <help>Add or edit raster and vector legend</help>
+		  <handler>OnAddLegend</handler>
+		  <shortcut>Ctrl+L</shortcut>
+		</menuitem>
+		<menuitem>
+		  <label>Map info</label>
+		  <help>Add or edit map info</help>
+		  <handler>OnAddMapinfo</handler>
+		  <shortcut>Ctrl+I</shortcut>
+		</menuitem>
+		<menuitem>
+		  <label>Scale bar</label>
+		  <help>Add or edit scale bar</help>
+		  <handler>OnAddScalebar</handler>
+		  <shortcut>Ctrl+B</shortcut>
+		</menuitem>
+		<menuitem>
+		  <label>Text</label>
+		  <help>Add text</help>
+		  <handler>OnAddText</handler>
+		  <shortcut>Ctrl+T</shortcut>
+		</menuitem>
+		<separator/>
+		<menuitem>
+		  <label>Delete</label>
+		  <help>Delete selected object</help>
+		  <handler>OnDelete</handler>
+		  <shortcut>Delete</shortcut>
+		</menuitem>
+      </items>
+    </menu>
+    <menu>
+      <label>&amp;Help</label>
+      <items>
+	<menuitem>
+	  <label>Help</label>
+	  <help>Display the HTML man pages of Hardcopy Map Output Utility</help>
+	  <handler>OnHelp</handler>
+	</menuitem>
+	<separator />
+	<menuitem>
+	  <label>About Hardcopy Map Output Utility</label>
+	  <help>Display information about Hardcopy Map Output Utility</help>
+	  <handler>OnAbout</handler>
+	</menuitem>
+      </items>
+    </menu>
+  </menubar>
+</menudata>



More information about the grass-commit mailing list