浏览代码

merge more update map requests into one according to delay limit

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@59204 15284696-431f-4ddb-bdfa-cd5b030d7da7
Štěpán Turek 11 年之前
父节点
当前提交
071914b95a
共有 4 个文件被更改,包括 96 次插入14 次删除
  1. 4 5
      gui/wxpython/gui_core/gselect.py
  2. 7 2
      gui/wxpython/iscatt/controllers.py
  3. 5 2
      gui/wxpython/lmgr/frame.py
  4. 80 5
      gui/wxpython/mapwin/buffered.py

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

@@ -2144,7 +2144,7 @@ class CoordinatesSelect(wx.Panel):
                                       btnId=self.buttonInsCoords.GetId(), 
                                       btnId=self.buttonInsCoords.GetId(), 
                                       toggleHandler=self.buttonInsCoords.SetValue)
                                       toggleHandler=self.buttonInsCoords.SetValue)
         self._doLayout()
         self._doLayout()
-        self.coordsField.Bind(wx.EVT_TEXT, lambda event : self._draw())
+        self.coordsField.Bind(wx.EVT_TEXT, lambda event : self._draw(delay=1))
         
         
     def _doLayout(self):
     def _doLayout(self):
         self.dialogSizer = wx.BoxSizer(wx.HORIZONTAL)
         self.dialogSizer = wx.BoxSizer(wx.HORIZONTAL)
@@ -2174,12 +2174,11 @@ class CoordinatesSelect(wx.Panel):
                 self.registered = False
                 self.registered = False
                 return
                 return
 
 
-
     def drawCleanUp(self):
     def drawCleanUp(self):
         if self.drawMapWin:
         if self.drawMapWin:
             self.drawMapWin.UnregisterGraphicsToDraw(self.pointsToDraw)
             self.drawMapWin.UnregisterGraphicsToDraw(self.pointsToDraw)
 
 
-    def _draw(self):
+    def _draw(self, delay):
         """!Draws points representing inserted coordinates in mapwindow."""
         """!Draws points representing inserted coordinates in mapwindow."""
         if self.drawMapWin != self.mapWin:
         if self.drawMapWin != self.mapWin:
             self.drawCleanUp()
             self.drawCleanUp()
@@ -2198,7 +2197,7 @@ class CoordinatesSelect(wx.Panel):
                         i = i * 2
                         i = i * 2
                         self.pointsToDraw.AddItem(coords=(coords[i], coords[i + 1]))
                         self.pointsToDraw.AddItem(coords=(coords[i], coords[i + 1]))
 
 
-                self._giface.updateMap.emit(render=False, renderVector=False)
+                self._giface.updateMap.emit(render=False, renderVector=False, delay=delay)
 
 
     def _getCoords(self):
     def _getCoords(self):
         """!Get list of coordinates.
         """!Get list of coordinates.
@@ -2226,7 +2225,7 @@ class CoordinatesSelect(wx.Panel):
         value = prevCoords + str(e) + "," + str(n)
         value = prevCoords + str(e) + "," + str(n)
         self.coordsField.SetValue(value)
         self.coordsField.SetValue(value)
 
 
-        self._draw()
+        self._draw(delay=0)
 
 
     def OnClose(self):
     def OnClose(self):
         """!Unregistrates _onMapClickHandler from mapWin"""
         """!Unregistrates _onMapClickHandler from mapWin"""

+ 7 - 2
gui/wxpython/iscatt/controllers.py

@@ -1111,6 +1111,8 @@ class IClassConnection:
             bands = res.split('\n')
             bands = res.split('\n')
             self.scatt_mgr.SetBands(bands)
             self.scatt_mgr.SetBands(bands)
 
 
+
+#TODO uses it also BufferedMapWindow class -> move to core?
 class gThread(threading.Thread, wx.EvtHandler):
 class gThread(threading.Thread, wx.EvtHandler):
     """!Thread for scatter plot backend"""
     """!Thread for scatter plot backend"""
     requestId = 0
     requestId = 0
