Revision: 5907
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5907&view=rev
Author:   pkienzle
Date:     2008-07-28 07:26:47 +0000 (Mon, 28 Jul 2008)

Log Message:
-----------
Render Wx backends only when necessary

Modified Paths:
--------------
    trunk/matplotlib/lib/matplotlib/backends/backend_wx.py
    trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py      2008-07-27 
20:42:13 UTC (rev 5906)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py      2008-07-28 
07:26:47 UTC (rev 5907)
@@ -700,12 +700,11 @@
         self.bitmap =wx.EmptyBitmap(w, h)
         DEBUG_MSG("__init__() - bitmap w:%d h:%d" % (w,h), 2, self)
         # TODO: Add support for 'point' inspection and plot navigation.
-        self._isRealized = False
-        self._isConfigured = False
-        self._printQued = []
+        self._isDrawn = False
 
         bind(self, wx.EVT_SIZE, self._onSize)
         bind(self, wx.EVT_PAINT, self._onPaint)
+        bind(self, wx.EVT_ERASE_BACKGROUND, self._onEraseBackground)
         bind(self, wx.EVT_KEY_DOWN, self._onKeyDown)
         bind(self, wx.EVT_KEY_UP, self._onKeyUp)
         bind(self, wx.EVT_RIGHT_DOWN, self._onRightButtonDown)
@@ -718,21 +717,12 @@
         bind(self, wx.EVT_MOTION, self._onMotion)
         bind(self, wx.EVT_LEAVE_WINDOW, self._onLeave)
         bind(self, wx.EVT_IDLE, self._onIdle)
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
 
         self.macros = {} # dict from wx id to seq of macros
 
         self.Printer_Init()
 
-        # Create an timer for handling draw_idle requests
-        # If there are events pending when the timer is
-        # complete, reset the timer and continue.  The
-        # alternative approach, binding to wx.EVT_IDLE,
-        # doesn't behave as nicely.
-        #self.idletimer = wx.CallLater(1,self._onDrawIdle)
-        self.idletimer = wx.FutureCall(1,self._onDrawIdle)
-        # FutureCall is a backwards-compatible alias;
-        # CallLater became available in 2.7.1.1.
-
     def Destroy(self, *args, **kwargs):
         wx.Panel.Destroy(self, *args, **kwargs)
 
@@ -887,20 +877,35 @@
         self.gui_repaint()
 
 
-    def draw_idle(self, *args, **kwargs):
+    def draw_idle(self):
         """
         Delay rendering until the GUI is idle.
         """
         DEBUG_MSG("draw_idle()", 1, self)
-        self.idletimer.Restart(50, *args, **kwargs)  # Delay by 50 ms
+        self._isDrawn = False  # Force redraw
+        # Create a timer for handling draw_idle requests
+        # If there are events pending when the timer is
+        # complete, reset the timer and continue.  The
+        # alternative approach, binding to wx.EVT_IDLE,
+        # doesn't behave as nicely.
+        if hasattr(self,'_idletimer'):
+            self._idletimer.Restart(50)
+        else:
+            self._idletimer = wx.FutureCall(50,self._onDrawIdle)
+            # FutureCall is a backwards-compatible alias;
+            # CallLater became available in 2.7.1.1.
 
     def _onDrawIdle(self, *args, **kwargs):
-        if False and wx.GetApp().Pending():
-            self.idletimer.Restart(5, *args, **kwargs)
+        if wx.GetApp().Pending():
+            self._idletimer.Restart(50, *args, **kwargs)
         else:
-            self.draw(*args, **kwargs)
+            del self._idletimer
+            # GUI event or explicit draw call may already
+            # have caused the draw to take place
+            if not self._isDrawn:
+                self.draw(*args, **kwargs)
 
