/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/view.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/UI/view.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1652 by bh, Mon Aug 25 15:59:58 2003 UTC revision 2454 by bh, Mon Dec 13 18:26:11 2004 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003, 2004 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  # Frank Koormann <[email protected]>  # Frank Koormann <[email protected]>
# Line 10  Line 10 
10  Classes for display of a map and interaction with it  Classes for display of a map and interaction with it
11  """  """
12    
13  __version__ = "$Revision$"  from __future__ import generators
14    
15  from Thuban import _  __version__ = "$Revision$"
16    # $Source$
17    # $Id$
18    
19  import os.path  import os.path
20    import time
21    import traceback
22    
23  from wxPython.wx import wxWindow, \  from wxPython.wx import wxWindow, \
24       wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\       wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\
# Line 28  if wxPlatform == '__WXMSW__': Line 32  if wxPlatform == '__WXMSW__':
32    
33  from wxPython import wx  from wxPython import wx
34    
35    from Thuban import _
36    
37  from Thuban.Model.messages import MAP_LAYERS_CHANGED, LAYER_CHANGED, \  from Thuban.Model.messages import MAP_LAYERS_CHANGED, LAYER_CHANGED, \
38       LAYER_VISIBILITY_CHANGED       LAYER_VISIBILITY_CHANGED
39    
# Line 49  class CanvasPanTool(PanTool): Line 55  class CanvasPanTool(PanTool):
55              width, height = self.view.GetSizeTuple()              width, height = self.view.GetSizeTuple()
56    
57              bitmapdc = wx.wxMemoryDC()              bitmapdc = wx.wxMemoryDC()
58              bitmapdc.SelectObject(self.view.bitmap)              bitmapdc.SelectObject(self.view.PreviewBitmap())
59    
60              dc = self.view.drag_dc              dc = self.view.drag_dc
61              dc.Blit(0, 0, width, height, bitmapdc, sx - x, sy - y)              dc.Blit(0, 0, width, height, bitmapdc, sx - x, sy - y)
# Line 85  class MapPrintout(wx.wxPrintout): Line 91  class MapPrintout(wx.wxPrintout):
91                                                      self.canvas.GetSizeTuple(),                                                      self.canvas.GetSizeTuple(),
92                                                      self.GetPageSizePixels())                                                      self.GetPageSizePixels())
93          resx, resy = self.GetPPIPrinter()          resx, resy = self.GetPPIPrinter()
         renderer = PrinterRenderer(dc, scale, offset, resolution = resy)  
         x, y, width, height = self.region  
94          canvas_scale = self.canvas.scale          canvas_scale = self.canvas.scale
95          renderer.RenderMap(self.map,          x, y, width, height = self.region
96                             (0,0,          renderer = PrinterRenderer(dc, self.map, scale, offset,
97                                  (width/canvas_scale)*scale,                                     region = (mapregion[0], mapregion[1],
98                                  (height/canvas_scale)*scale),                                               (width/canvas_scale)*scale,
99                                  mapregion,                                               (height/canvas_scale)*scale),
100                             self.selected_layer, self.selected_shapes)                                     resolution = resy,
101                                       destination_region = mapregion)
102            renderer.RenderMap(self.selected_layer, self.selected_shapes)
103          return True          return True
104    
105    
106  class MapCanvas(wxWindow, ViewPort):  class MapCanvas(wxWindow, ViewPort):
107    
108      """A widget that displays a map and offers some interaction"""      """A widget that displays a map and offers some interaction"""
# Line 108  class MapCanvas(wxWindow, ViewPort): Line 115  class MapCanvas(wxWindow, ViewPort):
115    
116          # the bitmap serving as backing store          # the bitmap serving as backing store
117          self.bitmap = None          self.bitmap = None
118            # the monochrome bitmap with the selection if any
119            self.selection_bitmap = None
120    
121          self.backgroundColor = wx.wxWHITE_BRUSH          self.backgroundColor = wx.wxWHITE_BRUSH
122    
123          # Set to true if there ever is an error during redraw. There          # The rendering iterator object. Used when rendering
124          # should never be errors, but unfortunately bugs happen.          # incrementally
125          self.error_on_redraw = 0          self.render_iter = None
126    
127          # subscribe the WX events we're interested in          # subscribe the WX events we're interested in
128          EVT_PAINT(self, self.OnPaint)          EVT_PAINT(self, self.OnPaint)
# Line 128  class MapCanvas(wxWindow, ViewPort): Line 137  class MapCanvas(wxWindow, ViewPort):
137          wxWindow.__del__(self)          wxWindow.__del__(self)
138          ViewPort.__del__(self)          ViewPort.__del__(self)
139    
140        def PreviewBitmap(self):
141            return self.bitmap
142    
143      def PanTool(self):      def PanTool(self):
144          """Start the canvas pan tool"""          """Start the canvas pan tool"""
145          self.SelectTool(CanvasPanTool(self))          self.SelectTool(CanvasPanTool(self))
# Line 152  class MapCanvas(wxWindow, ViewPort): Line 164  class MapCanvas(wxWindow, ViewPort):
164    
165      def OnPaint(self, event):      def OnPaint(self, event):
166          dc = wxPaintDC(self)          dc = wxPaintDC(self)
   
