[GRASS-SVN] r50797 - in grass/trunk/gui/wxpython: docs psmap

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Feb 13 10:12:38 EST 2012


Author: annakrat
Date: 2012-02-13 07:12:38 -0800 (Mon, 13 Feb 2012)
New Revision: 50797

Added:
   grass/trunk/gui/wxpython/psmap/utils.py
Modified:
   grass/trunk/gui/wxpython/docs/wxGUI.PsMap.html
   grass/trunk/gui/wxpython/psmap/dialogs.py
   grass/trunk/gui/wxpython/psmap/frame.py
   grass/trunk/gui/wxpython/psmap/toolbars.py
Log:
wxGUI/wxpsmap: support of point, line, rectangle instructions added

Modified: grass/trunk/gui/wxpython/docs/wxGUI.PsMap.html
===================================================================
--- grass/trunk/gui/wxpython/docs/wxGUI.PsMap.html	2012-02-13 15:01:04 UTC (rev 50796)
+++ grass/trunk/gui/wxpython/docs/wxGUI.PsMap.html	2012-02-13 15:12:38 UTC (rev 50797)
@@ -45,6 +45,9 @@
   <li> text
   <li> scalebar
   <li> mapinfo
+  <li> point
+  <li> line
+  <li> rectangle
 </ul>
 
 

Modified: grass/trunk/gui/wxpython/psmap/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/psmap/dialogs.py	2012-02-13 15:01:04 UTC (rev 50796)
+++ grass/trunk/gui/wxpython/psmap/dialogs.py	2012-02-13 15:12:38 UTC (rev 50797)
@@ -17,6 +17,9 @@
  - dialogs::Text
  - dialogs::Image
  - dialogs::NorthArrow
+ - dialogs::Point
+ - dialogs::Line
+ - dialogs::Rectangle
  - dialogs::Scalebar
  - dialogs::RasterLegend
  - dialogs::VectorLegend
@@ -38,6 +41,8 @@
  - dialogs::TextDialog
  - dialogs::ImageDialog
  - dialogs::NorthArrowDialog
+ - dialogs::PointDialog
+ - dialogs::RectangleDialog
 
 (C) 2011 by Anna Kratochvilova, and the GRASS Development Team
 
@@ -78,6 +83,7 @@
 from gui_core.gselect import Select
 from core.gcmd        import RunCommand, GError, GMessage, GWarning
 from gui_core.dialogs import SymbolDialog
+from psmap.utils      import *
 
 # grass.set_raise_on_error(True)
 
@@ -380,7 +386,7 @@
                     kwargs = {}
                     if instruction == 'scalebar':
                         kwargs['scale'] = map['scale']
-                    elif instruction in ('text', 'eps'):
+                    elif instruction in ('text', 'eps', 'point', 'line', 'rectangle'):
                         kwargs['mapInstruction'] = map
                     elif instruction in ('vpoints', 'vlines', 'vareas'):
                         kwargs['id'] = wx.NewId()
@@ -441,6 +447,21 @@
             elif line.startswith('eps'):
                 instruction = 'eps'
                 isBuffer = True
+                buffer.append(line)
+
+            elif line.startswith('point'):
+                instruction = 'point'
+                isBuffer = True
+                buffer.append(line)
+
+            elif line.startswith('line'):
+                instruction = 'line'
+                isBuffer = True
+                buffer.append(line)
+
+            elif line.startswith('rectangle'):
+                instruction = 'rectangle'
+                isBuffer = True
                 buffer.append(line) 
             
             elif line.startswith('colortable'):
@@ -512,8 +533,8 @@
                                                cols = rasterLegend['cols'] , 
                                                width = rasterLegend['width'],
                                                paperInstr = page)
-            rasterLegend['rect'] = wx.Rect2D(x = float(rasterLegend['where'][0]), y = float(rasterLegend['where'][1]),
-                                             w = width, h = height)
+            rasterLegend['rect'] = Rect2D(x = float(rasterLegend['where'][0]), y = float(rasterLegend['where'][1]),
+                                          width = width, height = height)
             
         # vectors, vlegend        
         
@@ -527,8 +548,8 @@
             if vectorLegend:
                 size = vectorLegend.EstimateSize(vectorInstr = vector, fontsize = vectorLegend['fontsize'],
                                                  width = vectorLegend['width'], cols = vectorLegend['cols'])                            
-                vectorLegend['rect'] = wx.Rect2D(x = float(vectorLegend['where'][0]), y = float(vectorLegend['where'][1]),
-                                                 w = size[0], h = size[1])
+                vectorLegend['rect'] = Rect2D(x = float(vectorLegend['where'][0]), y = float(vectorLegend['where'][1]),
+                                              width = size[0], height = size[1])
         
         
         page = self.FindInstructionByType('page')
@@ -552,6 +573,9 @@
                               scalebar = ['scalebar'],
                               text = ['text'],
                               eps = ['image', 'northArrow'],
+                              point = ['point'],
+                              line = ['line'],
+                              rectangle = ['rectangle'],
                               vpoints = ['vector', 'vProperties'],
                               vlines = ['vector', 'vProperties'],
                               vareas = ['vector', 'vProperties'],
@@ -567,6 +591,9 @@
                            text = Text,
                            image = Image,
                            northArrow = NorthArrow,
+                           point = Point,
+                           line = Line,
+                           rectangle = Rectangle,
                            rasterLegend = RasterLegend,
                            vectorLegend = VectorLegend,
                            vector = Vector,
@@ -577,7 +604,7 @@
         
         for i in myInstruction:
             instr = self.FindInstructionByType(i)
-            if i in ('text', 'vProperties', 'image', 'northArrow') or not instr:
+            if i in ('text', 'vProperties', 'image', 'northArrow', 'point', 'line', 'rectangle') or not instr:
                 
                 id = wx.NewId() #!vProperties expect subtype
                 if i == 'vProperties':
@@ -682,7 +709,15 @@
     def Read(self, instruction, text, **kwargs):
         """!Read instruction and save them"""
         pass
-    
+        
+    def PercentToReal(self, e, n):
+        """!Converts text coordinates from percent of region to map coordinates"""
+        e, n = float(e.strip('%')), float(n.strip('%'))
+        region = grass.region()
+        N = region['s'] + (region['n'] - region['s']) / 100 * n
+        E = region['w'] + (region['e'] - region['w']) / 100 * e
+        return E, N
+
 class InitMap(InstructionObject):
     """!Class representing virtual map"""
     def __init__(self, id):
@@ -702,7 +737,7 @@
         self.type = 'map'
         # default values
         self.defaultInstruction = dict(map = None, mapType = None, drawMap = True, region = None,
-                                       rect = wx.Rect2D(), scaleType = 0, scale = None, center = None,
+                                       rect = Rect2D(), scaleType = 0, scale = None, center = None,
                                        resolution = 300, border = 'y', width = 1, color = '0:0:0') 
         # current values
         self.instruction = dict(self.defaultInstruction)
@@ -935,7 +970,8 @@
         h = mapinfoDict['fontsize'] * 7
         width = self.unitConv.convert(value = w, fromUnit = 'point', toUnit = 'inch')
         height = self.unitConv.convert(value = h, fromUnit = 'point', toUnit = 'inch')
-        return wx.Rect2D(x = float(mapinfoDict['where'][0]), y = float(mapinfoDict['where'][1]), w = width, h = height)
+        return Rect2D(x = float(mapinfoDict['where'][0]), y = float(mapinfoDict['where'][1]),
+                      width = width, height = height)
     
 class Text(InstructionObject):
     """!Class representing text instruction"""
@@ -975,7 +1011,6 @@
             instr = instr.encode('latin1')
         except UnicodeEncodeError, err:
             try:
-                print err
                 pos = str(err).split('position')[1].split(':')[0].strip()
             except IndexError:
                 pos = ''
@@ -1045,14 +1080,6 @@
         self.instruction.update(instr)
 
         return True 
-    
-    def PercentToReal(self, e, n):
-        """!Converts text coordinates from percent of region to map coordinates"""
-        e, n = float(e.strip('%')), float(n.strip('%'))
-        region = grass.region()
-        N = region['s'] + (region['n'] - region['s']) / 100 * n
-        E = region['w'] + (region['e'] - region['w']) / 100 * e
-        return E, N
         
 class Image(InstructionObject):
     """!Class representing eps instruction - image"""
@@ -1121,19 +1148,11 @@
                                              y = self.instruction['north'], paperToMap = False)       
         w = self.unitConv.convert(value = instr['size'][0], fromUnit = 'point', toUnit = 'inch')
         h = self.unitConv.convert(value = instr['size'][1], fromUnit = 'point', toUnit = 'inch')