@@ -1140,7 +1142,10 @@ class gThread(threading.Thread, wx.EvtHandler):
         """!Run command in queue
         """!Run command in queue
 
 
         @param args unnamed command arguments
         @param args unnamed command arguments
-        @param kwds named command arguments
+        @param kwds named command arguments,
+               keyword 'callable' represents function to be run,
+               keyword 'ondone' represents function to be 
+                       called after the callable is done
 
 
         @return request id in queue
         @return request id in queue
         """
         """
@@ -1171,7 +1176,7 @@ class gThread(threading.Thread, wx.EvtHandler):
 
 
             ret = None
             ret = None
             exception = None
             exception = None
-            time.sleep(.1)
+            time.sleep(.01)
 
 
             if self.terminate:
             if self.terminate:
                 return
                 return

+ 5 - 2
gui/wxpython/lmgr/frame.py

@@ -1748,9 +1748,12 @@ class GMFrame(wx.Frame):
                                        lcmd = cmd,
                                        lcmd = cmd,
                                        lgroup = None)
                                        lgroup = None)
 
 
-    def _updateCurrentMap(self):
+    def _updateCurrentMap(self, **kwargs):
         """!Updates map of the current map window."""
         """!Updates map of the current map window."""
-        self.GetMapDisplay().GetWindow().UpdateMap()
+        if kwargs.has_key('delay'):
+            self.GetMapDisplay().GetWindow().UpdateMap(delay=kwargs['delay'])
+        else:
+            self.GetMapDisplay().GetWindow().UpdateMap()
 
 
     def OnMapCreated(self, name, ltype, add=None):
     def OnMapCreated(self, name, ltype, add=None):
         """!Decides wheter the map should be added to layer tree."""
         """!Decides wheter the map should be added to layer tree."""

+ 80 - 5
gui/wxpython/mapwin/buffered.py

@@ -33,6 +33,7 @@ from grass.pydispatch.signal import Signal
 
 
 import grass.script as grass
 import grass.script as grass
 
 
+
 from gui_core.dialogs   import SavedRegion
 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
@@ -41,6 +42,7 @@ 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
 from mapwin.graphics import GraphicsSet
+from iscatt.controllers import gThread
 
 
 try:
 try:
     import grass.lib.gis as gislib
     import grass.lib.gis as gislib
@@ -90,6 +92,20 @@ class BufferedMapWindow(MapWindowBase, wx.Window):
         # ID of poly line resulting from cumulative rubber band lines (e.g. measurement)
         # ID of poly line resulting from cumulative rubber band lines (e.g. measurement)
         self.plineid = None
         self.plineid = None
 
 
+        # following class members deals with merging more updateMap request
+        # into one UpdateMap process 
+
+        # thread where timer for measuring delay limit
+        self.renderTimingThr = gThread();
+        # relevant timer id given by the thread
+        self.timerRunId = None
+        # time, of last updateMap request
+        self.lastUpdateMapReq = None
+        # defines time limit for waiting for another update request
+        self.updDelay = 0
+        # holds information about level of rendering during the delay limit
+        self.render = self.renderVector = False 
+
         # Emitted when zoom of a window is changed
         # Emitted when zoom of a window is changed
         self.zoomChanged = Signal('BufferedWindow.zoomChanged')
         self.zoomChanged = Signal('BufferedWindow.zoomChanged')
 
 
@@ -169,7 +185,7 @@ class BufferedMapWindow(MapWindowBase, wx.Window):
         
         
         # list for registration of graphics to draw
         # list for registration of graphics to draw
         self.graphicsSetList = []
         self.graphicsSetList = []
-        
+  
     def _definePseudoDC(self):
     def _definePseudoDC(self):
         """!Define PseudoDC objects to use
         """!Define PseudoDC objects to use
         """
         """
