[GRASS-SVN] r57593 - grass/trunk/gui/wxpython/animation

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Sep 4 18:41:36 PDT 2013


Author: annakrat
Date: 2013-09-04 18:41:36 -0700 (Wed, 04 Sep 2013)
New Revision: 57593

Modified:
   grass/trunk/gui/wxpython/animation/controller.py
   grass/trunk/gui/wxpython/animation/dialogs.py
   grass/trunk/gui/wxpython/animation/mapwindow.py
   grass/trunk/gui/wxpython/animation/utils.py
Log:
wxGUI/animations: possibility to add raster legend

Modified: grass/trunk/gui/wxpython/animation/controller.py
===================================================================
--- grass/trunk/gui/wxpython/animation/controller.py	2013-09-04 01:12:37 UTC (rev 57592)
+++ grass/trunk/gui/wxpython/animation/controller.py	2013-09-05 01:41:36 UTC (rev 57593)
@@ -379,7 +379,13 @@
         prov = self.bitmapProviders[animationData.windowIndex]
         prov.SetData(datasource = animationData.mapData, dataType=animationData.inputMapType)
 
-        self.bitmapProviders[animationData.windowIndex].Load()
+        prov.Load()
+        if animationData.legendCmd:
+            try:
+                bitmap = prov.LoadOverlay(animationData.legendCmd)
+                self.mapwindows[animationData.windowIndex].SetOverlay(bitmap)
+            except GException:
+                GError(message=_("Failed to display legend."))
 
     def _load3DData(self, animationData):
         prov = self.bitmapProviders[animationData.windowIndex]

Modified: grass/trunk/gui/wxpython/animation/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/animation/dialogs.py	2013-09-04 01:12:37 UTC (rev 57592)
+++ grass/trunk/gui/wxpython/animation/dialogs.py	2013-09-05 01:41:36 UTC (rev 57593)
@@ -23,22 +23,20 @@
 import wx
 import copy
 import datetime
-from wx.lib.newevent import NewEvent
 import wx.lib.filebrowsebutton as filebrowse
 
 if __name__ == '__main__':
     sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
 
-import grass.temporal as tgis
-
 from core.gcmd import GMessage, GError, GException
 from core import globalvar
 from gui_core import gselect
 from gui_core.dialogs import MapLayersDialog, GetImageHandlers
+from gui_core.forms import GUI
 from core.settings import UserSettings
 from core.utils import _
 
-from utils import TemporalMode, validateTimeseriesName, validateMapNames
+from utils import TemporalMode, getRegisteredMaps, validateTimeseriesName, validateMapNames
 from nviztask import NvizTask
 
 from grass.pydispatch.signal import Signal
@@ -271,6 +269,7 @@
             self.SetTitle(_("Edit animation"))
 
         self.animationData = animationData
+        self._tmpLegendCmd = None
 
         self._layout()
         self.OnViewMode(event = None)
@@ -357,6 +356,15 @@
         self.addManyMapsButton = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bitmap)
         self.addManyMapsButton.Bind(wx.EVT_BUTTON, self.OnAddMaps)
 
+        self.legend = wx.CheckBox(panel, label=_("Show raster legend"))
+        self.legend.SetValue(bool(self.animationData.legendCmd))
+        self.legendBtn = wx.Button(panel, label=_("Set options"))
+        self.legendBtn.Bind(wx.EVT_BUTTON, self.OnLegend)
+        tooltip = _("By default, legend is created for the first raster map in case of multiple maps "
+                    "and for the first raster map of space time raster dataset.")
+        self.legend.SetToolTipString(tooltip) 
+        self.legendBtn.SetToolTipString(tooltip)
+
         self.OnDataType(None)
         if self.animationData.inputData is None:
             self.dataSelect.SetValue('')
@@ -375,7 +383,12 @@
         hbox.Add(item = self.dataSelect, proportion = 1, flag = wx.ALIGN_CENTER)
         hbox.Add(item = self.addManyMapsButton, proportion = 0, flag = wx.LEFT, border = 5)
         dataBoxSizer.Add(item = hbox, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 3)