-        instr['rect'] = wx.Rect2D(x = float(instr['where'][0]), y = float(instr['where'][1]),
-                                  w = w * self.instruction['scale'], h = h * self.instruction['scale'])
+        instr['rect'] = Rect2D(x = float(instr['where'][0]), y = float(instr['where'][1]),
+                               width = w * self.instruction['scale'], height = h * self.instruction['scale'])
         self.instruction.update(instr)
 
         return True 
-    
-    def PercentToReal(self, e, n):
-        """!Converts eps coordinates from percent of region to map coordinates"""
-        e, n = float(e.strip('%')), float(n.strip('%'))
-        region = grass.region()
-        N = region['s'] + (region['n'] - region['s']) / 100 * n
-        E = region['w'] + (region['e'] - region['w']) / 100 * e
-        return E, N
         
     def ChangeRefPoint(self, toCenter):
         """!Change reference point (left top x center)"""
@@ -1198,6 +1217,186 @@
         instr += "    end"
         return instr
         
+class Point(InstructionObject):
+    """!Class representing point instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'point'
+        # default values
+        self.defaultInstruction = dict(symbol = os.path.join('basic', 'x'),
+                                       color = '0:0:0', fcolor = '200:200:200',
+                                       rotate = 0, size = 10,
+                                       XY = True, where = (0,0), unit = 'inch',
+                                       east = None, north = None)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = string.Template("point $east $north\n").substitute(self.instruction)
+        instr += string.Template("    symbol $symbol\n").substitute(self.instruction)
+        instr += string.Template("    color $color\n").substitute(self.instruction)
+        instr += string.Template("    fcolor $fcolor\n").substitute(self.instruction)
+        instr += string.Template("    rotate $rotate\n").substitute(self.instruction)
+        instr += string.Template("    size $size\n").substitute(self.instruction)
+        instr += "    end"
+        return instr
+    
+    def Read(self, instruction, text, **kwargs):
+        """!Read instruction and save information"""
+        mapInstr = kwargs['mapInstruction']
+        instr = {}
+        for line in text:
+            try:
+                sub = line.split(None, 1)[0]
+                if sub == 'point':
+                    e, n = line.split(None, 3)[1:3]
+                    if '%' in e and '%' in n:
+                        instr['XY'] = True
+                        instr['east'], instr['north'] = self.PercentToReal(e, n)
+                    else:
+                        instr['XY'] = False
+                        instr['east'], instr['north'] = float(e), float(n)
+                
+                elif sub == 'symbol':
+                    instr['symbol'] = line.split(None, 1)[1]
+                elif sub == 'rotate':
+                    instr['rotate'] = float(line.split(None, 1)[1])
+                elif sub == 'size':
+                    instr['size'] = float(line.split(None, 1)[1])
+                elif sub == 'color':
+                    instr['color'] = line.split(None, 1)[1]
+                elif sub == 'fcolor':
+                    instr['fcolor'] = line.split(None, 1)[1]
+
+                        
+            except(IndexError, ValueError):
+                GError(_("Failed to read instruction %s") % instruction)
+                return False
+        
+        self.instruction.update(instr)
+        instr['where'] = PaperMapCoordinates(map = mapInstr, x = self.instruction['east'],
+                                             y = self.instruction['north'], paperToMap = False)
+        w = h = self.unitConv.convert(value = instr['size'], fromUnit = 'point', toUnit = 'inch')
+        instr['rect'] = Rect2D(x = float(instr['where'][0]) - w / 2, y = float(instr['where'][1] - h / 2),
+                               width = w, height = h)
+        self.instruction.update(instr)
+
+        return True
+
+class Line(InstructionObject):
+    """!Class representing line instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'line'
+        # default values
+        self.defaultInstruction = dict(color = '0:0:0', width = 2,
+                                       where = [wx.Point2D(), wx.Point2D()],
+                                       east1 = None, north1 = None,
+                                       east2 = None, north2 = None)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = string.Template("line $east1 $north1 $east2 $north2\n").substitute(self.instruction)
+        instr += string.Template("    color $color\n").substitute(self.instruction)
+        instr += string.Template("    width $width\n").substitute(self.instruction)
+        instr += "    end\n"
+        return instr
+    
+    def Read(self, instruction, text, **kwargs):
+        """!Read instruction and save information"""
+        mapInstr = kwargs['mapInstruction']
+        instr = {}
+        for line in text:
+            try:
+                sub = line.split(None, 1)[0]
+                if sub == 'line':
+                    e1, n1, e2, n2 = line.split(None, 5)[1:5]
+                    if '%' in e1 and '%' in n1 and '%' in e2 and '%' in n2:
+                        instr['east1'], instr['north1'] = self.PercentToReal(e1, n1)
+                        instr['east2'], instr['north2'] = self.PercentToReal(e2, n2)
+                    else:
+                        instr['east1'], instr['north1'] = float(e1), float(n1)
+                        instr['east2'], instr['north2'] = float(e2), float(n2)
+                
+                elif sub == 'width':
+                    instr['width'] = float(line.split(None, 1)[1])
+                elif sub == 'color':
+                    instr['color'] = line.split(None, 1)[1]
+                        
+            except(IndexError, ValueError):
+                GError(_("Failed to read instruction %s") % instruction)
+                return False
+        
+        self.instruction.update(instr)
+        e1, n1 = PaperMapCoordinates(map = mapInstr, x = self.instruction['east1'],
+                                     y = self.instruction['north1'], paperToMap = False)
+        e2, n2 = PaperMapCoordinates(map = mapInstr, x = self.instruction['east2'],
+                                     y = self.instruction['north2'], paperToMap = False)
+        instr['where'] = [wx.Point2D(e1, n1), wx.Point2D(e2, n2)]
+        instr['rect'] = Rect2DPP(instr['where'][0], instr['where'][1])
+        self.instruction.update(instr)
+
+        return True
+
+class Rectangle(InstructionObject):
+    """!Class representing rectangle instruction"""
+    def __init__(self, id):
+        InstructionObject.__init__(self, id = id)
+        self.type = 'rectangle'
+        # default values
+        self.defaultInstruction = dict(color = '0:0:0', fcolor = 'none', width = 2,
+                                       east1 = None, north1 = None,
+                                       east2 = None, north2 = None)
+        # current values
+        self.instruction = dict(self.defaultInstruction)
+        
+    def __str__(self):
+        instr = string.Template("rectangle $east1 $north1 $east2 $north2\n").substitute(self.instruction)
+        instr += string.Template("    color $color\n").substitute(self.instruction)
+        instr += string.Template("    fcolor $fcolor\n").substitute(self.instruction)
+        instr += string.Template("    width $width\n").substitute(self.instruction)
+        instr += "    end\n"
+        return instr
+    
+    def Read(self, instruction, text, **kwargs):
+        """!Read instruction and save information"""
+        mapInstr = kwargs['mapInstruction']
+        instr = {}
+        for line in text:
+            try:
+                sub = line.split(None, 1)[0]
+                if sub == 'rectangle':
+                    e1, n1, e2, n2 = line.split(None, 5)[1:5]
+                    if '%' in e1 and '%' in n1 and '%' in e2 and '%' in n2:
+                        instr['east1'], instr['north1'] = self.PercentToReal(e1, n1)
+                        instr['east2'], instr['north2'] = self.PercentToReal(e2, n2)
+                    else:
+                        instr['east1'], instr['north1'] = float(e1), float(n1)
+                        instr['east2'], instr['north2'] = float(e2), float(n2)
+                
+                elif sub == 'width':
+                    instr['width'] = float(line.split(None, 1)[1])
+                elif sub == 'color':
+                    instr['color'] = line.split(None, 1)[1]
+                elif sub == 'fcolor':
+                    instr['fcolor'] = line.split(None, 1)[1]
+
+                        
+            except(IndexError, ValueError):
+                GError(_("Failed to read instruction %s") % instruction)
+                return False
+        
+        self.instruction.update(instr)
+        e1, n1 = PaperMapCoordinates(map = mapInstr, x = self.instruction['east1'],
+                                       y = self.instruction['north1'], paperToMap = False)
+        e2, n2 = PaperMapCoordinates(map = mapInstr, x = self.instruction['east2'],
+                                       y = self.instruction['north2'], paperToMap = False)
+        instr['rect'] = Rect2DPP(wx.Point2D(e1, n1), wx.Point2D(e2, n2))
+        self.instruction.update(instr)
+
+        return True
+        
 class Scalebar(InstructionObject):
     """!Class representing scalebar instruction"""
     def __init__(self, id):
@@ -1261,7 +1460,7 @@
         w, h = self.EstimateSize(scalebarDict = self.instruction, scale = scale)
         x = self.instruction['where'][0] - w / 2 
         y = self.instruction['where'][1] - h / 2
-        self.instruction['rect'] = wx.Rect2D(x, y, w, h)
+        self.instruction['rect'] = Rect2D(x, y, w, h)
         return True 
     
     def EstimateSize(self, scalebarDict, scale):