-    def draw(self, repaint=True):
+    def draw(self, drawDC=None):
         """
         Render the figure using RendererWx instance renderer, or using a
         previously defined renderer if none is specified.
@@ -908,8 +913,8 @@
         DEBUG_MSG("draw()", 1, self)
         self.renderer = RendererWx(self.bitmap, self.figure.dpi)
         self.figure.draw(self.renderer)
-        if repaint:
-            self.gui_repaint()
+        self._isDrawn = True
+        self.gui_repaint(drawDC=drawDC)
 
     def flush_events(self):
         wx.Yield()
@@ -988,7 +993,6 @@
         """
         DEBUG_MSG("gui_repaint()", 1, self)
         if self.IsShownOnScreen():
-
             if drawDC is None:
                 drawDC=wx.ClientDC(self)
 
@@ -996,6 +1000,8 @@
             drawDC.DrawBitmap(self.bitmap, 0, 0)
             drawDC.EndDrawing()
             #wx.GetApp().Yield()
+        else:
+            pass
 
     filetypes = FigureCanvasBase.filetypes.copy()
     filetypes['bmp'] = 'Windows bitmap'
@@ -1007,6 +1013,16 @@
     filetypes['tiff'] = 'Tagged Image Format File'
     filetypes['xpm'] = 'X pixmap'
 
+    def print_figure(self, filename, *args, **kwargs):
+        # Use pure Agg renderer to draw
+        FigureCanvasBase.print_figure(self, filename, *args, **kwargs)
+        # Restore the current view; this is needed because the
+        # artist contains methods rely on particular attributes
+        # of the rendered figure for determining things like
+        # bounding boxes.
+        if self._isDrawn:
+            self.draw()
+
     def print_bmp(self, filename, *args, **kwargs):
         return self._print_image(filename, wx.BITMAP_TYPE_BMP, *args, **kwargs)
 
@@ -1034,8 +1050,6 @@
         width = int(math.ceil(width))
         height = int(math.ceil(height))
 
-        # Following performs the same function as realize(), but without
-        # setting GUI attributes - so GUI draw() will render correctly
         self.bitmap = wx.EmptyBitmap(width, height)
         renderer = RendererWx(self.bitmap, self.figure.dpi)
 
@@ -1048,9 +1062,6 @@
         if is_string_like(filename):
             if not self.bitmap.SaveFile(filename, filetype):
                 DEBUG_MSG('print_figure() file save error', 4, self)
-                # note the error must be displayed here because trapping
-                # the error on a call or print_figure may not work because
-                # printing can be qued and called from realize
                 raise RuntimeError('Could not save figure to %s\n' % 
(filename))
         elif is_writable_file_like(filename):
             if not self.bitmap.ConvertToImage().SaveStream(filename, filetype):
@@ -1063,40 +1074,35 @@
         # Note: draw is required here since bits of state about the
         # last renderer are strewn about the artist draw methods.  Do
         # not remove the draw without first verifying that these have
-        # been cleaned up.
-        self.draw()
+        # been cleaned up.  The artist contains() methods will fail
+        # otherwise.
+        if self._isDrawn:
+            self.draw()
         self.Refresh()
 
     def get_default_filetype(self):
         return 'png'
 
-    def realize(self):
-        """
-        This method will be called when the system is ready to draw,
-        eg when a GUI window is realized
-        """
-        DEBUG_MSG("realize()", 1, self)
-        self._isRealized = True
-        for fname, dpi, facecolor, edgecolor in self._printQued:
-            self.print_figure(fname, dpi, facecolor, edgecolor)
-        self._printQued = []
-
-
-
     def _onPaint(self, evt):
         """
         Called when wxPaintEvt is generated
         """
 
         DEBUG_MSG("_onPaint()", 1, self)
-        if not self._isRealized:
-            self.realize()
-        # Render to the bitmap
-        self.draw(repaint=False)
-        # Update the display using a PaintDC
-        self.gui_repaint(drawDC=wx.PaintDC(self))
+        drawDC = wx.PaintDC(self)
+        if not self._isDrawn:
+            self.draw(drawDC=drawDC)
+        else:
+            self.gui_repaint(drawDC=drawDC)
         evt.Skip()
 
