/[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 1454 by bh, Fri Jul 18 14:41:04 2003 UTC revision 1866 by bh, Mon Oct 27 13:01:58 2003 UTC
# 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    
 import sys  
19  import os.path  import os.path
20    import time
21  from math import hypot  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,\
25       EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION, EVT_LEAVE_WINDOW, \       EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION, EVT_LEAVE_WINDOW, \
26       wxBITMAP_TYPE_XPM, wxCursor, wxPlatform, \       wxPlatform, wxBeginBusyCursor, wxEndBusyCursor, wxFileDialog, wxSAVE, \
      wxBeginBusyCursor, wxEndBusyCursor, wxFileDialog, wxSAVE, \  
27       wxOVERWRITE_PROMPT, wxID_OK       wxOVERWRITE_PROMPT, wxID_OK
28    
29  # Export related stuff  # Export related stuff
# Line 32  if wxPlatform == '__WXMSW__': Line 32  if wxPlatform == '__WXMSW__':
32    
33  from wxPython import wx  from wxPython import wx
34    
35  from wxproj import point_in_polygon_shape, shape_centroid  from Thuban import _
36    
37  from Thuban.Model.messages import \  from Thuban.Model.messages import MAP_LAYERS_CHANGED, LAYER_CHANGED, \
38       MAP_PROJECTION_CHANGED, MAP_LAYERS_CHANGED, \       LAYER_VISIBILITY_CHANGED
      LAYER_PROJECTION_CHANGED, LAYER_CHANGED, LAYER_VISIBILITY_CHANGED  
39    
40  from renderer import ScreenRenderer, ExportRenderer, PrinterRenderer  from renderer import ScreenRenderer, ExportRenderer, PrinterRenderer
41    
# Line 56  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 92  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 = (0, 0,
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 115  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            # The rendering iterator object. Used when rendering
124            # incrementally
125            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)
129          EVT_LEFT_DOWN(self, self.OnLeftDown)          EVT_LEFT_DOWN(self, self.OnLeftDown)
# Line 131  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 155  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 180  class MapCanvas(wxWindow, ViewPort): Line 185  class MapCanvas(wxWindow, ViewPort):
185              dc.EndDrawing()              dc.EndDrawing()
186    
187      def OnIdle(self, event):      def OnIdle(self, event):
188          # render the screen if necessary          """Idle handler. Redraw the bitmap if necessary"""
189            if (self.bitmap is None
190                or self.render_iter is not None
191                or (self.HasSelectedShapes()
192                    and self.selection_bitmap is None)):
193                event.RequestMore(self._do_redraw())
194    
195        def _do_redraw(self):
196            """Redraw a bit and return whether this method has to be called again.
197    
198            Called by OnIdle to handle the actual redraw. Redraw is
199            incremental for both the bitmap with the normal layers and the
200            bitmap with the selection.
201            """
202            finished = False
203            if self.render_iter is not None:
204                try:
205                    if self.render_iter.next():
206                        # Redraw if the last preview redraw was some time
207                        # ago and the user is not currently dragging the
208                        # mouse because redrawing would interfere with what
209                        # the current tool is drawing on the window.
210                        if not self.dragging \
211                               and time.time() - self.render_last_preview > 0.5:
212                            client_dc = wxClientDC(self)
213                            client_dc.BeginDrawing()
214                            client_dc.DrawBitmap(self.bitmap, 0, 0)
215                            client_dc.EndDrawing()
216                            self.render_last_preview = time.time()
217                    else:
218                        self.render_iter = None
219                        # Redraw if not dragging because redrawing would
220                        # interfere with what the current tool is drawing on
221                        # the window.
222                        if not self.dragging:
223                            self.redraw()
224                        finished = True
225                except StopIteration:
226                    finished = True
227                    self.render_iter = None
228                except:
229                    finished = True
230                    self.render_iter = None
231                    traceback.print_exc()
232            else:
233                self.render_iter = self._render_iterator()
234                self.render_last_preview = time.time()
235            return not finished
236    
237          if self.bitmap != -1:      def _render_iterator(self):
238              return          width, height = self.GetSizeTuple()
239            dc = wx.wxMemoryDC()
240    
241          wxBeginBusyCursor()          render_start = time.time()
         try:  
             width, height = self.GetSizeTuple()  
242    
243              bitmap = wx.wxEmptyBitmap(width, height)          if self.bitmap is None:
244              dc = wx.wxMemoryDC()              self.bitmap = wx.wxEmptyBitmap(width, height)
245              dc.SelectObject(bitmap)              dc.SelectObject(self.bitmap)
246              dc.BeginDrawing()              dc.BeginDrawing()
247    
248              dc.SetBackground(self.backgroundColor)              dc.SetBackground(self.backgroundColor)
249              dc.Clear()              dc.Clear()
250    
             selected_layer = self.selection.SelectedLayer()  
             selected_shapes = self.selection.SelectedShapes()  
   