@@ -1690,7 +1889,6 @@
             vInstruction = vInstruction.encode('Latin_1')
         except UnicodeEncodeError, err:
             try:
-                print err
                 pos = str(err).split('position')[1].split(':')[0].strip()
             except IndexError:
                 pos = ''
@@ -4679,7 +4877,7 @@
             drawWidth = self.rasterLegend.EstimateWidth(raster = self.rLegendDict['raster'], discrete = self.rLegendDict['discrete'],
                                             fontsize = self.rLegendDict['fontsize'], cols = self.rLegendDict['cols'],
                                             width = self.rLegendDict['width'], paperInstr = self.instruction[self.pageId])
-            self.rLegendDict['rect'] = wx.Rect2D(x = x, y = y, w = drawWidth, h = drawHeight)
+            self.rLegendDict['rect'] = Rect2D(x = x, y = y, width = drawWidth, height = drawHeight)
                         
             # no data
             if self.rLegendDict['discrete'] == 'y':
@@ -4782,7 +4980,7 @@
                 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)
+                self.vLegendDict['rect'] = Rect2D(x, y, w, h)
                 
                 #border
                 if self.borderCheck.GetValue():
@@ -4862,7 +5060,7 @@
              
 class MapinfoDialog(PsmapDialog):
     def __init__(self, parent, id, settings):
-        PsmapDialog.__init__(self, parent = parent, id = id, title = "Mapinfo settings", settings = settings)
+        PsmapDialog.__init__(self, parent = parent, id = id, title = _("Mapinfo settings"), settings = settings)
         
         self.objectType = ('mapinfo',)
         if self.id is not None:
@@ -5290,7 +5488,7 @@
          
         rectSize = self.scalebar.EstimateSize(scalebarDict = self.scalebarDict,
                                                                 scale = self.instruction[mapId]['scale'])
-        self.scalebarDict['rect'] = wx.Rect2D(x = x, y = y, w = rectSize[0], h = rectSize[1])
+        self.scalebarDict['rect'] = Rect2D(x = x, y = y, width = rectSize[0], height = rectSize[1])
         self.scalebarDict['where'] = self.scalebarDict['rect'].GetCentre() 
 
         if self.id not in self.instruction:
@@ -6037,7 +6235,7 @@
         selected = self.imagePanel.image['list'].GetStringSelection()
         basePath = self.imagePanel.image['dir'].GetValue()
         if not selected:
-            gcmd.GMessage(parent = self, message = _("No image selected."))
+            GMessage(parent = self, message = _("No image selected."))
             return False
             
         self.imageDict['epsfile'] = os.path.join(basePath, selected)
@@ -6099,9 +6297,9 @@
                                   fromUnit = 'point', toUnit = 'inch')
                                   
     
-        self.imageDict['rect'] = wx.Rect2D(x = x, y = y,
-                                       w = w * self.imageDict['scale'],
-                                       h = h * self.imageDict['scale'])
+        self.imageDict['rect'] = Rect2D(x = x, y = y,
+                                        width = w * self.imageDict['scale'],
+                                        height = h * self.imageDict['scale'])
         
         if self.id not in self.instruction:
             image = self._newObject()
@@ -6161,6 +6359,456 @@
                 self.imagePanel.image['rotate'].SetValue(360 - convergence)
             
         
