[GRASS-SVN] r55366 - in grass-addons/grass7/gui/wxpython: . newgui

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Mar 13 11:02:02 PDT 2013


Author: rashadkm
Date: 2013-03-13 11:02:02 -0700 (Wed, 13 Mar 2013)
New Revision: 55366

Added:
   grass-addons/grass7/gui/wxpython/newgui/
   grass-addons/grass7/gui/wxpython/newgui/api_test.py
   grass-addons/grass7/gui/wxpython/newgui/frame.py
   grass-addons/grass7/gui/wxpython/newgui/gui_mapwindow.py
   grass-addons/grass7/gui/wxpython/newgui/mapwindow.py
   grass-addons/grass7/gui/wxpython/newgui/wxgui.py
Log:
test api code

Added: grass-addons/grass7/gui/wxpython/newgui/api_test.py
===================================================================
--- grass-addons/grass7/gui/wxpython/newgui/api_test.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/newgui/api_test.py	2013-03-13 18:02:02 UTC (rev 55366)
@@ -0,0 +1,467 @@
+"""!
+ at package api_test.py
+
+
+(C) 2006-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+"""
+
+import os
+import sys
+import copy
+import tempfile
+
+
+import wx
+
+
+try:
+    import wx.lib.agw.customtreectrl as CT
+except ImportError:
+    import wx.lib.customtreectrl as CT
+import wx.lib.buttons  as buttons
+try:
+    import treemixin 
+except ImportError:
+    from wx.lib.mixins import treemixin
+
+from ctypes import *
+import grass.script as grass
+from core import globalvar
+from core.gcmd          import GError, GMessage
+from mapdisp            import statusbar as sb
+from mapwindow  import BufferedWindow2
+from gui_core.mapdisp   import MapFrameBase
+import gettext
+import core.render as render
+from core.render        import Map, MapLayer
+from core.gcmd          import RunCommand, GMessage
+from core.debug          import Debug
+from lmgr.lmgr_layertree import LMIcons
+from gui_core.toolbars   import BaseIcons
+from icons.icon          import MetaIcon
+from core.utils          import GetLayerNameFromCmd
+
+
+class MySingleMapFrame(MapFrameBase):
+    """! Frame with one map window.
+    
+    It is base class for frames which needs only one map.
+    
+    Derived class should have \c self.MapWindow or
+    it has to override GetWindow() methods.
+    
+    @note To access maps use getters only
+    (when using class or when writing class itself).
+    """
+    def __init__(self, parent = None, giface = None, id = wx.ID_ANY, title = None,
+                 style = wx.DEFAULT_FRAME_STYLE,
+                 Map = Map(),
+                 auimgr = None, name = None, **kwargs):
+        """!
+        
+        @param parent gui parent
+        @param id wx id
+        @param title window title
+        @param style \c wx.Frame style
+        @param Map instance of render.Map
+        @param name frame name
+        @param kwargs arguments passed to MapFrameBase
+        """
+
+        MapFrameBase.__init__(self, parent = parent, id = id, title = title,
+                              style = style,
+                              auimgr = auimgr, name = name, **kwargs)
+
+        self.Map = Map       # instance of render.Map
+
+
+        vbox = wx.BoxSizer(wx.HORIZONTAL)
+        p = wx.Panel(self,-1)
+        
+
+      
+
+        #self.ltree = LayerTree(self, self.Map)
+
+        #
+        # initialize region values
+        #
+        self._initMap(Map = self.Map)
+        
+        self._lmgr = LayerManager(p,self.Map)
+        
+        self.MapWindow = BufferedWindow2(p, giface = giface, id = id, Map = self.Map)
+
+        vbox.Add(self._lmgr, 1, wx.EXPAND | wx.ALL, 20)
+        vbox.Add(self.MapWindow, 1, wx.EXPAND | wx.ALL, 20)
+        p.SetSizer(vbox)  
+        
+
+    def GetLayerByIndex(self, index):
+        return self.GetLayerManager().GetLayerByIndex(index)
+        
+    def GetCurrentIndex(self):
+        return self.GetLayerManager().GetCurrentIndex()
+
+    def GetLayerManager(self):
+        return self._lmgr
+        
+    def SetLayerManager(self, lmgr):
+        self._lmgr = lmgr
+        
+    def AddLayer(self, layer):
+        self.GetLayerManager().AddLayer(layer)
+        
+    def GetMap(self):
+        """!Returns map (renderer) instance"""
+        return self.Map
+
+    def GetWindow(self):
+        """!Returns map window"""
+        return self.MapWindow
+        
+    def GetWindows(self):
+        """!Returns list of map windows"""
+        return [self.MapWindow]
+
+    def OnRender(self, event):
+        """!Re-render map composition (each map layer)
+        """
+        self.GetWindow().UpdateMap(render = True, renderVector = True)
+        
+        # update statusbar
+        #rashad
+        #self.StatusbarUpdate()
+
+class LayerManager(wx.Panel):
+
+    def __init__(self, parent, Map, id = wx.ID_ANY, style = wx.SUNKEN_BORDER,
+                 ctstyle = CT.TR_HAS_BUTTONS | CT.TR_HAS_VARIABLE_ROW_HEIGHT |
+                 CT.TR_HIDE_ROOT | CT.TR_ROW_LINES | CT.TR_FULL_ROW_HIGHLIGHT |
+                 CT.TR_MULTIPLE, **kwargs):
+
+        wx.Panel.__init__(self, parent = parent, id =id, style = style)  
+
+        self._layerList = []
+        self._activeLayer = None
+        self._activeIndex = 0
+        self._Map = Map        
+        
+        self.ltree = LayerTree(self,Map, id = id, style = style, ctstyle = ctstyle, **kwargs)
+        self.ltree.SetSize((300,500))
+
+    def AddLayer(self, layer, active = True):
+        self.ltree.AddLayer(layer, True)
+
+    def GetLayerByIndex(self, index):
+        self.ltree.GetLayerByIndex(index)
+            
+    def GetCurrentIndex(self):
+        self.ltree.GetCurrentIndex()     
+        
+class LayerTree(treemixin.DragAndDrop, CT.CustomTreeCtrl):
+    """copied from lmgr.layertree.py"""
+    def __init__(self, parent, Map,  id, style, ctstyle, **kwargs):
+    
+        if globalvar.hasAgw:
+            super(LayerTree, self).__init__(parent, id, agwStyle = ctstyle, **kwargs)
+        else:
+            super(LayerTree, self).__init__(parent, id, style = ctstyle, **kwargs)    
+    
+        #wx.Window.__init__(self, parent = parent, id =-2)  
+        #self.panel = wx.Panel(self, )
+        self._layerList = []
+        self._activeLayer = None
+        self._activeIndex = 0
+        self._Map = Map
+        self.root = self.AddRoot(_("Map Layers"))
+        self.SetPyData(self.root, (None, None))
+
+
+        il = wx.ImageList(16, 16, mask = False)
+        
+        trart = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, (16, 16))
+        self.folder_open = il.Add(trart)
+        trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16))
+        self.folder = il.Add(trart)
+                
+        bmpsize = (16, 16)
+        trgif = BaseIcons["addRast"].GetBitmap(bmpsize)
+        self.rast_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addRast3d"].GetBitmap(bmpsize)
+        self.rast3d_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addRgb"].GetBitmap(bmpsize)
+        self.rgb_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addHis"].GetBitmap(bmpsize)
+        self.his_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addShaded"].GetBitmap(bmpsize)
+        self.shaded_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addRArrow"].GetBitmap(bmpsize)
+        self.rarrow_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addRNum"].GetBitmap(bmpsize)
+        self.rnum_icon = il.Add(trgif)
+        
+        trgif = BaseIcons["addVect"].GetBitmap(bmpsize)
+        self.vect_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addThematic"].GetBitmap(bmpsize)
+        self.theme_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addChart"].GetBitmap(bmpsize)
+        self.chart_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addGrid"].GetBitmap(bmpsize)
+        self.grid_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addGeodesic"].GetBitmap(bmpsize)
+        self.geodesic_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addRhumb"].GetBitmap(bmpsize)
+        self.rhumb_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addLabels"].GetBitmap(bmpsize)
+        self.labels_icon = il.Add(trgif)
+        
+        trgif = LMIcons["addCmd"].GetBitmap(bmpsize)
+        self.cmd_icon = il.Add(trgif)
+
+        trgif = LMIcons["wsImport"].GetBitmap(bmpsize)
+        self.ws_icon = il.Add(trgif)
+        
+        self.AssignImageList(il)
+             
+    def AddLayer(self, layer, active = True, multiple = True, lchecked = True):
+        self._Map.AddMapLayer(layer)
+        self._layerList.append(layer)
+        self._activeIndex = len(self._layerList) - 1
+        if layer.name and not multiple:
+            # check for duplicates
+            item = self.GetFirstVisibleItem()
+            while item and item.IsOk():
+                if self.GetLayerInfo(item, key = 'type') == 'vector':
+                    name = self.GetLayerInfo(item, key = 'maplayer').GetName()
+                    if name == lname:
+                        return
+                item = self.GetNextVisible(item)
+        
+        self.first = True
+        
+        # deselect active item
+        if self._activeLayer:
+            self.SelectItem(self._activeLayer, select = False)
+        
+        Debug.msg (3, "LayerTree().AddLayer(): ltype=%s" % (layer.type))
+        
+        if layer.type == 'command':
+            # generic command item
+            ctrl = wx.TextCtrl(self, id = wx.ID_ANY, value = '',
+                               pos = wx.DefaultPosition, size = (self.GetSize()[0]-100,25),
+                               # style = wx.TE_MULTILINE|wx.TE_WORDWRAP)
+                               style = wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
+            ctrl.Bind(wx.EVT_TEXT_ENTER, self.OnCmdChanged)
+            # ctrl.Bind(wx.EVT_TEXT,       self.OnCmdChanged)
+        elif layer.type == 'group':
+            # group item
+            ctrl = None
+            grouptext = _('Layer group:') + str(self.groupnode)
+            self.groupnode += 1
+        else:
+            btnbmp = LMIcons["layerOptions"].GetBitmap((16,16))
+            ctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24,24))
+            ctrl.SetToolTipString(_("Click to edit layer settings"))
+#rashad            self.Bind(wx.EVT_BUTTON, self.OnLayerContextMenu, ctrl)
+        # add layer to the layer tree
+        if self._activeLayer and self._activeLayer != self.GetRootItem():
+            if self.GetLayerInfo(self._activeLayer, key = 'type') == 'group' \
+                and self.IsExpanded(self._activeLayer):
+                # add to group (first child of self._activeLayer) if group expanded
+                layeritem = self.PrependItem(parent = self._activeLayer,
+                                         text = '', ct_type = 1, wnd = ctrl)
+            else:
+                # prepend to individual layer or non-expanded group
+                if lgroup == -1:
+                    # -> last child of root (loading from workspace)
+                    layeritem = self.AppendItem(parentId = self.root,
+                                            text = '', ct_type = 1, wnd = ctrl)
+                elif lgroup > -1:
+                    # -> last child of group (loading from workspace)
+                    parent = self.FindItemByIndex(index = lgroup)
+                    if not parent:
+                        parent = self.root
+                    layeritem = self.AppendItem(parentId = parent,
+                                            text = '', ct_type = 1, wnd = ctrl)
+                elif lgroup is None:
+                    # -> previous sibling of selected layer
+                    parent = self.GetItemParent(self._activeLayer)
+                    layeritem = self.InsertItem(parentId = parent,
+                                            input = self.GetPrevSibling(self._activeLayer),
+                                            text = '', ct_type = 1, wnd = ctrl)
+        else: # add first layer to the layer tree (first child of root)
+            layeritem = self.PrependItem(parent = self.root, text = '', ct_type = 1, wnd = ctrl)
+        
+        # layer is initially unchecked as inactive (beside 'command')
+        # use predefined value if given
+        if lchecked is not None:
+            checked = lchecked
+        else:
+            checked = True
+        
+        self.forceCheck = True
+        self.CheckItem(layeritem, checked = checked)
+        
+        # add text and icons for each layer layer.type
+        label =  _('(double click to set properties)') + ' ' * 15
+        if layer.type == 'raster':
+            self.SetItemImage(layeritem, self.rast_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('raster'), label))
+        elif layer.type == '3d-raster':
+            self.SetItemImage(layeritem, self.rast3d_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('3D raster'), label))
+        elif layer.type == 'rgb':
+            self.SetItemImage(layeritem, self.rgb_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('RGB'), label))
+        elif layer.type == 'his':
+            self.SetItemImage(layeritem, self.his_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('HIS'), label))
+        elif layer.type == 'shaded':
+            self.SetItemImage(layeritem, self.shaded_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('shaded relief'), label))
+        elif layer.type == 'rastnum':
+            self.SetItemImage(layeritem, self.rnum_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('raster cell numbers'), label))
+        elif layer.type == 'rastarrow':
+            self.SetItemImage(layeritem, self.rarrow_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('raster flow arrows'), label))
+        elif layer.type == 'vector':
+            self.SetItemImage(layeritem, self.vect_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('vector'), label))
+        elif layer.type == 'thememap':
+            self.SetItemImage(layeritem, self.theme_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('thematic area (choropleth) map'), label))
+        elif layer.type == 'themechart':
+            self.SetItemImage(layeritem, self.chart_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('thematic charts'), label))
+        elif layer.type == 'grid':
+            self.SetItemImage(layeritem, self.grid_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('grid'), label))
+        elif layer.type == 'geodesic':
+            self.SetItemImage(layeritem, self.geodesic_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('geodesic line'), label))
+        elif layer.type == 'rhumb':
+            self.SetItemImage(layeritem, self.rhumb_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('rhumbline'), label))
+        elif layer.type == 'labels':
+            self.SetItemImage(layeritem, self.labels_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('vector labels'), label))
+        elif layer.type == 'command':
+            self.SetItemImage(layeritem, self.cmd_icon)
+        elif layer.type == 'group':
+            self.SetItemImage(layeritem, self.folder, CT.TreeItemIcon_Normal)
+            self.SetItemImage(layeritem, self.folder_open, CT.TreeItemIcon_Expanded)
+            self.SetItemText(layeritem, grouptext)
+        elif layer.type == 'wms':            
+            self.SetItemImage(layeritem, self.ws_icon)
+            self.SetItemText(layeritem, '%s %s' % (_('wms'), label))
+    
+        self.first = False
+        
+        if layer.type != 'group':
+            if layer.cmd and len(layer.cmd) > 1:
+                cmd = layer.cmd
+                render = False
+                name, found = layer.name, True
+            else:
+                cmd = []
+                if layer.type == 'command' and layer.name:
+                    for c in lname.split(';'):
+                        cmd.append(c.split(' '))
+                
+                render = False
+                name = None
+            
+            if ctrl:
+                ctrlId = ctrl.GetId()
+            else:
+                ctrlId = None
+            
+            # add a data object to hold the layer's command (does not apply to generic command layers)
+            self.SetPyData(layeritem, ({'cmd'      : cmd,
+                                    'type'     : layer.type,
+                                    'ctrl'     : ctrlId,
+                                    'label'    : None,
+                                    'maplayer' : None,
+                                    'vdigit'   : None,
+                                    'nviz'     : None,
+                                    'propwin'  : None}, 
+                                   None))
+            
+            # find previous map layer instance 
+            prevItem = self.GetFirstChild(self.root)[0]
+            prevMapLayer = None 
+            pos = -1
+            while prevItem and prevItem.IsOk() and prevItem != layeritem: 
+                if self.GetLayerInfo(prevItem, key = 'maplayer'): 
+                    prevMapLayer = self.GetLayerInfo(prevItem, key = 'maplayer')
+                
+                prevItem = self.GetNextSibling(prevItem) 
+                
+                if prevMapLayer: 
+                    pos = self.Map.GetLayerIndex(prevMapLayer)
+                else: 
+                    pos = -1
+            
+#            maplayer = self.Map.AddLayer(pos = pos,
+#                                         ltype = ltype, command = self.GetLayerInfo(prevItem, key = 'cmd'), name = name,
+#                                         active = checked, hidden = False,
+#                                         opacity = lopacity, render = render)
+#            self.SetLayerInfo(layer, key = 'maplayer', value = maplayer)
+#            
+#            # run properties dialog if no properties given
+#            if len(cmd) == 0:
+#                self.PropertiesDialog(layer, show = True)
+        
+        else: # group
+            self.SetPyData(layeritem, ({'cmd'      : None,
+                                    'type'     : ltype,
+                                    'ctrl'     : None,
+                                    'label'    : None,
+                                    'maplayer' : None,
+                                    'propwin'  : None}, 
+                                   None))
+        
+        # select new item
+        self.SelectItem(layeritem, select = True)
+
+        # use predefined layer name if given
+        if layer.name:
+            if layer.type == 'group':
+                self.SetItemText(layeritem, layer.name)
+            elif layer.type == 'command':
+                ctrl.SetValue(layer.name)
+            else:
+                self.SetItemText(layeritem, 'ELEVATIOM at PERMANENT')
+        else:
+            if layer.type == 'group':
+                self.OnRenameLayer(None)
+                
+        return layeritem       
+   
+    def GetLayerByIndex(self, index):
+        if index > -1 and index < len(self._layerList):
+            return self._layerList[index]
+            
+    def GetCurrentIndex(self):
+        return self._activeIndex      
+
+         