251              # draw the map into the bitmap              # draw the map into the bitmap
252              renderer = ScreenRenderer(dc, self.scale, self.offset)              renderer = ScreenRenderer(dc, self.Map(), self.scale, self.offset,
253                                          (0, 0, width, height))
254                for cont in renderer.RenderMapIncrementally():
255                    yield True
256    
257              # Pass the entire bitmap as update region to the renderer.              dc.EndDrawing()
258              # We're redrawing the whole bitmap, after all.              dc.SelectObject(wx.wxNullBitmap)
259              renderer.RenderMap(self.Map(), (0, 0, width, height),  
260                                 selected_layer, selected_shapes)          if self.HasSelectedShapes() and self.selection_bitmap is None:
261                bitmap = wx.wxEmptyBitmap(width, height)
262                dc.SelectObject(bitmap)
263                dc.BeginDrawing()
264                dc.SetBackground(wx.wxWHITE_BRUSH)
265                dc.Clear()
266    
267                renderer = ScreenRenderer(dc, self.Map(), self.scale, self.offset,
268                                          (0, 0, width, height))
269                layer = self.SelectedLayer()
270                shapes = self.selection.SelectedShapes()
271                for cont in renderer.draw_selection_incrementally(layer, shapes):
272                    yield True
273    
274              dc.EndDrawing()              dc.EndDrawing()
275              dc.SelectObject(wx.wxNullBitmap)              dc.SelectObject(wx.wxNullBitmap)
276    
277              self.bitmap = bitmap              bitmap.SetMask(wx.wxMaskColour(bitmap, wx.wxWHITE))
278          finally:              self.selection_bitmap = bitmap
             wxEndBusyCursor()  
             pass  
279    
280          # This causes a paint event that then draws the bitmap          yield False
         self.redraw()  
281    
282      def Export(self):      def Export(self):
283    
# Line 240  class MapCanvas(wxWindow, ViewPort): Line 300  class MapCanvas(wxWindow, ViewPort):
300              selected_layer = self.selection.SelectedLayer()              selected_layer = self.selection.SelectedLayer()
301              selected_shapes = self.selection.SelectedShapes()              selected_shapes = self.selection.SelectedShapes()
302    
303              renderer = ExportRenderer(dc, scale, offset)              renderer = ExportRenderer(dc, self.Map(), scale, offset,
304                                          region = (0, 0,
305                                                    (width/self.scale)*scale,
306                                                    (height/self.scale)*scale),
307                                          destination_region = mapregion)
308    
309              # Pass the entire bitmap as update region to the renderer.              # Pass the entire bitmap as update region to the renderer.
310              # We're redrawing the whole bitmap, after all.              # We're redrawing the whole bitmap, after all.
311              width, height = self.GetSizeTuple()              width, height = self.GetSizeTuple()
312              renderer.RenderMap(self.Map(),              renderer.RenderMap(selected_layer, selected_shapes)
                                 (0,0,  
                                     (width/self.scale)*scale,  
                                     (height/self.scale)*scale),  
                                 mapregion,  
                                 selected_layer, selected_shapes)  
313              dc.EndDrawing()              dc.EndDrawing()
314              dc.Close()              dc.Close()
315          dlg.Destroy()          dlg.Destroy()
# Line 271  class MapCanvas(wxWindow, ViewPort): Line 330  class MapCanvas(wxWindow, ViewPort):
330    
331      def full_redraw(self, *args):      def full_redraw(self, *args):
332          self.bitmap = None          self.bitmap = None
333            self.selection_bitmap = None
334            self.render_iter = None
335            self.redraw()
336    
337        def redraw_selection(self, *args):
338            self.selection_bitmap = None
339            self.render_iter = None
340          self.redraw()          self.redraw()
341    
342      def map_projection_changed(self, map, old_proj):      def map_projection_changed(self, map, old_proj):
# Line 295  class MapCanvas(wxWindow, ViewPort): Line 361  class MapCanvas(wxWindow, ViewPort):
361              self.drag_dc.SetLogicalFunction(wxINVERT)              self.drag_dc.SetLogicalFunction(wxINVERT)
362              self.drag_dc.SetBrush(wxTRANSPARENT_BRUSH)              self.drag_dc.SetBrush(wxTRANSPARENT_BRUSH)
363              self.tool.Show(self.drag_dc)              self.tool.Show(self.drag_dc)
364                self.CaptureMouse()
365              self.dragging = 1              self.dragging = 1
366    
367      def OnLeftUp(self, event):      def OnLeftUp(self, event):
368          self.MouseLeftUp(event)          """Handle EVT_LEFT_UP
369    
370            Release the mouse if it was captured, if a tool is active call
371            its Hide method and call self.MouseLeftUp.
372            """
373            # It's important that ReleaseMouse is called before MouseLeftUp.
374            # MouseLeftUp may pop up modal dialogs which leads to an
375            # effectively frozen X session because the user can only
376            # interact with the dialog but the mouse is still grabbed by the
377            # canvas.
378          if self.dragging:          if self.dragging:
379              self.ReleaseMouse()              if self.HasCapture():
380                    self.ReleaseMouse()
381              try:              try:
382                  self.tool.Hide(self.drag_dc)                  self.tool.Hide(self.drag_dc)
383              finally:              finally:
384                  self.drag_dc = None                  self.drag_dc = None
385                  self.dragging = 0                  self.dragging = 0
386            self.MouseLeftUp(event)
387    
388      def OnMotion(self, event):      def OnMotion(self, event):
389          if self.dragging:          if self.dragging:
# Line 332  class MapCanvas(wxWindow, ViewPort): Line 410  class MapCanvas(wxWindow, ViewPort):
410          """Receiver for the SHAPES_SELECTED messages. Redraw the map."""          """Receiver for the SHAPES_SELECTED messages. Redraw the map."""
411          # The selection object takes care that it only issues          # The selection object takes care that it only issues
412          # SHAPES_SELECTED messages when the set of selected shapes has          # SHAPES_SELECTED messages when the set of selected shapes has
413          # actually changed, so we can do a full redraw unconditionally.          # actually changed, so we can do a full redraw of the
414          # 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.  
415          ViewPort.shape_selected(self, layer, shape)          ViewPort.shape_selected(self, layer, shape)
416          self.full_redraw()          self.redraw_selection()
417    
418      def GetTextExtent(self, text):      def GetTextExtent(self, text):
419          dc = wxClientDC(self)          dc = wxClientDC(self)

Legend:
Removed from v.1454  
changed lines
  Added in v.1866

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26