+class PointDialog(PsmapDialog):
+    """!Dialog for setting point properties."""
+    def __init__(self, parent, id, settings, coordinates = None, pointPanelName = _("Point")):
+        PsmapDialog.__init__(self, parent = parent, id = id, title = "Point settings",
+                             settings = settings)
+        
+        self.objectType = ('point',)
+        if self.id is not None:
+            self.pointObj = self.instruction[self.id]
+            self.pointDict = self.instruction[id].GetInstruction()
+        else:
+            self.id = wx.NewId()
+            self.pointObj = Point(self.id)
+            self.pointDict = self.pointObj.GetInstruction()
+            self.pointDict['where'] = coordinates 
+        self.defaultDict = self.pointObj.defaultInstruction
+                
+        mapObj = self.instruction.FindInstructionByType('map')
+        if not mapObj:
+            mapObj = self.instruction.FindInstructionByType('initMap')
+        self.mapId = mapObj.id
+        
+        self.pointDict['east'], self.pointDict['north'] = PaperMapCoordinates(map = mapObj, x = self.pointDict['where'][0], y = self.pointDict['where'][1], paperToMap = True)
+        
+        notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
+        self.pointPanelName = pointPanelName
+        self.pointPanel = self._pointPanel(notebook)
+        self.positionPanel = self._positionPanel(notebook)
+        self.OnPositionType(None)
+        
+     
+        self._layout(notebook)
+        
+    def _pointPanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = self.pointPanelName)
+        border = wx.BoxSizer(wx.VERTICAL)
+        #
+        # choose image
+        #
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Symbol"))
+        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        
+        gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        gridSizer.AddGrowableCol(1)
+
+        gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Select symbol:")),
+                      pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+        
+        self.symbolLabel = wx.StaticText(parent = panel, id = wx.ID_ANY,
+                                          label = self.pointDict['symbol'])
+        gridSizer.Add(item = self.symbolLabel, pos = (0, 1),
+                      flag = wx.ALIGN_CENTER_VERTICAL )
+        bitmap = wx.Bitmap(os.path.join(globalvar.ETCSYMBOLDIR,
+                                        self.pointDict['symbol']) + '.png')
+        self.symbolButton = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bitmap)
+        self.symbolButton.Bind(wx.EVT_BUTTON, self.OnSymbolSelection)
+
+        gridSizer.Add(self.symbolButton, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+        self.noteLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, 
+                                       label = _("Note: Selected symbol is not displayed\n"
+                                                 "in draft mode (only in preview mode)"))
+        gridSizer.Add(self.noteLabel, pos = (1, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+        sizer.Add(item = gridSizer, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        
+        #
+        # outline/fill color
+        #
+
+        # outline
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Color"))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        
+        gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        
+        outlineLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Outline color:"))
+        self.outlineColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.outlineTranspCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent"))
+
+        if self.pointDict['color'] != 'none':
+            self.outlineTranspCtrl.SetValue(False)
+            self.outlineColorCtrl.SetColour(convertRGB(self.pointDict['color']))
+        else:
+            self.outlineTranspCtrl.SetValue(True)
+            self.outlineColorCtrl.SetColour(convertRGB(self.defaultDict['color']))
+
+        gridSizer.Add(item = outlineLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item = self.outlineColorCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item = self.outlineTranspCtrl, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+        fillLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Fill color:"))
+        self.fillColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.fillTranspCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent"))
+
+        if self.pointDict['fcolor'] != 'none':
+            self.fillTranspCtrl.SetValue(False)
+            self.fillColorCtrl.SetColour(convertRGB(self.pointDict['fcolor']))
+        else:
+            self.fillTranspCtrl.SetValue(True)
+            self.fillColorCtrl.SetColour(convertRGB(self.defaultDict['fcolor']))
+
+        gridSizer.Add(item = fillLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item = self.fillColorCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item = self.fillTranspCtrl, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+        
+        sizer.Add(item = gridSizer, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+        #
+        # size and rotation
+        #
+
+        # size
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size and Rotation"))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        
+        gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        
+        sizeLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Size (pt):"))
+        self.sizeCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize)
+        self.sizeCtrl.SetToolTipString(_("Symbol size in points"))
+        self.sizeCtrl.SetValue(self.pointDict['size'])
+        
+        gridSizer.Add(item = sizeLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item = self.sizeCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+        
+        # rotation
+        rotLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Rotation angle (deg):"))
+        if fs:
+            self.rotCtrl = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = -360, max_val = 360,
+                                          increment = 1, value = 0, style = fs.FS_RIGHT, size = self.spinCtrlSize)
+            self.rotCtrl.SetFormat("%f")
+            self.rotCtrl.SetDigits(1)
+        else:
+            self.rotCtrl = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = self.spinCtrlSize,
+                                                min = -360, max = 360, initial = 0)
+        self.rotCtrl.SetToolTipString(_("Counterclockwise rotation in degrees"))
+        self.rotCtrl.SetValue(float(self.pointDict['rotate']))
+            
+        gridSizer.Add(item = rotLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+        gridSizer.Add(item = self.rotCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+        
+        sizer.Add(item = gridSizer, proportion = 0, 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 _positionPanel(self, notebook):
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+        notebook.AddPage(page = panel, text = _("Position"))
+        border = wx.BoxSizer(wx.VERTICAL)
+        #
+        # set position
+        #
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position"))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        
+        gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+        gridBagSizer.AddGrowableCol(0)
+        gridBagSizer.AddGrowableCol(1)
+        
+        self.AddExtendedPosition(panel, gridBagSizer, self.pointDict)
+        
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toPaper']) 
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toMap'])
+        
+        
+        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)
+        
+        panel.SetSizer(border)
+        panel.Fit()
+        
+        return panel
+        
+    def OnPositionType(self, event):
+        if self.positionPanel.position['toPaper'].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 OnSymbolSelection(self, event):
+        dlg = SymbolDialog(self, symbolPath = globalvar.ETCSYMBOLDIR,
+                           currentSymbol = self.symbolLabel.GetLabel())
+        if dlg.ShowModal() == wx.ID_OK:
+            img = dlg.GetSelectedSymbol(fullPath = True)
+            name = dlg.GetSelectedSymbol(fullPath = False)
+            self.symbolButton.SetBitmapLabel(wx.Bitmap(img + '.png'))
+            self.symbolLabel.SetLabel(name)
+            
+        dlg.Destroy()
+        
+    def update(self): 
+        # symbol
+        self.pointDict['symbol'] = self.symbolLabel.GetLabel()
+
+        
+        #position
+        if self.positionPanel.position['toPaper'].GetValue():
+            self.pointDict['XY'] = True
+            currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection())
+            self.pointDict['unit'] = currUnit
+            if self.positionPanel.position['xCtrl'].GetValue():
+                x = self.positionPanel.position['xCtrl'].GetValue() 
+            else:
+                x = self.pointDict['where'][0]
+
+            if self.positionPanel.position['yCtrl'].GetValue():
+                y = self.positionPanel.position['yCtrl'].GetValue() 
+            else:
+                y = self.pointDict['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.pointDict['where'] = x, y
+            
+        else:
+            self.pointDict['XY'] = False
+            if self.positionPanel.position['eCtrl'].GetValue():
+                e = self.positionPanel.position['eCtrl'].GetValue() 
+            else:
+                self.pointDict['east'] = self.pointDict['east']
+
+            if self.positionPanel.position['nCtrl'].GetValue():
+                n = self.positionPanel.position['nCtrl'].GetValue() 
+            else:
+                self.pointDict['north'] = self.pointDict['north']
+
+            x, y = PaperMapCoordinates(map = self.instruction[self.mapId], x = float(self.pointDict['east']),
+                                       y = float(self.pointDict['north']), paperToMap = False)
+
+        #rotation
+        self.pointDict['rotate'] = self.rotCtrl.GetValue()
+        
+        # size
+        self.pointDict['size'] = self.sizeCtrl.GetValue()
+            
+        w = h = self.unitConv.convert(value = self.pointDict['size'],
+                                  fromUnit = 'point', toUnit = 'inch')
+                                  
+        # outline color
+        if self.outlineTranspCtrl.GetValue():
+            self.pointDict['color'] = 'none'
+        else:
+            self.pointDict['color'] = convertRGB(self.outlineColorCtrl.GetColour())
+
+        # fill color
+        if self.fillTranspCtrl.GetValue():
+            self.pointDict['fcolor'] = 'none'
+        else:
+            self.pointDict['fcolor'] = convertRGB(self.fillColorCtrl.GetColour())
+
+        self.pointDict['rect'] = Rect2D(x = x - w / 2, y = y - h / 2, width = w, height = h)
+        
+        if self.id not in self.instruction:
+            point = Point(self.id)
+            self.instruction.AddInstruction(point)
+        self.instruction[self.id].SetInstruction(self.pointDict)
+        
+        if self.id not in self.parent.objectId:
+            self.parent.objectId.append(self.id)
+
+        return True
+        
+    def updateDialog(self):
+        """!Update text coordinates, after moving"""
+        # XY coordinates
+        x, y = self.pointDict['where'][:2]
+        currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection())
+        x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit)
+        y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit)
+        self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x)
+        self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y)
+        # EN coordinates
+        e, n = self.pointDict['east'], self.pointDict['north']
+        self.positionPanel.position['eCtrl'].SetValue(str(self.pointDict['east']))
+        self.positionPanel.position['nCtrl'].SetValue(str(self.pointDict['north']))
+        
+class RectangleDialog(PsmapDialog):
+    def __init__(self, parent, id, settings, type = 'rectangle', coordinates = None):
+        """!
+
+        @param coordinates begin and end point coordinate (wx.Point, wx.Point)
+        """
+        if type == 'rectangle':
+            title = _("Rectangle settings")
+        else:
+            title = _("Line settings")
+        PsmapDialog.__init__(self, parent = parent, id = id, title = title, settings = settings)
+        
+        self.objectType = (type,)
+
+        if self.id is not None:
+            self.rectObj = self.instruction[self.id]
+            self.rectDict = self.rectObj.GetInstruction()
+        else:
+            self.id = wx.NewId()
+            if type == 'rectangle':
+                self.rectObj = Rectangle(self.id)
+            else:
+                self.rectObj = Line(self.id)
+            self.rectDict = self.rectObj.GetInstruction()
+
+            self.rectDict['rect'] = Rect2DPP(coordinates[0], coordinates[1])
+            self.rectDict['where'] = coordinates
+
+        self.defaultDict = self.rectObj.defaultInstruction
+        self.panel = self._rectPanel()
+        
+        self._layout(self.panel)
+
+    def _rectPanel(self):
+        panel = wx.Panel(parent = self, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
+        border = wx.BoxSizer(wx.VERTICAL)
+                
+        # color
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Color"))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+        
+        outlineLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Outline color:"))
+        self.outlineColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+        self.outlineTranspCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent"))
+
+        if self.rectDict['color'] != 'none':
+            self.outlineTranspCtrl.SetValue(False)
+            self.outlineColorCtrl.SetColour(convertRGB(self.rectDict['color']))
+        else:
+            self.outlineTranspCtrl.SetValue(True)
+            self.outlineColorCtrl.SetColour(convertRGB(self.defaultDict['color']))
+
+        # transparent outline makes sense only for rectangle
+        if self.objectType == ('line',):
+            self.outlineTranspCtrl.Hide()
+
+        gridSizer.Add(item = outlineLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item = self.outlineColorCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item = self.outlineTranspCtrl, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+        # fill color only in rectangle
+        if self.objectType == ('rectangle',):
+            fillLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Fill color:"))
+            self.fillColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+            self.fillTranspCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent"))
+
+            if self.rectDict['fcolor'] != 'none':
+                self.fillTranspCtrl.SetValue(False)
+                self.fillColorCtrl.SetColour(convertRGB(self.rectDict['fcolor']))
+            else:
+                self.fillTranspCtrl.SetValue(True)
+                self.fillColorCtrl.SetColour(wx.WHITE)
+
+            gridSizer.Add(item = fillLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+            gridSizer.Add(item = self.fillColorCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+            gridSizer.Add(item = self.fillTranspCtrl, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+        sizer.Add(gridSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+        gridSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+
+        # width
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Line style"))
+        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        
+        widthLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Line width:"))
+        if fs:
+            self.widthCtrl = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 50,
+                                          increment = 1, value = 0, style = fs.FS_RIGHT, size = self.spinCtrlSize)
+            self.widthCtrl.SetFormat("%f")
+            self.widthCtrl.SetDigits(1)
+        else:
+            self.widthCtrl = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = self.spinCtrlSize,
+                                                min = -360, max = 360, initial = 0)
+        self.widthCtrl.SetToolTipString(_("Line width in points"))
+        self.widthCtrl.SetValue(float(self.rectDict['width']))
+
+        gridSizer.Add(item = widthLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+        gridSizer.Add(item = self.widthCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+
+        sizer.Add(gridSizer, 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)
+        
+        return panel
+        
+
+    def update(self):
+        mapInstr = self.instruction.FindInstructionByType('map')
+        if not mapInstr:
+            mapInstr = self.instruction.FindInstructionByType('initMap')
+        self.mapId = mapInstr.id
+        point1 = self.rectDict['where'][0]
+        point2 = self.rectDict['where'][1]
+        self.rectDict['east1'], self.rectDict['north1'] = PaperMapCoordinates(map = mapInstr,
+                                                                                x = point1[0],
+                                                                                y = point1[1],
+                                                                                paperToMap = True)
+        self.rectDict['east2'], self.rectDict['north2'] = PaperMapCoordinates(map = mapInstr,
+                                                                                x = point2[0],
+                                                                                y = point2[1],
+                                                                                paperToMap = True)
+        # width
+        self.rectDict['width'] = self.widthCtrl.GetValue()
+        
+        # outline color
+        if self.outlineTranspCtrl.GetValue():
+            self.rectDict['color'] = 'none'
+        else:
+            self.rectDict['color'] = convertRGB(self.outlineColorCtrl.GetColour())
+
+        # fill color
+        if self.objectType == ('rectangle',):
+            if self.fillTranspCtrl.GetValue():
+                self.rectDict['fcolor'] = 'none'
+            else:
+                self.rectDict['fcolor'] = convertRGB(self.fillColorCtrl.GetColour())
+
+        if self.id not in self.instruction:
+            if self.objectType == ('rectangle',):
+                rect = Rectangle(self.id)
+            else:
+                rect = Line(self.id)
+            self.instruction.AddInstruction(rect)
+            
+        self.instruction[self.id].SetInstruction(self.rectDict)
+
+        if self.id not in self.parent.objectId:
+            self.parent.objectId.append(self.id)
+            
+        self.updateDialog()
+
+        return True
+
+    def updateDialog(self):
+        """!Update text coordinates, after moving"""
+        pass
+
 def convertRGB(rgb):
     """!Converts wx.Colour(r,g,b,a) to string 'r:g:b' or named color,
             or named color/r:g:b string to wx.Colour, depending on input""" 
@@ -6288,7 +6936,7 @@
     # center
     cE = (currRegionDict['w'] + currRegionDict['e'])/2
     cN = (currRegionDict['n'] + currRegionDict['s'])/2
-    return scale, (cE, cN), wx.Rect2D(x, y, rWNew, rHNew) #inch
+    return scale, (cE, cN), Rect2D(x, y, rWNew, rHNew) #inch
 
 def SetResolution(dpi, width, height):
     """!If resolution is too high, lower it
@@ -6378,7 +7026,7 @@
     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])
+    return Rect2D(bb[0], bb[3], bb[2] - bb[0], bb[1] - bb[3])
 
 def getRasterType(map):
     """!Returns type of raster map (CELL, FCELL, DCELL)"""

Modified: grass/trunk/gui/wxpython/psmap/frame.py
===================================================================
--- grass/trunk/gui/wxpython/psmap/frame.py	2012-02-13 15:01:04 UTC (rev 50796)
+++ grass/trunk/gui/wxpython/psmap/frame.py	2012-02-13 15:12:38 UTC (rev 50797)
@@ -19,7 +19,7 @@
 import sys
 import textwrap
 import Queue
-from math import sin, cos, pi
+from math import sin, cos, pi, sqrt
 try:
     import Image as PILImage
     havePILImage = True
@@ -47,6 +47,7 @@
 from psmap.menudata   import PsMapData
 
 from psmap.dialogs    import *
+from psmap.utils      import *
 
 class PsMapFrame(wx.Frame):
     def __init__(self, parent = None, id = wx.ID_ANY,
@@ -101,6 +102,8 @@
             'scalebar': wx.Pen(colour = wx.Color(150, 150, 150), width = 2),
             'image': wx.Pen(colour = wx.Color(255, 150, 50), width = 2),
             'northArrow': wx.Pen(colour = wx.Color(200, 200, 200), width = 2),
+            'point': wx.Pen(colour = wx.Color(100, 100, 100), width = 2),
+            'line': wx.Pen(colour = wx.Color(0, 0, 0), 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)
@@ -115,6 +118,8 @@
             'scalebar': wx.Brush(wx.Color(200, 200, 200)),
             'image': wx.Brush(wx.Color(255, 200, 50)),
             'northArrow': wx.Brush(wx.Color(255, 255, 255)),
+            'point': wx.Brush(wx.Color(200, 200, 200)),
+            'line': wx.TRANSPARENT_BRUSH,
             'box': wx.TRANSPARENT_BRUSH,
             'select':wx.TRANSPARENT_BRUSH,
             'resize': wx.BLACK_BRUSH
@@ -657,7 +662,81 @@
             dlg.SetPosition(position)
         dlg.Show()
         
+    def OnAddPoint(self, event):
+        """!Add point action selected"""
+        self.mouse["use"] = "addPoint"
+        self.canvas.SetCursor(self.cursors["cross"])
         
+    def AddPoint(self, id = None, coordinates = None):
+        """!Add point and open property dialog.
+
+        @param id id point id (None if creating new point)
+        @param coordinates coordinates of new point
+        """
+        position = None
+        if 'point' in self.openDialogs:
+            position = self.openDialogs['point'].GetPosition()
+            self.openDialogs['point'].OnApply(event = None)
+            self.openDialogs['point'].Destroy()
+        dlg = PointDialog(self, id = id, settings = self.instruction,
+                          coordinates = coordinates)
+        self.openDialogs['point'] = dlg
+        if position: 
+            dlg.SetPosition(position)
+        if coordinates:
+            dlg.OnApply(event = None)
+        dlg.Show()
+        
+    def OnAddLine(self, event):
+        """!Add line action selected"""
+        self.mouse["use"] = "addLine"
+        self.canvas.SetCursor(self.cursors["cross"])
+
+    def AddLine(self, id = None, coordinates = None):
+        """!Add line and open property dialog.
+        
+        @param id id line id (None if creating new line)
+        @param coordinates coordinates of new line
+        """
+        position = None
+        if 'line' in self.openDialogs:
+            position = self.openDialogs['line'].GetPosition()
+            self.openDialogs['line'].OnApply(event = None)
+            self.openDialogs['line'].Destroy()
+        dlg = RectangleDialog(self, id = id, settings = self.instruction,
+                              type = 'line', coordinates = coordinates)
+        self.openDialogs['line'] = dlg
+        if position: 
+            dlg.SetPosition(position)
+        if coordinates:
+            dlg.OnApply(event = None)
+        dlg.Show()
+
+    def OnAddRectangle(self, event):
+        """!Add rectangle action selected"""
+        self.mouse["use"] = "addRectangle"
+        self.canvas.SetCursor(self.cursors["cross"])
+
+    def AddRectangle(self, id = None, coordinates = None):
+        """!Add rectangle and open property dialog.
+        
+        @param id id rectangle id (None if creating new rectangle)
+        @param coordinates coordinates of new rectangle
+        """
+        position = None
+        if 'rectangle' in self.openDialogs:
+            position = self.openDialogs['rectangle'].GetPosition()
+            self.openDialogs['rectangle'].OnApply(event = None)
+            self.openDialogs['rectangle'].Destroy()
+        dlg = RectangleDialog(self, id = id, settings = self.instruction,
+                              type = 'rectangle', coordinates = coordinates)
+        self.openDialogs['rectangle'] = dlg
+        if position: 
+            dlg.SetPosition(position)
+        if coordinates:
+            dlg.OnApply(event = None)
+        dlg.Show()
+
     def getModifiedTextBounds(self, x, y, textExtent, rotation):
         """!computes bounding box of rotated text, not very precisely"""
         w, h = textExtent
@@ -804,6 +883,32 @@
                 self.canvas.Draw(pen = self.pen[itype], brush = self.brush[itype],
                                  pdc = self.canvas.pdcObj, drawid = id, pdctype = 'bitmap', bb = drawRectangle)
                 self.canvas.RedrawSelectBox(id)
+
+            if itype in ('point', 'line', 'rectangle'):
+                drawRectangle = self.canvas.CanvasPaperCoordinates(rect = self.instruction[id]['rect'], canvasToPaper = False)
+                # coords only for line
+                coords = None
+                if itype == 'line':
+                    point1 = self.instruction[id]['where'][0]
+                    point2 = self.instruction[id]['where'][1]
+                    point1Coords = self.canvas.CanvasPaperCoordinates(rect = Rect2DPS(point1, (0, 0)), canvasToPaper = False)[:2]
+                    point2Coords = self.canvas.CanvasPaperCoordinates(rect = Rect2DPS(point2, (0, 0)), canvasToPaper = False)[:2]
+                    coords = (point1Coords, point2Coords)
+
+                # fill color is not in line
+                fcolor = None
+                if 'fcolor' in self.instruction[id].GetInstruction():
+                    fcolor = self.instruction[id]['fcolor']
+                # width is not in point
+                width = None
+                if 'width' in self.instruction[id].GetInstruction():
+                    width = self.instruction[id]['width']
+
+                self.canvas.DrawGraphics(drawid = id, color = self.instruction[id]['color'], shape = itype,
+                                       fcolor = fcolor, width = width, bb = drawRectangle, lineCoords = coords)
+
+                self.canvas.RedrawSelectBox(id)
+
             if itype == 'text':
                 
                 if self.instruction[id]['rotate']:
@@ -812,7 +917,7 @@
                     rot = 0
 
                 extent = self.getTextExtent(textDict = self.instruction[id].GetInstruction())
-                rect = wx.Rect2D(self.instruction[id]['where'][0], self.instruction[id]['where'][1], 0, 0)
+                rect = Rect2DPS(self.instruction[id]['where'], (0, 0))
                 self.instruction[id]['coords'] = list(self.canvas.CanvasPaperCoordinates(rect = rect, canvasToPaper = False)[:2])
                 
                 #computes text coordinates according to reference point, not precisely
@@ -993,6 +1098,9 @@
         self.idBoxTmp = wx.NewId()
         self.idZoomBoxTmp = wx.NewId()
         self.idResizeBoxTmp = wx.NewId()
+        self.idLinePointsTmp = (wx.NewId(), wx.NewId()) # ids of marks for moving line vertices
+
+        self.resizeBoxSize = wx.Size(8, 8)
         
         
 
@@ -1051,12 +1159,12 @@
             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
+        Width = units.convert(value = rect.GetWidth(), fromUnit = fromU, toUnit = toU) * scale
+        Height = units.convert(value = rect.GetHeight(), fromUnit = fromU, toUnit = toU) * scale
+        X = units.convert(value = (rect.GetX() - pRectx), fromUnit = fromU, toUnit = toU) * scale
+        Y = units.convert(value = (rect.GetY() - pRecty), fromUnit = fromU, toUnit = toU) * scale
 
-        return wx.Rect2D(X, Y, Width, Height)
+        return Rect2D(X, Y, Width, Height)
 
     
     
@@ -1099,12 +1207,29 @@
         except AttributeError:
             mapId = self.instruction.FindInstructionByType('initMap').id
         
-        for itemType in ('text', 'image', 'northArrow'):
+        for itemType in ('text', 'image', 'northArrow', 'point', 'line', 'rectangle'):
             items = self.instruction.FindInstructionByType(itemType, list = True)
             for item in items:
-                e, n = PaperMapCoordinates(map = self.instruction[mapId], x = self.instruction[item.id]['where'][0],
-                                           y = self.instruction[item.id]['where'][1], paperToMap = True)
-                self.instruction[item.id]['east'], self.instruction[item.id]['north'] = e, n
+                instr = self.instruction[item.id]
+                if itemType in ('line', 'rectangle'):
+                    if itemType == 'line':
+                        e1, n1 = PaperMapCoordinates(map = self.instruction[mapId], x = instr['where'][0][0],
+                                                     y = instr['where'][0][1], paperToMap = True)
+                        e2, n2 = PaperMapCoordinates(map = self.instruction[mapId], x = instr['where'][1][0],
+                                                     y = instr['where'][1][1], paperToMap = True)
+                    else: 
+                        e1, n1 = PaperMapCoordinates(map = self.instruction[mapId], x = instr['rect'].GetLeft(),
+                                                     y = instr['rect'].GetTop(), paperToMap = True)
+                        e2, n2 = PaperMapCoordinates(map = self.instruction[mapId], x = instr['rect'].GetRight(),
+                                                     y = instr['rect'].GetBottom(), paperToMap = True)
+                    instr['east1'] = e1
+                    instr['north1'] = n1
+                    instr['east2'] = e2
+                    instr['north2'] = n2
+                else:
+                    e, n = PaperMapCoordinates(map = self.instruction[mapId], x = instr['where'][0],
+                                               y = instr['where'][1], paperToMap = True)
+                    instr['east'], instr['north'] = e, n
                 
     def OnPaint(self, event):
         """!Draw pseudo DC to buffer
@@ -1158,7 +1283,7 @@
             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:
+                if foundResize and foundResize[0] in (self.idResizeBoxTmp,) + self.idLinePointsTmp:
                     self.SetCursor(self.cursors["sizenwse"])
                     self.parent.SetStatusText(_('Click and drag to resize object'), 0)
                 else:
@@ -1179,7 +1304,7 @@
                 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:
+                if foundResize and foundResize[0] in (self.idResizeBoxTmp,) + self.idLinePointsTmp:
                     self.mouse['use'] = 'resize'
                     
                     # when resizing, proportions match region
@@ -1189,18 +1314,27 @@
                         if self.instruction[self.dragId]['scaleType'] in (0, 1, 2):
                             self.constraint = True
                             self.mapBounds = self.pdcObj.GetIdBounds(self.dragId)
+
+                    if self.instruction[self.dragId].type == 'line':
+                        self.currentLinePoint = self.idLinePointsTmp.index(foundResize[0])
                     
                 elif found:
                     self.dragId = found[0]  
                     self.RedrawSelectBox(self.dragId)
-                    if self.instruction[self.dragId].type != 'map':
+                    if self.instruction[self.dragId].type not in ('map', 'rectangle'):
                         self.pdcTmp.RemoveId(self.idResizeBoxTmp)
                         self.Refresh()
+                    if self.instruction[self.dragId].type != 'line':
+                        for id in self.idLinePointsTmp:
+                            self.pdcTmp.RemoveId(id)
+                        self.Refresh()
                         
                 else:
                     self.dragId = -1
                     self.pdcTmp.RemoveId(self.idBoxTmp)
                     self.pdcTmp.RemoveId(self.idResizeBoxTmp)
+                    for id in self.idLinePointsTmp:
+                        self.pdcTmp.RemoveId(id)
                     self.Refresh()           
                     
         elif event.Dragging() and event.MiddleIsDown():
@@ -1210,14 +1344,32 @@
             
         elif event.Dragging() and event.LeftIsDown():
             #draw box when zooming, creating map 
-            if self.mouse['use'] in ('zoomin', 'zoomout', 'addMap'):
+            if self.mouse['use'] in ('zoomin', 'zoomout', 'addMap', 'addLine', 'addRectangle'):
                 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)
                 
+                if self.mouse['use'] in ('addLine', 'addRectangle'):
+                    if self.mouse['use'] == 'addLine':
+                        pdcType = 'line'
+                        lineCoords = (self.mouse['begin'], self.mouse['end'])
+                    else:
+                        pdcType = 'rect'
+                        lineCoords = None
+                        if r[2] < 2 or r[3] < 2:
+                            # to avoid strange behavoiur
+                            return
+
+                    self.Draw(pen = self.pen['line'], brush = self.brush['line'],
+                              pdc = self.pdcTmp, drawid = self.idZoomBoxTmp,
+                              pdctype = pdcType, bb = r, lineCoords = lineCoords)
+
+                else:
+                    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()
@@ -1232,6 +1384,8 @@
                 self.pdcObj.TranslateId(self.dragId, dx, dy)
                 self.pdcTmp.TranslateId(self.idBoxTmp, dx, dy)
                 self.pdcTmp.TranslateId(self.idResizeBoxTmp, dx, dy)
+                for id in self.idLinePointsTmp:
+                    self.pdcTmp.TranslateId(id, 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
@@ -1240,32 +1394,63 @@
                 
             # resize object
             if self.mouse['use'] == 'resize':
-                type = self.instruction[self.dragId].type
                 pos = event.GetPosition()
-                x, y = self.mapBounds.GetX(), self.mapBounds.GetY()
-                width, height = self.mapBounds.GetWidth(), self.mapBounds.GetHeight()
                 diffX = pos[0] - self.mouse['begin'][0]
                 diffY = pos[1] - self.mouse['begin'][1]
-                # match given region
-                if self.constraint:
-                    if width > height:
+                if self.instruction[self.dragId].type == 'map':
+                    x, y = self.mapBounds.GetX(), self.mapBounds.GetY()
+                    width, height = self.mapBounds.GetWidth(), self.mapBounds.GetHeight()
+                    # match given region
+                    if self.constraint:
+                        if width > height:
+                            newWidth = width + diffX
+                            newHeight = height + diffX * (float(height) / width)
+                        else:
+                            newWidth = width + diffY * (float(width) / height)
+                            newHeight = height + diffY
+                    else:
                         newWidth = width + diffX
-                        newHeight = height + diffX * (float(height) / width)
-                    else:
-                        newWidth = width + diffY * (float(width) / height)
                         newHeight = height + diffY
-                else:
-                    newWidth = width + diffX
-                    newHeight = height + diffY
+                        
+                    if newWidth < 10 or newHeight < 10:
+                        return
                     
-                if newWidth < 10 or newHeight < 10:
-                    return
-                
-                bounds = wx.Rect(x, y, newWidth, newHeight)    
-                self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcObj, drawid = self.dragId,
-                          pdctype = 'rectText', bb = bounds)
+                    bounds = wx.Rect(x, y, newWidth, newHeight)
+                    self.Draw(pen = self.pen['map'], brush = self.brush['map'], pdc = self.pdcObj, drawid = self.dragId,
+                              pdctype = 'rectText', bb = bounds)
+
+                elif self.instruction[self.dragId].type == 'rectangle':
+                    instr = self.instruction[self.dragId]
+                    rect = self.CanvasPaperCoordinates(rect = instr['rect'], canvasToPaper = False)
+                    rect.SetWidth(rect.GetWidth() + diffX)
+                    rect.SetHeight(rect.GetHeight() + diffY)
+
+                    if rect.GetWidth() < 5 or rect.GetHeight() < 5:
+                        return
+
+                    self.DrawGraphics(drawid = self.dragId, shape = 'rectangle', color = instr['color'],
+                                    fcolor = instr['fcolor'], width = instr['width'], bb = rect)
+
+                elif self.instruction[self.dragId].type == 'line':
+                    instr = self.instruction[self.dragId]
+                    points = instr['where']
+                    # moving point
+                    if self.currentLinePoint == 0:
+                        pPaper = points[1]
+                    else:
+                        pPaper = points[0]
+                    pCanvas = self.CanvasPaperCoordinates(rect = Rect2DPS(pPaper, (0, 0)),
+                                                          canvasToPaper = False)[:2]
+                    bounds = wx.RectPP(pCanvas, pos)
+                    self.DrawGraphics(drawid = self.dragId, shape = 'line', color = instr['color'],
+                                    width = instr['width'], bb = bounds, lineCoords = (pos, pCanvas))
+
+                    # update paper coordinates
+                    points[self.currentLinePoint] = self.CanvasPaperCoordinates(rect = wx.RectPS(pos, (0, 0)),
+                                                                                canvasToPaper = True)[:2]
+                                                                                
                 self.RedrawSelectBox(self.dragId)
-                
+
         elif event.LeftUp():
             # zoom in, zoom out
             if self.mouse['use'] in ('zoomin','zoomout'):
@@ -1291,19 +1476,21 @@
                 self.openDialogs['map'] = dlg
                 self.openDialogs['map'].Show()
                 
-                
                 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
-                
+                return
 
 
-            # resize resizable objects (only map sofar)
+            # resize resizable objects (map, line, rectangle)
             if self.mouse['use'] == 'resize':
-                mapId = self.instruction.FindInstructionByType('map').id
+                mapObj = self.instruction.FindInstructionByType('map')
+                if not mapObj:
+                    mapObj = self.instruction.FindInstructionByType('initMap')
+                mapId = mapObj.id
                 
                 if self.dragId == mapId:
                     # necessary to change either map frame (scaleType 0,1,2) or region (scaletype 3)
@@ -1342,6 +1529,15 @@
                     
                     self.RedrawSelectBox(mapId)
                     self.Zoom(zoomFactor = 1, view = (0, 0))
+
+                elif self.instruction[self.dragId].type == 'line':
+                    points = self.instruction[self.dragId]['where']
+                    self.instruction[self.dragId]['rect'] = Rect2DPP(points[0], points[1])
+                    self.RecalculatePosition(ids = [self.dragId])
+
+                elif self.instruction[self.dragId].type == 'rectangle':
+                    self.RecalculatePosition(ids = [self.dragId])
+
                 self.mouse['use'] = 'pointer'
                 
             # recalculate the position of objects after dragging    
@@ -1351,20 +1547,60 @@
                     self.RecalculatePosition(ids = [self.dragId])
                     if self.instruction[self.dragId].type in self.openDialogs:
                         self.openDialogs[self.instruction[self.dragId].type].updateDialog()
+            
+            elif self.mouse['use'] in ('addPoint', 'addLine', 'addRectangle'):
+                endCoordinates = self.CanvasPaperCoordinates(rect = wx.Rect(event.GetX(), event.GetY(), 0, 0),
+                                                          canvasToPaper = True)[:2]
 
+                diffX = event.GetX() - self.mouse['begin'][0]
+                diffY = event.GetY() - self.mouse['begin'][1]
+
+                if self.mouse['use'] == 'addPoint':
+                    self.parent.AddPoint(coordinates = endCoordinates)
+                elif self.mouse['use'] in ('addLine', 'addRectangle'):
+                    # not too small lines/rectangles
+                    if sqrt(diffX * diffX + diffY * diffY) < 5:
+                        self.pdcTmp.RemoveId(self.idZoomBoxTmp)
+                        self.Refresh()
+                        return
+
+                    beginCoordinates = self.CanvasPaperCoordinates(rect = wx.Rect(self.mouse['begin'][0],
+                                                                                  self.mouse['begin'][1], 0, 0),
+                                                                   canvasToPaper = True)[:2]
+                    if self.mouse['use'] == 'addLine':
+                        self.parent.AddLine(coordinates = [beginCoordinates, endCoordinates])
+                    else:
+                        self.parent.AddRectangle(coordinates = [beginCoordinates, endCoordinates])
+                    self.pdcTmp.RemoveId(self.idZoomBoxTmp)
+                    self.Refresh()
+                
         # 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, 'image': self.parent.OnAddImage,
-                                'northArrow' : self.parent.OnAddNorthArrow,
-                                '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), 'image': dict(event = None, id = self.dragId),
+                itemCall = {'text':self.parent.OnAddText,
+                            'mapinfo': self.parent.OnAddMapinfo,
+                            'scalebar': self.parent.OnAddScalebar,
+                            'image': self.parent.OnAddImage,
+                            'northArrow' : self.parent.OnAddNorthArrow,
+                            'point': self.parent.AddPoint,
+                            'line': self.parent.AddLine,
+                            'rectangle': self.parent.AddRectangle,
+                            '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),
+                            'image': dict(event = None, id = self.dragId),
                             'northArrow': dict(event = None, id = self.dragId),
-                            'rasterLegend': dict(event = None), 'vectorLegend': dict(event = None, page = 1),
+                            'point': dict(id = self.dragId),
+                            'line': dict(id = self.dragId),
+                            'rectangle': dict(id = self.dragId),
+                            '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])
 
@@ -1381,7 +1617,7 @@
     def RecalculatePosition(self, ids):
         for id in ids:
             itype = self.instruction[id].type
-            if itype == 'map':
+            if itype in ('map', 'rectangle'):
                 self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = self.pdcObj.GetIdBounds(id),
                                                                            canvasToPaper = True)
                 self.RecalculateEN()
@@ -1393,6 +1629,30 @@
                                                                             canvasToPaper = True)[:2] 
                 if itype in ('image', 'northArrow'):
                     self.RecalculateEN()
+
+            elif itype == 'point':
+                rect = self.pdcObj.GetIdBounds(id)
+                self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = rect,
+                                                                           canvasToPaper = True)
+                rect.OffsetXY(rect.GetWidth()/2, rect.GetHeight()/2)
+                self.instruction[id]['where'] = self.CanvasPaperCoordinates(rect = rect,
+                                                                            canvasToPaper = True)[:2]
+                self.RecalculateEN()
+
+            elif itype == 'line':
+                rect = self.pdcObj.GetIdBounds(id)
+                oldRect = self.instruction[id]['rect']
+                newRect = self.CanvasPaperCoordinates(rect = rect, canvasToPaper = True)
+                xDiff = newRect[0] - oldRect[0]
+                yDiff = newRect[1] - oldRect[1]
+                self.instruction[id]['rect'] = newRect
+
+                point1 = wx.Point2D(xDiff, yDiff) + self.instruction[id]['where'][0]
+                point2 = wx.Point2D(xDiff, yDiff) + self.instruction[id]['where'][1]
+                self.instruction[id]['where'] = [point1, point2]
+                
+                self.RecalculateEN()
+
             elif  itype == 'scalebar':
                 self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = self.pdcObj.GetIdBounds(id),
                                                                            canvasToPaper = True)
@@ -1420,7 +1680,7 @@
                     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),
+                self.instruction[id]['where'] = self.CanvasPaperCoordinates(rect = Rect2D(x, y, 0, 0),
                                                                             canvasToPaper = True)[:2]
                 self.RecalculateEN()
         
@@ -1510,6 +1770,27 @@
                 elif type == 'northArrow':
                     self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcObj,
                               drawid = id, pdctype = 'bitmap', bb = oRect)
+
+                elif type in ('point', 'line', 'rectangle'):
+                    instr = self.instruction[id]
+                    color = self.instruction[id]['color']
+                    width = fcolor = coords = None
+
+                    if type in ('point', 'rectangle'):
+                        fcolor = self.instruction[id]['fcolor']
+                    if type in ('line', 'rectangle'):
+                        width = self.instruction[id]['width']
+                    if type in ('line'):
+                        point1, point2 = instr['where'][0], instr['where'][1]
+                        point1 = self.CanvasPaperCoordinates(rect = Rect2DPS(point1, (0, 0)),
+                                                             canvasToPaper = False)[:2]
+                        point2 = self.CanvasPaperCoordinates(rect = Rect2DPS(point2, (0, 0)),
+                                                             canvasToPaper = False)[:2]
+                        coords = (point1, point2)
+
+                    self.DrawGraphics(drawid = id, shape = type, bb = oRect, lineCoords = coords,
+                                    color = color, fcolor = fcolor, width = width)
+
                 else:
                     self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcObj,
                               drawid = id, pdctype = 'rectText', bb = oRect)