Added: grass-addons/grass7/gui/wxpython/newgui/frame.py
===================================================================
--- grass-addons/grass7/gui/wxpython/newgui/frame.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/newgui/frame.py	2013-03-13 18:02:02 UTC (rev 55366)
@@ -0,0 +1,62 @@
+"""!
+ at package frame.py
+
+
+(C) 2006-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+"""
+
+import os
+import sys
+import copy
+import tempfile
+import gettext
+
+if __name__ == "__main__":
+    sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
+import wx
+
+
+from api_test           import MySingleMapFrame
+from core.render        import MapLayer        
+class MyFrame(MySingleMapFrame):
+    """!main frame
+    """
+    def __init__(self, parent = None, giface = None, title = _("GRASS UI"),
+              size = (875, 600), name = 'Frame', **kwargs):
+        """!
+        @param parent (no parent is expected)
+        @param title window title
+        @param size default size
+        """
+        #self.Map = Map()
+        #self.giface = giface
+        
+        MySingleMapFrame.__init__(self, parent = parent, title = title, size = size, name = name, **kwargs)
+       
+        
+        self.cmd =["d.rast", "map=aspect at PERMANENT"]
+        self.rlayer = MapLayer(ltype = 'raster', cmd = self.cmd, Map = self.GetMap(), name = "elevation")
+        self.AddLayer(self.rlayer)
+        #print self.GetLayerByIndex(0).name
+        #print self.GetCurrentIndex()
+        
+       
+
+def main():
+
+    gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
+    
+    app = wx.PySimpleApp()
+    wx.InitAllImageHandlers()
+    frame = MyFrame()
+    frame.Show()
+    app.MainLoop()
+
+if __name__ == "__main__":
+    main()
+    

Added: grass-addons/grass7/gui/wxpython/newgui/gui_mapwindow.py
===================================================================
--- grass-addons/grass7/gui/wxpython/newgui/gui_mapwindow.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/newgui/gui_mapwindow.py	2013-03-13 18:02:02 UTC (rev 55366)
@@ -0,0 +1,248 @@
+"""!
+ at package gui_core.mapwindow
+
+ at brief Map display canvas - base class for buffered window.
+
+Classes:
+ - mapwindow::MapWindow
+
+(C) 2006-2012 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+ at author Michael Barton
+ at author Jachym Cepicky
+ at author Vaclav Petras <wenzeslaus gmail.com> (handlers support)
+ at author Stepan Turek <stepan.turek seznam.cz> (handlers support)
+"""
+
+import wx
+
+from core.settings import UserSettings
+from core.gcmd     import GError
+
+from grass.script import core as grass
+
+class MapWindow(object):
+    """!Abstract map display window class
+    
+    Superclass for BufferedWindow class (2D display mode), and GLWindow
+    (3D display mode).
+    
+    Subclasses have to define
+     - _bindMouseEvents method which binds MouseEvent handlers
+     - Pixel2Cell
+     - Cell2Pixel (if it is possible)
+    """
+    def __init__(self, parent, giface, Map, frame, **kwargs):
+        self.parent = parent
+        self.Map = Map
+        self.frame = frame
+        self._giface = giface
+        self.Map.SetReceiver(self)
+        
+        # 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",
+            'box'  : "point"
+            }
+        # last east, north coordinates, changes on mouse motion
+        self.lastEN = None 
+        
+        # stores overridden cursor
+        self._overriddenCursor = None
+
+        # dictionary where event types are stored as keys and lists of
+        # handlers for these types as values
+        self.handlersContainer = {
+            wx.EVT_LEFT_DOWN : [],
+            wx.EVT_LEFT_UP : [],
+            wx.EVT_LEFT_DCLICK : [],
+            wx.EVT_MIDDLE_DOWN : [],
+            wx.EVT_MIDDLE_UP : [],
+            wx.EVT_MIDDLE_DCLICK : [],
+            wx.EVT_RIGHT_DOWN : [],
+            wx.EVT_RIGHT_UP : [],
+            wx.EVT_RIGHT_DCLICK : [],
+            wx.EVT_MOTION : [],
+            wx.EVT_ENTER_WINDOW : [],
+            wx.EVT_LEAVE_WINDOW : [],
+            wx.EVT_MOUSEWHEEL : [],
+            wx.EVT_MOUSE_EVENTS : []
+            }
+        
+        wx.CallAfter(self.InitBinding)
+
+    def __del__(self):
+        self.UnregisterAllHandlers()
+
+    def InitBinding(self):
+        """!Binds helper functions, which calls all handlers
+           registered to events with the events
+        """
+        for ev, handlers in self.handlersContainer.iteritems():
+            self.Bind(ev, self.EventTypeHandler(handlers))
+    
+    def EventTypeHandler(self, evHandlers):
+        return lambda event:self.HandlersCaller(event, evHandlers)  
+    
+    def HandlersCaller(self, event, handlers):
+        """!Hepler function which calls all handlers registered for
+        event
+        """
+        for handler in handlers:
+            try:
+                handler(event)
+            except:
+                handlers.remove(handler)
+                GError(parent = self,
+                       message=_("Error occured during calling of handler: %s \n"
+                                 "Handler was unregistered.") % handler.__name__)
+        
+        event.Skip() 
+
+    def RegisterMouseEventHandler(self, event, handler, cursor = None):
+        """!Binds event handler
+        
+        Call event.Skip() in handler to allow default processing in MapWindow.
+
+        If any error occures inside of handler, the handler is removed.
+
+        Before handler is unregistered it is called with 
+        string value "unregistered" of event parameter.
+
+        @code
+        # your class methods
+        def OnButton(self, event):
+            # current map display's map window
+            # expects LayerManager to be the parent
+            self.mapwin = self.parent.GetLayerTree().GetMapDisplay().GetWindow()
+            if self.mapwin.RegisterEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction,
+                                                wx.StockCursor(wx.CURSOR_CROSS)):
+                self.parent.GetLayerTree().GetMapDisplay().Raise()
+            else:
+                # handle that you cannot get coordinates
+        
+        def OnMouseAction(self, event):
+            # get real world coordinates of mouse click
+            coor = self.mapwin.Pixel2Cell(event.GetPositionTuple()[:])
+            self.text.SetLabel('Coor: ' + str(coor))
+            self.mapwin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction)
+            event.Skip()
+        @endcode
+        
+        @param event one of mouse events
+        @param handler function to handle event
+        @param cursor cursor which temporary overrides current cursor
+        
+        @return True if successful
+        @return False if event cannot be bind
+        """
+        # inserts handler into list
+        for containerEv, handlers in self.handlersContainer.iteritems():
+            if event == containerEv: 
+                handlers.append(handler)
+        
+        self.mouse['useBeforeGenericEvent'] = self.mouse['use']
+        self.mouse['use'] = 'genericEvent'
+        
+        if cursor:
+            self._overriddenCursor = self.GetCursor()
+            self.SetCursor(cursor)
+        
+        return True
+
+    def UnregisterAllHandlers(self):
+        """!Unregisters all registered handlers 
+
+        Before each handler is unregistered it is called with string
+        value "unregistered" of event parameter.
+        """
+        for containerEv, handlers in self.handlersContainer.iteritems():
+            for handler in handlers:
+                try:
+                    handler("unregistered")
+                    handlers.remove(handler)
+                except:
+                    GError(parent = self,
+                           message = _("Error occured during unregistration of handler: %s \n \
+                                       Handler was unregistered.") % handler.__name__)
+                    handlers.remove(handler)
+        
+    def UnregisterMouseEventHandler(self, event, handler):
+        """!Unbinds event handler for event
+        
+        Before handler is unregistered it is called with string value
+        "unregistered" of event parameter.
+
+        @param handler handler to unbind
+        @param event event from which handler will be unbinded
+        
+        @return True if successful
+        @return False if event cannot be unbind
+        """
+        # removes handler from list 
+        for containerEv, handlers in self.handlersContainer.iteritems():
+            if event != containerEv:
+                continue
+            try:
+                handler("unregistered")
+                if handler in handlers:
+                    handlers.remove(handler)
+                else:
+                    grass.warning(_("Handler: %s was not registered") \
+                                      % handler.__name__)
+            except:
+                GError(parent = self,
+                       message = _("Error occured during unregistration of handler: %s \n \
+                                       Handler was unregistered") % handler.__name__)
+                handlers.remove(handler) 
+        
+        # restore mouse use (previous state)
+        self.mouse['use'] = self.mouse['useBeforeGenericEvent']
+        
+        # restore overridden cursor
+        if self._overriddenCursor:
+            self.SetCursor(self._overriddenCursor)
+        
+        return True
+    
+    def Pixel2Cell(self, (x, y)):
+        raise NotImplementedError()
+    
+    def Cell2Pixel(self, (east, north)):
+        raise NotImplementedError()
+
+    def OnMotion(self, event):
+        """!Tracks mouse motion and update statusbar
+        
+        @see GetLastEN
+        """
+        try:
+            self.lastEN = self.Pixel2Cell(event.GetPositionTuple())
+        except (ValueError):
+            self.lastEN = None
+        # FIXME: special case for vdigit and access to statusbarManager
+#rashad        if self.frame.statusbarManager.GetMode() == 0: # Coordinates            
+#            updated = False
+#            if hasattr(self, "digit"):
+#                precision = int(UserSettings.Get(group = 'projection', key = 'format',
+#                                             subkey = 'precision'))
+#                updated = self._onMotion(self.lastEN, precision)
+
+#            if not updated:
+#                self.frame.CoordinatesChanged()
+#        
+        event.Skip()
+
+    def GetLastEN(self):
+        """!Returns last coordinates of mouse cursor.
+        
+        @see OnMotion
+        """
+        return self.lastEN

