/[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 288 by bh, Thu Aug 29 13:31:43 2002 UTC revision 433 by jonathan, Mon Feb 24 18:47:49 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# Line 30  from Thuban.Model.layer import SHAPETYPE Line 30  from Thuban.Model.layer import SHAPETYPE
30  from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \  from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
31       ALIGN_LEFT, ALIGN_RIGHT       ALIGN_LEFT, ALIGN_RIGHT
32  from Thuban.Lib.connector import Publisher  from Thuban.Lib.connector import Publisher
33    from Thuban.Model.color import Color
34    
35  from renderer import ScreenRenderer, PrinterRender  from renderer import ScreenRenderer, PrinterRender
36    
# Line 279  class MapCanvas(wxWindow, Publisher): Line 280  class MapCanvas(wxWindow, Publisher):
280          # if the mouse is outside the window.          # if the mouse is outside the window.
281          self.current_position = None          self.current_position = None
282    
         # If true, OnIdle will call do_redraw to do the actual  
         # redrawing. Set by OnPaint to avoid some unnecessary redraws.  
         # To force a redraw call full_redraw().  
         self.redraw_on_idle = 0  
   
         # The region to update when idle  
         self.update_region = wx.wxRegion()  
   
283          # the bitmap serving as backing store          # the bitmap serving as backing store
284          self.bitmap = None          self.bitmap = None
285    
# Line 306  class MapCanvas(wxWindow, Publisher): Line 299  class MapCanvas(wxWindow, Publisher):
299          EVT_MOTION(self, self.OnMotion)          EVT_MOTION(self, self.OnMotion)
300          EVT_LEAVE_WINDOW(self, self.OnLeaveWindow)          EVT_LEAVE_WINDOW(self, self.OnLeaveWindow)
301          wx.EVT_SIZE(self, self.OnSize)          wx.EVT_SIZE(self, self.OnSize)
         wx.EVT_IDLE(self, self.OnIdle)  
302    
303      def __del__(self):      def __del__(self):
304          wxWindow.__del__(self)          wxWindow.__del__(self)
# Line 315  class MapCanvas(wxWindow, Publisher): Line 307  class MapCanvas(wxWindow, Publisher):
307      def OnPaint(self, event):      def OnPaint(self, event):
308          dc = wxPaintDC(self)          dc = wxPaintDC(self)
309          if self.map is not None and self.map.HasLayers():          if self.map is not None and self.map.HasLayers():
310              # We have a non-empty map. Redraw it in idle time              self.do_redraw()
             self.redraw_on_idle = 1  
             # update the region that has to be redrawn  
             self.update_region.UnionRegion(self.GetUpdateRegion())  
311          else:          else:
312              # 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
313              # the screen.              # the screen.
# Line 331  class MapCanvas(wxWindow, Publisher): Line 320  class MapCanvas(wxWindow, Publisher):
320              dc.Clear()              dc.Clear()
321              dc.EndDrawing()              dc.EndDrawing()
322    
             # clear the region  
             self.update_region = wx.wxRegion()  
   
323      def do_redraw(self):      def do_redraw(self):
324          # This should only be called if we have a non-empty map.          # This should only be called if we have a non-empty map.
325    
         # get the update region and reset it. We're not actually using  
         # it anymore, though.  
         update_box = self.update_region.GetBox()  
         self.update_region = wx.wxRegion()  
   
326          # Get the window size.          # Get the window size.
327          width, height = self.GetSizeTuple()          width, height = self.GetSizeTuple()
328    
# Line 369  class MapCanvas(wxWindow, Publisher): Line 350  class MapCanvas(wxWindow, Publisher):
350              # draw the map into the bitmap              # draw the map into the bitmap
351              renderer = ScreenRenderer(dc, self.scale, self.offset)              renderer = ScreenRenderer(dc, self.scale, self.offset)
352    
353              # Pass the entire bitmap as update_region to the renderer.              # Pass the entire bitmap as update region to the renderer.
354              # We're redrawing the whole bitmap, after all.              # We're redrawing the whole bitmap, after all.
355              renderer.RenderMap(self.map, (0, 0, width, height),              renderer.RenderMap(self.map, (0, 0, width, height),
356                                 selected_layer, selected_shape)                                 selected_layer, selected_shape)
# Line 412  class MapCanvas(wxWindow, Publisher): Line 393  class MapCanvas(wxWindow, Publisher):
393          self.full_redraw()          self.full_redraw()
394    
395      def Map(self):      def Map(self):
396            """Return the map displayed by this canvas"""
397          return self.map          return self.map
398    
399      def redraw(self, *args):      def redraw(self, *args):
# Line 445  class MapCanvas(wxWindow, Publisher): Line 427  class MapCanvas(wxWindow, Publisher):
427          return ((x - offx) / self.scale, (offy - y) / self.scale)          return ((x - offx) / self.scale, (offy - y) / self.scale)
428    
429      def FitRectToWindow(self, rect):      def FitRectToWindow(self, rect):
430            """Fit the rectangular region given by rect into the window.
431            
432            Set scale so that rect (in projected coordinates) just fits into
433            the window and center it.
434            """
435          width, height = self.GetSizeTuple()          width, height = self.GetSizeTuple()
436          llx, lly, urx, ury = rect          llx, lly, urx, ury = rect
437          if llx == urx or lly == ury:          if llx == urx or lly == ury:
# Line 458  class MapCanvas(wxWindow, Publisher): Line 445  class MapCanvas(wxWindow, Publisher):
445          self.set_view_transform(scale, (offx, offy))          self.set_view_transform(scale, (offx, offy))
446    
447      def FitMapToWindow(self):      def FitMapToWindow(self):
448          """\          """Fit the map to the window
449          Set the scale and offset so that the map is centered in the          
450          window          Set the scale so that the map fits exactly into the window and
451            center it in the window.
452          """          """
453          bbox = self.map.ProjectedBoundingBox()          bbox = self.map.ProjectedBoundingBox()
454          if bbox is not None:          if bbox is not None:
# Line 486  class MapCanvas(wxWindow, Publisher): Line 474  class MapCanvas(wxWindow, Publisher):
474          self.set_view_transform(scale, offset)          self.set_view_transform(scale, offset)
475    
476      def ZoomOutToRect(self, rect):      def ZoomOutToRect(self, rect):
477          # rect is given in window coordinates          """Zoom out to fit the currently visible region into rect.
478    
479            The rect parameter is given in window coordinates
480            """
481          # determine the bbox of the displayed region in projected          # determine the bbox of the displayed region in projected
482          # coordinates          # coordinates
483          width, height = self.GetSizeTuple()          width, height = self.GetSizeTuple()
# Line 504  class MapCanvas(wxWindow, Publisher): Line 494  class MapCanvas(wxWindow, Publisher):
494          self.set_view_transform(scale, (offx, offy))          self.set_view_transform(scale, (offx, offy))
495    
496      def Translate(self, dx, dy):      def Translate(self, dx, dy):
497            """Move the map by dx, dy pixels"""
498          offx, offy = self.offset          offx, offy = self.offset
499          self.set_view_transform(self.scale, (offx + dx, offy + dy))          self.set_view_transform(self.scale, (offx + dx, offy + dy))
500    
501        def SelectTool(self, tool):
502            """Make tool the active tool.
503    
504            The parameter should be an instance of Tool or None to indicate
505            that no tool is active.
506            """
507            self.tool = tool
508    
509      def ZoomInTool(self):      def ZoomInTool(self):
510          self.tool = ZoomInTool(self)          """Start the zoom in tool"""
511            self.SelectTool(ZoomInTool(self))
512    
513      def ZoomOutTool(self):      def ZoomOutTool(self):
514          self.tool = ZoomOutTool(self)          """Start the zoom out tool"""
515            self.SelectTool(ZoomOutTool(self))
516    
517      def PanTool(self):      def PanTool(self):
518          self.tool = PanTool(self)          """Start the pan tool"""
519            self.SelectTool(PanTool(self))
520    
521      def IdentifyTool(self):      def IdentifyTool(self):
522          self.tool = IdentifyTool(self)          """Start the identify tool"""
523            self.SelectTool(IdentifyTool(self))
524    
525      def LabelTool(self):      def LabelTool(self):
526          self.tool = LabelTool(self)          """Start the label tool"""
527            self.SelectTool(LabelTool(self))
528    
529      def CurrentTool(self):      def CurrentTool(self):
530            """Return the name of the current tool or None if no tool is active"""
531          return self.tool and self.tool.Name() or None          return self.tool and self.tool.Name() or None
532    
533      def CurrentPosition(self):      def CurrentPosition(self):
# Line 565  class MapCanvas(wxWindow, Publisher): Line 570  class MapCanvas(wxWindow, Publisher):
570          self.set_current_position(event)          self.set_current_position(event)
571          if self.dragging:          if self.dragging:
572              self.ReleaseMouse()              self.ReleaseMouse()
573              self.tool.Hide(self.drag_dc)              try:
574              self.tool.MouseUp(event)                  self.tool.Hide(self.drag_dc)
575              self.drag_dc = None                  self.tool.MouseUp(event)
576          self.dragging = 0              finally:
577                    self.drag_dc = None
578                    self.dragging = 0
579    
580      def OnMotion(self, event):      def OnMotion(self, event):
581          self.set_current_position(event)          self.set_current_position(event)
# Line 580  class MapCanvas(wxWindow, Publisher): Line 587  class MapCanvas(wxWindow, Publisher):
587      def OnLeaveWindow(self, event):      def OnLeaveWindow(self, event):
588          self.set_current_position(None)          self.set_current_position(None)
589    
     def OnIdle(self, event):  
         if self.redraw_on_idle:  
             self.do_redraw()  
         self.redraw_on_idle = 0  
   
590      def OnSize(self, event):      def OnSize(self, event):
591          # the window's size has changed. We have to get a new bitmap. If          # the window's size has changed. We have to get a new bitmap. If
592          # we want to be clever we could try to get by without throwing          # we want to be clever we could try to get by without throwing
# Line 615  class MapCanvas(wxWindow, Publisher): Line 617  class MapCanvas(wxWindow, Publisher):
617          self.last_selected_layer = layer          self.last_selected_layer = layer
618          self.last_selected_shape = shape          self.last_selected_shape = shape
619    
620      def unprojected_rect_around_point(self, x, y):      def unprojected_rect_around_point(self, x, y, dist):
621          """return a rect a few pixels around (x, y) in unprojected corrdinates          """return a rect dist pixels around (x, y) in unprojected corrdinates
622    
623          The return value is a tuple (minx, miny, maxx, maxy) suitable a          The return value is a tuple (minx, miny, maxx, maxy) suitable a
624          parameter to a layer's ShapesInRegion method.          parameter to a layer's ShapesInRegion method.
# Line 630  class MapCanvas(wxWindow, Publisher): Line 632  class MapCanvas(wxWindow, Publisher):
632          xs = []          xs = []
633          ys = []          ys = []
634          for dx, dy in ((-1, -1), (1, -1), (1, 1), (-1, 1)):          for dx, dy in ((-1, -1), (1, -1), (1, 1), (-1, 1)):
635              px, py = self.win_to_proj(x + dx, y + dy)              px, py = self.win_to_proj(x + dist * dx, y + dist * dy)
636              if inverse:              if inverse:
637                  px, py = inverse(px, py)                  px, py = inverse(px, py)
638              xs.append(px)              xs.append(px)
# Line 659  class MapCanvas(wxWindow, Publisher): Line 661  class MapCanvas(wxWindow, Publisher):
661          scale = self.scale          scale = self.scale
662          offx, offy = self.offset          offx, offy = self.offset
663    
         box = self.unprojected_rect_around_point(px, py)  
   
664          if select_labels:          if select_labels:
665              labels = self.map.LabelLayer().Labels()              labels = self.map.LabelLayer().Labels()
666    
# Line 707  class MapCanvas(wxWindow, Publisher): Line 707  class MapCanvas(wxWindow, Publisher):
707              if not layer.Visible():              if not layer.Visible():
708                  continue                  continue
709    
710              filled = layer.fill is not None              filled = layer.GetClassification().GetDefaultFill() \
711              stroked = layer.stroke is not None                       is not Color.None
712                stroked = layer.GetClassification().GetDefaultStroke() \
713                          is not Color.None
714    
715              layer_proj = layer.projection              layer_proj = layer.projection
716              if layer_proj is not None:              if layer_proj is not None:
# Line 720  class MapCanvas(wxWindow, Publisher): Line 722  class MapCanvas(wxWindow, Publisher):
722    
723              select_shape = -1              select_shape = -1
724    
725                # Determine the ids of the shapes that overlap a tiny area
726                # around the point. For layers containing points we have to
727                # choose a larger size of the box we're testing agains so
728                # that we take the size of the markers into account
729                # FIXME: Once the markers are more flexible this part has to
730                # become more flexible too, of course
731                if shapetype == SHAPETYPE_POINT:
732                    box = self.unprojected_rect_around_point(px, py, 5)
733                else:
734                    box = self.unprojected_rect_around_point(px, py, 1)
735              shape_ids = layer.ShapesInRegion(box)              shape_ids = layer.ShapesInRegion(box)
736              shape_ids.reverse()              shape_ids.reverse()
737    
# Line 782  class MapCanvas(wxWindow, Publisher): Line 794  class MapCanvas(wxWindow, Publisher):
794          return result          return result
795    
796      def LabelShapeAt(self, x, y):      def LabelShapeAt(self, x, y):
797            """Add or remove a label at window position x, y.
798    
799            If there's a label at the given position, remove it. Otherwise
800            determine the shape at the position, run the label dialog and
801            unless the user cancels the dialog, add a laber.
802            """
803          ox = x; oy = y          ox = x; oy = y
804          label_layer = self.map.LabelLayer()          label_layer = self.map.LabelLayer()
805          layer, shape_index = self.find_shape_at(x, y, select_labels = 1)          layer, shape_index = self.find_shape_at(x, y, select_labels = 1)

Legend:
Removed from v.288  
changed lines
  Added in v.433

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26