@@ -661,25 +677,84 @@ class BufferedMapWindow(MapWindowBase, wx.Window):
     def IsAlwaysRenderEnabled(self):
     def IsAlwaysRenderEnabled(self):
         return self.alwaysRender
         return self.alwaysRender
 
 
-    def UpdateMap(self, render = True, renderVector = True):
+    def UpdateMap(self, render=True, renderVector=True, delay=0.0):
         """!Updates the canvas anytime there is a change to the
         """!Updates the canvas anytime there is a change to the
         underlaying images or to the geometry of the canvas.
         underlaying images or to the geometry of the canvas.
         
         
         This method should not be called directly.
         This method should not be called directly.
 
 
-        @todo change direct calling of UpdateMap method to emittig grass
+        @todo change direct calling of UpdateMap method to emitting grass
         interface updateMap signal
         interface updateMap signal
 
 
+        @todo consider using strong/weak signal instead of delay limit in giface
+
         @param render re-render map composition
         @param render re-render map composition
         @param renderVector re-render vector map layer enabled for editing (used for digitizer)
         @param renderVector re-render vector map layer enabled for editing (used for digitizer)
+        @param delay defines time threshold  in seconds for postponing rendering to merge more update requests. 
+               If another request do come within the limit, rendering is delayed again.
+               Next delay limit is chosen according to the lowest delay value of all requests 
+               which have come during waiting period.
+               Arguments 'render' and 'renderVector' have priority for True. It means that 
+               if more UpdateMap requests come within waiting period and at least one request
+               has argument set for True, map will be updated with the True value of the argument.
+        """
+
+        if self.timerRunId is None or delay < self.updDelay:
+            self.updDelay = delay
+        
+        if render:
+            self.render = render
+        if renderVector:
+            self.renderVector = renderVector
+
+        updTime = time.time()
+        self.lastUpdateMapReq = updTime
+
+        if self.updDelay == 0.0:
+            self._runUpdateMap()
+        else:
+            self.timerRunId = self.renderTimingThr.GetId()
+            self.renderTimingThr.Run(callable=self._timingFunction, 
+                                     ondone=self._onUpdateMap, 
+                                     pid=self.timerRunId)
+
+    def _timingFunction(self, pid):
+        """!Timer measuring elapsed time, since last update request.
+
+        It terminates, when delay limit is exceeded. 
+
+        @param pid - id which defines whether it is newest timer, or there is another one 
+                     (representing newer Update map request).
+                     If it is not the newest, it is terminated.
+        """
+        while True:
+            updTime = time.time()
+            time.sleep(.01)
+            if updTime > self.lastUpdateMapReq + self.updDelay or pid != self.timerRunId:
+                return
+
+    def _onUpdateMap(self, event):
+        if self.timerRunId == event.pid:
+            self._runUpdateMap()
+
+    def _runUpdateMap(self):
+        """!Update map when delay limit is over."""
+        self.timerRunId = None
+        self._updateM(self.render, self.renderVector)
+        self.render = self.renderVector = False
+
+    def _updateM(self, render=True, renderVector=True):
+        """
+        @see method UpdateMap for arguments description.
         """
         """
-        start = time.clock()
         self.resize = False
         self.resize = False
+        start = time.clock()
         
         
         # was if self.Map.cmdfile and ...
         # was if self.Map.cmdfile and ...
         if self.IsAlwaysRenderEnabled() and self.img is None:
         if self.IsAlwaysRenderEnabled() and self.img is None:
             render = True
             render = True
         
         
+
         #
         #
         # render background image if needed
         # render background image if needed
         #
         #
@@ -1160,7 +1235,7 @@ class BufferedMapWindow(MapWindowBase, wx.Window):
         self.Zoom(begin, end, zoomtype)
         self.Zoom(begin, end, zoomtype)
         
         
         # redraw map
         # redraw map
-        self.UpdateMap()
+        self.UpdateMap(delay=0.2)
 
 
         self.Refresh()
         self.Refresh()
         self.processMouse = True
         self.processMouse = True