167          if self.Map() is not None and self.Map().HasLayers():          if self.Map() is not None and self.Map().HasLayers():
168              if self.bitmap in (None, -1):              if self.bitmap is not None:
                 # set the flag that we should redraw the  
                 # bitmap in idle time  
                 self.bitmap = -1  
             else:  
                 # blit the bitmap to the screen  
169                  dc.BeginDrawing()                  dc.BeginDrawing()
170                  dc.DrawBitmap(self.bitmap, 0, 0)                  dc.DrawBitmap(self.bitmap, 0, 0)
171                    if self.selection_bitmap is not None:
172                        dc.DrawBitmap(self.selection_bitmap, 0, 0, True)
173                  dc.EndDrawing()                  dc.EndDrawing()
174          else:          else:
175              # If we've got no map or if the map is empty, simply clear              # If we've got no map or if the map is empty, simply clear
# Line 178  class MapCanvas(wxWindow, ViewPort): Line 186  class MapCanvas(wxWindow, ViewPort):
186    
187      def OnIdle(self, event):      def OnIdle(self, event):
188          """Idle handler. Redraw the bitmap if necessary"""          """Idle handler. Redraw the bitmap if necessary"""
189            if (self.Map() is not None
190                and (self.bitmap is None
191                     or self.render_iter is not None
192                     or (self.HasSelectedShapes()
193                         and self.selection_bitmap is None))):
194                event.RequestMore(self._do_redraw())
195    
196          if self.bitmap != -1:      def _do_redraw(self):
197              return          """Redraw a bit and return whether this method has to be called again.
         if self.error_on_redraw:  
             return  
198    
199          wxBeginBusyCursor()          Called by OnIdle to handle the actual redraw. Redraw is
200          try:          incremental for both the bitmap with the normal layers and the
201            bitmap with the selection.
202            """
203            finished = False
204            if self.render_iter is not None:
205              try:              try:
206                  self._do_redraw()                  if self.render_iter.next():
207                        # Redraw if the last preview redraw was some time
208                        # ago and the user is not currently dragging the
209                        # mouse because redrawing would interfere with what
210                        # the current tool is drawing on the window.
211                        if not self.dragging \
212                               and time.time() - self.render_last_preview > 0.5:
213                            client_dc = wxClientDC(self)
214                            client_dc.BeginDrawing()
215                            client_dc.DrawBitmap(self.bitmap, 0, 0)
216                            client_dc.EndDrawing()
217                            self.render_last_preview = time.time()
218                    else:
219                        self.render_iter = None
220                        # Redraw if not dragging because redrawing would
221                        # interfere with what the current tool is drawing on
222                        # the window.
223                        if not self.dragging:
224                            self.redraw()
225                        finished = True
226                except StopIteration:
227                    finished = True
228                    self.render_iter = None
229              except:              except:
230                  self.error_on_redraw = True                  finished = True
231                  raise                  self.render_iter = None
232          finally:                  traceback.print_exc()
233              wxEndBusyCursor()          else:
234                self.render_iter = self._render_iterator()
235                self.render_last_preview = time.time()
236            return not finished
237    
238      def _do_redraw(self):      def _render_iterator(self):
         """Called by OnIdle to do the actual redraw.  
         """  
239          width, height = self.GetSizeTuple()          width, height = self.GetSizeTuple()
   
         bitmap = wx.wxEmptyBitmap(width, height)  
240          dc = wx.wxMemoryDC()          dc = wx.wxMemoryDC()
         dc.SelectObject(bitmap)  
         dc.BeginDrawing()  
241    
242          dc.SetBackground(self.backgroundColor)          render_start = time.time()
         dc.Clear()  