Added: grass-addons/grass7/gui/wxpython/newgui/mapwindow.py
===================================================================
--- grass-addons/grass7/gui/wxpython/newgui/mapwindow.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/newgui/mapwindow.py	2013-03-13 18:02:02 UTC (rev 55366)
@@ -0,0 +1,2173 @@
+"""!
+ at package mapdisp.mapwindow
+
+ at brief Map display canvas - buffered window.
+
+Classes:
+ - mapwindow::BufferedWindow2
+ - mapwindow::GraphicsSet
+ - mapwindow::GraphicsSetItem
+
+(C) 2006-2012 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+ at author Michael Barton
+ at author Jachym Cepicky
+ at author Vaclav Petras <wenzeslaus gmail.com> (handlers support)
+ at author Stepan Turek <stepan.turek seznam.cz> (handlers support, GraphicsSet)
+"""
+
+import os
+import time
+import math
+import sys
+from copy import copy
+
+import wx
+
+from grass.pydispatch.signal import Signal
+
+import grass.script as grass
+
+from gui_core.dialogs   import SavedRegion
+from core.gcmd          import RunCommand, GException, GError, GMessage
+from core.debug         import Debug
+from core.settings      import UserSettings
+from core.events        import EVT_UPDATE_MAP
+from gui_mapwindow import MapWindow
+from core.ws            import EVT_UPDATE_PRGBAR
+from core.utils         import GetGEventAttribsForHandler
+
+try:
+    import grass.lib.gis as gislib
+    haveCtypes = True
+except ImportError:
+    haveCtypes = False
+
+class BufferedWindow2(MapWindow, wx.Window):
+    """!A Buffered window class (2D view mode)
+
+    Superclass for VDigitWindow (vector digitizer).
+    
+    When the drawing needs to change, you app needs to call the
+    UpdateMap() method. Since the drawing is stored in a bitmap, you
+    can also save the drawing to file by calling the
+    SaveToFile() method.
+    """
+    def __init__(self, parent, giface, Map, frame=None,
+                 id = wx.ID_ANY, tree = None, lmgr = None, overlays = None,
+                 style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
+        MapWindow.__init__(self, parent = parent, giface = giface, Map = Map,
+                           frame = frame, **kwargs)
+        wx.Window.__init__(self, parent = parent, id = id, style = style, **kwargs)
+        
+        self.tree = tree
+        # flags
+        self.resize = False # indicates whether or not a resize event has taken place
+        self.dragimg = None # initialize variable for map panning
+        self.alwaysRender = False # if it always sets render to True in self.UpdateMap()
+        
+        # variables for drawing on DC
+        self.pen = None      # pen for drawing zoom boxes, etc.
+        self.polypen = None  # pen for drawing polylines (measurements, profiles, etc)
+        # List of wx.Point tuples defining a polyline (geographical coordinates)
+        self.polycoords = []
+        # ID of rubber band line
+        self.lineid = None
+        # ID of poly line resulting from cumulative rubber band lines (e.g. measurement)
+        self.plineid = None
+
+        # Emitted when zoom of a window is changed
+        self.zoomChanged = Signal('BufferedWindow2.zoomChanged')
+
+        #rashad self._giface.updateMap.connect(self.UpdateMap)
+
+        # event bindings
+        self.Bind(wx.EVT_PAINT,           self.OnPaint)
+        self.Bind(wx.EVT_SIZE,            self.OnSize)
+        self.Bind(wx.EVT_IDLE,            self.OnIdle)
+        self.Bind(EVT_UPDATE_MAP,         self.OnUpdateMap)
+        if self.frame and hasattr(self.frame, 'OnUpdateProgress'):
+            self.Bind(EVT_UPDATE_PRGBAR,   self.frame.OnUpdateProgress)
+
+        self._bindMouseEvents()
+        
+        self.processMouse = True
+        
+        # render output objects
+        self.mapfile = None   # image file to be rendered
+        self.img     = None   # wx.Image object (self.mapfile)
+        # decoration overlays
+        self.overlays = overlays
+        # images and their PseudoDC ID's for painting and dragging
+        self.imagedict = {}   
+        self.select = {}      # selecting/unselecting decorations for dragging
+        self.textdict = {}    # text, font, and color indexed by id
+        self.currtxtid = None # PseudoDC id for currently selected text
+        
+        # zoom objects
+        self.zoomhistory  = [] # list of past zoom extents
+        self.currzoom     = 0  # current set of extents in zoom history being used
+        self.zoomtype     = 1  # 1 zoom in, 0 no zoom, -1 zoom out
+        self.hitradius    = 10 # distance for selecting map decorations
+        self.dialogOffset = 5  # offset for dialog (e.g. DisplayAttributesDialog)
+        
+        # OnSize called to make sure the buffer is initialized.
+        # This might result in OnSize getting called twice on some
+        # platforms at initialization, but little harm done.
+        ### self.OnSize(None)
+        
+        self._definePseudoDC()
+        # redraw all pdc's, pdcTmp layer is redrawn always (speed issue)
+        self.redrawAll = True
+        
+        # will store an off screen empty bitmap for saving to file
+        self._buffer = wx.EmptyBitmap(max(1, self.Map.width), max(1, self.Map.height))
+        
+        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x:None)
+        
+        # vars for handling mouse clicks
+        self.dragid   = -1
+        self.lastpos  = (0, 0)
+        
+        # list for registration of graphics to draw
+        self.graphicsSetList = []
+        
+    def _definePseudoDC(self):
+        """!Define PseudoDC objects to use
+        """
+        # create PseudoDC used for background map, map decorations like scales and legends
+        self.pdc = wx.PseudoDC()
+        # used for digitization tool
+        self.pdcVector = None
+        # decorations (region box, etc.)
+        self.pdcDec = wx.PseudoDC()
+        # pseudoDC for temporal objects (select box, measurement tool, etc.)
+        self.pdcTmp = wx.PseudoDC()
+        
+    def _bindMouseEvents(self):
+        self.Bind(wx.EVT_MOUSE_EVENTS, self.MouseActions)
+        self.Bind(wx.EVT_MOTION,       self.OnMotion)
+        self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
+
+    def OnContextMenu(self, event):
+        """!Show Map Display context menu"""
+        if hasattr(self, "digit"):
+            event.Skip()
+            return
+
+        if not hasattr(self, "popupCopyCoordinates"):
+            self.popupCopyCoordinates = wx.NewId()
+            self.Bind(wx.EVT_MENU, self.OnCopyCoordinates, id = self.popupCopyCoordinates)
+
+        # generate popup-menu
+        menu = wx.Menu()
+        menu.Append(self.popupCopyCoordinates, _("Copy coordinates to clipboard"))
+
+        self.PopupMenu(menu)
+        menu.Destroy()
+
+    def Draw(self, pdc, img = None, drawid = None, pdctype = 'image', coords = [0, 0, 0, 0], pen = None):
+        """!Draws map and overlay decorations
+        """
+        if drawid == None:
+            if pdctype == 'image' and img:
+                drawid = self.imagedict[img]
+            elif pdctype == 'clear':
+                drawid = None
+            else:
+                drawid = wx.NewId()
+        
+        # TODO: find better solution
+        if not pen:
+            if pdctype == 'polyline':
+                pen = self.polypen
+            else:
+                pen = self.pen
+
+        if img and pdctype == 'image':
+            # self.imagedict[img]['coords'] = coords
+            self.select[self.imagedict[img]['id']] = False # ?
+        
+        pdc.BeginDrawing()
+        
+        if drawid != 99:
+            bg = wx.TRANSPARENT_BRUSH
+        else:
+            bg = wx.Brush(self.GetBackgroundColour())
+        
+        pdc.SetBackground(bg)
+        
+        Debug.msg (5, "BufferedWindow2.Draw(): id=%s, pdctype = %s, coord=%s" % \
+                       (drawid, pdctype, coords))
+        
+        # set PseudoDC id
+        if drawid is not None:
+            pdc.SetId(drawid)
+            
+        if pdctype == 'clear': # erase the display
+            bg = wx.WHITE_BRUSH
+            # bg = wx.Brush(self.GetBackgroundColour())
+            pdc.SetBackground(bg)
+            pdc.RemoveAll()
+            pdc.Clear()
+            pdc.EndDrawing()
+            
+            self.Refresh()
+            return
+        
+        if pdctype == 'image': # draw selected image
+            bitmap = wx.BitmapFromImage(img)
+            w,h = bitmap.GetSize()
+            pdc.DrawBitmap(bitmap, coords[0], coords[1], True) # draw the composite map
+            pdc.SetIdBounds(drawid, wx.Rect(coords[0],coords[1], w, h))
+        
+        elif pdctype == 'box': # draw a box on top of the map
+            if pen:
+                pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+                pdc.SetPen(pen)
+                x2 = max(coords[0],coords[2])
+                x1 = min(coords[0],coords[2])
+                y2 = max(coords[1],coords[3])
+                y1 = min(coords[1],coords[3])
+                rwidth = x2-x1
+                rheight = y2-y1
+                rect = wx.Rect(x1, y1, rwidth, rheight)
+                pdc.DrawRectangleRect(rect)
+                pdc.SetIdBounds(drawid, rect)
+                
+        elif pdctype == 'line': # draw a line on top of the map
+            if pen:
+                pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+                pdc.SetPen(pen)
+                pdc.DrawLinePoint(wx.Point(coords[0], coords[1]),wx.Point(coords[2], coords[3]))
+                pdc.SetIdBounds(drawid, wx.Rect(coords[0], coords[1], coords[2], coords[3]))
+        
+        elif pdctype == 'polyline': # draw a polyline on top of the map
+            if pen:
+                pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+                pdc.SetPen(pen)
+                if (len(coords) < 2):
+                    return
+                i = 1
+                while i < len(coords):
+                    pdc.DrawLinePoint(wx.Point(coords[i-1][0], coords[i-1][1]),
+                                      wx.Point(coords[i][0], coords[i][1]))
+                    i += 1
+                
+                # get bounding rectangle for polyline
+                xlist = []
+                ylist = []
+                if len(coords) > 0:
+                    for point in coords:
+                        x,y = point
+                        xlist.append(x)
+                        ylist.append(y)
+                    x1 = min(xlist)
+                    x2 = max(xlist)
+                    y1 = min(ylist)
+                    y2 = max(ylist)
+                    pdc.SetIdBounds(drawid, wx.Rect(x1,y1,x2,y2))
+                    # self.ovlcoords[drawid] = [x1,y1,x2,y2]
+        
+        elif pdctype == 'point': # draw point
+            if pen:
+                pdc.SetPen(pen)
+                pdc.DrawPoint(coords[0], coords[1])
+                coordsBound = (coords[0] - 5,
+                               coords[1] - 5,
+                               coords[0] + 5,
+                               coords[1] + 5)
+                pdc.SetIdBounds(drawid, wx.Rect(coordsBound))
+        
+        elif pdctype == 'text': # draw text on top of map
+            if not img['active']:
+                return # only draw active text
+            if 'rotation' in img:
+                rotation = float(img['rotation'])
+            else:
+                rotation = 0.0
+            w, h = self.GetFullTextExtent(img['text'])[0:2]
+            pdc.SetFont(img['font'])
+            pdc.SetTextForeground(img['color'])
+            coords, bbox = self.TextBounds(img)
+            if rotation == 0:
+                pdc.DrawText(img['text'], coords[0], coords[1])
+            else:
+                pdc.DrawRotatedText(img['text'], coords[0], coords[1], rotation)
+            pdc.SetIdBounds(drawid, bbox)
+        
+        pdc.EndDrawing()
+        
+        self.Refresh()
+        
+        return drawid
+    
+    def TextBounds(self, textinfo, relcoords = False):
+        """!Return text boundary data
+        
+        @param textinfo text metadata (text, font, color, rotation)
+        @param coords reference point
+        
+        @return coords of nonrotated text bbox (TL corner)
+        @return bbox of rotated text bbox (wx.Rect)
+        @return relCoords are text coord inside bbox
+        """
+        if 'rotation' in textinfo:
+            rotation = float(textinfo['rotation'])
+        else:
+            rotation = 0.0
+        
+        coords = textinfo['coords']
+        bbox = wx.Rect(coords[0], coords[1], 0, 0)
+        relCoords = (0, 0)
+        Debug.msg (4, "BufferedWindow2.TextBounds(): text=%s, rotation=%f" % \
+                   (textinfo['text'], rotation))
+        
+        self.Update()
+        
+        self.SetFont(textinfo['font'])
+        
+        w, h = self.GetTextExtent(textinfo['text'])
+        
+        if rotation == 0:
+            bbox[2], bbox[3] = w, h
+            if relcoords:
+                return coords, bbox, relCoords
+            else:
+                return coords, bbox
+        
+        boxh = math.fabs(math.sin(math.radians(rotation)) * w) + h
+        boxw = math.fabs(math.cos(math.radians(rotation)) * w) + h
+        if rotation > 0 and rotation < 90:
+            bbox[1] -= boxh
+            relCoords = (0, boxh)
+        elif rotation >= 90 and rotation < 180:
+            bbox[0] -= boxw
+            bbox[1] -= boxh
+            relCoords = (boxw, boxh)
+        elif rotation >= 180 and rotation < 270:
+            bbox[0] -= boxw
+            relCoords = (boxw, 0)
+        bbox[2] = boxw
+        bbox[3] = boxh
+        bbox.Inflate(h,h)
+        if relcoords:
+            return coords, bbox, relCoords
+        else:
+            return coords, bbox
+
+    def OnPaint(self, event):
+        """!Draw PseudoDC's to buffered paint DC
+        
+        If self.redrawAll is False on self.pdcTmp content is re-drawn
+        """
+        Debug.msg(4, "BufferedWindow2.OnPaint(): redrawAll=%s" % self.redrawAll)
+        dc = wx.BufferedPaintDC(self, self._buffer)
+        dc.Clear()
+        
+        # use PrepareDC to set position correctly
+        # probably does nothing, removed from wxPython 2.9
+        # self.PrepareDC(dc)
+        
+        # create a clipping rect from our position and size
+        # and update region
+        rgn = self.GetUpdateRegion().GetBox()
+        dc.SetClippingRect(rgn)
+        
+        switchDraw = False
+        if self.redrawAll is None:
+            self.redrawAll = True
+            switchDraw = True
+        
+        if self.redrawAll: # redraw pdc and pdcVector
+            # draw to the dc using the calculated clipping rect
+            self.pdc.DrawToDCClipped(dc, rgn)
+            
+            # draw vector map layer
+            if hasattr(self, "digit"):
+                # decorate with GDDC (transparency)
+                try:
+                    gcdc = wx.GCDC(dc)
+                    self.pdcVector.DrawToDCClipped(gcdc, rgn)
+                except NotImplementedError, e:
+                    print >> sys.stderr, e
+                    self.pdcVector.DrawToDCClipped(dc, rgn)
+            
+            self.bufferLast = None
+        else: # do not redraw pdc and pdcVector
+            if self.bufferLast is None:
+                # draw to the dc
+                self.pdc.DrawToDC(dc)
+                
+                if hasattr(self, "digit"):
+                    # decorate with GDDC (transparency)
+                    try:
+                        gcdc = wx.GCDC(dc)
+                        self.pdcVector.DrawToDC(gcdc)
+                    except NotImplementedError, e:
+                        print >> sys.stderr, e
+                        self.pdcVector.DrawToDC(dc)
+                
+                # store buffered image
+                # self.bufferLast = wx.BitmapFromImage(self.buffer.ConvertToImage())
+                self.bufferLast = dc.GetAsBitmap(wx.Rect(0, 0, self.Map.width, self.Map.height))
+            
+            self.pdc.DrawBitmap(self.bufferLast, 0, 0, False)
+            self.pdc.DrawToDC(dc)
+        
+        # draw decorations (e.g. region box)
+        try:
+            gcdc = wx.GCDC(dc)
+            self.pdcDec.DrawToDC(gcdc)
+        except NotImplementedError, e:
+            print >> sys.stderr, e
+            self.pdcDec.DrawToDC(dc)
+        
+        # draw temporary object on the foreground
+        ### self.pdcTmp.DrawToDCClipped(dc, rgn)
+        self.pdcTmp.DrawToDC(dc)
+        
+        if switchDraw:
+            self.redrawAll = False
+        
+    def OnSize(self, event):
+        """!Scale map image so that it is the same size as the Window
+        """
+        # re-render image on idle
+        self.resize = time.clock()
+
+    def OnIdle(self, event):
+        """!Only re-render a composite map image from GRASS during
+        idle time instead of multiple times during resizing.
+        """
+        
+        # use OnInternalIdle() instead ?
+
+        if self.resize and self.resize + 0.2 < time.clock():
+            Debug.msg(3, "BufferedWindow2.OnSize():")
+            
+            # set size of the input image
+            self.Map.ChangeMapSize(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.Destroy()
+            self._buffer = wx.EmptyBitmap(max(1, self.Map.width), max(1, self.Map.height))
+            
+            # get the image to be rendered
+            self.img = self.GetImage()
+            
+            # update map display
+            updatemap = True
+            if self.img and self.Map.width + self.Map.height > 0: # scale image after resize
+                self.img = self.img.Scale(self.Map.width, self.Map.height)
+                if len(self.Map.GetListOfLayers()) > 0:
+                    self.UpdateMap()
+                    updatemap = False
+#rashad
+#            # reposition checkbox in statusbar
+#            self.frame.StatusbarReposition()
+#            
+#            # update statusbar
+#            self.frame.StatusbarUpdate()
+
+            if updatemap:
+                self.UpdateMap(render = True)
+            self.resize = False
+        elif self.resize:
+            event.RequestMore()
+        
+        event.Skip()
+
+    def SaveToFile(self, FileName, FileType, width, height):
+        """!This draws the pseudo DC to a buffer that can be saved to
+        a file.
+        
+        @param FileName file name
+        @param FileType type of bitmap
+        @param width image width
+        @param height image height
+        """
+        busy = wx.BusyInfo(message = _("Please wait, exporting image..."),
+                           parent = self)
+        wx.Yield()
+        
+        self.Map.ChangeMapSize((width, height))
+        ibuffer = wx.EmptyBitmap(max(1, width), max(1, height))
+        self.Map.Render(force = True, windres = self.frame.GetProperty('resolution'))
+        img = self.GetImage()
+        self.pdc.RemoveAll()
+        self.Draw(self.pdc, img, drawid = 99)
+        
+        # compute size ratio to move overlay accordingly
+        cSize = self.GetClientSizeTuple()
+        ratio = float(width) / cSize[0], float(height) / cSize[1]
+        
+        # redraw legend, scalebar
+        for img in self.GetOverlay():
+            # draw any active and defined overlays
+            if self.imagedict[img]['layer'].IsActive():
+                id = self.imagedict[img]['id']
+                coords = int(ratio[0] * self.overlays[id].coords[0]),\
+                         int(ratio[1] * self.overlays[id].coords[1])
+                self.Draw(self.pdc, img = img, drawid = id,
+                          pdctype = self.overlays[id].pdcType, coords = coords)
+                          
+        # redraw text labels
+        for id in self.textdict.keys():
+            textinfo = self.textdict[id]
+            oldCoords = textinfo['coords']
+            textinfo['coords'] = ratio[0] * textinfo['coords'][0],\
+                                 ratio[1] * textinfo['coords'][1]
+            self.Draw(self.pdc, img = self.textdict[id], drawid = id,
+                      pdctype = 'text')
+            # set back old coordinates
+            textinfo['coords'] = oldCoords
+            
+        dc = wx.BufferedDC(None, ibuffer)
+        dc.Clear()
+        # probably does nothing, removed from wxPython 2.9
+        # self.PrepareDC(dc)
+        self.pdc.DrawToDC(dc)
+        if self.pdcVector:
+            self.pdcVector.DrawToDC(dc)
+        ibuffer.SaveFile(FileName, FileType)
+        
+        busy.Destroy()
+        
+        self.UpdateMap(render = True)
+        self.Refresh()
+        
+    def GetOverlay(self):
+        """!Converts rendered overlay files to wx.Image
+        
+        Updates self.imagedict
+        
+        @return list of images
+        """
+        imgs = []
+        for overlay in self.Map.GetListOfLayers(ltype = "overlay", active = True):
+            if overlay.mapfile is not None \
+               and os.path.isfile(overlay.mapfile) and os.path.getsize(overlay.mapfile):
+                img = wx.Image(overlay.mapfile, wx.BITMAP_TYPE_ANY)
+
+                for key in self.imagedict.keys():
+                    if self.imagedict[key]['id'] == overlay.id:
+                        del self.imagedict[key]
+                
+                self.imagedict[img] = { 'id' : overlay.id,
+                                        'layer' : overlay }
+                imgs.append(img)
+
+        return imgs
+    
+    def GetImage(self):
+        """!Converts redered map files to wx.Image
+        
+        Updates self.imagedict (id=99)
+        
+        @return wx.Image instance (map composition)
+        """
+        imgId = 99
+        if self.mapfile and self.Map.mapfile and os.path.isfile(self.Map.mapfile) and \
+                os.path.getsize(self.Map.mapfile):
+            img = wx.Image(self.Map.mapfile, wx.BITMAP_TYPE_ANY)
+        else:
+            img = None
+        
+        for key in self.imagedict.keys():
+            if self.imagedict[key]['id'] == imgId:
+                del self.imagedict[key]
+
+        self.imagedict[img] = { 'id': imgId }
+        
+        return img
+
+    def SetAlwaysRenderEnabled(self, alwaysRender = True):
+        self.alwaysRender = alwaysRender
+        
+    def IsAlwaysRenderEnabled(self):
+        return self.alwaysRender
+
+    def OnUpdateMap(self, event):
+        """!Called when this class receives core.events.gUpdateMap event. 
+        """
+        kwargs, missing_args = GetGEventAttribsForHandler(self.UpdateMap, event)
+
+        if missing_args:
+            Debug.msg (1, "Invalid call of EVT_UPDATE_MAP event.")
+            return
+
+        self.UpdateMap(**kwargs)
+
+    def UpdateMap(self, render = True, renderVector = True):
+        """!Updates the canvas anytime there is a change to the
+        underlaying images or to the geometry of the canvas.
+        
+        This method should not be called directly.
+
+        @todo change direct calling of UpdateMap method to emittig grass
+        interface updateMap signal
+
+        @param render re-render map composition
+        @param renderVector re-render vector map layer enabled for editing (used for digitizer)
+        """
+        start = time.clock()
+        self.resize = False
+        
+        # was if self.Map.cmdfile and ...
+        if self.IsAlwaysRenderEnabled() and self.img is None:
+            render = True
+        
+        #
+        # render background image if needed
+        #
+        # update layer dictionary if there has been a change in layers
+        if self.tree and self.tree.reorder:
+            self.tree.ReorderLayers()
+        
+        # reset flag for auto-rendering
+        if self.tree:
+            self.tree.rerender = False
+        
+        try:
+            if render:
+                # update display size
+                self.Map.ChangeMapSize(self.GetClientSize())
+#############rashad
+                windres = True                  
+#                if self.frame.GetProperty('resolution'):
+                    # use computation region resolution for rendering
+                 #   windres = True
+                #else:
+                  #  windres = False
+                
+                self.mapfile = self.Map.Render(force = True,
+                                               windres = windres)
+            else:
+                self.mapfile = self.Map.Render(force = False)
+            
+        except GException, e:
+            GError(message = e.value)
+            self.mapfile = None
+        
+        self.img = self.GetImage() # id=99
+        
+        #
+        # clear pseudoDcs
+        #
+        for pdc in (self.pdc,
+                    self.pdcDec,
+                    self.pdcTmp):
+            pdc.Clear()
+            pdc.RemoveAll()
+        
+        #
+        # draw background map image to PseudoDC
+        #
+        if not self.img:
+            self.Draw(self.pdc, pdctype = 'clear')
+        else:
+            try:
+                id = self.imagedict[self.img]['id']
+            except:
+                return False
+            
+            self.Draw(self.pdc, self.img, drawid = id)
+        
+        #
+        # render vector map layer
+        #
+        if renderVector and hasattr(self, "digit"):
+            self._updateMap()
+        #
+        # render overlays
+        #
+        for img in self.GetOverlay():
+            # draw any active and defined overlays
+            if self.imagedict[img]['layer'].IsActive():
+                id = self.imagedict[img]['id']
+                self.Draw(self.pdc, img = img, drawid = id,
+                          pdctype = self.overlays[id].pdcType, coords = self.overlays[id].coords)
+        
+        for id in self.textdict.keys():
+            self.Draw(self.pdc, img = self.textdict[id], drawid = id,
+                      pdctype = 'text', coords = [10, 10, 10, 10])
+        
+        # optionally draw computational extent box
+        self.DrawCompRegionExtent()
+        
+        #
+        # redraw pdcTmp if needed
+        #
+        
+        # draw registered graphics
+        if  len(self.graphicsSetList) > 0:
+            penOrig = self.pen
+            polypenOrig = self.polypen
+            
+            for item in self.graphicsSetList:
+                try:
+                    item.Draw(self.pdcTmp)
+                except:
+                    GError(parent = self,
+                           message = _('Unable to draw registered graphics. '
+                                       'The graphics was unregistered.'))
+                    self.UnregisterGraphicsToDraw(item) 
+            
+            self.pen = penOrig 
+            self.polypen = polypenOrig 
+        
+        if len(self.polycoords) > 0:
+            self.DrawLines(self.pdcTmp)
+        
+        # 
+        # clear measurement
+        #
+        if self.mouse["use"] == "measure":
+            self.ClearLines(pdc = self.pdcTmp)
+            self.polycoords = []
+            self.mouse['use'] = 'pointer'
+            self.mouse['box'] = 'point'
+            self.mouse['end'] = [0, 0]
+            self.SetCursor(self.frame.cursors["default"])
+            
+        stop = time.clock()
+        
+        Debug.msg (1, "BufferedWindow2.UpdateMap(): render=%s, renderVector=%s -> time=%g" % \
+                   (render, renderVector, (stop-start)))
+        
+        return True
+
+    def DrawCompRegionExtent(self):
+        """!Draw computational region extent in the display
+        
+        Display region is drawn as a blue box inside the computational region,
+        computational region inside a display region as a red box).
+        """
+        if hasattr(self, "regionCoords"):
+            compReg = self.Map.GetRegion()
+            dispReg = self.Map.GetCurrentRegion()
+            reg = None
+            if self.IsInRegion(dispReg, compReg):
+                self.polypen = wx.Pen(colour = wx.Colour(0, 0, 255, 128), width = 3, style = wx.SOLID)
+                reg = dispReg
+            else:
+                self.polypen = wx.Pen(colour = wx.Colour(255, 0, 0, 128),
+                                      width = 3, style = wx.SOLID)
+                reg = compReg
+            
+            self.regionCoords = []
+            self.regionCoords.append((reg['w'], reg['n']))
+            self.regionCoords.append((reg['e'], reg['n']))
+            self.regionCoords.append((reg['e'], reg['s']))
+            self.regionCoords.append((reg['w'], reg['s']))
+            self.regionCoords.append((reg['w'], reg['n']))
+            # draw region extent
+            self.DrawLines(pdc = self.pdcDec, polycoords = self.regionCoords)
+
+    def IsInRegion(self, region, refRegion):
+        """!
+        Test if 'region' is inside of 'refRegion'
+
+        @param region input region
+        @param refRegion reference region (e.g. computational region)
+
+        @return True if region is inside of refRegion
+        @return False 
+        """
+        if region['s'] >= refRegion['s'] and \
+                region['n'] <= refRegion['n'] and \
+                region['w'] >= refRegion['w'] and \
+                region['e'] <= refRegion['e']:
+            return True
+        
+        return False
+
+    def EraseMap(self):
+        """!Erase map canvas
+        """
+        self.Draw(self.pdc, pdctype = 'clear')
+        
+        if hasattr(self, "digit"):
+            self.Draw(self.pdcVector, pdctype = 'clear')
+        
+        self.Draw(self.pdcDec, pdctype = 'clear')
+        self.Draw(self.pdcTmp, pdctype = 'clear')
+
+        self.Map.AbortAllThreads()
+
+    def DragMap(self, moveto):
+        """!Drag the entire map image for panning.
+        
+        @param moveto dx,dy
+        """
+        dc = wx.BufferedDC(wx.ClientDC(self))
+        dc.SetBackground(wx.Brush("White"))
+        dc.Clear()
+        
+        self.dragimg = wx.DragImage(self._buffer)
+        self.dragimg.BeginDrag((0, 0), self)
+        self.dragimg.GetImageRect(moveto)
+        self.dragimg.Move(moveto)
+        
+        self.dragimg.DoDrawImage(dc, moveto)
+        self.dragimg.EndDrag()
+        
+    def DragItem(self, id, coords):
+        """!Drag an overlay decoration item
+        """
+        if id == 99 or id == '' or id == None: return
+        Debug.msg (5, "BufferedWindow2.DragItem(): id=%d" % id)
+        x, y = self.lastpos
+        dx = coords[0] - x
+        dy = coords[1] - y
+        self.pdc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+        r = self.pdc.GetIdBounds(id)
+        
+        if type(r) is list:
+            r = wx.Rect(r[0], r[1], r[2], r[3])
+        if id > 100: # text dragging
+            rtop = (r[0],r[1]-r[3],r[2],r[3])
+            r = r.Union(rtop)
+            rleft = (r[0]-r[2],r[1],r[2],r[3])
+            r = r.Union(rleft)
+        self.pdc.TranslateId(id, dx, dy)
+        
+        r2 = self.pdc.GetIdBounds(id)
+        if type(r2) is list:
+            r2 = wx.Rect(r[0], r[1], r[2], r[3])
+        if id > 100: # text
+            self.textdict[id]['bbox'] = r2
+            self.textdict[id]['coords'][0] += dx
+            self.textdict[id]['coords'][1] += dy
+        r = r.Union(r2)
+        r.Inflate(4,4)
+        self.RefreshRect(r, False)
+        self.lastpos = (coords[0], coords[1])
+                
+    def MouseDraw(self, pdc = None, begin = None, end = None):
+        """!Mouse box or line from 'begin' to 'end'
+        
+        If not given from self.mouse['begin'] to self.mouse['end'].
+        """
+        if not pdc:
+            return
+        
+        if begin is None:
+            begin = self.mouse['begin']
+        if end is None:
+            end   = self.mouse['end']
+        
+        Debug.msg (5, "BufferedWindow2.MouseDraw(): use=%s, box=%s, begin=%f,%f, end=%f,%f" % \
+                       (self.mouse['use'], self.mouse['box'],
+                        begin[0], begin[1], end[0], end[1]))
+        
+        if self.mouse['box'] == "box":
+            boxid = wx.ID_NEW
+            mousecoords = [begin[0], begin[1],
+                           end[0], end[1]]
+            r = pdc.GetIdBounds(boxid)
+            if type(r) is list:
+                r = wx.Rect(r[0], r[1], r[2], r[3])
+            r.Inflate(4, 4)
+            try:
+                pdc.ClearId(boxid)
+            except:
+                pass
+            self.RefreshRect(r, False)
+            pdc.SetId(boxid)
+            self.Draw(pdc, drawid = boxid, pdctype = 'box', coords = mousecoords)
+        
+        elif self.mouse['box'] == "line":
+            self.lineid = wx.ID_NEW
+            mousecoords = [begin[0], begin[1], \
+                           end[0], end[1]]
+            x1 = min(begin[0],end[0])
+            x2 = max(begin[0],end[0])
+            y1 = min(begin[1],end[1])
+            y2 = max(begin[1],end[1])
+            r = wx.Rect(x1,y1,x2-x1,y2-y1)
+            r.Inflate(4,4)
+            try:
+                pdc.ClearId(self.lineid)
+            except:
+                pass
+            self.RefreshRect(r, False)
+            pdc.SetId(self.lineid)
+            self.Draw(pdc, drawid = self.lineid, pdctype = 'line', coords = mousecoords)
+
+    def DrawLines(self, pdc = None, polycoords = None):
+        """!Draw polyline in PseudoDC
+        
+        Set self.pline to wx.NEW_ID + 1
+        
+        polycoords - list of polyline vertices, geographical coordinates
+        (if not given, self.polycoords is used)
+        """
+        if not pdc:
+            pdc = self.pdcTmp
+        
+        if not polycoords:
+            polycoords = self.polycoords
+        
+        if len(polycoords) > 0:
+            self.plineid = wx.ID_NEW + 1
+            # convert from EN to XY
+            coords = []
+            for p in polycoords:
+                coords.append(self.Cell2Pixel(p))
+
+            self.Draw(pdc, drawid = self.plineid, pdctype = 'polyline', coords = coords)
+            
+            Debug.msg (4, "BufferedWindow2.DrawLines(): coords=%s, id=%s" % \
+                           (coords, self.plineid))
+            
+            return self.plineid
+        
+        return -1
+
+    def DrawCross(self, pdc, coords, size, rotation = 0, pen = None,
+                  text = None, textAlign = 'lr', textOffset = (5, 5)):
+        """!Draw cross in PseudoDC
+
+        @todo implement rotation
+
+        @param pdc PseudoDC
+        @param coords center coordinates
+        @param rotation rotate symbol
+        @param text draw also text (text, font, color, rotation)
+        @param textAlign alignment (default 'lower-right')
+        @param textOffset offset for text (from center point)
+        """
+        Debug.msg(4, "BufferedWindow2.DrawCross(): pdc=%s, coords=%s, size=%d" % \
+                  (pdc, coords, size))
+        coordsCross = ((coords[0] - size, coords[1], coords[0] + size, coords[1]),
+                       (coords[0], coords[1] - size, coords[0], coords[1] + size))
+
+        self.lineid = wx.NewId()
+        for lineCoords in coordsCross:
+            self.Draw(pdc, drawid = self.lineid, pdctype = 'line', coords = lineCoords, pen = pen)
+        
+        if not text:
+            return self.lineid
+        
+        if textAlign == 'ul':
+            coord = [coords[0] - textOffset[0], coords[1] - textOffset[1], 0, 0]
+        elif textAlign == 'ur':
+            coord = [coords[0] + textOffset[0], coords[1] - textOffset[1], 0, 0]
+        elif textAlign == 'lr':
+            coord = [coords[0] + textOffset[0], coords[1] + textOffset[1], 0, 0]
+        else:
+            coord = [coords[0] - textOffset[0], coords[1] + textOffset[1], 0, 0]
+        
+        self.Draw(pdc, img = text,
+                  pdctype = 'text', coords = coord, pen = pen)
+        
+        return self.lineid
+
+    def _computeZoomToPointAndRecenter(self, position, zoomtype):
+        """!Computes zoom parameters for recenter mode.
+
+        Computes begin and end parameters for Zoom() method.
+        Used for zooming by single click (not box)
+        and mouse wheel zooming (zoom and recenter mode).
+        """
+        if zoomtype > 0:
+            begin = (position[0] - self.Map.width / 4,
+                     position[1] - self.Map.height / 4)
+            end   = (position[0] + self.Map.width / 4,
+                     position[1] + self.Map.height / 4)
+        else:
+            begin = ((self.Map.width - position[0]) / 2,
+                     (self.Map.height - position[1]) / 2)
+            end = (begin[0] + self.Map.width / 2,
+                   begin[1] + self.Map.height / 2)
+        return begin, end
+
+    def MouseActions(self, event):
+        """!Mouse motion and button click notifier
+        """
+        if not self.processMouse:
+            return
+        
+        # zoom with mouse wheel
+        if event.GetWheelRotation() != 0:
+            self.OnMouseWheel(event)
+            
+        # left mouse button pressed
+        elif event.LeftDown():
+            self.OnLeftDown(event)
+        
+        # left mouse button released
+        elif event.LeftUp():
+            self.OnLeftUp(event)
+        
+        # dragging
+        elif event.Dragging():
+            self.OnDragging(event)
+        
+        # double click
+        elif event.ButtonDClick():
+            self.OnButtonDClick(event)
+        
+        # middle mouse button pressed
+        elif event.MiddleDown():
+            self.OnMiddleDown(event)
+        
+        # middle mouse button relesed
+        elif event.MiddleUp():
+            self.OnMiddleUp(event)
+        
+        # right mouse button pressed
+        elif event.RightDown():
+            self.OnRightDown(event)
+        
+        # right mouse button released
+        elif event.RightUp():
+            self.OnRightUp(event)
+        
+        elif event.Entering():
+            self.OnMouseEnter(event)
+        
+        elif event.Moving():
+            self.OnMouseMoving(event)
+                
+    def OnMouseWheel(self, event):
+        """!Mouse wheel moved
+        """
+        zoomBehaviour = UserSettings.Get(group = 'display',
+                                         key = 'mouseWheelZoom',
+                                         subkey = 'selection')
+        if zoomBehaviour == 2:
+            event.Skip()
+            return
+            
+        self.processMouse = False
+        current  = event.GetPositionTuple()[:]
+        wheel = event.GetWheelRotation()
+        Debug.msg (5, "BufferedWindow2.MouseAction(): wheel=%d" % wheel)
+        
+        if wheel > 0:
+            zoomtype = 1
+        else:
+            zoomtype = -1
+        if UserSettings.Get(group = 'display',
+                            key = 'scrollDirection',
+                            subkey = 'selection'):
+            zoomtype *= -1
+        # zoom 1/2 of the screen (TODO: settings)
+        if zoomBehaviour == 0:  # zoom and recenter
+            begin, end = self._computeZoomToPointAndRecenter(position = current, zoomtype = zoomtype)
+
+        elif zoomBehaviour == 1:  # zoom to current cursor position
+            begin = (current[0]/2, current[1]/2)
+            end = ((self.Map.width - current[0])/2 + current[0],
+                   (self.Map.height - current[1])/2 + current[1])
+        
+            
+        # zoom
+        self.Zoom(begin, end, zoomtype)
+        
+        # redraw map
+        self.UpdateMap()
+        
+        # update statusbar
+        #rashad self.frame.StatusbarUpdate()
+        
+        self.Refresh()
+        self.processMouse = True
+        
+    def OnDragging(self, event):
+        """!Mouse dragging
+        """
+        Debug.msg (5, "BufferedWindow2.MouseAction(): Dragging")
+        current  = event.GetPositionTuple()[:]
+        previous = self.mouse['begin']
+        move = (current[0] - previous[0],
+                current[1] - previous[1])
+        
+        if hasattr(self, "digit"):
+            digitToolbar = self.toolbar
+        else:
+            digitToolbar = None
+        
+        # dragging or drawing box with left button
+        if self.mouse['use'] == 'pan' or \
+                event.MiddleIsDown():
+            self.DragMap(move)
+        
+        # dragging decoration overlay item
+        elif (self.mouse['use'] == 'pointer' and 
+                not digitToolbar and 
+                self.dragid != None):
+            coords = event.GetPositionTuple()
+            self.DragItem(self.dragid, coords)
+        
+        # dragging anything else - rubber band box or line
+        else:
+            if (self.mouse['use'] == 'pointer' and 
+                not digitToolbar):
+                return
+            
+            self.mouse['end'] = event.GetPositionTuple()[:]
+            if (event.LeftIsDown() and 
+                not (digitToolbar and 
+                    digitToolbar.GetAction() in ("moveLine",) and 
+                     self.digit.GetDisplay().GetSelected() > 0)):
+                self.MouseDraw(pdc = self.pdcTmp)
+        
+    def OnLeftDown(self, event):
+        """!Left mouse button pressed
+        """
+        Debug.msg (5, "BufferedWindow2.OnLeftDown(): use=%s" % \
+                   self.mouse["use"])
+        
+        self.mouse['begin'] = event.GetPositionTuple()[:]
+        
+        if self.mouse["use"] in ["measure", "profile"]:
+            # measure or profile
+            if len(self.polycoords) == 0:
+                self.mouse['end'] = self.mouse['begin']
+                self.polycoords.append(self.Pixel2Cell(self.mouse['begin']))
+                self.ClearLines(pdc=self.pdcTmp)
+            else:
+                self.mouse['begin'] = self.mouse['end']
+        
+        elif self.mouse['use'] in ('zoom', 'legend'):
+            pass
+        
+        # vector digizer
+        elif self.mouse["use"] == "pointer" and \
+                hasattr(self, "digit"):
+            if event.ControlDown():
+                self.OnLeftDownUndo(event)
+            else:
+                self._onLeftDown(event)
+        
+        elif self.mouse['use'] == 'pointer':
+            # get decoration or text id
+            idlist = []
+            self.dragid = ''
+            self.lastpos = self.mouse['begin']
+            idlist = self.pdc.FindObjects(self.lastpos[0], self.lastpos[1],
+                                          self.hitradius)
+            if 99 in idlist:
+                idlist.remove(99)
+            if idlist != []:
+                self.dragid = idlist[0] #drag whatever is on top
+        else:
+            pass
+        
+        event.Skip()
+        
+    def OnLeftUp(self, event):
+        """!Left mouse button released
+        """
+        Debug.msg (5, "BufferedWindow2.OnLeftUp(): use=%s" % \
+                       self.mouse["use"])
+        
+        self.mouse['end'] = event.GetPositionTuple()[:]
+        
+        if self.mouse['use'] in ["zoom", "pan"]:
+            # set region in zoom or pan
+            begin = self.mouse['begin']
+            end = self.mouse['end']
+            
+            if self.mouse['use'] == 'zoom':
+                # set region for click (zero-width box)
+                if begin[0] - end[0] == 0 or \
+                        begin[1] - end[1] == 0:
+                    begin, end = self._computeZoomToPointAndRecenter(position = end, zoomtype = self.zoomtype)
+            self.Zoom(begin, end, self.zoomtype)
+
+            # redraw map
+            self.UpdateMap(render = True)
+            
+            # update statusbar
+###############rashad 
+#            self.frame.StatusbarUpdate()
+#            
+#        elif self.mouse["use"] == "query":
+#            self.frame.Query(self.mouse['end'][0], self.mouse['end'][1])
+#        
+#        elif self.mouse["use"] in ["measure", "profile"]:
+#            # measure or profile
+#            if self.mouse["use"] == "measure":
+#                self.frame.MeasureDist(self.mouse['begin'], self.mouse['end'])
+#            
+#            self.polycoords.append(self.Pixel2Cell(self.mouse['end']))
+#            self.ClearLines(pdc = self.pdcTmp)
+#            self.DrawLines(pdc = self.pdcTmp)
+#        
+#        elif self.mouse["use"] == "pointer" and \
+#                not self.frame.IsStandalone() and \
+#                self.frame.GetLayerManager().gcpmanagement:
+#            # -> GCP manager
+#            if self.frame.GetToolbar('gcpdisp'):
+#                coord = self.Pixel2Cell(self.mouse['end'])
+#                if self.frame.MapWindow == self.frame.SrcMapWindow:
+#                    coordtype = 'source'
+#                else:
+#                    coordtype = 'target'
+#                
+#                self.frame.GetLayerManager().gcpmanagement.SetGCPData(coordtype, coord, self, confirm = True)
+#                self.UpdateMap(render = False, renderVector = False)
+            
+        elif self.mouse["use"] == "pointer" and \
+                hasattr(self, "digit"):
+            self._onLeftUp(event)
+            
+        elif (self.mouse['use'] == 'pointer' and 
+                self.dragid >= 0):
+            # end drag of overlay decoration
+            
+            if self.dragid < 99 and self.dragid in self.overlays:
+                self.overlays[self.dragid].coords = self.pdc.GetIdBounds(self.dragid)
+            elif self.dragid > 100 and self.dragid in self.textdict:
+                self.textdict[self.dragid]['bbox'] = self.pdc.GetIdBounds(self.dragid)
+            else:
+                pass
+            self.dragid = None
+            self.currtxtid = None
+#########rashad            
+#        elif self.mouse['use'] == 'legend':
+#            self.frame.dialogs['legend'].resizeBtn.SetValue(False)
+#            screenSize = self.GetClientSizeTuple()
+#            self.overlays[1].ResizeLegend(self.mouse["begin"], self.mouse["end"], screenSize)
+
+#            self.frame.MapWindow.SetCursor(self.frame.cursors["default"])
+#            self.frame.MapWindow.mouse['use'] = 'pointer'
+#            
+#            self.UpdateMap()
+            
+    def OnButtonDClick(self, event):
+        """!Mouse button double click
+        """
+        Debug.msg (5, "BufferedWindow2.OnButtonDClick(): use=%s" % \
+                   self.mouse["use"])
+        
+        if self.mouse["use"] == "measure":
+            # measure
+            self.ClearLines(pdc=self.pdcTmp)
+            self.polycoords = []
+            self.mouse['use'] = 'pointer'
+            self.mouse['box'] = 'point'
+            self.mouse['end'] = [0, 0]
+            self.Refresh()
+#############rashad              
+            #self.SetCursor(self.frame.cursors["default"])
+        
+        elif self.mouse["use"] != "profile" or \
+                (self.mouse['use'] != 'pointer' and \
+                     hasattr(self, "digit")):
+               # select overlay decoration options dialog
+            clickposition = event.GetPositionTuple()[:]
+            idlist  = self.pdc.FindObjects(clickposition[0], clickposition[1], self.hitradius)
+            if idlist == []:
+                return
+            self.dragid = idlist[0]
+
+            # self.ovlcoords[self.dragid] = self.pdc.GetIdBounds(self.dragid)
+#############rashad            
+#            if self.dragid > 100:
+#                self.currtxtid = self.dragid
+#                self.frame.OnAddText(None)
+#            elif self.dragid == 0:
+#                self.frame.AddBarscale()
+#            elif self.dragid == 1:
+#                self.frame.AddLegend()
+        
+    def OnRightDown(self, event):
+        """!Right mouse button pressed
+        """
+        Debug.msg (5, "BufferedWindow2.OnRightDown(): use=%s" % \
+                   self.mouse["use"])
+        
+        if hasattr(self, "digit"):
+            self._onRightDown(event)
+        
+        event.Skip()
+        
+    def OnRightUp(self, event):
+        """!Right mouse button released
+        """
+        Debug.msg (5, "BufferedWindow2.OnRightUp(): use=%s" % \
+                   self.mouse["use"])
+        
+        if hasattr(self, "digit"):
+            self._onRightUp(event)
+        
+        self.redrawAll = True
+        self.Refresh()
+        
+        event.Skip()
+        
+    def OnMiddleDown(self, event):
+        """!Middle mouse button pressed
+        """
+        if not event:
+            return
+        
+        self.mouse['begin'] = event.GetPositionTuple()[:]
+        
+    def OnMiddleUp(self, event):
+        """!Middle mouse button released
+        """
+        self.mouse['end'] = event.GetPositionTuple()[:]
+        
+        # set region in zoom or pan
+        begin = self.mouse['begin']
+        end   = self.mouse['end']
+        
+        self.Zoom(begin, end, 0) # no zoom
+        
+        # redraw map
+        self.UpdateMap(render = True)
+        
+        # update statusbar
+        self.frame.StatusbarUpdate()
+        
+    def OnMouseEnter(self, event):
+        """!Mouse entered window and no mouse buttons were pressed
+
+        """
+#############rashad          
+#        if not self.frame.IsStandalone() and \
+#                self.frame.GetLayerManager().gcpmanagement:
+#            if self.frame.GetToolbar('gcpdisp'):
+#                if not self.frame.MapWindow == self:
+#                    self.frame.MapWindow = self
+#                    self.frame.Map = self.Map
+#                    self.frame.UpdateActive(self)
+#                    # needed for wingrass
+#                    self.SetFocus()
+#        else:
+#            event.Skip()
+        
+    def OnMouseMoving(self, event):
+        """!Motion event and no mouse buttons were pressed
+        """
+        if self.mouse["use"] == "pointer" and \
+                hasattr(self, "digit"):
+            self._onMouseMoving(event)
+        
+        event.Skip()
+
+    def OnCopyCoordinates(self, event):
+        """!Copy coordinates to cliboard"""
+        e, n = self.GetLastEN()
+        if wx.TheClipboard.Open():
+            do = wx.TextDataObject()
+            # TODO: put delimiter in settings and apply also for Go to in statusbar
+            delim = ';'
+            do.SetText(str(e) + delim + str(n))
+            wx.TheClipboard.SetData(do)
+            wx.TheClipboard.Close()
+        
+    def ClearLines(self, pdc = None):
+        """!Clears temporary drawn lines from PseudoDC
+        """
+        if not pdc:
+            pdc = self.pdcTmp
+        try:
+            pdc.ClearId(self.lineid)
+            pdc.RemoveId(self.lineid)
+        except:
+            pass
+        
+        try:
+            pdc.ClearId(self.plineid)
+            pdc.RemoveId(self.plineid)
+        except:
+            pass
+        
+        Debug.msg(4, "BufferedWindow2.ClearLines(): lineid=%s, plineid=%s" %
+                  (self.lineid, self.plineid))
+        
+        return True
+
+    def Pixel2Cell(self, (x, y)):
+        """!Convert image coordinates to real word coordinates
+        
+        @param x, y image coordinates
+        
+        @return easting, northing
+        @return None on error
+        """
+        try:
+            x = int(x)
+            y = int(y)
+        except:
+            return None
+        
+        if self.Map.region["ewres"] > self.Map.region["nsres"]:
+            res = self.Map.region["ewres"]
+        else:
+            res = self.Map.region["nsres"]
+        
+        w = self.Map.region["center_easting"] - (self.Map.width / 2) * res
+        n = self.Map.region["center_northing"] + (self.Map.height / 2) * res
+        
+        east  = w + x * res
+        north = n - y * res
+        
+        return (east, north)
+    
+    def Cell2Pixel(self, (east, north)):
+        """!Convert real word coordinates to image coordinates
+        """
+        try:
+            east  = float(east)
+            north = float(north)
+        except:
+            return None
+        
+        if self.Map.region["ewres"] > self.Map.region["nsres"]:
+            res = self.Map.region["ewres"]
+        else:
+            res = self.Map.region["nsres"]
+        
+        w = self.Map.region["center_easting"] - (self.Map.width / 2) * res
+        n = self.Map.region["center_northing"] + (self.Map.height / 2) * res
+        
+        x = (east  - w) / res
+        y = (n - north) / res
+        
+        return (x, y)
+
+    def Zoom(self, begin, end, zoomtype):
+        """!Calculates new region while (un)zoom/pan-ing
+        """
+        x1, y1 = begin
+        x2, y2 = end
+        newreg = {}
+        
+        # threshold - too small squares do not make sense
+        # can only zoom to windows of > 5x5 screen pixels
+        if abs(x2-x1) > 5 and abs(y2-y1) > 5 and zoomtype != 0:
+            if x1 > x2:
+                x1, x2 = x2, x1
+            if y1 > y2:
+                y1, y2 = y2, y1
+            
+            # zoom in
+            if zoomtype > 0:
+                newreg['w'], newreg['n'] = self.Pixel2Cell((x1, y1))
+                newreg['e'], newreg['s'] = self.Pixel2Cell((x2, y2))
+            
+            # zoom out
+            elif zoomtype < 0:
+                newreg['w'], newreg['n'] = self.Pixel2Cell((-x1 * 2, -y1 * 2))
+                newreg['e'], newreg['s'] = self.Pixel2Cell((self.Map.width  + 2 * \
+                                                                (self.Map.width  - x2),
+                                                            self.Map.height + 2 * \
+                                                                (self.Map.height - y2)))
+        # pan
+        elif zoomtype == 0:
+            dx = x1 - x2
+            dy = y1 - y2
+            if dx == 0 and dy == 0:
+                dx = x1 - self.Map.width / 2
+                dy = y1 - self.Map.height / 2
+            newreg['w'], newreg['n'] = self.Pixel2Cell((dx, dy))
+            newreg['e'], newreg['s'] = self.Pixel2Cell((self.Map.width  + dx,
+                                                        self.Map.height + dy))
+        
+        # if new region has been calculated, set the values
+        if newreg != {}:
+            # LL locations
+            if self.Map.projinfo['proj'] == 'll':
+                self.Map.region['n'] = min(self.Map.region['n'], 90.0)
+                self.Map.region['s'] = max(self.Map.region['s'], -90.0)
+            
+            ce = newreg['w'] + (newreg['e'] - newreg['w']) / 2
+            cn = newreg['s'] + (newreg['n'] - newreg['s']) / 2
+            
+            # calculate new center point and display resolution
+            self.Map.region['center_easting'] = ce
+            self.Map.region['center_northing'] = cn
+            self.Map.region['ewres'] = (newreg['e'] - newreg['w']) / self.Map.width
+            self.Map.region['nsres'] = (newreg['n'] - newreg['s']) / self.Map.height
+#############rashad              
+#            if not self.frame.HasProperty('alignExtent') or \
+#                    self.frame.GetProperty('alignExtent'):
+#                self.Map.AlignExtentFromDisplay()
+#            else:
+#                for k in ('n', 's', 'e', 'w'):
+#                    self.Map.region[k] = newreg[k]
+            
+            if hasattr(self, "digit") and \
+                    hasattr(self, "moveInfo"):
+                self._zoom(None)
+            
+            self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+                             self.Map.region['e'], self.Map.region['w'])
+        
+        if self.redrawAll is False:
+            self.redrawAll = True
+        
+    def ZoomBack(self):
+        """!Zoom to previous extents in zoomhistory list
+        """
+        zoom = list()
+        
+        if len(self.zoomhistory) > 1:
+            self.zoomhistory.pop()
+            zoom = self.zoomhistory[-1]
+        
+        # disable tool if stack is empty
+        if len(self.zoomhistory) < 2: # disable tool
+            toolbar = self.frame.GetMapToolbar()
+            toolbar.Enable('zoomBack', enable = False)
+        
+        # zoom to selected region
+        self.Map.GetRegion(n = zoom[0], s = zoom[1],
+                           e = zoom[2], w = zoom[3],
+                           update = True)
+        # update map
+        self.UpdateMap()
+        
+        # update statusbar
+        self.frame.StatusbarUpdate()
+
+        self.zoomChanged.emit()
+
+    def ZoomHistory(self, n, s, e, w):
+        """!Manages a list of last 10 zoom extents
+
+        @param n,s,e,w north, south, east, west
+
+        @return removed history item if exists (or None)
+        """
+        removed = None
+        self.zoomhistory.append((n,s,e,w))
+        
+        if len(self.zoomhistory) > 10:
+            removed = self.zoomhistory.pop(0)
+        
+        if removed:
+            Debug.msg(4, "BufferedWindow2.ZoomHistory(): hist=%s, removed=%s" %
+                      (self.zoomhistory, removed))
+        else:
+            Debug.msg(4, "BufferedWindow2.ZoomHistory(): hist=%s" %
+                      (self.zoomhistory))
+        
+        # update toolbar
+        if len(self.zoomhistory) > 1:
+            enable = True
+        else:
+            enable = False
+        
+        toolbar = self.frame.GetMapToolbar()
+        
+        toolbar.Enable('zoomBack', enable)
+
+        self.zoomChanged.emit()
+        
+        return removed
+
+    def ResetZoomHistory(self):
+        """!Reset zoom history"""
+        self.zoomhistory = list()
+                
+    def ZoomToMap(self, layers = None, ignoreNulls = False, render = True):
+        """!Set display extents to match selected raster
+        or vector map(s).
+
+        @param layers list of layers to be zoom to
+        @param ignoreNulls True to ignore null-values (valid only for rasters)
+        @param render True to re-render display
+        """
+        if not layers:
+            layers = self.tree.GetSelectedLayer(multi = True, checkedOnly = False)
+            layers = [self.tree.GetLayerInfo(layer, key = 'maplayer') for layer in layers]
+
+        if not layers:
+            return
+        
+        rast = []
+        vect = []
+        updated = False
+        for l in layers:
+            # only raster/vector layers are currently supported
+            if l.type == 'raster':
+                rast.append(l.GetName())
+            elif l.type == 'vector':
+                if hasattr(self, "digit") and \
+                        self.toolbar.GetLayer() == l:
+                    w, s, b, e, n, t = self.digit.GetDisplay().GetMapBoundingBox()
+                    self.Map.GetRegion(n = n, s = s, w = w, e = e,
+                                       update = True)
+                    updated = True
+                else:
+                    vect.append(l.name)
+            elif l.type == 'rgb':
+                for rname in l.GetName().splitlines():
+                    rast.append(rname)
+            
+        if not updated:
+            self.Map.GetRegion(rast = rast,
+                               vect = vect,
+                               zoom = ignoreNulls,
+                               update = True)
+        
+        self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+                         self.Map.region['e'], self.Map.region['w'])
+        
+        if render:
+            self.UpdateMap()
+        
+        self.frame.StatusbarUpdate()
+        
+    def ZoomToWind(self):
+        """!Set display geometry to match computational region
+        settings (set with g.region)
+        """
+        self.Map.region = self.Map.GetRegion()
+        
+        self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+                         self.Map.region['e'], self.Map.region['w'])
+        
+        self.UpdateMap()
+        
+        self.frame.StatusbarUpdate()
+
+    def ZoomToDefault(self):
+        """!Set display geometry to match default region settings
+        """
+        self.Map.region = self.Map.GetRegion(default = True)
+        self.Map.AdjustRegion() # aling region extent to the display
+
+        self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+                         self.Map.region['e'], self.Map.region['w'])
+        
+        self.UpdateMap()
+        
+        self.frame.StatusbarUpdate()
+    
+    
+    def GoTo(self, e, n):
+        region = self.Map.GetCurrentRegion()
+
+        region['center_easting'], region['center_northing'] = e, n
+        
+        dn = (region['nsres'] * region['rows']) / 2.
+        region['n'] = region['center_northing'] + dn
+        region['s'] = region['center_northing'] - dn
+        de = (region['ewres'] * region['cols']) / 2.
+        region['e'] = region['center_easting'] + de
+        region['w'] = region['center_easting'] - de
+
+        self.Map.AdjustRegion()
+
+        # add to zoom history
+        self.ZoomHistory(region['n'], region['s'],
+                                   region['e'], region['w'])        
+        self.UpdateMap()
+    
+    def DisplayToWind(self):
+        """!Set computational region (WIND file) to match display
+        extents
+        """
+        tmpreg = os.getenv("GRASS_REGION")
+        if tmpreg:
+            del os.environ["GRASS_REGION"]
+        
+        # We ONLY want to set extents here. Don't mess with resolution. Leave that
+        # for user to set explicitly with g.region
+        new = self.Map.AlignResolution()
+        RunCommand('g.region',
+                   parent = self,
+                   overwrite = True,
+                   n = new['n'],
+                   s = new['s'],
+                   e = new['e'],
+                   w = new['w'],
+                   rows = int(new['rows']),
+                   cols = int(new['cols']))
+        
+        if tmpreg:
+            os.environ["GRASS_REGION"] = tmpreg
+        
+    def ZoomToSaved(self):
+        """!Set display geometry to match extents in
+        saved region file
+        """
+        dlg = SavedRegion(parent = self,
+                          title = _("Zoom to saved region extents"),
+                          loadsave = 'load')
+        
+        if dlg.ShowModal() == wx.ID_CANCEL or not dlg.GetName():
+            dlg.Destroy()
+            return
+        
+        if not grass.find_file(name = dlg.GetName(), element = 'windows')['name']:
+            wx.MessageBox(parent = self,
+                          message = _("Region <%s> not found. Operation canceled.") % dlg.GetName(),
+                          caption = _("Error"), style = wx.ICON_ERROR | wx.OK | wx.CENTRE)
+            dlg.Destroy()
+            return
+        
+        self.Map.GetRegion(regionName = dlg.GetName(),
+                           update = True)
+        
+        dlg.Destroy()
+        
+        self.ZoomHistory(self.Map.region['n'],
+                         self.Map.region['s'],
+                         self.Map.region['e'],
+                         self.Map.region['w'])
+        
+        self.UpdateMap()
+                
+    def SaveRegion(self, display = True):
+        """!Save display extents/compulational region to named region
+        file.
+
+        @param display True for display extends otherwise computational region
+        """
+        if display:
+            title = _("Save display extents to region file")
+        else:
+            title = _("Save computational region to region file")
+        
+        dlg = SavedRegion(parent = self, title = title, loadsave = 'save')
+        if dlg.ShowModal() == wx.ID_CANCEL or not dlg.GetName():
+            dlg.Destroy()
+            return
+        
+        # test to see if it already exists and ask permission to overwrite
+        if grass.find_file(name = dlg.GetName(), element = 'windows')['name']:
+            overwrite = wx.MessageBox(parent = self,
+                                      message = _("Region file <%s> already exists. "
+                                                  "Do you want to overwrite it?") % (dlg.GetName()),
+                                      caption = _("Warning"), style = wx.YES_NO | wx.CENTRE)
+            if overwrite != wx.YES:
+                dlg.Destroy()
+                return
+        
+        if display:
+            self._saveDisplayRegion(dlg.GetName())
+        else:
+            self._saveCompRegion(dlg.GetName())
+        
+        dlg.Destroy()
+
+    def _saveCompRegion(self, name):
+        """!Save region settings to region file
+        
+        @param name region name
+        """
+        RunCommand('g.region',
+                   overwrite = True,
+                   parent = self,
+                   flags = 'u',
+                   save = name)
+        
+    def _saveDisplayRegion(self, name):
+        """!Save display extents to region file
+        
+        @param name region name
+        """
+        new = self.Map.GetCurrentRegion()
+        
+        tmpreg = os.getenv("GRASS_REGION")
+        if tmpreg:
+            del os.environ["GRASS_REGION"]
+        
+        RunCommand('g.region',
+                   overwrite = True,
+                   parent = self,
+                   flags = 'u',
+                   n = new['n'],
+                   s = new['s'],
+                   e = new['e'],
+                   w = new['w'],
+                   rows = int(new['rows']),
+                   cols = int(new['cols']),
+                   save = name)
+        
+        if tmpreg:
+            os.environ["GRASS_REGION"] = tmpreg
+        
+    def Distance(self, beginpt, endpt, screen = True):
+        """!Calculates distance
+        
+        Ctypes required for LL-locations
+        
+        @param beginpt first point
+        @param endpt second point
+        @param screen True for screen coordinates otherwise EN
+        """
+        if screen:
+            e1, n1 = self.Pixel2Cell(beginpt)
+            e2, n2 = self.Pixel2Cell(endpt)
+        else:
+            e1, n1 = beginpt
+            e2, n2 = endpt
+            
+        dEast  = (e2 - e1)
+        dNorth = (n2 - n1)
+        
+        if self.frame.Map.projinfo['proj'] == 'll' and haveCtypes:
+            dist = gislib.G_distance(e1, n1, e2, n2)
+        else:
+            dist = math.sqrt(math.pow((dEast), 2) + math.pow((dNorth), 2))
+        
+        return (dist, (dEast, dNorth))
+
+    def GetMap(self):
+        """!Get render.Map() instance"""
+        return self.Map
+
+    def RegisterMouseEventHandler(self, event, handler, cursor = None):
+        """!Calls UpdateTools to manage connected toolbars"""
+        self.frame.UpdateTools(None)
+        MapWindow.RegisterMouseEventHandler(self, event, handler, cursor)
+
+    def UnregisterMouseEventHandler(self, event, handler):
+        """!Sets pointer and toggles it after unregistration"""
+        MapWindow.UnregisterMouseEventHandler(self, event, handler)
+        
+        # sets pointer mode
+        toolbar = self.frame.toolbars['map']
+        toolbar.action['id'] = vars(toolbar)["pointer"]
+        toolbar.OnTool(None)
+        self.frame.OnPointer(event = None)
+        
+    def RegisterGraphicsToDraw(self, graphicsType, setStatusFunc = None, drawFunc = None):
+        """! Method allows to register graphics to draw.
+        
+        @param type (string) - graphics type: "point" or "line"
+        @param setStatusFunc (function reference) - function called before drawing each item
+                Status function should be in this form: setStatusFunc(item, itemOrderNum)
+                    item - passes instance of GraphicsSetItem which will be drawn
+                    itemOrderNum - number of item in drawing order (from O)
+                                   Hidden items are also counted in drawing order.
+        @param drawFunc (function reference) - allows to define own function for drawing
+                            If function is not defined DrawCross method is used for type "point"
+                            or DrawLines method for type "line".
+                            
+        @return reference to GraphicsSet, which was added.
+        """
+        item = GraphicsSet(parentMapWin = self, 
+                           graphicsType = graphicsType, 
+                           setStatusFunc = setStatusFunc, 
+                           drawFunc = drawFunc)
+        self.graphicsSetList.append(item)
+        
+        return item
+
+    def UnregisterGraphicsToDraw(self, item):
+        """!Unregisteres GraphicsSet instance
+        
+        @param item (GraphicsSetItem) - item to unregister
+        
+        @return True - if item was unregistered
+        @return False - if item was not found
+        """     
+        if item in self.graphicsSetList:
+            self.graphicsSetList.remove(item)
+            return True
+        
+        return False
+    
+class GraphicsSet:
+    def __init__(self, parentMapWin, graphicsType, setStatusFunc = None, drawFunc = None):
+        """!Class, which contains instances of GraphicsSetItem and
+            draws them For description of parameters look at method
+            RegisterGraphicsToDraw in BufferedWindow2 class.
+        """
+        self.pens =  {
+            "default"  :  wx.Pen(colour = wx.BLACK, width = 2, style = wx.SOLID),
+            "selected" :  wx.Pen(colour = wx.GREEN, width = 2, style = wx.SOLID),
+            "unused"   :  wx.Pen(colour = wx.LIGHT_GREY, width = 2, style = wx.SOLID),
+            "highest"  :  wx.Pen(colour = wx.RED, width = 2, style = wx.SOLID)
+            }
+        
+        # list contains instances of GraphicsSetItem
+        self.itemsList = []
+        
+        self.properties    = {}
+        self.graphicsType  = graphicsType
+        self.parentMapWin  = parentMapWin
+        self.setStatusFunc = setStatusFunc
+        
+        if drawFunc:
+            self.drawFunc = drawFunc
+        
+        elif self.graphicsType == "point":
+            self.properties["size"] = 5
+            
+            self.properties["text"] = {}
+            self.properties["text"]['font'] = wx.Font(pointSize = self.properties["size"],
+                                                      family = wx.FONTFAMILY_DEFAULT,
+                                                      style = wx.FONTSTYLE_NORMAL,
+                                                      weight = wx.FONTWEIGHT_NORMAL) 
+            self.properties["text"]['active'] = True
+            
+            self.drawFunc = self.parentMapWin.DrawCross
+        
+        elif self.graphicsType == "line":
+            self.drawFunc = self.parentMapWin.DrawLines
+        
+    def Draw(self, pdc):
+        """!Draws all containing items.
+        
+        @param pdc - device context, where items are drawn 
+        """
+        itemOrderNum = 0
+        for item in self.itemsList:
+            if self.setStatusFunc is not None:
+                self.setStatusFunc(item, itemOrderNum)
+            
+            if item.GetPropertyVal("hide") == True:
+                itemOrderNum += 1
+                continue
+            
+            if self.graphicsType  == "point":
+                if item.GetPropertyVal("penName"):
+                    self.parentMapWin.pen = self.pens[item.GetPropertyVal("penName")]
+                else:
+                    self.parentMapWin.pen = self.pens["default"]
+                
+                coords = self.parentMapWin.Cell2Pixel(item.GetCoords())
+                size = self.properties["size"]
+                
+                self.properties["text"]['coords'] = [coords[0] + size, coords[1] + size, size, size]
+                self.properties["text"]['color'] = self.parentMapWin.pen.GetColour() 
+                self.properties["text"]['text'] = item.GetPropertyVal("label")
+                
+                self.drawFunc(pdc = pdc,
+                              coords = coords, 
+                              text = self.properties["text"], 
+                              size = self.properties["size"])
+            
+            elif self.graphicsType == "line":
+                if item.GetPropertyVal("pen"):
+                    self.parentMapWin.polypen = self.pens[item.GetPropertyVal("pen")]
+                else:
+                    self.parentMapWin.polypen = self.pens["default"]
+                self.drawFunc(pdc = pdc, 
+                              polycoords = coords)
+            itemOrderNum += 1
+        
+    def AddItem(self, coords, penName = None, label = None, hide = False):
+        """!Append item to the list.
+        
+        Added item is put to the last place in drawing order. 
+        Could be 'point' or 'line' according to graphicsType.
+        
+        @param coords - list of east, north coordinates (double) of item
+                        Example: point: [1023, 122] 
+                                 line: [[10, 12],[20,40],[23, 2334]] 
+        @param penName (string) - the 'default' pen is used if is not defined
+        @param label (string) - label, which will be drawn with point. It is relavant just for 'point' type.
+        @param hide (bool) -  If it is True, the item is not drawn, when self.Draw is called. 
+                              Hidden items are also counted in drawing order.
+                              
+        @return (GraphicsSetItem) - added item reference
+        """
+        item = GraphicsSetItem(coords = coords, penName = penName, label = label, hide = hide)
+        self.itemsList.append(item)
+        
+        return item
+    
+    def DeleteItem(self, item):
+        """!Deletes item
+
+        @param item (GraphicsSetItem) - item to remove
+        
+        @return True if item was removed
+        @return False if item was not found 
+        """
+        try:
+            self.itemsList.remove(item)
+        except ValueError:
+            return False
+        
+        return True
+
+    def GetAllItems(self):
+        """!Returns list of all containing instances of GraphicsSetItem, in order 
+        as they are drawn. If you want to change order of drawing use: SetItemDrawOrder method.
+        """
+        # user can edit objects but not order in list, that is reason,
+        # why is returned shallow copy of data list it should be used
+        # SetItemDrawOrder for changing order
+        return copy(self.itemsList)
+
+    def GetItem(self, drawNum):
+        """!Get given item from the list.
+        
+        @param drawNum (int) - drawing order (index) number of item 
+        
+        @return instance of GraphicsSetItem which is drawn in drawNum order
+        @return False if drawNum was out of range
+        """
+        if drawNum < len(self.itemsList) and drawNum >= 0:
+            return self.itemsList[drawNum]
+        else:
+            return False
+
+    def SetPropertyVal(self, propName, propVal):
+        """!Set property value
+        
+        @param propName (string) - property name: "size", "text"
+                                 - both properties are relevant for "point" type
+        @param propVal - property value to be set  
+        
+        @return True - if value was set
+        @return False - if propName is not "size" or "text" or type is "line"   
+        """
+        if self.properties.has_key(propName):
+            self.properties[propName] = propVal
+            return True
+        
+        return False       
+
+    def GetPropertyVal(self, propName):
+        """!Get property value
+        
+        Raises KeyError if propName is not "size" or "text" or type is
+        "line"
+
+        @param propName (string) - property name: "size", "text"
+                                 - both properties are relevant for "point" type
+                                
+        @return value of property
+        """       
+        if self.properties.has_key(propName):
+            return self.properties[propName]
+        
+        raise KeyError(_("Property does not exist: %s") % (propName))          
+        
+    def AddPen(self, penName, pen):
+        """!Add pen
+        
+        @param penName (string) - name of added pen
+        @param pen (wx.Pen) - added pen
+        
+        @return True - if pen was added
+        @return False - if pen already exists   
+        """       
+        if self.pens.has_key(penName):
+            return False
+        
+        self.pens[penName] = pen
+        return True
+
+    def GetPen(self, penName):
+        """!Get existing pen
+        
+        @param penName (string) - name of pen
+        
+        @return wx.Pen reference if is found
+        @return None if penName was not found
+        """       
+        if self.pens.has_key(penName):
+            return self.pens[penName]
+        
+        return None
+
+    def SetItemDrawOrder(self, item, drawNum): 
+        """!Set draw order for item
+        
+        @param item (GraphicsSetItem)
+        @param drawNum (int) - drawing order of item to be set
+        
+        @return True - if order was changed
+        @return False - if drawNum is out of range or item was not found
+        """ 
+        if drawNum < len(self.itemsList) and drawNum >= 0 and \
+            item in self.itemsList:
+            self.itemsList.insert(drawNum, self.itemsList.pop(self.itemsList.index(item)))
+            return True
+        
+        return False
+
+    def GetItemDrawOrder(self, item):       
+        """!Get draw order for given item
+        
+        @param item (GraphicsSetItem) 
+        
+        @return (int) - drawing order of item
+        @return None - if item was not found
+        """ 
+        try:
+            return self.itemsList.index(item)
+        except ValueError:
+            return None
+
+class GraphicsSetItem:
+    def __init__(self, coords, penName = None, label = None, hide = False):
+        """!Could be point or line according to graphicsType in
+        GraphicsSet class
+
+        @param coords - list of coordinates (double) of item 
+                        Example: point: [1023, 122] 
+                                 line: [[10, 12],[20,40],[23, 2334]] 
+        @param penName (string) - if it is not defined 'default' pen is used
+        @param label (string) - label, which will be drawn with point. It is relevant just for 'point' type
+        @param hide (bool) - if it is True, item is not drawn
+                             Hidden items are also counted in drawing order in GraphicsSet class.
+        """
+        self.coords = coords
+        
+        self.properties = { "penName" : penName,
+                            "hide"    : hide,
+                            "label"   : label }
+        
+    def SetPropertyVal(self, propName, propVal):
+        """!Set property value
+        
+        @param propName (string) - property name: "penName", "hide" or "label"
+                                 - property "label" is relevant just for 'point' type
+        @param propVal - property value to be set  
+        
+        @return True - if value was set
+        @return False - if propName is not "penName", "hide" or "label"  
+        """
+        if self.properties.has_key(propName):
+            self.properties[propName] = propVal
+            return True
+        
+        return False
+
+    def GetPropertyVal(self, propName):
+        """!Get property value
+
+        Raises KeyError if propName is not "penName", "hide" or
+        "label".
+        
+        @param propName (string) - property name: "penName", "hide" or "label"
+                                 - property "label" is relevant just for 'point' type
+                                 
+        @return value of property
+        """       
+        if self.properties.has_key(propName):
+            return self.properties[propName]
+        
+        raise KeyError(_("Property does not exist: %s") % (propName))          
+
+    def SetCoords(self, coords):
+        """!Set coordinates of item
+        
+        @param coords - list of east, north coordinates (double) of item
+                        Example: point: [1023, 122] 
+                                 line: [[10, 12],[20,40],[23, 2334]]  
+        """   
+        self.coords = coords
+        
+    def GetCoords(self):
+        """!Get item coordinates
+        
+        @returns coordinates
+        """ 
+        return self.coords