-        
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add(item=self.legend, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL)
+        hbox.Add(item=self.legendBtn, proportion=0, flag=wx.LEFT, border=5)
+        dataBoxSizer.Add(item=hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=3)
+
         panel.SetSizerAndFit(dataBoxSizer)
         panel.SetAutoLayout(True)
 
@@ -446,6 +459,9 @@
             self.dataSelect.SetType(etype = etype, multiple = False)
             self.addManyMapsButton.Enable(False)
 
+        self.legend.Enable(etype in ('rast', 'strds'))
+        self.legendBtn.Enable(etype in ('rast', 'strds'))
+
         self.dataSelect.SetValue('')
 
     def OnAddMaps(self, event):
@@ -466,6 +482,45 @@
 
         dlg.Destroy()
 
+    def OnLegend(self, event):
+        """!Set options for legend"""
+        if self._tmpLegendCmd:
+            cmd = self._tmpLegendCmd 
+        elif self.animationData.legendCmd:
+            cmd = self.animationData.legendCmd
+        else:
+            cmd = ['d.legend', 'at=5,50,2,5']
+
+            mapName = self._getLegendMapHint()
+            if mapName:
+                cmd.append("map=%s" % mapName)
+
+        GUI(parent=self, modal=True).ParseCommand(cmd=cmd,
+                                                  completed=(self.GetOptData, '', ''))
+
+    def _getLegendMapHint(self):
+        """!Determine probable map"""
+        inputData = self.dataSelect.GetValue()
+        etype = self.dataChoice.GetClientData(self.dataChoice.GetSelection())
+        if etype == 'strds':
+            timeseries = validateTimeseriesName(inputData, etype=etype)
+            timeseriesMaps = getRegisteredMaps(timeseries, etype)
+            if len(timeseriesMaps):
+                return timeseriesMaps[0]
+        else:  # multiple raster
+            maps = inputData.split(',')
+            if len(maps):
+                return maps[0]
+
+        return None
+
+    def GetOptData(self, dcmd, layer, params, propwin):
+        """!Process decoration layer data"""
+        self._tmpLegendCmd = dcmd
+
+        if dcmd and not self.legend.IsChecked():
+            self.legend.SetValue(True)
+
     def _update(self):
         self.animationData.name = self.nameCtrl.GetValue()
         self.animationData.windowIndex = self.windowChoice.GetSelection()
@@ -475,6 +530,13 @@
         self.animationData.inputData = self.dataSelect.GetValue()
         sel = self.nDChoice.GetSelection()
         self.animationData.viewMode = self.nDChoice.GetClientData(sel)
+        if self._tmpLegendCmd:
+            if self.legend.IsChecked():
+                self.animationData.legendCmd = self._tmpLegendCmd
+        else:
+            if self.legend.IsChecked():
+                self.animationData.legendCmd = ['d.legend', 'at=5,50,2,5', 
+                                                'map=%s' % self._getLegendMapHint()]
 
         if self.threeDPanel.IsShown():
             self.animationData.workspaceFile = self.fileSelector.GetValue()
@@ -639,6 +701,7 @@
         self.nvizParameter = self._nvizParameters[0]
 
         self.workspaceFile = None
+        self.legendCmd = None
 
     def GetName(self):
         return self._name
@@ -691,21 +754,8 @@
             self.mapData = newNames
 
         elif self.inputMapType in ('strds', 'stvds'):
-            timeseries = validateTimeseriesName(data, etype = self.inputMapType)
-            if self.inputMapType == 'strds':
-                sp = tgis.SpaceTimeRasterDataset(ident = timeseries)
-            elif self.inputMapType == 'stvds':
-                sp = tgis.SpaceTimeVectorDataset(ident = timeseries)
-                
-            if sp.is_in_db() == False:
-                raise GException(_("Space time dataset <%s> not found.") % timeseries)
-        
-            sp.select()
-            rows = sp.get_registered_maps(columns = "id", where = None, order = "start_time", dbif = None)
-            timeseriesMaps = []
-            if rows:
-                for row in rows:
-                    timeseriesMaps.append(row["id"])
+            timeseries = validateTimeseriesName(data, etype=self.inputMapType)
+            timeseriesMaps = getRegisteredMaps(timeseries, self.inputMapType)
             self._inputData = timeseries
             self.mapData = timeseriesMaps
         else:
@@ -769,7 +819,15 @@
         return self._viewModes
 
     viewModes = property(fget = GetViewModes)
+    
+    def SetLegendCmd(self, cmd):
+        self._legendCmd = cmd
 
+    def GetLegendCmd(self):
+        return self._legendCmd
+
+    legendCmd = property(fget=GetLegendCmd, fset=SetLegendCmd)
+
     def GetNvizCommands(self):
         if not self.workspaceFile or not self.mapData:
             return []

Modified: grass/trunk/gui/wxpython/animation/mapwindow.py
===================================================================
--- grass/trunk/gui/wxpython/animation/mapwindow.py	2013-09-04 01:12:37 UTC (rev 57592)
+++ grass/trunk/gui/wxpython/animation/mapwindow.py	2013-09-05 01:41:36 UTC (rev 57593)
@@ -21,10 +21,10 @@
 from multiprocessing import Process, Queue
 import tempfile
 import grass.script as grass
-from core.gcmd import RunCommand
+from core.gcmd import RunCommand, GException
 from core.debug import Debug
 from core.settings import UserSettings
-from core.utils import _
+from core.utils import _, CmdToTuple
 
 from grass.pydispatch.signal import Signal
 
@@ -71,7 +71,7 @@
         # The Buffer init is done here, to make sure the buffer is always
         # the same size as the Window
         #Size  = self.GetClientSizeTuple()
-        size  = self.ClientSize
+        size  = self.GetClientSize()
 
         # Make new offscreen bitmap: this bitmap will always have the
         # current drawing in it, so it can be used to save the image to
@@ -112,6 +112,8 @@
         self.bitmap = wx.EmptyBitmap(1, 1)
         self.text = ''
         self.parent = parent
+        self._pdc = wx.PseudoDC()
+        self._overlay = None
 
         BufferedWindow.__init__(self, parent=parent, id=id, style=style)
         self.SetBackgroundColour(wx.BLACK)
@@ -147,6 +149,33 @@
         self.text = text
         self.UpdateDrawing()
 
+    def DrawOverlay(self):
+        self._pdc.BeginDrawing()
+        self._pdc.DrawBitmap(bmp=self._overlay, x=0, y=0)
+        self._pdc.EndDrawing()
+
+    def SetOverlay(self, bitmap):
+        """!Sets overlay bitmap (legend)"""
+        Debug.msg(3, "AnimationWindow.SetOverlay()")
+        if bitmap:
+            if self._overlay:
+                self._pdc.RemoveAll()
+            self._overlay = bitmap
+            self._pdc.BeginDrawing()
+            self._pdc.DrawBitmap(bmp=bitmap, x=0, y=0)
+            self._pdc.EndDrawing()
+        else:
+            self._overlay = None
+            self._pdc.RemoveAll()
+        self.UpdateDrawing()
+
+    def OnPaint(self, event):
+        Debug.msg(5, "AnimationWindow.OnPaint()")
+        # All that is needed here is to draw the buffer to screen
+        dc = wx.BufferedPaintDC(self, self._Buffer)
+        if self._overlay:
+            self._pdc.DrawToDC(dc)
+
 class BitmapProvider(object):
     """!Class responsible for loading data and providing bitmaps"""
     def __init__(self, frame, bitmapPool, imageWidth=640, imageHeight=480, nprocs=4):
@@ -405,6 +434,30 @@
         grass.try_remove(tempFileFormat)
         os.environ.pop('GRASS_REGION')
 