+    def _onEraseBackground(self, evt):
+        """
+        Called when window is redrawn; since we are blitting the entire
+        image, we can leave this blank to suppress flicker.
+        """
+        pass
+
     def _onSize(self, evt):
         """
         Called when wxEventSize is generated.
@@ -1109,21 +1115,19 @@
         # Create a new, correctly sized bitmap
         self._width, self._height = self.GetClientSize()
         self.bitmap =wx.EmptyBitmap(self._width, self._height)
+        self._isDrawn = False
 
         if self._width <= 1 or self._height <= 1: return # Empty figure
 
-        # Scale the displayed image (but don't update self.figsize)
-        if not self._isConfigured:
-            self._isConfigured = True
-
         dpival = self.figure.dpi
         winch = self._width/dpival
         hinch = self._height/dpival
         self.figure.set_size_inches(winch, hinch)
 
-        if self._isRealized:
-            self.draw_idle()
-        evt.Skip()
+        # Rendering will happen on the associated paint event
+        # so no need to do anything here except to make sure
+        # the whole background is repainted.
+        self.Refresh(eraseBackground=False)
 
     def _get_key(self, evt):
 
@@ -1288,8 +1292,6 @@
 
     for figwin in Gcf.get_all_fig_managers():
         figwin.frame.Show()
-        figwin.canvas.realize()
-        figwin.canvas.draw()
 
     if show._needmain and not matplotlib.is_interactive():
         # start the wxPython gui event if there is not already one running
@@ -1316,7 +1318,6 @@
     frame = FigureFrameWx(num, fig)
     figmgr = frame.get_figure_manager()
     if matplotlib.is_interactive():
-        figmgr.canvas.realize()
         figmgr.frame.Show()
 
     return figmgr
@@ -1436,8 +1437,6 @@
 
         def showfig(*args):
             frame.Show()
-            canvas.realize()
-            canvas.draw()
 
         # attach a show method to the figure
         self.canvas.figure.show = showfig
@@ -1732,7 +1731,6 @@
             except Exception, e:
                 error_msg_wx(str(e))
 
-
     def set_cursor(self, cursor):
         cursor =wx.StockCursor(cursord[cursor])
         self.canvas.SetCursor( cursor )
@@ -1999,9 +1997,6 @@
             direction = -1
         self.button_fn(direction)
 
-    def _onRedraw(self, evt):
-        self.canvas.draw()
-
     _onSave = NavigationToolbar2Wx.save
 
     def _onClose(self, evt):

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py   2008-07-27 
20:42:13 UTC (rev 5906)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py   2008-07-28 
07:26:47 UTC (rev 5907)
@@ -52,7 +52,7 @@
     size.
     """
 
-    def draw(self, repaint=True):
+    def draw(self, drawDC=None):
         """
         Render the figure using agg.
         """
@@ -60,8 +60,8 @@
         FigureCanvasAgg.draw(self)
 
         self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
-        if repaint:
-            self.gui_repaint()
+        self._isDrawn = True
+        self.gui_repaint(drawDC=drawDC)
 
     def blit(self, bbox=None):
         """
@@ -97,8 +97,14 @@
     filetypes = FigureCanvasAgg.filetypes
 
     def print_figure(self, filename, *args, **kwargs):
+        # Use pure Agg renderer to draw
         FigureCanvasAgg.print_figure(self, filename, *args, **kwargs)
-        self.draw()
+        # Restore the current view; this is needed because the
+        # artist contains methods rely on particular attributes
+        # of the rendered figure for determining things like
+        # bounding boxes.
+        if self._isDrawn:
+            self.draw()
 
 class NavigationToolbar2WxAgg(NavigationToolbar2Wx):
     def get_canvas(self, frame, fig):
@@ -119,7 +125,6 @@
     frame = FigureFrameWxAgg(num, fig)
     figmgr = frame.get_figure_manager()
     if matplotlib.is_interactive():
-        figmgr.canvas.realize()
         figmgr.frame.Show()
     return figmgr
 


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-checkins mailing list
Matplotlib-checkins@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to