Added: grass-addons/grass7/gui/wxpython/newgui/wxgui.py
===================================================================
--- grass-addons/grass7/gui/wxpython/newgui/wxgui.py	                        (rev 0)
+++ grass-addons/grass7/gui/wxpython/newgui/wxgui.py	2013-03-13 18:02:02 UTC (rev 55366)
@@ -0,0 +1,140 @@
+"""!
+ at package wxgui
+
+ at brief Main Python application for GRASS wxPython GUI
+
+Classes:
+ - wxgui::GMApp
+ - wxgui::Usage
+
+(C) 2006-2011 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Michael Barton (Arizona State University)
+ at author Jachym Cepicky (Mendel University of Agriculture)
+ at author Martin Landa <landa.martin gmail.com>
+ at author Vaclav Petras <wenzeslaus gmail.com> (menu customization)
+"""
+
+import os
+import sys
+import getopt
+
+if __name__ == "__main__":
+    sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'gui', 'wxpython'))
+from core import globalvar
+import wx
+try:
+    import wx.lib.agw.advancedsplash as SC
+except ImportError:
+    SC = None
+
+from lmgr.frame import GMFrame
+
+class GMApp(wx.App):
+    def __init__(self, workspace = None):
+        """!Main GUI class.
+
+        @param workspace path to the workspace file
+        """
+        self.workspaceFile = workspace
+        
+        # call parent class initializer
+        wx.App.__init__(self, False)
+        
+        self.locale = wx.Locale(language = wx.LANGUAGE_DEFAULT)
+        
+    def OnInit(self):
+        """!Initialize all available image handlers
+        
+        @return True
+        """
+        if not globalvar.CheckWxVersion([2, 9]):
+            wx.InitAllImageHandlers()
+        
+        # create splash screen
+        introImagePath = os.path.join(globalvar.ETCIMGDIR, "silesia_splash.png")
+        introImage     = wx.Image(introImagePath, wx.BITMAP_TYPE_PNG)
+        introBmp       = introImage.ConvertToBitmap()
+        if SC and sys.platform != 'darwin':
+            # AdvancedSplash is buggy on the Mac as of 2.8.12.1 
+            # and raises annoying (though seemingly harmless) errors everytime the GUI is started
+            splash = SC.AdvancedSplash(bitmap = introBmp, 
+                                       timeout = 2000, parent = None, id = wx.ID_ANY)
+            splash.SetText(_('Starting GRASS GUI...'))
+            splash.SetTextColour(wx.Colour(45, 52, 27))
+            splash.SetTextFont(wx.Font(pointSize = 15, family = wx.DEFAULT, style = wx.NORMAL,
+                                       weight = wx.BOLD))
+            splash.SetTextPosition((150, 430))
+        else:
+            wx.SplashScreen (bitmap = introBmp, splashStyle = wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
+                             milliseconds = 2000, parent = None, id = wx.ID_ANY)
+        
+        wx.Yield()
+        
+        # create and show main frame
+        mainframe = GMFrame(parent = None, id = wx.ID_ANY,
+                            workspace = self.workspaceFile)
+        
+        mainframe.Show()
+        self.SetTopWindow(mainframe)
+        
+        return True
+
+class Usage(Exception):
+    def __init__(self, msg):
+        self.msg = msg
+
+def printHelp():
+    """!Print program help"""
+    print >> sys.stderr, "Usage:"
+    print >> sys.stderr, " python wxgui.py [options]"
+    print >> sys.stderr, "%sOptions:" % os.linesep
+    print >> sys.stderr, " -w\t--workspace file\tWorkspace file to load"
+    sys.exit(1)
+
+def process_opt(opts, args):
+    """!Process command-line arguments"""
+    workspaceFile = None
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            printHelp()
+            
+        if o in ("-w", "--workspace"):
+            if a != '':
+                workspaceFile = str(a)
+            else:
+                workspaceFile = args.pop(0)
+
+    return (workspaceFile,)
+
+def main(argv = None):
+    import gettext
+    gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
+    
+    if argv is None:
+        argv = sys.argv
+    try:
+        try:
+            opts, args = getopt.getopt(argv[1:], "hw:",
+                                       ["help", "workspace"])
+        except getopt.error, msg:
+            raise Usage(msg)
+    
+    except Usage, err:
+        print >> sys.stderr, err.msg
+        print >> sys.stderr, "for help use --help"
+        printHelp()
+    
+    workspaceFile = process_opt(opts, args)[0]
+    
+    app = GMApp(workspaceFile)
+    # suppress wxPython logs
+    q = wx.LogNull()
+    
+    app.MainLoop()
+    
+if __name__ == "__main__":
+    sys.exit(main())



More information about the grass-commit mailing list