瀏覽代碼

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 11 年之前
父節點
當前提交
5545e755c5

+ 2 - 2
gui/wxpython/Makefile

@@ -11,7 +11,7 @@ ETCDIR = $(ETC)/gui/wxpython
 
 
 SRCFILES := $(wildcard icons/*.py scripts/*.py xml/*) \
 SRCFILES := $(wildcard icons/*.py scripts/*.py xml/*) \
 	$(wildcard animation/* core/*.py dbmgr/* gcp/*.py gmodeler/* \
 	$(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/* \
 	mapswipe/* modules/*.py nviz/*.py psmap/* rlisetup/* vdigit/* \
 	vnet/*.py web_services/*.py wxplot/*.py) \
 	vnet/*.py web_services/*.py wxplot/*.py) \
 	gis_set.py gis_set_error.py wxgui.py README
 	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)))
 	$(patsubst %.py,$(ETCDIR)/%.pyc,$(filter %.py,$(SRCFILES)))
 
 
 PYDSTDIRS := $(patsubst %,$(ETCDIR)/%,animation core dbmgr gcp gmodeler \
 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)
 	mapswipe vdigit wxplot web_services rlisetup vnet)
 
 
 DSTDIRS := $(patsubst %,$(ETCDIR)/%,icons scripts xml)
 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.dialogs  import GetImageHandlers, ImageSizeDialog
 from gui_core.mapdisp  import SingleMapFrame
 from gui_core.mapdisp  import SingleMapFrame
 from core.settings     import UserSettings
 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 mapdisp.statusbar as sb
 import gcp.statusbar as sbgcp
 import gcp.statusbar as sbgcp
@@ -114,14 +114,14 @@ class MapFrame(SingleMapFrame):
         # Init map display (buffered DC & set default cursor)
         # Init map display (buffered DC & set default cursor)
         #
         #
         self.grwiz.SwitchEnv('source')
         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.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.MapWindow = self.SrcMapWindow
         self.Map = self.SrcMap
         self.Map = self.SrcMap
         self._setUpMapWindow(self.SrcMapWindow)
         self._setUpMapWindow(self.SrcMapWindow)

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

@@ -9,8 +9,6 @@ List of classes:
  - dialogs::MapsetDialog
  - dialogs::MapsetDialog
  - dialogs::NewVectorDialog
  - dialogs::NewVectorDialog
  - dialogs::SavedRegion
  - dialogs::SavedRegion
- - dialogs::DecorationDialog
- - dialogs::TextLayerDialog 
  - dialogs::GroupDialog
  - dialogs::GroupDialog
  - dialogs::MapLayersDialog
  - dialogs::MapLayersDialog
  - dialogs::ImportDialog
  - dialogs::ImportDialog
@@ -49,9 +47,8 @@ from grass.pydispatch.signal import Signal
 from core             import globalvar
 from core             import globalvar
 from core.gcmd        import GError, RunCommand, GMessage
 from core.gcmd        import GError, RunCommand, GMessage
 from gui_core.gselect import LocationSelect, MapsetSelect, Select, OgrTypeSelect, GdalSelect, MapsetSelect
 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 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.settings    import UserSettings, GetDisplayVectSettings
 from core.debug       import Debug
 from core.debug       import Debug
 
 
@@ -510,365 +507,7 @@ class SavedRegion(wx.Dialog):
     def GetName(self):
     def GetName(self):
         """!Return region name"""
         """!Return region name"""
         return self.wind
         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):
 class GroupDialog(wx.Dialog):
     """!Dialog for creating/editing groups"""
     """!Dialog for creating/editing groups"""

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

@@ -45,13 +45,13 @@ except ImportError, e:
 import grass.script as grass
 import grass.script as grass
 
 
 from mapdisp            import statusbar as sb
 from mapdisp            import statusbar as sb
-from mapdisp.mapwindow  import BufferedWindow
+from mapwin.buffered import BufferedMapWindow
 from vdigit.toolbars    import VDigitToolbar
 from vdigit.toolbars    import VDigitToolbar
 from gui_core.mapdisp   import DoubleMapFrame
 from gui_core.mapdisp   import DoubleMapFrame
 from core.render        import Map, MapLayer
 from core.render        import Map, MapLayer
 from core.gcmd          import RunCommand, GMessage, GError, GWarning
 from core.gcmd          import RunCommand, GMessage, GError, GWarning
 from gui_core.dialogs   import SetOpacityDialog
 from gui_core.dialogs   import SetOpacityDialog
-from gui_core.mapwindow import MapWindowProperties
+from mapwin.base import MapWindowProperties
 from dbmgr.vinfo        import VectorDBInfo
 from dbmgr.vinfo        import VectorDBInfo
 import grass.script as grass
 import grass.script as grass
 
 
@@ -96,9 +96,9 @@ class IClassMapFrame(DoubleMapFrame):
         self.firstMapWindow = IClassVDigitWindow(parent = self, giface = self._giface,
         self.firstMapWindow = IClassVDigitWindow(parent = self, giface = self._giface,
                                                  properties=self.mapWindowProperties,
                                                  properties=self.mapWindowProperties,
                                                  map = self.firstMap)
                                                  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.MapWindow = self.firstMapWindow # current by default
         
         
         self._bindWindowsActivation()
         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 core.gcmd          import GError, GMessage
 from dbmgr.dialogs      import DisplayAttributesDialog
 from dbmgr.dialogs      import DisplayAttributesDialog
 from core.utils         import ListOfCatsToRange, GetLayerNameFromCmd, _
 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.debug         import Debug
 from core.settings      import UserSettings
 from core.settings      import UserSettings
 from gui_core.mapdisp   import SingleMapFrame
 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 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 modules.histogram  import HistogramFrame
 from wxplot.histogram   import HistogramPlotFrame
 from wxplot.histogram   import HistogramPlotFrame
 from wxplot.profile     import ProfileFrame
 from wxplot.profile     import ProfileFrame
 from wxplot.scatter     import ScatterFrame
 from wxplot.scatter     import ScatterFrame
-from mapdisp.analysis import ProfileController, MeasureDistanceController
+from mapwin.analysis import ProfileController, MeasureDistanceController
 
 
 from mapdisp import statusbar as sb
 from mapdisp import statusbar as sb
 
 
@@ -71,7 +72,7 @@ class MapFrame(SingleMapFrame):
                  toolbars = ["map"], tree = None, notebook = None, lmgr = None,
                  toolbars = ["map"], tree = None, notebook = None, lmgr = None,
                  page = None, Map = Map(), auimgr = None, name = 'MapWindow', **kwargs):
                  page = None, Map = Map(), auimgr = None, name = 'MapWindow', **kwargs):
         """!Main map display window with toolbars, statusbar and
         """!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 toolbars array of activated toolbars, e.g. ['map', 'digit']
         @param tree reference to layer tree
         @param tree reference to layer tree
@@ -154,10 +155,10 @@ class MapFrame(SingleMapFrame):
         #
         #
         # Init map display (buffered DC & set default cursor)
         # 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.mapQueried.connect(self.Query)
         self.MapWindow2D.overlayActivated.connect(self._activateOverlay)
         self.MapWindow2D.overlayActivated.connect(self._activateOverlay)
         self._setUpMapWindow(self.MapWindow2D)
         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.settings import UserSettings
 from core.globalvar import CheckWxVersion
 from core.globalvar import CheckWxVersion
 from core.giface import StandaloneGrassInterface
 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
 from core.render import Map
 
 
 
 
@@ -174,14 +173,16 @@ class Tester(object):
         mapWindowProperties.setValuesFromUserSettings()
         mapWindowProperties.setValuesFromUserSettings()
         width, height = self.frame.GetClientSize()
         width, height = self.frame.GetClientSize()
         copyOfInitMap(map_, width, height)
         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)
         sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
         panel.SetSizer(sizer)
         panel.SetSizer(sizer)
         panel.Layout()
         panel.Layout()
         self.frame.Show()
         self.frame.Show()
 
 
     def testMapDisplay(self, giface, map_):
     def testMapDisplay(self, giface, map_):
+        from mapdisp.frame import MapFrame
+
         # known issues (should be similar with d.mon):
         # known issues (should be similar with d.mon):
         # * opening map in digitizer ends with: vdigit/toolbars.py:723: 'selection' referenced before assignment
         # * 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'
         # * 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()
         width, height = self.frame.GetClientSize()
         copyOfInitMap(map_, width, height)
         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
         giface.mapWindow = window
 
 
@@ -234,8 +235,8 @@ class Tester(object):
 
 
         width, height = self.frame.GetClientSize()
         width, height = self.frame.GetClientSize()
         copyOfInitMap(map_, width, height)
         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
         giface.mapWindow = window
 
 
@@ -249,7 +250,7 @@ class Tester(object):
 
 
         self.frame.Show()
         self.frame.Show()
 
 
-        from mapdisp.analysis import MeasureDistanceController
+        from mapwin.analysis import MeasureDistanceController
         self.controller = MeasureDistanceController(giface, window)
         self.controller = MeasureDistanceController(giface, window)
         self.controller.Start()
         self.controller.Start()
 
 
@@ -265,8 +266,8 @@ class Tester(object):
 
 
         width, height = self.frame.GetClientSize()
         width, height = self.frame.GetClientSize()
         copyOfInitMap(map_, width, height)
         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
         giface.mapWindow = window
 
 
@@ -280,7 +281,7 @@ class Tester(object):
 
 
         self.frame.Show()
         self.frame.Show()
 
 
-        from mapdisp.analysis import ProfileController
+        from mapwin.analysis import ProfileController
         self.controller = ProfileController(giface, window)
         self.controller = ProfileController(giface, window)
         self.controller.Start()
         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.mapdisp   import DoubleMapFrame
 from gui_core.dialogs   import GetImageHandlers
 from gui_core.dialogs   import GetImageHandlers
-from gui_core.mapwindow import MapWindowProperties
+from mapwin.base import MapWindowProperties
 from core.render        import Map
 from core.render        import Map
 from mapdisp            import statusbar as sb
 from mapdisp            import statusbar as sb
 from core.debug         import Debug
 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.debug import Debug
 from core.utils import _
 from core.utils import _
-from mapdisp.mapwindow import BufferedWindow
+from mapwin.buffered import BufferedMapWindow
 
 
 
 
 EVT_MY_MOUSE_EVENTS = wx.NewEventType()
 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)
 EVT_MOTION = wx.PyEventBinder(EVT_MY_MOTION)
 
 
 
 
-class SwipeBufferedWindow(BufferedWindow):
+class SwipeBufferedWindow(BufferedMapWindow):
     """!A subclass of BufferedWindow class. 
     """!A subclass of BufferedWindow class. 
 
 
     Enables to draw the image translated.
     Enables to draw the image translated.
     Special mouse events with changed coordinates are used.
     Special mouse events with changed coordinates are used.
     """
     """
     def __init__(self, parent, giface, Map, properties, **kwargs):
     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__()")
         Debug.msg(2, "SwipeBufferedWindow.__init__()")
 
 
         self.specialSize = super(SwipeBufferedWindow, self).GetClientSize()
         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 -*-
 # -*- coding: utf-8 -*-
 """!
 """!
-@package mapdisp.analysis
+@package mapwin.analysis
 
 
 @brief Map display controllers for analyses (profiling, measuring)
 @brief Map display controllers for analyses (profiling, measuring)
 
 
@@ -33,7 +33,7 @@ class AnalysisControllerBase:
         """!
         """!
 
 
         @param giface grass interface
         @param giface grass interface
-        @param mapWindow instance of BufferedWindow
+        @param mapWindow instance of BufferedMapWindow
         """
         """
         self._giface = giface
         self._giface = giface
         self._mapWindow = mapWindow
         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:
 Classes:
- - mapwindow::MapWindow
+ - mapwindow::MapWindowProperties
+ - mapwindow::MapWindowBase
 
 
 (C) 2006-2012 by the GRASS Development Team
 (C) 2006-2012 by the GRASS Development Team
 
 
@@ -92,7 +93,7 @@ class MapWindowProperties(object):
             self.alignExtentChanged.emit(value=value)
             self.alignExtentChanged.emit(value=value)
 
 
 
 
-class MapWindow(object):
+class MapWindowBase(object):
     """!Abstract map display window class
     """!Abstract map display window class
     
     
     Superclass for BufferedWindow class (2D display mode), and GLWindow
     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.
 @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.gcmd          import RunCommand, GException, GError, GMessage
 from core.debug         import Debug
 from core.debug         import Debug
 from core.settings      import UserSettings
 from core.settings      import UserSettings
-from gui_core.mapwindow import MapWindow
+from mapwin.base import MapWindowBase
 from core.utils         import GetGEventAttribsForHandler, _
 from core.utils         import GetGEventAttribsForHandler, _
 import core.utils as utils
 import core.utils as utils
+from mapwin.graphics import GraphicsSet
 
 
 try:
 try:
     import grass.lib.gis as gislib
     import grass.lib.gis as gislib
@@ -47,7 +48,7 @@ try:
 except ImportError:
 except ImportError:
     haveCtypes = False
     haveCtypes = False
 
 
-class BufferedWindow(MapWindow, wx.Window):
+class BufferedMapWindow(MapWindowBase, wx.Window):
     """!A Buffered window class (2D view mode)
     """!A Buffered window class (2D view mode)
 
 
     Superclass for VDigitWindow (vector digitizer).
     Superclass for VDigitWindow (vector digitizer).
@@ -69,7 +70,7 @@ class BufferedWindow(MapWindow, wx.Window):
         @param style wx window style
         @param style wx window style
         @param kwargs keyword arguments passed to MapWindow and wx.Window
         @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)
         wx.Window.__init__(self, parent=parent, id=id, style=style, **kwargs)
 
 
         self._properties = properties
         self._properties = properties
@@ -1788,299 +1789,3 @@ class BufferedWindow(MapWindow, wx.Window):
             return True
             return True
         
         
         return False
         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.gcmd          import GMessage, GException, GError
 from core.debug         import Debug
 from core.debug         import Debug
-from gui_core.mapwindow import MapWindow
+from mapwin.base import MapWindowBase
 from core.settings      import UserSettings
 from core.settings      import UserSettings
 from nviz.workspace     import NvizSettings
 from nviz.workspace     import NvizSettings
 from nviz.animation     import Animation
 from nviz.animation     import Animation
@@ -69,7 +69,7 @@ class NvizThread(Thread):
         """!Get display instance"""
         """!Get display instance"""
         return self._display
         return self._display
 
 
-class GLWindow(MapWindow, glcanvas.GLCanvas):
+class GLWindow(MapWindowBase, glcanvas.GLCanvas):
     """!OpenGL canvas for Map Display Window"""
     """!OpenGL canvas for Map Display Window"""
     def __init__(self, parent, giface, frame, Map, tree, lmgr, id=wx.ID_ANY):
     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
         """All parameters except for id are mandatory. The todo is to remove
@@ -90,10 +90,10 @@ class GLWindow(MapWindow, glcanvas.GLCanvas):
         else:
         else:
             glcanvas.GLCanvas.__init__(self, parent, id)
             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()
         self.Hide()
 
 
-        # TODO: same signals as in BufferedWindow
+        # TODO: same signals as in BufferedMapWindow
         # same interface is good, but how to ensure same names
         # same interface is good, but how to ensure same names
         # or avoid duplication, define in map window base class?
         # 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 cats  directory of lines (layer/categories) - used by vdigit
         @param style dialog style
         @param style dialog style
         """
         """
-        self.parent = parent       # mapdisplay.BufferedWindow class instance
+        self.parent = parent  # map window class instance
         self.digit = parent.digit
         self.digit = parent.digit
         
         
         # map name
         # map name
@@ -584,7 +584,7 @@ class VDigitZBulkDialog(wx.Dialog):
         """
         """
         wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style)
         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)
         # 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,
         wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style,
                            pos = pos)
                            pos = pos)
         
         
-        self.parent = parent # BufferedWindow
+        self.parent = parent  # map window instance
         self.data = data
         self.data = data
         self.winList = []
         self.winList = []
 
 

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

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

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

@@ -129,7 +129,7 @@ class IVDigit:
     def __init__(self, mapwindow, driver = DisplayDriver):
     def __init__(self, mapwindow, driver = DisplayDriver):
         """!Base class for vector digitizer (ctypes interface)
         """!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.poMapInfo   = None      # pointer to Map_info
         self.mapWindow = mapwindow
         self.mapWindow = mapwindow