Procházet zdrojové kódy

wxGUI/mapwin: new mapwin subdirectory with map window related code including buffered window

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@57427 15284696-431f-4ddb-bdfa-cd5b030d7da7
Vaclav Petras před 11 roky
rodič
revize
5545e755c5

+ 2 - 2
gui/wxpython/Makefile

@@ -11,7 +11,7 @@ ETCDIR = $(ETC)/gui/wxpython
 
 SRCFILES := $(wildcard icons/*.py scripts/*.py xml/*) \
 	$(wildcard animation/* core/*.py dbmgr/* gcp/*.py gmodeler/* \
-	gui_core/*.py iclass/* lmgr/*.py location_wizard/*.py mapdisp/*.py \
+	gui_core/*.py iclass/* lmgr/*.py location_wizard/*.py mapwin/*.py mapdisp/*.py \
 	mapswipe/* modules/*.py nviz/*.py psmap/* rlisetup/* vdigit/* \
 	vnet/*.py web_services/*.py wxplot/*.py) \
 	gis_set.py gis_set_error.py wxgui.py README
@@ -20,7 +20,7 @@ DSTFILES := $(patsubst %,$(ETCDIR)/%,$(SRCFILES)) \
 	$(patsubst %.py,$(ETCDIR)/%.pyc,$(filter %.py,$(SRCFILES)))
 
 PYDSTDIRS := $(patsubst %,$(ETCDIR)/%,animation core dbmgr gcp gmodeler \
-	gui_core iclass lmgr location_wizard mapdisp modules nviz psmap \
+	gui_core iclass lmgr location_wizard mapwin mapdisp modules nviz psmap \
 	mapswipe vdigit wxplot web_services rlisetup vnet)
 
 DSTDIRS := $(patsubst %,$(ETCDIR)/%,icons scripts xml)

+ 8 - 8
gui/wxpython/gcp/mapdisplay.py

@@ -31,8 +31,8 @@ from core.utils import _
 from gui_core.dialogs  import GetImageHandlers, ImageSizeDialog
 from gui_core.mapdisp  import SingleMapFrame
 from core.settings     import UserSettings
-from mapdisp.mapwindow import BufferedWindow
-from gui_core.mapwindow import MapWindowProperties
+from mapwin.buffered import BufferedMapWindow
+from mapwin.base import MapWindowProperties
 
 import mapdisp.statusbar as sb
 import gcp.statusbar as sbgcp
@@ -114,14 +114,14 @@ class MapFrame(SingleMapFrame):
         # Init map display (buffered DC & set default cursor)
         #
         self.grwiz.SwitchEnv('source')
-        self.SrcMapWindow = BufferedWindow(parent=self, giface=self._giface, id=wx.ID_ANY,
-                                           properties=self.mapWindowProperties,
-                                           Map=self.SrcMap)
+        self.SrcMapWindow = BufferedMapWindow(parent=self, giface=self._giface, id=wx.ID_ANY,
+                                              properties=self.mapWindowProperties,
+                                              Map=self.SrcMap)
 
         self.grwiz.SwitchEnv('target')
-        self.TgtMapWindow = BufferedWindow(parent=self, giface=self._giface, id=wx.ID_ANY,
-                                           properties=self.mapWindowProperties,
-                                          Map=self.TgtMap)
+        self.TgtMapWindow = BufferedMapWindow(parent=self, giface=self._giface, id=wx.ID_ANY,
+                                              properties=self.mapWindowProperties,
+                                              Map=self.TgtMap)
         self.MapWindow = self.SrcMapWindow
         self.Map = self.SrcMap
         self._setUpMapWindow(self.SrcMapWindow)

+ 1 - 362
gui/wxpython/gui_core/dialogs.py

@@ -9,8 +9,6 @@ List of classes:
  - dialogs::MapsetDialog
  - dialogs::NewVectorDialog
  - dialogs::SavedRegion
- - dialogs::DecorationDialog
- - dialogs::TextLayerDialog 
  - dialogs::GroupDialog
  - dialogs::MapLayersDialog
  - dialogs::ImportDialog
@@ -49,9 +47,8 @@ from grass.pydispatch.signal import Signal
 from core             import globalvar
 from core.gcmd        import GError, RunCommand, GMessage
 from gui_core.gselect import LocationSelect, MapsetSelect, Select, OgrTypeSelect, GdalSelect, MapsetSelect
-from gui_core.forms   import GUI
 from gui_core.widgets import SingleSymbolPanel, GListCtrl, SimpleValidator
-from core.utils       import GetLayerNameFromCmd, GetValidLayerName, _
+from core.utils       import GetValidLayerName, _
 from core.settings    import UserSettings, GetDisplayVectSettings
 from core.debug       import Debug
 
@@ -510,365 +507,7 @@ class SavedRegion(wx.Dialog):
     def GetName(self):
         """!Return region name"""
         return self.wind
-    
-DECOR_DIALOG_LEGEND = 0
-DECOR_DIALOG_BARSCALE = 1
-
-class DecorationDialog(wx.Dialog):
-    """!Controls setting options and displaying/hiding map overlay
-    decorations
-    """
-    def __init__(self, parent, title, giface, overlayController,
-                 ddstyle, **kwargs):
-        
-        wx.Dialog.__init__(self, parent, wx.ID_ANY, title, **kwargs)
-        
-        self.parent  = parent  # MapFrame
-        self._overlay = overlayController
-        self._ddstyle = ddstyle
-        self._giface = giface
-        
-        self._oldMouseUse = None
-        self._oldCursor = None
-        
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        
-        box = wx.BoxSizer(wx.HORIZONTAL)
-        self.chkbox = wx.CheckBox(parent = self, id = wx.ID_ANY)
-        self.chkbox.SetValue(True)
-
-        if self._ddstyle == DECOR_DIALOG_LEGEND:
-            self.chkbox.SetLabel("Show legend")
-        else:
-            self.chkbox.SetLabel("Show scale and North arrow")
-
-
-        box.Add(item = self.chkbox, proportion = 0,
-                flag = wx.ALIGN_CENTRE|wx.ALL, border = 5)
-        sizer.Add(item = box, proportion = 0,
-                  flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
-
-        box = wx.BoxSizer(wx.HORIZONTAL)
-        optnbtn = wx.Button(parent = self, id = wx.ID_ANY, label = _("Set options"))
-        box.Add(item = optnbtn, proportion = 0, flag = wx.ALIGN_CENTRE|wx.ALL, border = 5)
-        sizer.Add(item = box, proportion = 0,
-                  flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
-        if self._ddstyle == DECOR_DIALOG_LEGEND:
-            box = wx.BoxSizer(wx.HORIZONTAL)
-            self.resizeBtn = wx.ToggleButton(parent = self, id = wx.ID_ANY, label = _("Set size and position"))
-            self.resizeBtn.SetToolTipString(_("Click and drag on the map display to set legend "
-                                              "size and position and then press OK"))
-            self.resizeBtn.Disable()
-            self.resizeBtn.Bind(wx.EVT_TOGGLEBUTTON, self.OnResize)
-            box.Add(item = self.resizeBtn, proportion = 0, flag = wx.ALIGN_CENTRE|wx.ALL, border = 5)
-            sizer.Add(item = box, proportion = 0,
-                      flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
-
-        box = wx.BoxSizer(wx.HORIZONTAL)
-        if self._ddstyle == DECOR_DIALOG_LEGEND:
-            labelText = _("Drag legend object with mouse in pointer mode to position.\n"
-                          "Double-click to change options.\n"
-                          "Define raster map name for legend in properties dialog.")
-        else:
-            labelText = _("Drag scale object with mouse in pointer mode to position.\n"
-                          "Double-click to change options.")
-
-        label = wx.StaticText(parent = self, id = wx.ID_ANY,
-                              label = labelText)
-
-        box.Add(item = label, proportion = 0,
-                flag = wx.ALIGN_CENTRE|wx.ALL, border = 5)
-        sizer.Add(item = box, proportion = 0,
-                  flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
-
-        line = wx.StaticLine(parent = self, id = wx.ID_ANY, size = (20,-1), style = wx.LI_HORIZONTAL)
-        sizer.Add(item = line, proportion = 0,
-                  flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
-
-        # buttons
-        btnsizer = wx.StdDialogButtonSizer()
-
-        self.btnOK = wx.Button(parent = self, id = wx.ID_OK)
-        self.btnOK.SetDefault()
-        self.btnOK.Enable(self._ddstyle != DECOR_DIALOG_LEGEND)
-        btnsizer.AddButton(self.btnOK)
-
-        btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL)
-        btnsizer.AddButton(btnCancel)
-        btnsizer.Realize()
-
-        sizer.Add(item = btnsizer, proportion = 0,
-                  flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 5)
-
-        #
-        # bindings
-        #
-        optnbtn.Bind(wx.EVT_BUTTON, self.OnOptions)
-        btnCancel.Bind(wx.EVT_BUTTON, lambda evt: self.CloseDialog())
-        self.btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
-
-        self.SetSizer(sizer)
-        sizer.Fit(self)
-
-        mapName, found = GetLayerNameFromCmd(self._overlay.cmd)
-        if found:
-            # enable 'OK' and 'Resize' button
-            self.btnOK.Enable()
-
-            # set title
-            self.SetTitle(_('Legend of raster map <%s>') % \
-                              mapName)
-        
-    def OnOptions(self, event):
-        """!Sets option for decoration map overlays
-        """
-        if self._overlay.propwin is None:
-            # build properties dialog
-            GUI(parent = self.parent).ParseCommand(cmd = self._overlay.cmd,
-                                                   completed = (self.GetOptData, self._overlay.name, ''))
-            
-        else:
-            if self._overlay.propwin.IsShown():
-                self._overlay.propwin.SetFocus()
-            else:
-                self._overlay.propwin.Show()
-
-    def OnResize(self, event):
-        window = self._giface.GetMapWindow()
-        if event.GetInt(): 
-            self._oldMouseUse = window.mouse['use']
-            self._oldCursor = window.GetNamedCursor()
-            window.SetNamedCursor('cross')
-            window.mouse['use'] = None
-            window.mouse['box'] = 'box'
-            window.pen = wx.Pen(colour = 'Black', width = 2, style = wx.SHORT_DASH)
-            window.mouseLeftUp.connect(self._resizeLegend)
-        else:
-            self.Restore()
-            self.DisconnectResizing()
-
-    def Restore(self):
-        """!Restore conditions before resizing"""
-        window = self._giface.GetMapWindow()
-        if self._oldCursor:
-            window.SetNamedCursor(self._oldCursor)
-        if self._oldMouseUse:
-            window.mouse['use'] = self._oldMouseUse
-
-    def DisconnectResizing(self):
-        self._giface.GetMapWindow().mouseLeftUp.disconnect(self._resizeLegend)
-
-    def _resizeLegend(self, x, y):
-        """!Update legend after drawing new legend size (moved from BufferedWindow)"""
-        self.resizeBtn.SetValue(False)
-        window = self._giface.GetMapWindow()
-        self.DisconnectResizing()
-        self.Restore()
-        # resize legend
-        screenSize = window.GetClientSizeTuple()
-        self._overlay.ResizeLegend(window.mouse["begin"], window.mouse["end"], screenSize)
-        # redraw
-        self._giface.updateMap.emit()
-
-    def CloseDialog(self):
-        """!Hide dialog"""
-        if self._ddstyle == DECOR_DIALOG_LEGEND and self.resizeBtn.GetValue():
-            self.Restore()
-            self.resizeBtn.SetValue(False)
-            self.DisconnectResizing()
-
-        self.Hide()
-
-    def OnOK(self, event):
-        """!Button 'OK' pressed"""
-        # enable or disable overlay
-        self._overlay.Show(self.chkbox.IsChecked())
 
-        # update map
-        if self.parent.IsPaneShown('3d'):
-            self.parent.MapWindow.UpdateOverlays()
-
-        self._giface.updateMap.emit()
-
-        # hide dialog
-        self.CloseDialog()
-
-    def GetOptData(self, dcmd, layer, params, propwin):
-        """!Process decoration layer data"""
-        if dcmd:
-            self._overlay.cmd = dcmd
-        self._overlay.propwin = propwin
-        if params:
-            self.btnOK.Enable()
-            if self._ddstyle == DECOR_DIALOG_LEGEND and not self.parent.IsPaneShown('3d'):
-                self.resizeBtn.Enable()
-
-    def Show(self, show=True):
-        if show:
-            self.resizeBtn.Enable(not self.parent.IsPaneShown('3d'))
-        wx.Dialog.Show(self, show)
-        
-class TextLayerDialog(wx.Dialog):
-    """
-    Controls setting options and displaying/hiding map overlay decorations
-    """
-
-    def __init__(self, parent, ovlId, title, name = 'text',
-                 pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_DIALOG_STYLE):
-
-        wx.Dialog.__init__(self, parent, wx.ID_ANY, title, pos, size, style)
-        from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED
-
-        self.ovlId = ovlId
-        self.parent = parent
-
-        if self.ovlId in self.parent.MapWindow.textdict.keys():
-            self.currText = self.parent.MapWindow.textdict[self.ovlId]['text']
-            self.currFont = self.parent.MapWindow.textdict[self.ovlId]['font']
-            self.currClr  = self.parent.MapWindow.textdict[self.ovlId]['color']
-            self.currRot  = self.parent.MapWindow.textdict[self.ovlId]['rotation']
-            self.currCoords = self.parent.MapWindow.textdict[self.ovlId]['coords']
-            self.currBB = self.parent.MapWindow.textdict[self.ovlId]['bbox']
-        else:
-            self.currClr = wx.BLACK
-            self.currText = ''
-            self.currFont = self.GetFont()
-            self.currRot = 0.0
-            self.currCoords = [10, 10]
-            self.currBB = wx.Rect()
-
-        self.sizer = wx.BoxSizer(wx.VERTICAL)
-        box = wx.GridBagSizer(vgap = 5, hgap = 5)
-
-        # show/hide
-        self.chkbox = wx.CheckBox(parent = self, id = wx.ID_ANY,
-                                  label = _('Show text object'))
-        if self.parent.Map.GetOverlay(self.ovlId) is None:
-            self.chkbox.SetValue(True)
-        else:
-            self.chkbox.SetValue(self.parent.MapWindow.overlays[self.ovlId]['layer'].IsActive())
-        box.Add(item = self.chkbox, span = (1,2),
-                flag = wx.ALIGN_LEFT|wx.ALL, border = 5,
-                pos = (0, 0))
-
-        # text entry
-        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Enter text:"))
-        box.Add(item = label,
-                flag = wx.ALIGN_CENTER_VERTICAL,
-                pos = (1, 0))
-
-        self.textentry = ExpandoTextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (300,-1))
-        self.textentry.SetFont(self.currFont)
-        self.textentry.SetForegroundColour(self.currClr)
-        self.textentry.SetValue(self.currText)
-        # get rid of unneeded scrollbar when text box first opened
-        self.textentry.SetClientSize((300,-1))
-        
-        box.Add(item = self.textentry,
-                pos = (1, 1))
-
-        # rotation
-        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Rotation:"))
-        box.Add(item = label,
-                flag = wx.ALIGN_CENTER_VERTICAL,
-                pos = (2, 0))
-        self.rotation = wx.SpinCtrl(parent = self, id = wx.ID_ANY, value = "", pos = (30, 50),
-                                    size = (75,-1), style = wx.SP_ARROW_KEYS)
-        self.rotation.SetRange(-360, 360)
-        self.rotation.SetValue(int(self.currRot))
-        box.Add(item = self.rotation,
-                flag = wx.ALIGN_RIGHT,
-                pos = (2, 1))
-
-        # font
-        fontbtn = wx.Button(parent = self, id = wx.ID_ANY, label = _("Set font"))
-        box.Add(item = fontbtn,
-                flag = wx.ALIGN_RIGHT,
-                pos = (3, 1))
-
-        self.sizer.Add(item = box, proportion = 1,
-                  flag = wx.ALL, border = 10)
-
-        # note
-        box = wx.BoxSizer(wx.HORIZONTAL)
-        label = wx.StaticText(parent = self, id = wx.ID_ANY,
-                              label = _("Drag text with mouse in pointer mode "
-                                      "to position.\nDouble-click to change options"))
-        box.Add(item = label, proportion = 0,
-                flag = wx.ALIGN_CENTRE | wx.ALL, border = 5)
-        self.sizer.Add(item = box, proportion = 0,
-                  flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | wx.ALL, border = 5)
-
-        line = wx.StaticLine(parent = self, id = wx.ID_ANY,
-                             size = (20,-1), style = wx.LI_HORIZONTAL)
-        self.sizer.Add(item = line, proportion = 0,
-                  flag = wx.EXPAND | wx.ALIGN_CENTRE | wx.ALL, border = 5)
-
-        btnsizer = wx.StdDialogButtonSizer()
-
-        btn = wx.Button(parent = self, id = wx.ID_OK)
-        btn.SetDefault()
-        btnsizer.AddButton(btn)
-
-        btn = wx.Button(parent = self, id = wx.ID_CANCEL)
-        btnsizer.AddButton(btn)
-        btnsizer.Realize()
-
-        self.sizer.Add(item = btnsizer, proportion = 0,
-                  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
-
-        self.SetSizer(self.sizer)
-        self.sizer.Fit(self)
-
-        # bindings
-        self.Bind(EVT_ETC_LAYOUT_NEEDED, self.OnRefit, self.textentry)
-        self.Bind(wx.EVT_BUTTON,     self.OnSelectFont, fontbtn)
-        self.Bind(wx.EVT_TEXT,       self.OnText,       self.textentry)
-        self.Bind(wx.EVT_SPINCTRL,   self.OnRotation,   self.rotation)
-
-    def OnRefit(self, event):
-        """!Resize text entry to match text"""
-        self.sizer.Fit(self)
-
-    def OnText(self, event):
-        """!Change text string"""
-        self.currText = event.GetString()
-
-    def OnRotation(self, event):
-        """!Change rotation"""
-        self.currRot = event.GetInt()
-
-        event.Skip()
-
-    def OnSelectFont(self, event):
-        """!Change font"""
-        data = wx.FontData()
-        data.EnableEffects(True)
-        data.SetColour(self.currClr)         # set colour
-        data.SetInitialFont(self.currFont)
-
-        dlg = wx.FontDialog(self, data)
-
-        if dlg.ShowModal() == wx.ID_OK:
-            data = dlg.GetFontData()
-            self.currFont = data.GetChosenFont()
-            self.currClr = data.GetColour()
-
-            self.textentry.SetFont(self.currFont)
-            self.textentry.SetForegroundColour(self.currClr)
-
-            self.Layout()
-
-        dlg.Destroy()
-
-    def GetValues(self):
-        """!Get text properties"""
-        return { 'text' : self.currText,
-                 'font' : self.currFont,
-                 'color' : self.currClr,
-                 'rotation' : self.currRot,
-                 'coords' : self.currCoords,
-                 'active' : self.chkbox.IsChecked() }
 
 class GroupDialog(wx.Dialog):
     """!Dialog for creating/editing groups"""

+ 5 - 5
gui/wxpython/iclass/frame.py

@@ -45,13 +45,13 @@ except ImportError, e:
 import grass.script as grass
 
 from mapdisp            import statusbar as sb
-from mapdisp.mapwindow  import BufferedWindow
+from mapwin.buffered import BufferedMapWindow
 from vdigit.toolbars    import VDigitToolbar
 from gui_core.mapdisp   import DoubleMapFrame
 from core.render        import Map, MapLayer
 from core.gcmd          import RunCommand, GMessage, GError, GWarning
 from gui_core.dialogs   import SetOpacityDialog
-from gui_core.mapwindow import MapWindowProperties
+from mapwin.base import MapWindowProperties
 from dbmgr.vinfo        import VectorDBInfo
 import grass.script as grass
 
@@ -96,9 +96,9 @@ class IClassMapFrame(DoubleMapFrame):
         self.firstMapWindow = IClassVDigitWindow(parent = self, giface = self._giface,
                                                  properties=self.mapWindowProperties,
                                                  map = self.firstMap)
-        self.secondMapWindow = BufferedWindow(parent = self, giface = self._giface,
-                                              properties=self.mapWindowProperties,
-                                              Map = self.secondMap)
+        self.secondMapWindow = BufferedMapWindow(parent=self, giface=self._giface,
+                                                 properties=self.mapWindowProperties,
+                                                 Map=self.secondMap)
         self.MapWindow = self.firstMapWindow # current by default
         
         self._bindWindowsActivation()

+ 12 - 11
gui/wxpython/mapdisp/frame.py

@@ -43,20 +43,21 @@ from mapdisp.gprint     import PrintOptions
 from core.gcmd          import GError, GMessage
 from dbmgr.dialogs      import DisplayAttributesDialog
 from core.utils         import ListOfCatsToRange, GetLayerNameFromCmd, _
-from gui_core.dialogs   import GetImageHandlers, ImageSizeDialog, DecorationDialog, TextLayerDialog, \
-                               DECOR_DIALOG_LEGEND, DECOR_DIALOG_BARSCALE
+from gui_core.dialogs import GetImageHandlers, ImageSizeDialog
 from core.debug         import Debug
 from core.settings      import UserSettings
 from gui_core.mapdisp   import SingleMapFrame
-from gui_core.mapwindow import MapWindowProperties
+from mapwin.base import MapWindowProperties
 from gui_core.query     import QueryDialog, PrepareQueryResults
-from mapdisp.mapwindow  import BufferedWindow
-from mapdisp.overlays   import LegendController, BarscaleController
+from mapwin.buffered import BufferedMapWindow
+from mapwin.decorations import DecorationDialog, TextLayerDialog, \
+    LegendController, BarscaleController, \
+    DECOR_DIALOG_LEGEND, DECOR_DIALOG_BARSCALE
 from modules.histogram  import HistogramFrame
 from wxplot.histogram   import HistogramPlotFrame
 from wxplot.profile     import ProfileFrame
 from wxplot.scatter     import ScatterFrame
-from mapdisp.analysis import ProfileController, MeasureDistanceController
+from mapwin.analysis import ProfileController, MeasureDistanceController
 
 from mapdisp import statusbar as sb
 
@@ -71,7 +72,7 @@ class MapFrame(SingleMapFrame):
                  toolbars = ["map"], tree = None, notebook = None, lmgr = None,
                  page = None, Map = Map(), auimgr = None, name = 'MapWindow', **kwargs):
         """!Main map display window with toolbars, statusbar and
-        BufferedWindow (map canvas)
+        2D map window, 3D map window and digitizer.
         
         @param toolbars array of activated toolbars, e.g. ['map', 'digit']
         @param tree reference to layer tree
@@ -154,10 +155,10 @@ class MapFrame(SingleMapFrame):
         #
         # Init map display (buffered DC & set default cursor)
         #
-        self.MapWindow2D = BufferedWindow(self, giface = self._giface,
-                                          Map=self.Map,
-                                          properties=self.mapWindowProperties,
-                                          overlays=self.decorations)
+        self.MapWindow2D = BufferedMapWindow(self, giface = self._giface,
+                                             Map=self.Map,
+                                             properties=self.mapWindowProperties,
+                                             overlays=self.decorations)
         self.MapWindow2D.mapQueried.connect(self.Query)
         self.MapWindow2D.overlayActivated.connect(self._activateOverlay)
         self._setUpMapWindow(self.MapWindow2D)

+ 0 - 156
gui/wxpython/mapdisp/overlays.py

@@ -1,156 +0,0 @@
-"""!
-@package mapdisp.overlays
-
-@brief Map display overlays - barscale and legend
-
-Classes:
- - overlays::OverlayController
- - overlays::BarscaleController
- - overlays::LegendController
-
-(C) 2006-2013 by the GRASS Development Team
-
-This program is free software under the GNU General Public License
-(>=v2). Read the file COPYING that comes with GRASS for details.
-
-@author Anna Kratochvilova <kratochanna gmail.com>
-"""
-
-class OverlayController(object):
-    """!Base class for decorations (barscale, legend) controller."""
-    def __init__(self, renderer):
-        self._renderer = renderer
-        self._overlay = None
-        self._coords = [0, 0]
-        self._pdcType = 'image'
-        self._propwin = None
-        self._defaultAt = ''
-        self._cmd = None   # to be set by user
-        self._name = None  # to be defined by subclass
-        self._id = None    # to be defined by subclass
-
-    def SetCmd(self, cmd):
-        hasAt = False
-        for i in cmd:
-            if i.startswith("at="):
-                hasAt = True
-                break
-        if not hasAt:
-            cmd.append(self._defaultAt)
-        self._cmd = cmd
-
-    def GetCmd(self):
-        return self._cmd
-
-    cmd = property(fset = SetCmd, fget = GetCmd)
-
-    def SetCoords(self, coords):
-        self._coords = list(coords)
-
-    def GetCoords(self):
-        return self._coords
-
-    coords = property(fset = SetCoords, fget = GetCoords)
-
-    def GetPdcType(self):
-        return self._pdcType
-
-    pdcType = property(fget = GetPdcType)
-
-    def GetName(self):
-        return self._name
-
-    name = property(fget = GetName)
-
-    def GetId(self):
-        return self._id
-
-    id = property(fget = GetId)
-
-    def GetPropwin(self):
-        return self._propwin
-
-    def SetPropwin(self, win):
-        self._propwin = win
-
-    propwin = property(fget = GetPropwin, fset = SetPropwin)
-
-    def GetLayer(self):
-        return self._overlay
-
-    layer = property(fget = GetLayer)
-
-    def IsShown(self):
-        if self._overlay and self._overlay.IsActive():
-            return True
-        return False
-
-    def Show(self, show = True):
-        """!Activate or deactivate overlay."""
-        if show:
-            if not self._overlay:
-                self._add()
-            self._overlay.SetActive(True)
-            self._update()
-        else:
-            self.Hide()
-
-    def Hide(self):
-        if self._overlay:
-            self._overlay.SetActive(False)
-
-    def _add(self):
-        self._overlay = self._renderer.AddOverlay(id = self._id, ltype = self._name,
-                                                  command = self.cmd, active = False,
-                                                  render = False, hidden = True)
-        # check if successful
-
-    def _update(self):
-        self._renderer.ChangeOverlay(id = self._id, command = self._cmd,
-                                     render = False)
-
-
-class BarscaleController(OverlayController):
-    def __init__(self, renderer):
-        OverlayController.__init__(self, renderer)
-        self._id = 0
-        self._name = 'barscale'
-        self._defaultAt = 'at=0,95'
-        self._cmd = ['d.barscale', self._defaultAt]
-
-
-class LegendController(OverlayController):
-    def __init__(self, renderer):
-        OverlayController.__init__(self, renderer)
-        self._id = 1
-        self._name = 'legend'
-        # TODO: synchronize with d.legend?
-        self._defaultAt = 'at=5,50,2,5'
-        self._cmd = ['d.legend', self._defaultAt]
-
-    def ResizeLegend(self, begin, end, screenSize):
-        """!Resize legend according to given bbox coordinates."""
-        w = abs(begin[0] - end[0])
-        h = abs(begin[1] - end[1])
-        if begin[0] < end[0]:
-            x = begin[0]
-        else:
-            x = end[0]
-        if begin[1] < end[1]:
-            y = begin[1]
-        else:
-            y = end[1]
-        
-        at = [(screenSize[1] - (y + h)) / float(screenSize[1]) * 100,
-              (screenSize[1] - y) / float(screenSize[1]) * 100,
-              x / float(screenSize[0]) * 100,
-              (x + w) / float(screenSize[0]) * 100]
-        atStr = "at=%d,%d,%d,%d" % (at[0], at[1], at[2], at[3])
-
-        for i, subcmd in enumerate(self._cmd):
-            if subcmd.startswith('at='):
-                self._cmd[i] = atStr
-                break
-
-        self._coords = [0, 0]
-        self.Show()

+ 14 - 13
gui/wxpython/mapdisp/test_mapdisp.py

@@ -66,9 +66,8 @@ from core.utils import _
 from core.settings import UserSettings
 from core.globalvar import CheckWxVersion
 from core.giface import StandaloneGrassInterface
-from gui_core.mapwindow import MapWindowProperties
-from mapdisp.mapwindow import BufferedWindow
-from mapdisp.frame import MapFrame
+from mapwin.base import MapWindowProperties
+from mapwin.buffered import BufferedMapWindow
 from core.render import Map
 
 
@@ -174,14 +173,16 @@ class Tester(object):
         mapWindowProperties.setValuesFromUserSettings()
         width, height = self.frame.GetClientSize()
         copyOfInitMap(map_, width, height)
-        window = BufferedWindow(parent=panel, giface=giface, Map=map_,
-                                properties=mapWindowProperties)
+        window = BufferedMapWindow(parent=panel, giface=giface, Map=map_,
+                                   properties=mapWindowProperties)
         sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
         panel.SetSizer(sizer)
         panel.Layout()
         self.frame.Show()
 
     def testMapDisplay(self, giface, map_):
+        from mapdisp.frame import MapFrame
+
         # known issues (should be similar with d.mon):
         # * opening map in digitizer ends with: vdigit/toolbars.py:723: 'selection' referenced before assignment
         # * nviz start fails (closes window? segfaults?) after mapdisp/frame.py:306: 'NoneType' object has no attribute 'GetLayerNotebook'
@@ -204,8 +205,8 @@ class Tester(object):
 
         width, height = self.frame.GetClientSize()
         copyOfInitMap(map_, width, height)
-        window = BufferedWindow(parent=panel, giface=giface, Map=map_,
-                                properties=mapWindowProperties)
+        window = BufferedMapWindow(parent=panel, giface=giface, Map=map_,
+                                   properties=mapWindowProperties)
 
         giface.mapWindow = window
 
@@ -234,8 +235,8 @@ class Tester(object):
 
         width, height = self.frame.GetClientSize()
         copyOfInitMap(map_, width, height)
-        window = BufferedWindow(parent=panel, giface=giface, Map=map_,
-                                properties=mapWindowProperties)
+        window = BufferedMapWindow(parent=panel, giface=giface, Map=map_,
+                                   properties=mapWindowProperties)
 
         giface.mapWindow = window
 
@@ -249,7 +250,7 @@ class Tester(object):
 
         self.frame.Show()
 
-        from mapdisp.analysis import MeasureDistanceController
+        from mapwin.analysis import MeasureDistanceController
         self.controller = MeasureDistanceController(giface, window)
         self.controller.Start()
 
@@ -265,8 +266,8 @@ class Tester(object):
 
         width, height = self.frame.GetClientSize()
         copyOfInitMap(map_, width, height)
-        window = BufferedWindow(parent=panel, giface=giface, Map=map_,
-                                properties=mapWindowProperties)
+        window = BufferedMapWindow(parent=panel, giface=giface, Map=map_,
+                                   properties=mapWindowProperties)
 
         giface.mapWindow = window
 
@@ -280,7 +281,7 @@ class Tester(object):
 
         self.frame.Show()
 
-        from mapdisp.analysis import ProfileController
+        from mapwin.analysis import ProfileController
         self.controller = ProfileController(giface, window)
         self.controller.Start()
 

+ 1 - 1
gui/wxpython/mapswipe/frame.py

@@ -23,7 +23,7 @@ import grass.script as grass
 
 from gui_core.mapdisp   import DoubleMapFrame
 from gui_core.dialogs   import GetImageHandlers
-from gui_core.mapwindow import MapWindowProperties
+from mapwin.base import MapWindowProperties
 from core.render        import Map
 from mapdisp            import statusbar as sb
 from core.debug         import Debug

+ 4 - 4
gui/wxpython/mapswipe/mapwindow.py

@@ -21,7 +21,7 @@ import wx
 
 from core.debug import Debug
 from core.utils import _
-from mapdisp.mapwindow import BufferedWindow
+from mapwin.buffered import BufferedMapWindow
 
 
 EVT_MY_MOUSE_EVENTS = wx.NewEventType()
@@ -30,15 +30,15 @@ EVT_MOUSE_EVENTS = wx.PyEventBinder(EVT_MY_MOUSE_EVENTS)
 EVT_MOTION = wx.PyEventBinder(EVT_MY_MOTION)
 
 
-class SwipeBufferedWindow(BufferedWindow):
+class SwipeBufferedWindow(BufferedMapWindow):
     """!A subclass of BufferedWindow class. 
 
     Enables to draw the image translated.
     Special mouse events with changed coordinates are used.
     """
     def __init__(self, parent, giface, Map, properties, **kwargs):
-        BufferedWindow.__init__(self, parent=parent, giface=giface, Map=Map, 
-                                properties=properties, **kwargs)
+        BufferedMapWindow.__init__(self, parent=parent, giface=giface, Map=Map,
+                                   properties=properties, **kwargs)
         Debug.msg(2, "SwipeBufferedWindow.__init__()")
 
         self.specialSize = super(SwipeBufferedWindow, self).GetClientSize()

+ 7 - 0
gui/wxpython/mapwin/__init__.py

@@ -0,0 +1,7 @@
+all = [
+    'graphics',
+    'buffered',
+    'analysis',
+    'decorations',
+    'base',
+    ]

+ 2 - 2
gui/wxpython/mapdisp/analysis.py

@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 """!
-@package mapdisp.analysis
+@package mapwin.analysis
 
 @brief Map display controllers for analyses (profiling, measuring)
 
@@ -33,7 +33,7 @@ class AnalysisControllerBase:
         """!
 
         @param giface grass interface
-        @param mapWindow instance of BufferedWindow
+        @param mapWindow instance of BufferedMapWindow
         """
         self._giface = giface
         self._mapWindow = mapWindow

+ 5 - 4
gui/wxpython/gui_core/mapwindow.py

@@ -1,10 +1,11 @@
 """!
-@package gui_core.mapwindow
+@package mapwin.mapwindow
 
-@brief Map display canvas - base class for buffered window.
+@brief Map display canvas basic functionality - base class and properties.
 
 Classes:
- - mapwindow::MapWindow
+ - mapwindow::MapWindowProperties
+ - mapwindow::MapWindowBase
 
 (C) 2006-2012 by the GRASS Development Team
 
@@ -92,7 +93,7 @@ class MapWindowProperties(object):
             self.alignExtentChanged.emit(value=value)
 
 
-class MapWindow(object):
+class MapWindowBase(object):
     """!Abstract map display window class
     
     Superclass for BufferedWindow class (2D display mode), and GLWindow

+ 5 - 300
gui/wxpython/mapdisp/mapwindow.py

@@ -1,5 +1,5 @@
 """!
-@package mapdisp.mapwindow
+@package mapwin.mapwindow
 
 @brief Map display canvas - buffered window.
 
@@ -37,9 +37,10 @@ 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 gui_core.mapwindow import MapWindow
+from mapwin.base import MapWindowBase
 from core.utils         import GetGEventAttribsForHandler, _
 import core.utils as utils
+from mapwin.graphics import GraphicsSet
 
 try:
     import grass.lib.gis as gislib
@@ -47,7 +48,7 @@ try:
 except ImportError:
     haveCtypes = False
 
-class BufferedWindow(MapWindow, wx.Window):
+class BufferedMapWindow(MapWindowBase, wx.Window):
     """!A Buffered window class (2D view mode)
 
     Superclass for VDigitWindow (vector digitizer).
@@ -69,7 +70,7 @@ class BufferedWindow(MapWindow, wx.Window):
         @param style wx window style
         @param kwargs keyword arguments passed to MapWindow and wx.Window
         """
-        MapWindow.__init__(self, parent=parent, giface=giface, Map=Map)
+        MapWindowBase.__init__(self, parent=parent, giface=giface, Map=Map)
         wx.Window.__init__(self, parent=parent, id=id, style=style, **kwargs)
 
         self._properties = properties
@@ -1788,299 +1789,3 @@ class BufferedWindow(MapWindow, wx.Window):
             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 BufferedWindow 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("penName"):
-                    self.parentMapWin.polypen = self.pens[item.GetPropertyVal("penName")]
-                else:
-                    self.parentMapWin.polypen = self.pens["default"]
-                coords = item.GetCoords()
-                
-                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

+ 536 - 0
gui/wxpython/mapwin/decorations.py

@@ -0,0 +1,536 @@
+"""!
+@package mapwin.decorations
+
+@brief Map display decorations (overlays) - text, barscale and legend
+
+Classes:
+ - decorations::OverlayController
+ - decorations::BarscaleController
+ - decorations::LegendController
+ - decorations::DecorationDialog
+ - decorations::TextLayerDialog
+
+(C) 2006-2013 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+@author Anna Kratochvilova <kratochanna gmail.com>
+"""
+
+import wx
+from core.utils import GetLayerNameFromCmd, _
+from gui_core.forms import GUI
+
+
+class OverlayController(object):
+
+    """!Base class for decorations (barscale, legend) controller."""
+
+    def __init__(self, renderer):
+        self._renderer = renderer
+        self._overlay = None
+        self._coords = [0, 0]
+        self._pdcType = 'image'
+        self._propwin = None
+        self._defaultAt = ''
+        self._cmd = None   # to be set by user
+        self._name = None  # to be defined by subclass
+        self._id = None    # to be defined by subclass
+
+    def SetCmd(self, cmd):
+        hasAt = False
+        for i in cmd:
+            if i.startswith("at="):
+                hasAt = True
+                break
+        if not hasAt:
+            cmd.append(self._defaultAt)
+        self._cmd = cmd
+
+    def GetCmd(self):
+        return self._cmd
+
+    cmd = property(fset=SetCmd, fget=GetCmd)
+
+    def SetCoords(self, coords):
+        self._coords = list(coords)
+
+    def GetCoords(self):
+        return self._coords
+
+    coords = property(fset=SetCoords, fget=GetCoords)
+
+    def GetPdcType(self):
+        return self._pdcType
+
+    pdcType = property(fget=GetPdcType)
+
+    def GetName(self):
+        return self._name
+
+    name = property(fget=GetName)
+
+    def GetId(self):
+        return self._id
+
+    id = property(fget=GetId)
+
+    def GetPropwin(self):
+        return self._propwin
+
+    def SetPropwin(self, win):
+        self._propwin = win
+
+    propwin = property(fget=GetPropwin, fset=SetPropwin)
+
+    def GetLayer(self):
+        return self._overlay
+
+    layer = property(fget=GetLayer)
+
+    def IsShown(self):
+        if self._overlay and self._overlay.IsActive():
+            return True
+        return False
+
+    def Show(self, show=True):
+        """!Activate or deactivate overlay."""
+        if show:
+            if not self._overlay:
+                self._add()
+            self._overlay.SetActive(True)
+            self._update()
+        else:
+            self.Hide()
+
+    def Hide(self):
+        if self._overlay:
+            self._overlay.SetActive(False)
+
+    def _add(self):
+        self._overlay = self._renderer.AddOverlay(id=self._id, ltype=self._name,
+                                                  command=self.cmd, active=False,
+                                                  render=False, hidden=True)
+        # check if successful
+
+    def _update(self):
+        self._renderer.ChangeOverlay(id=self._id, command=self._cmd,
+                                     render=False)
+
+
+class BarscaleController(OverlayController):
+
+    def __init__(self, renderer):
+        OverlayController.__init__(self, renderer)
+        self._id = 0
+        self._name = 'barscale'
+        self._defaultAt = 'at=0,95'
+        self._cmd = ['d.barscale', self._defaultAt]
+
+
+class LegendController(OverlayController):
+
+    def __init__(self, renderer):
+        OverlayController.__init__(self, renderer)
+        self._id = 1
+        self._name = 'legend'
+        # TODO: synchronize with d.legend?
+        self._defaultAt = 'at=5,50,2,5'
+        self._cmd = ['d.legend', self._defaultAt]
+
+    def ResizeLegend(self, begin, end, screenSize):
+        """!Resize legend according to given bbox coordinates."""
+        w = abs(begin[0] - end[0])
+        h = abs(begin[1] - end[1])
+        if begin[0] < end[0]:
+            x = begin[0]
+        else:
+            x = end[0]
+        if begin[1] < end[1]:
+            y = begin[1]
+        else:
+            y = end[1]
+
+        at = [(screenSize[1] - (y + h)) / float(screenSize[1]) * 100,
+              (screenSize[1] - y) / float(screenSize[1]) * 100,
+              x / float(screenSize[0]) * 100,
+              (x + w) / float(screenSize[0]) * 100]
+        atStr = "at=%d,%d,%d,%d" % (at[0], at[1], at[2], at[3])
+
+        for i, subcmd in enumerate(self._cmd):
+            if subcmd.startswith('at='):
+                self._cmd[i] = atStr
+                break
+
+        self._coords = [0, 0]
+        self.Show()
+
+
+DECOR_DIALOG_LEGEND = 0
+DECOR_DIALOG_BARSCALE = 1
+
+
+class DecorationDialog(wx.Dialog):
+
+    """!Controls setting options and displaying/hiding map overlay
+    decorations
+    """
+
+    def __init__(self, parent, title, giface, overlayController,
+                 ddstyle, **kwargs):
+
+        wx.Dialog.__init__(self, parent, wx.ID_ANY, title, **kwargs)
+
+        self.parent = parent  # MapFrame
+        self._overlay = overlayController
+        self._ddstyle = ddstyle
+        self._giface = giface
+
+        self._oldMouseUse = None
+        self._oldCursor = None
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        self.chkbox = wx.CheckBox(parent=self, id=wx.ID_ANY)
+        self.chkbox.SetValue(True)
+
+        if self._ddstyle == DECOR_DIALOG_LEGEND:
+            self.chkbox.SetLabel("Show legend")
+        else:
+            self.chkbox.SetLabel("Show scale and North arrow")
+
+        box.Add(item=self.chkbox, proportion=0,
+                flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
+        sizer.Add(item=box, proportion=0,
+                  flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        optnbtn = wx.Button(parent=self, id=wx.ID_ANY, label=_("Set options"))
+        box.Add(item=optnbtn, proportion=0, flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
+        sizer.Add(item=box, proportion=0,
+                  flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+        if self._ddstyle == DECOR_DIALOG_LEGEND:
+            box = wx.BoxSizer(wx.HORIZONTAL)
+            self.resizeBtn = wx.ToggleButton(
+                parent=self, id=wx.ID_ANY, label=_("Set size and position"))
+            self.resizeBtn.SetToolTipString(_("Click and drag on the map display to set legend "
+                                              "size and position and then press OK"))
+            self.resizeBtn.Disable()
+            self.resizeBtn.Bind(wx.EVT_TOGGLEBUTTON, self.OnResize)
+            box.Add(item=self.resizeBtn, proportion=0,
+                    flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
+            sizer.Add(item=box, proportion=0,
+                      flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        if self._ddstyle == DECOR_DIALOG_LEGEND:
+            labelText = _("Drag legend object with mouse in pointer mode to position.\n"
+                          "Double-click to change options.\n"
+                          "Define raster map name for legend in properties dialog.")
+        else:
+            labelText = _("Drag scale object with mouse in pointer mode to position.\n"
+                          "Double-click to change options.")
+
+        label = wx.StaticText(parent=self, id=wx.ID_ANY,
+                              label=labelText)
+
+        box.Add(item=label, proportion=0,
+                flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
+        sizer.Add(item=box, proportion=0,
+                  flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+
+        line = wx.StaticLine(
+            parent=self, id=wx.ID_ANY, size=(20, -1), style = wx.LI_HORIZONTAL)
+        sizer.Add(item=line, proportion=0,
+                  flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+
+        # buttons
+        btnsizer = wx.StdDialogButtonSizer()
+
+        self.btnOK = wx.Button(parent=self, id=wx.ID_OK)
+        self.btnOK.SetDefault()
+        self.btnOK.Enable(self._ddstyle != DECOR_DIALOG_LEGEND)
+        btnsizer.AddButton(self.btnOK)
+
+        btnCancel = wx.Button(parent=self, id=wx.ID_CANCEL)
+        btnsizer.AddButton(btnCancel)
+        btnsizer.Realize()
+
+        sizer.Add(item=btnsizer, proportion=0,
+                  flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+
+        #
+        # bindings
+        #
+        optnbtn.Bind(wx.EVT_BUTTON, self.OnOptions)
+        btnCancel.Bind(wx.EVT_BUTTON, lambda evt: self.CloseDialog())
+        self.btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
+
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+
+        mapName, found = GetLayerNameFromCmd(self._overlay.cmd)
+        if found:
+            # enable 'OK' and 'Resize' button
+            self.btnOK.Enable()
+
+            # set title
+            self.SetTitle(_('Legend of raster map <%s>') %
+                          mapName)
+
+    def OnOptions(self, event):
+        """!Sets option for decoration map overlays
+        """
+        if self._overlay.propwin is None:
+            # build properties dialog
+            GUI(parent=self.parent).ParseCommand(cmd=self._overlay.cmd,
+                                                 completed=(self.GetOptData, self._overlay.name, ''))
+
+        else:
+            if self._overlay.propwin.IsShown():
+                self._overlay.propwin.SetFocus()
+            else:
+                self._overlay.propwin.Show()
+
+    def OnResize(self, event):
+        window = self._giface.GetMapWindow()
+        if event.GetInt():
+            self._oldMouseUse = window.mouse['use']
+            self._oldCursor = window.GetNamedCursor()
+            window.SetNamedCursor('cross')
+            window.mouse['use'] = None
+            window.mouse['box'] = 'box'
+            window.pen = wx.Pen(colour='Black', width=2, style=wx.SHORT_DASH)
+            window.mouseLeftUp.connect(self._resizeLegend)
+        else:
+            self.Restore()
+            self.DisconnectResizing()
+
+    def Restore(self):
+        """!Restore conditions before resizing"""
+        window = self._giface.GetMapWindow()
+        if self._oldCursor:
+            window.SetNamedCursor(self._oldCursor)
+        if self._oldMouseUse:
+            window.mouse['use'] = self._oldMouseUse
+
+    def DisconnectResizing(self):
+        self._giface.GetMapWindow().mouseLeftUp.disconnect(self._resizeLegend)
+
+    def _resizeLegend(self, x, y):
+        """!Update legend after drawing new legend size (moved from BufferedWindow)"""
+        self.resizeBtn.SetValue(False)
+        window = self._giface.GetMapWindow()
+        self.DisconnectResizing()
+        self.Restore()
+        # resize legend
+        screenSize = window.GetClientSizeTuple()
+        self._overlay.ResizeLegend(window.mouse["begin"], window.mouse["end"], screenSize)
+        # redraw
+        self._giface.updateMap.emit()
+
+    def CloseDialog(self):
+        """!Hide dialog"""
+        if self._ddstyle == DECOR_DIALOG_LEGEND and self.resizeBtn.GetValue():
+            self.Restore()
+            self.resizeBtn.SetValue(False)
+            self.DisconnectResizing()
+
+        self.Hide()
+
+    def OnOK(self, event):
+        """!Button 'OK' pressed"""
+        # enable or disable overlay
+        self._overlay.Show(self.chkbox.IsChecked())
+
+        # update map
+        if self.parent.IsPaneShown('3d'):
+            self.parent.MapWindow.UpdateOverlays()
+
+        self._giface.updateMap.emit()
+
+        # hide dialog
+        self.CloseDialog()
+
+    def GetOptData(self, dcmd, layer, params, propwin):
+        """!Process decoration layer data"""
+        if dcmd:
+            self._overlay.cmd = dcmd
+        self._overlay.propwin = propwin
+        if params:
+            self.btnOK.Enable()
+            if self._ddstyle == DECOR_DIALOG_LEGEND and not self.parent.IsPaneShown('3d'):
+                self.resizeBtn.Enable()
+
+    def Show(self, show=True):
+        if show:
+            self.resizeBtn.Enable(not self.parent.IsPaneShown('3d'))
+        wx.Dialog.Show(self, show)
+
+
+class TextLayerDialog(wx.Dialog):
+
+    """
+    Controls setting options and displaying/hiding map overlay decorations
+    """
+
+    def __init__(self, parent, ovlId, title, name='text',
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+
+        wx.Dialog.__init__(self, parent, wx.ID_ANY, title, pos, size, style)
+        from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED
+
+        self.ovlId = ovlId
+        self.parent = parent
+
+        if self.ovlId in self.parent.MapWindow.textdict.keys():
+            self.currText = self.parent.MapWindow.textdict[self.ovlId]['text']
+            self.currFont = self.parent.MapWindow.textdict[self.ovlId]['font']
+            self.currClr = self.parent.MapWindow.textdict[self.ovlId]['color']
+            self.currRot = self.parent.MapWindow.textdict[self.ovlId]['rotation']
+            self.currCoords = self.parent.MapWindow.textdict[self.ovlId]['coords']
+            self.currBB = self.parent.MapWindow.textdict[self.ovlId]['bbox']
+        else:
+            self.currClr = wx.BLACK
+            self.currText = ''
+            self.currFont = self.GetFont()
+            self.currRot = 0.0
+            self.currCoords = [10, 10]
+            self.currBB = wx.Rect()
+
+        self.sizer = wx.BoxSizer(wx.VERTICAL)
+        box = wx.GridBagSizer(vgap=5, hgap=5)
+
+        # show/hide
+        self.chkbox = wx.CheckBox(parent=self, id=wx.ID_ANY,
+                                  label=_('Show text object'))
+        if self.parent.Map.GetOverlay(self.ovlId) is None:
+            self.chkbox.SetValue(True)
+        else:
+            self.chkbox.SetValue(self.parent.MapWindow.overlays[self.ovlId]['layer'].IsActive())
+        box.Add(item=self.chkbox, span=(1, 2),
+                flag=wx.ALIGN_LEFT | wx.ALL, border=5,
+                pos=(0, 0))
+
+        # text entry
+        label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Enter text:"))
+        box.Add(item=label,
+                flag=wx.ALIGN_CENTER_VERTICAL,
+                pos=(1, 0))
+
+        self.textentry = ExpandoTextCtrl(
+            parent=self, id=wx.ID_ANY, value="", size=(300, -1))
+        self.textentry.SetFont(self.currFont)
+        self.textentry.SetForegroundColour(self.currClr)
+        self.textentry.SetValue(self.currText)
+        # get rid of unneeded scrollbar when text box first opened
+        self.textentry.SetClientSize((300, -1))
+
+        box.Add(item=self.textentry,
+                pos=(1, 1))
+
+        # rotation
+        label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Rotation:"))
+        box.Add(item=label,
+                flag=wx.ALIGN_CENTER_VERTICAL,
+                pos=(2, 0))
+        self.rotation = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
+                                    size = (75, -1), style = wx.SP_ARROW_KEYS)
+        self.rotation.SetRange(-360, 360)
+        self.rotation.SetValue(int(self.currRot))
+        box.Add(item=self.rotation,
+                flag=wx.ALIGN_RIGHT,
+                pos=(2, 1))
+
+        # font
+        fontbtn = wx.Button(parent=self, id=wx.ID_ANY, label=_("Set font"))
+        box.Add(item=fontbtn,
+                flag=wx.ALIGN_RIGHT,
+                pos=(3, 1))
+
+        self.sizer.Add(item=box, proportion=1,
+                       flag=wx.ALL, border=10)
+
+        # note
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        label = wx.StaticText(parent=self, id=wx.ID_ANY,
+                              label=_("Drag text with mouse in pointer mode "
+                                      "to position.\nDouble-click to change options"))
+        box.Add(item=label, proportion=0,
+                flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
+        self.sizer.Add(item=box, proportion=0,
+                       flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | wx.ALL, border=5)
+
+        line = wx.StaticLine(parent=self, id=wx.ID_ANY,
+                             size=(20, -1), style = wx.LI_HORIZONTAL)
+        self.sizer.Add(item=line, proportion=0,
+                       flag=wx.EXPAND | wx.ALIGN_CENTRE | wx.ALL, border=5)
+
+        btnsizer = wx.StdDialogButtonSizer()
+
+        btn = wx.Button(parent=self, id=wx.ID_OK)
+        btn.SetDefault()
+        btnsizer.AddButton(btn)
+
+        btn = wx.Button(parent=self, id=wx.ID_CANCEL)
+        btnsizer.AddButton(btn)
+        btnsizer.Realize()
+
+        self.sizer.Add(item=btnsizer, proportion=0,
+                       flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+
+        self.SetSizer(self.sizer)
+        self.sizer.Fit(self)
+
+        # bindings
+        self.Bind(EVT_ETC_LAYOUT_NEEDED, self.OnRefit, self.textentry)
+        self.Bind(wx.EVT_BUTTON,     self.OnSelectFont, fontbtn)
+        self.Bind(wx.EVT_TEXT,       self.OnText,       self.textentry)
+        self.Bind(wx.EVT_SPINCTRL,   self.OnRotation,   self.rotation)
+
+    def OnRefit(self, event):
+        """!Resize text entry to match text"""
+        self.sizer.Fit(self)
+
+    def OnText(self, event):
+        """!Change text string"""
+        self.currText = event.GetString()
+
+    def OnRotation(self, event):
+        """!Change rotation"""
+        self.currRot = event.GetInt()
+
+        event.Skip()
+
+    def OnSelectFont(self, event):
+        """!Change font"""
+        data = wx.FontData()
+        data.EnableEffects(True)
+        data.SetColour(self.currClr)         # set colour
+        data.SetInitialFont(self.currFont)
+
+        dlg = wx.FontDialog(self, data)
+
+        if dlg.ShowModal() == wx.ID_OK:
+            data = dlg.GetFontData()
+            self.currFont = data.GetChosenFont()
+            self.currClr = data.GetColour()
+
+            self.textentry.SetFont(self.currFont)
+            self.textentry.SetForegroundColour(self.currClr)
+
+            self.Layout()
+
+        dlg.Destroy()
+
+    def GetValues(self):
+        """!Get text properties"""
+        return {'text': self.currText,
+                'font': self.currFont,
+                'color': self.currClr,
+                'rotation': self.currRot,
+                'coords': self.currCoords,
+                'active': self.chkbox.IsChecked()}

+ 328 - 0
gui/wxpython/mapwin/graphics.py

@@ -0,0 +1,328 @@
+"""!
+@package mapwin.graphics
+
+@brief Map display canvas - buffered window.
+
+Classes:
+ - graphics::GraphicsSet
+ - graphics::GraphicsSetItem
+
+(C) 2006-2013 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+@author Stepan Turek <stepan.turek seznam.cz> (handlers support, GraphicsSet)
+"""
+
+
+from copy import copy
+
+import wx
+
+from core.utils import _
+
+
+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 BufferedWindow 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") is 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("penName"):
+                    self.parentMapWin.polypen = self.pens[item.GetPropertyVal("penName")]
+                else:
+                    self.parentMapWin.polypen = self.pens["default"]
+                coords = item.GetCoords()
+
+                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 propName in self.properties:
+            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 propName in self.properties:
+            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 penName in self.pens:
+            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 penName in self.pens:
+            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 propName in self.properties:
+            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 propName in self.properties:
+            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

+ 4 - 4
gui/wxpython/nviz/mapwindow.py

@@ -37,7 +37,7 @@ from grass.pydispatch.signal import Signal
 
 from core.gcmd          import GMessage, GException, GError
 from core.debug         import Debug
-from gui_core.mapwindow import MapWindow
+from mapwin.base import MapWindowBase
 from core.settings      import UserSettings
 from nviz.workspace     import NvizSettings
 from nviz.animation     import Animation
@@ -69,7 +69,7 @@ class NvizThread(Thread):
         """!Get display instance"""
         return self._display
 
-class GLWindow(MapWindow, glcanvas.GLCanvas):
+class GLWindow(MapWindowBase, glcanvas.GLCanvas):
     """!OpenGL canvas for Map Display Window"""
     def __init__(self, parent, giface, frame, Map, tree, lmgr, id=wx.ID_ANY):
         """All parameters except for id are mandatory. The todo is to remove
@@ -90,10 +90,10 @@ class GLWindow(MapWindow, glcanvas.GLCanvas):
         else:
             glcanvas.GLCanvas.__init__(self, parent, id)
 
-        MapWindow.__init__(self, parent=parent, giface=giface, Map=Map)
+        MapWindowBase.__init__(self, parent=parent, giface=giface, Map=Map)
         self.Hide()
 
-        # TODO: same signals as in BufferedWindow
+        # TODO: same signals as in BufferedMapWindow
         # same interface is good, but how to ensure same names
         # or avoid duplication, define in map window base class?
 

+ 3 - 3
gui/wxpython/vdigit/dialogs.py

@@ -42,7 +42,7 @@ class VDigitCategoryDialog(wx.Dialog, listmix.ColumnSorterMixin):
         @param cats  directory of lines (layer/categories) - used by vdigit
         @param style dialog style
         """
-        self.parent = parent       # mapdisplay.BufferedWindow class instance
+        self.parent = parent  # map window class instance
         self.digit = parent.digit
         
         # map name
@@ -584,7 +584,7 @@ class VDigitZBulkDialog(wx.Dialog):
         """
         wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style)
 
-        self.parent = parent # mapdisplay.BufferedWindow class instance
+        self.parent = parent  # map window class instance
 
         # panel  = wx.Panel(parent=self, id=wx.ID_ANY)
 
@@ -648,7 +648,7 @@ class VDigitDuplicatesDialog(wx.Dialog):
         wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style,
                            pos = pos)
         
-        self.parent = parent # BufferedWindow
+        self.parent = parent  # map window instance
         self.data = data
         self.winList = []
 

+ 2 - 2
gui/wxpython/vdigit/main.py

@@ -29,7 +29,7 @@ except (ImportError, NameError), err:
 class VDigit(IVDigit):
     def __init__(self, mapwindow):
         """!Base class of vector digitizer
-        
-        @param mapwindow reference to mapwindow (mapdisp_window.BufferedWindow) instance
+
+        @param mapwindow reference to a map window instance
         """
         IVDigit.__init__(self, mapwindow)

+ 13 - 13
gui/wxpython/vdigit/mapwindow.py

@@ -22,22 +22,22 @@ from grass.pydispatch.signal import Signal
 from dbmgr.dialogs  import DisplayAttributesDialog
 from core.gcmd      import RunCommand, GMessage, GError
 from core.debug     import Debug
-from mapdisp.mapwindow import BufferedWindow
+from mapwin.buffered import BufferedMapWindow
 from core.settings  import UserSettings
 from core.utils     import ListOfCatsToRange, _
 from core.globalvar import QUERYLAYER
 from vdigit.dialogs import VDigitCategoryDialog, VDigitZBulkDialog, VDigitDuplicatesDialog
 from gui_core       import gselect
 
-class VDigitWindow(BufferedWindow):
+class VDigitWindow(BufferedMapWindow):
     """!A Buffered window extended for vector digitizer.
     """
     def __init__(self, parent, giface, Map, properties, tree=None,
                  id=wx.ID_ANY, lmgr=None,
                  style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
-        BufferedWindow.__init__(self, parent=parent, giface=giface, Map=Map,
-                                properties=properties,
-                                style=style, **kwargs)
+        BufferedMapWindow.__init__(self, parent=parent, giface=giface, Map=Map,
+                                   properties=properties,
+                                   style=style, **kwargs)
         self.lmgr = lmgr
         self.tree = tree
         self.pdcVector = wx.PseudoDC()
@@ -49,13 +49,13 @@ class VDigitWindow(BufferedWindow):
         # Parameter text is a string with information
         # currently used only for coordinates of mouse cursor + segmnt and
         # total feature length
-        self.digitizingInfo = Signal('BufferedWindow.digitizingInfo')
+        self.digitizingInfo = Signal('VDigitWindow.digitizingInfo')
         # Emitted when some info about digitizing is or will be availbale
-        self.digitizingInfoAvailable = Signal('BufferedWindow.digitizingInfo')
+        self.digitizingInfoAvailable = Signal('VDigitWindow.digitizingInfo')
         # Emitted when some info about digitizing is or will be availbale
         # digitizingInfo signal is emmited only between digitizingInfoAvailable
         # and digitizingInfoUnavailable signals
-        self.digitizingInfoUnavailable = Signal('BufferedWindow.digitizingInfo')
+        self.digitizingInfoUnavailable = Signal('VDigitWindow.digitizingInfo')
 
         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
         self.mouseMoving.connect(self._mouseMovingToDigitizingInfo)
@@ -469,8 +469,8 @@ class VDigitWindow(BufferedWindow):
             # add line or boundary -> remove last point from the line
             try:
                 removed = self.polycoords.pop()
-                Debug.msg(4, "BufferedWindow.OnMiddleDown(): polycoords_poped=%s" % \
-                              [removed,])
+                Debug.msg(4, "VDigitWindow.OnMiddleDown(): polycoords_poped=%s" %
+                          [removed, ])
                 # self.mouse['begin'] = self.Cell2Pixel(self.polycoords[-1])
             except:
                 pass
@@ -1050,9 +1050,9 @@ class VDigitWindow(BufferedWindow):
         
     def _onMouseMoving(self, event):
         self.mouse['end'] = event.GetPositionTuple()[:]
-        
-        Debug.msg (5, "BufferedWindow.OnMouseMoving(): coords=%f,%f" % \
-                       (self.mouse['end'][0], self.mouse['end'][1]))
+
+        Debug.msg(5, "VDigitWindow.OnMouseMoving(): coords=%f,%f" %
+                  (self.mouse['end'][0], self.mouse['end'][1]))
 
         action = self.toolbar.GetAction()
         if action == "addLine" and \

+ 1 - 1
gui/wxpython/vdigit/wxdigit.py

@@ -129,7 +129,7 @@ class IVDigit:
     def __init__(self, mapwindow, driver = DisplayDriver):
         """!Base class for vector digitizer (ctypes interface)
         
-        @param mapwindow reference for map window (BufferedWindow)
+        @param mapwindow reference to a map window
         """
         self.poMapInfo   = None      # pointer to Map_info
         self.mapWindow = mapwindow