243    
244          selected_layer = self.selection.SelectedLayer()          if self.bitmap is None:
245          selected_shapes = self.selection.SelectedShapes()              self.bitmap = wx.wxEmptyBitmap(width, height)
246                dc.SelectObject(self.bitmap)
247                dc.BeginDrawing()
248    
249          # draw the map into the bitmap              dc.SetBackground(self.backgroundColor)
250          renderer = ScreenRenderer(dc, self.scale, self.offset)              dc.Clear()
251    
252          # Pass the entire bitmap as update region to the renderer.              # draw the map into the bitmap
253          # We're redrawing the whole bitmap, after all.              renderer = ScreenRenderer(dc, self.Map(), self.scale, self.offset,
254          renderer.RenderMap(self.Map(), (0, 0, width, height),                                        (0, 0, width, height))
255                             selected_layer, selected_shapes)              for cont in renderer.RenderMapIncrementally():
256                    yield True
257    
258          dc.EndDrawing()              dc.EndDrawing()
259          dc.SelectObject(wx.wxNullBitmap)              dc.SelectObject(wx.wxNullBitmap)
260    
261          self.bitmap = bitmap          if self.HasSelectedShapes() and self.selection_bitmap is None:
262          # This causes a paint event that then draws the bitmap              bitmap = wx.wxEmptyBitmap(width, height)
263          self.redraw()              dc.SelectObject(bitmap)
264                dc.BeginDrawing()
265                dc.SetBackground(wx.wxWHITE_BRUSH)
266                dc.Clear()
267    
268                renderer = ScreenRenderer(dc, self.Map(), self.scale, self.offset,
269                                          (0, 0, width, height))
270                layer = self.SelectedLayer()
271                shapes = self.selection.SelectedShapes()
272                for cont in renderer.draw_selection_incrementally(layer, shapes):
273                    yield True
274    
275                dc.EndDrawing()
276                dc.SelectObject(wx.wxNullBitmap)
277    
278                bitmap.SetMask(wx.wxMaskColour(bitmap, wx.wxWHITE))
279                self.selection_bitmap = bitmap
280    
281            yield False
282    
283      def Export(self):      def Export(self):
284    
# Line 246  class MapCanvas(wxWindow, ViewPort): Line 301  class MapCanvas(wxWindow, ViewPort):
301              selected_layer = self.selection.SelectedLayer()              selected_layer = self.selection.SelectedLayer()
302              selected_shapes = self.selection.SelectedShapes()              selected_shapes = self.selection.SelectedShapes()
303    
             renderer = ExportRenderer(dc, scale, offset)  
   
             # Pass the entire bitmap as update region to the renderer.  
             # We're redrawing the whole bitmap, after all.  
304              width, height = self.GetSizeTuple()              width, height = self.GetSizeTuple()
305              renderer.RenderMap(self.Map(),              renderer = ExportRenderer(dc, self.Map(), scale, offset,
306                                  (0,0,                                        region = (0, 0,
307                                      (width/self.scale)*scale,                                                  (width/self.scale)*scale,
308                                      (height/self.scale)*scale),                                                  (height/self.scale)*scale),
309                                  mapregion,                                        destination_region = mapregion)
310                                  selected_layer, selected_shapes)              renderer.RenderMap(selected_layer, selected_shapes)
311    
312              dc.EndDrawing()              dc.EndDrawing()
313              dc.Close()              dc.Close()
314          dlg.Destroy()          dlg.Destroy()
# Line 277  class MapCanvas(wxWindow, ViewPort): Line 329  class MapCanvas(wxWindow, ViewPort):
329    
330      def full_redraw(self, *args):      def full_redraw(self, *args):
331          self.bitmap = None          self.bitmap = None
332            self.selection_bitmap = None
333            self.render_iter = None
334            self.redraw()
335    
336        def redraw_selection(self, *args):
337            self.selection_bitmap = None
338            self.render_iter = None
339          self.redraw()          self.redraw()
340    
341      def map_projection_changed(self, map, old_proj):      def map_projection_changed(self, map, old_proj):
# Line 350  class MapCanvas(wxWindow, ViewPort): Line 409  class MapCanvas(wxWindow, ViewPort):
409          """Receiver for the SHAPES_SELECTED messages. Redraw the map."""          """Receiver for the SHAPES_SELECTED messages. Redraw the map."""
410          # The selection object takes care that it only issues          # The selection object takes care that it only issues
411          # SHAPES_SELECTED messages when the set of selected shapes has          # SHAPES_SELECTED messages when the set of selected shapes has
412          # actually changed, so we can do a full redraw unconditionally.          # actually changed, so we can do a full redraw of the
413          # FIXME: We should perhaps try to limit the redraw to the are          # selection_bitmap unconditionally.
         # actually covered by the shapes before and after the selection  
         # change.  
414          ViewPort.shape_selected(self, layer, shape)          ViewPort.shape_selected(self, layer, shape)
415          self.full_redraw()          self.redraw_selection()
416    
417      def GetTextExtent(self, text):      def GetTextExtent(self, text):
418          dc = wxClientDC(self)          dc = wxClientDC(self)

Legend:
Removed from v.1652  
changed lines
  Added in v.2454

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26