@@ -1534,8 +1815,14 @@
         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"""    
+    def Draw(self, pen, brush, pdc, drawid = None, pdctype = 'rect', bb = wx.Rect(0,0,0,0), lineCoords = None): 
+        """! Draw object with given pen and brush.
+
+        @param pdc PseudoDC
+        @param pdctype 'bitmap'/'rectText'/'rect'/'point'/'line'
+        @param bb bounding box
+        @param lineCoords coordinates of line start, end points (wx.Point, wx.Point)
+        """    
         if drawid is None:
             drawid = wx.NewId()
         bb = bb.Get()
@@ -1580,12 +1867,53 @@
             pdc.SetBackgroundMode(wx.TRANSPARENT)
             pdc.DrawText(text = text, x = textRect.x, y = textRect.y)
                 
+        elif pdctype == 'point':
+            pdc.DrawCircle(x = bb[0] + bb[2] / 2,
+                           y = bb[1] + bb[3] / 2,
+                           radius = bb[2] / 2)
+                           
+        elif pdctype == 'line':
+            pdc.DrawLinePoint(lineCoords[0], lineCoords[1])
+
         pdc.SetIdBounds(drawid, bb)
         pdc.EndDrawing()
         self.Refresh()
 
         return drawid
     
+    def DrawGraphics(self, drawid, shape, color, bb, width = None, fcolor = None, lineCoords = None):
+        """!Draw point/line/rectangle with given color and width
+
+        @param drawid id of drawn object
+        @param shape drawn shape: 'point'/'line'/'rectangle'
+        @param color pen outline color ('RRR:GGG:BBB')
+        @param fcolor brush fill color, if meaningful ('RRR:GGG:BBB')
+        @param width pen width
+        @param bb bounding box
+        @param lineCoords line coordinates (for line only)
+        """
+        pdctype = {'point'     : 'point',
+                   'line'      : 'line',
+                   'rectangle' : 'rect'}
+
+        if color == 'none':
+            pen = wx.TRANSPARENT_PEN
+        else:
+            if width is not None:
+                units = UnitConversion(self)
+                width = int(units.convert(value = width, fromUnit = 'point', toUnit = 'pixel') * self.currScale)
+            else:
+                width = 2
+            pen = wx.Pen(colour = convertRGB(color), width = width)
+            pen.SetCap(wx.CAP_BUTT) # this is how ps.map draws
+
+        brush = wx.TRANSPARENT_BRUSH
+        if fcolor and fcolor != 'none':
+            brush = wx.Brush(colour = convertRGB(fcolor))
+        
+        self.Draw(pen = pen, brush = brush, pdc = self.pdcObj, pdctype = pdctype[shape],
+                  drawid = drawid, bb = bb, lineCoords = lineCoords)
+
     def DrawBitmap(self, pdc, filePath, rotation, bbox):
         """!Draw bitmap using PIL"""
         pImg = PILImage.open(filePath)
@@ -1702,17 +2030,32 @@
     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':
+            rect = self.pdcObj.GetIdBounds(id)
+            if self.instruction[id].type != 'line':
+                rect = rect.Inflate(3,3)
+            # draw select box around object
+            self.Draw(pen = self.pen['select'], brush = self.brush['select'], pdc = self.pdcTmp,
+                      drawid = self.idBoxTmp, pdctype = 'rect', bb = rect)
+            
+            # draw small marks signalizing resizing
+            if self.instruction[id].type in ('map', 'rectangle'):
                 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)
+                rect  = wx.RectPS(controlP, self.resizeBoxSize)
+                self.Draw(pen = self.pen['resize'], brush = self.brush['resize'], pdc = self.pdcTmp,
+                          drawid = self.idResizeBoxTmp, pdctype = 'rect', bb = rect)
+
+            elif self.instruction[id].type == 'line':
+                p1Paper = self.instruction[id]['where'][0]
+                p2Paper = self.instruction[id]['where'][1]
+                p1Canvas = self.CanvasPaperCoordinates(rect = Rect2DPS(p1Paper, (0, 0)), canvasToPaper = False)[:2]
+                p2Canvas = self.CanvasPaperCoordinates(rect = Rect2DPS(p2Paper, (0, 0)), canvasToPaper = False)[:2]
+                rect = []
+                box = wx.RectS(self.resizeBoxSize)
+                rect.append(box.CenterIn(wx.RectPS(p1Canvas, wx.Size())))
+                rect.append(box.CenterIn(wx.RectPS(p2Canvas, wx.Size())))
+                for i, point in enumerate((p1Canvas, p2Canvas)):
+                    self.Draw(pen = self.pen['resize'], brush = self.brush['resize'], pdc = self.pdcTmp,
+                              drawid = self.idLinePointsTmp[i], pdctype = 'rect', bb = rect[i])
         
     def UpdateMapLabel(self):
         """!Updates map frame label"""

Modified: grass/trunk/gui/wxpython/psmap/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/psmap/toolbars.py	2012-02-13 15:01:04 UTC (rev 50796)
+++ grass/trunk/gui/wxpython/psmap/toolbars.py	2012-02-13 15:12:38 UTC (rev 50797)
@@ -83,6 +83,14 @@
                                     label = _('Image')),
             'addNorthArrow': MetaIcon(img = 'north-arrow-add',
                                       label = _('North Arrow')),
+            'drawGraphics': MetaIcon(img = 'edit',
+                                     label = _('Add simple graphics')),
+            'pointAdd'    : MetaIcon(img = '',
+                                     label = _('Point')),
+            'lineAdd'     : MetaIcon(img = '',
+                                     label = _('Line')),
+            'rectangleAdd': MetaIcon(img = '',
+                                     label = _('Rectangle')),
             }
         self.icons = icons
         
@@ -113,6 +121,8 @@
                                       self.parent.OnAddVect),
                                      ("dec", BaseIcons["overlay"],
                                       self.OnDecoration),
+                                     ("drawGraphics", icons["drawGraphics"],
+                                      self.OnDrawGraphics, wx.ITEM_CHECK),
                                      ("delete", icons["deleteObj"],
                                       self.parent.OnDelete),
                                      (None, ),
@@ -138,4 +148,15 @@
                       (self.icons["addText"],       self.parent.OnAddText),
                       (self.icons["addImage"],      self.parent.OnAddImage),
                       (self.icons["addNorthArrow"], self.parent.OnAddNorthArrow)))
-        
+
+    def OnDrawGraphics(self, event):
+        """!Simple geometry features (point, line, rectangle) overlay menu
+        """
+        # we need the previous id
+        self.actionOld = self.action['id']
+        self.OnTool(event)
+        self.action['id'] = self.actionOld
+        self._onMenu(((self.icons["pointAdd"],      self.parent.OnAddPoint),
+                      (self.icons["lineAdd"],       self.parent.OnAddLine),
+                      (self.icons["rectangleAdd"],  self.parent.OnAddRectangle),
+                    ))

Added: grass/trunk/gui/wxpython/psmap/utils.py
===================================================================
--- grass/trunk/gui/wxpython/psmap/utils.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/psmap/utils.py	2012-02-13 15:12:38 UTC (rev 50797)
@@ -0,0 +1,70 @@
+"""!
+ at package psmap.utils
+
+ at brief utilities for wxpsmap
+
+Classes:
+ - utils::Rect2D
+ - utils::Rect2DPP
+ - utils::Rect2DPS
+
+(C) 2012 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 <kratochanna gmail.com>
+"""
+
+import wx
+
+class Rect2D(wx.Rect2D):
+    """!Class representing rectangle with floating point values.
+
+    Overrides wx.Rect2D to unify Rect access methods, which are
+    different (e.g. wx.Rect.GetTopLeft() x wx.Rect2D.GetLeftTop()).
+    More methods can be added depending on needs.
+    """
+    def __init__(self, x = 0, y = 0, width = 0, height = 0):
+        wx.Rect2D.__init__(self, x = x, y = y, w = width, h = height)
+
+    def GetX(self):
+        return self.x
+        
+    def GetY(self):
+        return self.y
+
+    def GetWidth(self):
+        return self.width
+
+    def SetWidth(self, width):
+        self.width = width
+        
+    def GetHeight(self):
+        return self.height
+
+    def SetHeight(self, height):
+        self.height = height
+
+class Rect2DPP(Rect2D):
+    """!Rectangle specified by 2 points (with floating point values).
+
+    @see Rect2D, Rect2DPS
+    """
+    def __init__(self, topLeft = wx.Point2D(), bottomRight = wx.Point2D()):
+        Rect2D.__init__(self, x = 0, y = 0, width = 0, height = 0)
+
+        x1, y1 = topLeft[0], topLeft[1]
+        x2, y2 = bottomRight[0], bottomRight[1]
+
+        self.SetLeft(min(x1, x2))
+        self.SetTop(min(y1, y2))
+        self.SetRight(max(x1, x2))
+        self.SetBottom(max(y1, y2))
+
+class Rect2DPS(Rect2D):
+    """!Rectangle specified by point and size (with floating point values).
+
+    @see Rect2D, Rect2DPP
+    """
+    def __init__(self, pos = wx.Point2D(), size = (0, 0)):
+        Rect2D.__init__(self, x = pos[0], y = pos[1], width = size[0], height = size[1])


Property changes on: grass/trunk/gui/wxpython/psmap/utils.py
___________________________________________________________________
Added: svn:mime-type
   + text/python
Added: svn:keywords
   + Author Date Id
Added: svn:eol-style
   + native



More information about the grass-commit mailing list