+    def LoadOverlay(self, cmd):
+        """!Creates raster legend with d.legend
+
+        @param cmd d.legend command as a list
+
+        @return bitmap with legend
+        """
+        fileHandler, filename = tempfile.mkstemp(suffix=".png")
+        os.close(fileHandler)
+        # Set the environment variables for this process
+        _setEnvironment(self.imageWidth, self.imageHeight, filename, transparent=True)
+
+        Debug.msg(1, "Render raster legend " + str(filename))
+        cmdTuple = CmdToTuple(cmd)
+        returncode, stdout, messages = read2_command(cmdTuple[0], **cmdTuple[1])
+
+        if returncode == 0:
+            bitmap = wx.Bitmap(filename, wx.BITMAP_TYPE_PNG)
+            return bitmap
+        else:
+            os.remove(filename)
+            raise GException(messages)
+
+
 def mapRenderProcess(mapType, mapname, width, height, fileQueue):
     """!Render raster or vector files as png image and write the 
        resulting png filename in the provided file queue
@@ -421,13 +474,7 @@
     os.close(fileHandler)
     
     # Set the environment variables for this process
-    os.environ['GRASS_WIDTH'] = str(width) 
-    os.environ['GRASS_HEIGHT'] = str(height)
-    driver = UserSettings.Get(group = 'display', key = 'driver', subkey = 'type')
-    os.environ['GRASS_RENDER_IMMEDIATE'] = driver
-    os.environ['GRASS_TRUECOLOR'] = "1" 
-    os.environ['GRASS_TRANSPARENT'] = "1"
-    os.environ['GRASS_PNGFILE'] = str(filename)
+    _setEnvironment(width, height, filename, transparent=False)
 
     if mapType in ('rast', 'strds'):
         Debug.msg(1, "Render raster image " + str(filename))
@@ -446,6 +493,21 @@
 
     fileQueue.put(filename)
     
+
+def _setEnvironment(width, height, filename, transparent):
+    os.environ['GRASS_WIDTH'] = str(width)
+    os.environ['GRASS_HEIGHT'] = str(height)
+    driver = UserSettings.Get(group='display', key='driver', subkey='type')
+    os.environ['GRASS_RENDER_IMMEDIATE'] = driver
+    os.environ['GRASS_BACKGROUNDCOLOR'] = 'ffffff'
+    os.environ['GRASS_TRUECOLOR'] = "TRUE"
+    if transparent:
+        os.environ['GRASS_TRANSPARENT'] = "TRUE"
+    else:
+        os.environ['GRASS_TRANSPARENT'] = "FALSE"
+    os.environ['GRASS_PNGFILE'] = str(filename)
+
+
 class BitmapPool():
     """!Class storing bitmaps (emulates dictionary)"""
     def __init__(self):

Modified: grass/trunk/gui/wxpython/animation/utils.py
===================================================================
--- grass/trunk/gui/wxpython/animation/utils.py	2013-09-04 01:12:37 UTC (rev 57592)
+++ grass/trunk/gui/wxpython/animation/utils.py	2013-09-05 01:41:36 UTC (rev 57593)
@@ -93,6 +93,27 @@
                 raise GException(_("Map <%s> not found.") % name)
     return newNames
 
+
+def getRegisteredMaps(timeseries, etype):
+    """!Returns list of maps registered in dataset"""
+    timeseriesMaps = []
+    if etype == 'strds':
+        sp = tgis.SpaceTimeRasterDataset(ident=timeseries)
+    elif etype == 'stvds':
+        sp = tgis.SpaceTimeVectorDataset(ident=timeseries)
+
+    if sp.is_in_db() == False:
+        raise GException(_("Space time dataset <%s> not found.") % timeseries)
+        
+    sp.select()
+    rows = sp.get_registered_maps(columns="id", where=None, order="start_time", dbif=None)
+    timeseriesMaps = []
+    if rows:
+        for row in rows:
+            timeseriesMaps.append(row["id"])
+    return timeseriesMaps
+
+
 def ComputeScaledRect(sourceSize, destSize):
     """!Fits source rectangle into destination rectangle
     by scaling and centering.



More information about the grass-commit mailing list