/[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 6 by bh, Tue Aug 28 15:41:52 2001 UTC revision 176 by bh, Wed May 15 13:38:49 2002 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2002 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# Line 15  from math import hypot Line 15  from math import hypot
15    
16  from wxPython.wx import wxWindow,\  from wxPython.wx import wxWindow,\
17       wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\       wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\
18       EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION       EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION, EVT_LEAVE_WINDOW
19    
20    
21  from wxPython import wx  from wxPython import wx
# Line 29  from Thuban.Model.layer import SHAPETYPE Line 29  from Thuban.Model.layer import SHAPETYPE
29       SHAPETYPE_POINT       SHAPETYPE_POINT
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
33    
34  from renderer import ScreenRenderer, PrinterRender  from renderer import ScreenRenderer, PrinterRender
35    
36  import labeldialog  import labeldialog
37    
38  from messages import SELECTED_SHAPE  from messages import SELECTED_SHAPE, VIEW_POSITION
39    
40    
41  #  #
# Line 127  class ZoomInTool(RectTool): Line 127  class ZoomInTool(RectTool):
127      def MouseUp(self, event):      def MouseUp(self, event):
128          if self.dragging:          if self.dragging:
129              Tool.MouseUp(self, event)              Tool.MouseUp(self, event)
130              self.view.FitRectToWindow(self.proj_rect())              sx, sy = self.start
131                cx, cy = self.current
132                if sx == cx and sy == cy:
133                    # Just a mouse click. Simply zoom in by a factor of two
134                    self.view.ZoomFactor(2, center = (cx, cy))
135                else:
136                    # A drag. Zoom in to the rectangle
137                    self.view.FitRectToWindow(self.proj_rect())
138    
139    
140  class ZoomOutTool(RectTool):  class ZoomOutTool(RectTool):
# Line 142  class ZoomOutTool(RectTool): Line 149  class ZoomOutTool(RectTool):
149              Tool.MouseUp(self, event)              Tool.MouseUp(self, event)
150              sx, sy = self.start              sx, sy = self.start
151              cx, cy = self.current              cx, cy = self.current
152              self.view.ZoomOutToRect((min(sx, cx), min(sy, cy),              if sx == cx and sy == cy:
153                                       max(sx, cx), max(sy, cy)))                  # Just a mouse click. Simply zoom out by a factor of two
154                    self.view.ZoomFactor(0.5, center = (cy, cy))
155                else:
156                    # A drag. Zoom out to the rectangle
157                    self.view.ZoomOutToRect((min(sx, cx), min(sy, cy),
158                                             max(sx, cx), max(sy, cy)))
159    
160    
161  class PanTool(Tool):  class PanTool(Tool):
# Line 155  class PanTool(Tool): Line 167  class PanTool(Tool):
167    
168      def MouseMove(self, event):      def MouseMove(self, event):
169          if self.dragging:          if self.dragging:
             x0, y0 = self.current  
170              Tool.MouseMove(self, event)              Tool.MouseMove(self, event)
171                sx, sy = self.start
172              x, y = self.current              x, y = self.current
173              width, height = self.view.GetSizeTuple()              width, height = self.view.GetSizeTuple()
174    
175                bitmapdc = wx.wxMemoryDC()
176                bitmapdc.SelectObject(self.view.bitmap)
177    
178              dc = self.view.drag_dc              dc = self.view.drag_dc
179              dc.Blit(0, 0, width, height, dc, x0 - x, y0 - y)              dc.Blit(0, 0, width, height, bitmapdc, sx - x, sy - y)
180    
181      def MouseUp(self, event):      def MouseUp(self, event):
182          if self.dragging:          if self.dragging:
# Line 228  class MapPrintout(wx.wxPrintout): Line 244  class MapPrintout(wx.wxPrintout):
244          return wx.true          return wx.true
245                    
246    
247  class MapCanvas(wxWindow):  class MapCanvas(wxWindow, Publisher):
248    
249      """A widget that displays a map and offers some interaction"""      """A widget that displays a map and offers some interaction"""
250    
251      def __init__(self, parent, winid):      def __init__(self, parent, winid, interactor):
252          wxWindow.__init__(self, parent, winid)          wxWindow.__init__(self, parent, winid)
253          self.SetBackgroundColour(wxColour(255, 255, 255))          self.SetBackgroundColour(wxColour(255, 255, 255))
254    
255            # the map displayed in this canvas. Set with SetMap()
256          self.map = None          self.map = None
257    
258            # scale and offset describe the transformation from projected
259            # coordinates to window coordinates.
260          self.scale = 1.0          self.scale = 1.0
261          self.offset = (0, 0)          self.offset = (0, 0)
262    
263            # whether the user is currently dragging the mouse, i.e. moving
264            # the mouse while pressing a mouse button
265          self.dragging = 0          self.dragging = 0
266    
267            # the currently active tool
268          self.tool = None          self.tool = None
269    
270            # The current mouse position of the last OnMotion event or None
271            # if the mouse is outside the window.
272            self.current_position = None
273    
274            # If true, OnIdle will call do_redraw to do the actual
275            # redrawing. Set by OnPaint to avoid some unnecessary redraws.
276            # To force a redraw call full_redraw().
277          self.redraw_on_idle = 0          self.redraw_on_idle = 0
278    
279            # The region to update when idle
280            self.update_region = wx.wxRegion()
281    
282            # the bitmap serving as backing store
283            self.bitmap = None
284    
285            # the interactor
286            self.interactor = interactor
287            self.interactor.Subscribe(SELECTED_SHAPE, self.shape_selected)
288    
289            # keep track of which layers/shapes are selected to make sure we
290            # only redraw when necessary
291            self.last_selected_layer = None
292            self.last_selected_shape = None
293    
294            # subscribe the WX events we're interested in
295          EVT_PAINT(self, self.OnPaint)          EVT_PAINT(self, self.OnPaint)
296          EVT_LEFT_DOWN(self, self.OnLeftDown)          EVT_LEFT_DOWN(self, self.OnLeftDown)
297          EVT_LEFT_UP(self, self.OnLeftUp)          EVT_LEFT_UP(self, self.OnLeftUp)
298          EVT_MOTION(self, self.OnMotion)          EVT_MOTION(self, self.OnMotion)
299            EVT_LEAVE_WINDOW(self, self.OnLeaveWindow)
300            wx.EVT_SIZE(self, self.OnSize)
301          wx.EVT_IDLE(self, self.OnIdle)          wx.EVT_IDLE(self, self.OnIdle)
302          import main  
303          self.interactor = main.app.interactor      def __del__(self):
304          self.interactor.Subscribe(SELECTED_SHAPE, self.shape_selected)          wxWindow.__del__(self)
305            Publisher.__del__(self)
306    
307      def OnPaint(self, event):      def OnPaint(self, event):
308          dc = wxPaintDC(self)          dc = wxPaintDC(self)
309          if self.map is None or not self.map.HasLayers():          if self.map is not None and self.map.HasLayers():
310              return              # We have a non-empty map. Redraw it in idle time
311          self.redraw_on_idle = 1              self.redraw_on_idle = 1
312                # update the region that has to be redrawn
313                self.update_region.UnionRegion(self.GetUpdateRegion())
314            else:
315                # If we've got no map or if the map is empty, simply clear
316                # the screen.
317                
318                # XXX it's probably possible to get rid of this. The
319                # background color of the window is already white and the
320                # only thing we may have to do is to call self.Refresh()
321                # with a true argument in the right places.
322                dc.BeginDrawing()
323                dc.Clear()            
324                dc.EndDrawing()
325    
326                # clear the region
327                self.update_region = wx.wxRegion()
328    
329      def do_redraw(self):      def do_redraw(self):
330          width, height = self.GetSizeTuple()          # This should only be called if we have a non-empty map.
         bitmap = wx.wxEmptyBitmap(width, height)  
331    
332          dc = wx.wxMemoryDC()          # get the update region and reset it. We're not actually using
333          dc.SelectObject(bitmap)          # it anymore, though.
334            update_box = self.update_region.GetBox()
335            self.update_region = wx.wxRegion()
336    
337          dc.BeginDrawing()          # Get the window size.
338            width, height = self.GetSizeTuple()
339    
340          dc.SetBrush(wx.wxWHITE_BRUSH)          # If self.bitmap's still there, reuse it. Otherwise redraw it
341          dc.SetPen(wx.wxTRANSPARENT_PEN)          if self.bitmap is not None:
342          dc.DrawRectangle(0, 0, width, height)              bitmap = self.bitmap
   
         if 1: #self.interactor.selected_map is self.map:  
             selected_layer = self.interactor.selected_layer  
             selected_shape = self.interactor.selected_shape  
343          else:          else:
344              selected_layer = None              bitmap = wx.wxEmptyBitmap(width, height)
345              selected_shape = None              dc = wx.wxMemoryDC()
346                            dc.SelectObject(bitmap)
347          renderer = ScreenRenderer(dc, self.scale, self.offset)              dc.BeginDrawing()
348          renderer.RenderMap(self.map, selected_layer, selected_shape)  
349                # clear the background
350                dc.SetBrush(wx.wxWHITE_BRUSH)
351                dc.SetPen(wx.wxTRANSPARENT_PEN)
352                dc.DrawRectangle(0, 0, width, height)
353    
354                if 1: #self.interactor.selected_map is self.map:
355                    selected_layer = self.interactor.selected_layer
356                    selected_shape = self.interactor.selected_shape
357                else:
358                    selected_layer = None
359                    selected_shape = None
360    
361                # draw the map into the bitmap
362                renderer = ScreenRenderer(dc, self.scale, self.offset)
363    
364                # Pass the entire bitmap as update_region to the renderer.
365                # We're redrawing the whole bitmap, after all.
366                renderer.RenderMap(self.map, (0, 0, width, height),
367                                   selected_layer, selected_shape)
368    
369                dc.EndDrawing()
370                dc.SelectObject(wx.wxNullBitmap)
371                self.bitmap = bitmap
372    
373            # blit the bitmap to the screen
374            dc = wx.wxMemoryDC()
375            dc.SelectObject(bitmap)
376          clientdc = wxClientDC(self)          clientdc = wxClientDC(self)
377          clientdc.BeginDrawing()          clientdc.BeginDrawing()
378          clientdc.Blit(0, 0, width, height, dc, 0, 0)          clientdc.Blit(0, 0, width, height, dc, 0, 0)
379          clientdc.EndDrawing()          clientdc.EndDrawing()
380    
   
381      def Print(self):      def Print(self):
382          printer = wx.wxPrinter()          printer = wx.wxPrinter()
383          printout = MapPrintout(self.map)          printout = MapPrintout(self.map)
# Line 296  class MapCanvas(wxWindow): Line 389  class MapCanvas(wxWindow):
389                             LAYER_VISIBILITY_CHANGED)                             LAYER_VISIBILITY_CHANGED)
390          if self.map is not None:          if self.map is not None:
391              for channel in redraw_channels:              for channel in redraw_channels:
392                  self.map.Unsubscribe(channel, self.redraw)                  self.map.Unsubscribe(channel, self.full_redraw)
393              self.map.Unsubscribe(MAP_PROJECTION_CHANGED,              self.map.Unsubscribe(MAP_PROJECTION_CHANGED,
394                                   self.projection_changed)                                   self.projection_changed)
395          self.map = map          self.map = map
396          if self.map is not None:          if self.map is not None:
397              for channel in redraw_channels:              for channel in redraw_channels:
398                  self.map.Subscribe(channel, self.redraw)                  self.map.Subscribe(channel, self.full_redraw)
399              self.map.Subscribe(MAP_PROJECTION_CHANGED, self.projection_changed)              self.map.Subscribe(MAP_PROJECTION_CHANGED, self.projection_changed)
400          self.FitMapToWindow()          self.FitMapToWindow()
401            # force a redraw. If map is not empty, it's already been called
402            # by FitMapToWindow but if map is empty it hasn't been called
403            # yet so we have to explicitly call it.
404            self.full_redraw()
405    
406      def Map(self):      def Map(self):
407          return self.map          return self.map
# Line 312  class MapCanvas(wxWindow): Line 409  class MapCanvas(wxWindow):
409      def redraw(self, *args):      def redraw(self, *args):
410          self.Refresh(0)          self.Refresh(0)
411    
412        def full_redraw(self, *args):
413            self.bitmap = None
414            self.redraw()
415    
416      def projection_changed(self, *args):      def projection_changed(self, *args):
417          self.FitMapToWindow()          self.FitMapToWindow()
418          self.redraw()          self.full_redraw()
419    
420      def set_view_transform(self, scale, offset):      def set_view_transform(self, scale, offset):
421          self.scale = scale          self.scale = scale
422          self.offset = offset          self.offset = offset
423          self.redraw()          self.full_redraw()
424    
425      def proj_to_win(self, x, y):      def proj_to_win(self, x, y):
426          """\          """\
# Line 338  class MapCanvas(wxWindow): Line 439  class MapCanvas(wxWindow):
439      def FitRectToWindow(self, rect):      def FitRectToWindow(self, rect):
440          width, height = self.GetSizeTuple()          width, height = self.GetSizeTuple()
441          llx, lly, urx, ury = rect          llx, lly, urx, ury = rect
442            if llx == urx or lly == ury:
443                # zero with or zero height. Do Nothing
444                return
445          scalex = width / (urx - llx)          scalex = width / (urx - llx)
446          scaley = height / (ury - lly)          scaley = height / (ury - lly)
447          scale = min(scalex, scaley)          scale = min(scalex, scaley)
# Line 354  class MapCanvas(wxWindow): Line 458  class MapCanvas(wxWindow):
458          if bbox is not None:          if bbox is not None:
459              self.FitRectToWindow(bbox)              self.FitRectToWindow(bbox)
460    
461      def ZoomFactor(self, factor):      def ZoomFactor(self, factor, center = None):
462            """Multiply the zoom by factor and center on center.
463    
464            The optional parameter center is a point in window coordinates
465            that should be centered. If it is omitted, it defaults to the
466            center of the window
467            """
468          width, height = self.GetSizeTuple()          width, height = self.GetSizeTuple()
469          scale = self.scale * factor          scale = self.scale * factor
470          offx, offy = self.offset          offx, offy = self.offset
471          offset = (factor * (offx - width / 2) + width / 2,          if center is not None:
472                    factor * (offy - height / 2) + height / 2)              cx, cy = center
473            else:
474                cx = width / 2
475                cy = height / 2
476            offset = (factor * (offx - cx) + width / 2,
477                      factor * (offy - cy) + height / 2)
478          self.set_view_transform(scale, offset)          self.set_view_transform(scale, offset)
479    
480      def ZoomOutToRect(self, rect):      def ZoomOutToRect(self, rect):
# Line 402  class MapCanvas(wxWindow): Line 517  class MapCanvas(wxWindow):
517      def CurrentTool(self):      def CurrentTool(self):
518          return self.tool and self.tool.Name() or None          return self.tool and self.tool.Name() or None
519    
520        def CurrentPosition(self):
521            """Return current position of the mouse in projected coordinates.
522    
523            The result is a 2-tuple of floats with the coordinates. If the
524            mouse is not in the window, the result is None.
525            """
526            if self.current_position is not None:
527                x, y = self.current_position
528                return self.win_to_proj(x, y)
529            else:
530                return None
531    
532        def set_current_position(self, event):
533            """Set the current position from event
534    
535            Should be called by all events that contain mouse positions
536            especially EVT_MOTION. The event paramete may be None to
537            indicate the the pointer left the window.
538            """
539            if event is not None:
540                self.current_position = (event.m_x, event.m_y)
541            else:
542                self.current_position = None
543            self.issue(VIEW_POSITION)
544    
545      def OnLeftDown(self, event):      def OnLeftDown(self, event):
546            self.set_current_position(event)
547          if self.tool is not None:          if self.tool is not None:
548              self.drag_dc = wxClientDC(self)              self.drag_dc = wxClientDC(self)
549              self.drag_dc.SetLogicalFunction(wxINVERT)              self.drag_dc.SetLogicalFunction(wxINVERT)
# Line 414  class MapCanvas(wxWindow): Line 555  class MapCanvas(wxWindow):
555                    
556      def OnLeftUp(self, event):      def OnLeftUp(self, event):
557          self.ReleaseMouse()          self.ReleaseMouse()
558            self.set_current_position(event)
559          if self.dragging:          if self.dragging:
560              self.tool.Hide(self.drag_dc)              self.tool.Hide(self.drag_dc)
561              self.tool.MouseUp(event)              self.tool.MouseUp(event)
# Line 421  class MapCanvas(wxWindow): Line 563  class MapCanvas(wxWindow):
563          self.dragging = 0          self.dragging = 0
564    
565      def OnMotion(self, event):      def OnMotion(self, event):
566            self.set_current_position(event)
567          if self.dragging:          if self.dragging:
568              self.tool.Hide(self.drag_dc)              self.tool.Hide(self.drag_dc)
569              self.tool.MouseMove(event)              self.tool.MouseMove(event)
570              self.tool.Show(self.drag_dc)              self.tool.Show(self.drag_dc)
571    
572        def OnLeaveWindow(self, event):
573            self.set_current_position(None)
574    
575      def OnIdle(self, event):      def OnIdle(self, event):
576          if self.redraw_on_idle:          if self.redraw_on_idle:
577              self.do_redraw()              self.do_redraw()
578          self.redraw_on_idle = 0          self.redraw_on_idle = 0
579    
580        def OnSize(self, event):
581            # the window's size has changed. We have to get a new bitmap. If
582            # we want to be clever we could try to get by without throwing
583            # everything away. E.g. when the window gets smaller, we could
584            # either keep the bitmap or create the new one from the old one.
585            # Even when the window becomes larger some parts of the bitmap
586            # could be reused.
587            self.full_redraw()
588    
589      def shape_selected(self, layer, shape):      def shape_selected(self, layer, shape):
590          self.redraw()          """Redraw the map.
591    
592      def find_shape_at(self, px, py, select_labels = 0):          Receiver for the SELECTED_SHAPE messages. Try to redraw only
593          """Return a tuple shape at point px, py in window coords."""          when necessary.
594            """
595            # A redraw is necessary when the display has to change, which
596            # means that either the status changes from having no selection
597            # to having a selection shape or vice versa, or when the fact
598            # whether there is a selection at all doesn't change, when the
599            # shape which is selected has changed (which means that layer or
600            # shapeid changes).
601            if ((shape is not None or self.last_selected_shape is not None)
602                and (shape != self.last_selected_shape
603                     or layer != self.last_selected_layer)):
604                self.full_redraw()
605    
606            # remember the selection so we can compare when it changes again.
607            self.last_selected_layer = layer
608            self.last_selected_shape = shape
609    
610        def unprojected_rect_around_point(self, x, y):
611            """return a rect a few pixels around (x, y) in unprojected corrdinates
612    
613            The return value is a tuple (minx, miny, maxx, maxy) suitable a
614            parameter to a layer's ShapesInRegion method.
615            """
616            map_proj = self.map.projection
617            if map_proj is not None:
618                inverse = map_proj.Inverse
619            else:
620                inverse = None
621    
622            xs = []
623            ys = []
624            for dx, dy in ((-1, -1), (1, -1), (1, 1), (-1, 1)):
625                px, py = self.win_to_proj(x + dx, y + dy)
626                if inverse:
627                    px, py = inverse(px, py)
628                xs.append(px)
629                ys.append(py)
630            return (min(xs), min(ys), max(xs), max(ys))
631    
632        def find_shape_at(self, px, py, select_labels = 0, selected_layer = 1):
633            """Determine the shape at point px, py in window coords
634    
635            Return the shape and the corresponding layer as a tuple (layer,
636            shape).
637    
638            If the optional parameter select_labels is true (default false)
639            search through the labels. If a label is found return it's index
640            as the shape and None as the layer.
641    
642            If the optional parameter selected_layer is true (default), only
643            search in the currently selected layer.
644            """
645          map_proj = self.map.projection          map_proj = self.map.projection
646          if map_proj is not None:          if map_proj is not None:
647              forward = map_proj.Forward              forward = map_proj.Forward
# Line 445  class MapCanvas(wxWindow): Line 651  class MapCanvas(wxWindow):
651          scale = self.scale          scale = self.scale
652          offx, offy = self.offset          offx, offy = self.offset
653    
654            box = self.unprojected_rect_around_point(px, py)
655    
656          if select_labels:          if select_labels:
657              labels = self.map.LabelLayer().Labels()              labels = self.map.LabelLayer().Labels()
658                            
# Line 452  class MapCanvas(wxWindow): Line 660  class MapCanvas(wxWindow):
660                  dc = wxClientDC(self)                  dc = wxClientDC(self)
661                  font = wxFont(10, wx.wxSWISS, wx.wxNORMAL, wx.wxNORMAL)                  font = wxFont(10, wx.wxSWISS, wx.wxNORMAL, wx.wxNORMAL)
662                  dc.SetFont(font)                  dc.SetFont(font)
663                  for i in range(len(labels)):                  for i in range(len(labels) - 1, -1, -1):
664                      label = labels[i]                      label = labels[i]
665                      x = label.x                      x = label.x
666                      y = label.y                      y = label.y
# Line 478  class MapCanvas(wxWindow): Line 686  class MapCanvas(wxWindow):
686                          y = y - height/2                          y = y - height/2
687                      if x <= px < x + width and y <= py <= y + height:                      if x <= px < x + width and y <= py <= y + height:
688                          return None, i                          return None, i
689                    
690          layers = self.map.Layers()          if selected_layer:
691                layer = self.interactor.SelectedLayer()
692                if layer is not None:
693                    layers = [layer]
694                else:
695                    # no layer selected. Use an empty list to effectively
696                    # ignore all layers.
697                    layers = []
698            else:
699                layers = self.map.Layers()
700    
701          for layer_index in range(len(layers) - 1, -1, -1):          for layer_index in range(len(layers) - 1, -1, -1):
702              layer = layers[layer_index]              layer = layers[layer_index]
703    
# Line 499  class MapCanvas(wxWindow): Line 717  class MapCanvas(wxWindow):
717              shapetype = layer.ShapeType()              shapetype = layer.ShapeType()
718    
719              select_shape = -1              select_shape = -1
720    
721                shape_ids = layer.ShapesInRegion(box)
722                shape_ids.reverse()
723    
724              if shapetype == SHAPETYPE_POLYGON:              if shapetype == SHAPETYPE_POLYGON:
725                  for i in range(layer.NumShapes()):                  for i in shape_ids:
726                      result = point_in_polygon_shape(layer.shapefile.cobject(),                      result = point_in_polygon_shape(layer.shapefile.cobject(),
727                                                      i,                                                      i,
728                                                      filled, stroked,                                                      filled, stroked,
# Line 511  class MapCanvas(wxWindow): Line 733  class MapCanvas(wxWindow):
733                          select_shape = i                          select_shape = i
734                          break                          break
735              elif shapetype == SHAPETYPE_ARC:              elif shapetype == SHAPETYPE_ARC:
736                  for i in range(layer.NumShapes()):                  for i in shape_ids:
737                      result = point_in_polygon_shape(layer.shapefile.cobject(),                      result = point_in_polygon_shape(layer.shapefile.cobject(),
738                                                      i, 0, 1,                                                      i, 0, 1,
739                                                      map_proj, layer_proj,                                                      map_proj, layer_proj,
# Line 521  class MapCanvas(wxWindow): Line 743  class MapCanvas(wxWindow):
743                          select_shape = i                          select_shape = i
744                          break                          break
745              elif shapetype == SHAPETYPE_POINT:              elif shapetype == SHAPETYPE_POINT:
746                  for i in range(layer.NumShapes()):                  for i in shape_ids:
747                      shape = layer.Shape(i)                      shape = layer.Shape(i)
748                      x, y = shape.Points()[0]                      x, y = shape.Points()[0]
749                      if inverse:                      if inverse:
# Line 539  class MapCanvas(wxWindow): Line 761  class MapCanvas(wxWindow):
761          return None, None          return None, None
762    
763      def SelectShapeAt(self, x, y):      def SelectShapeAt(self, x, y):
764          layer, shape = self.find_shape_at(x, y)          layer, shape = self.find_shape_at(x, y, selected_layer = 0)
765            # If layer is None, then shape will also be None. We don't want
766            # to deselect the currently selected layer, so we simply select
767            # the already selected layer again.
768            if layer is None:
769                layer = self.interactor.SelectedLayer()
770          self.interactor.SelectLayerAndShape(layer, shape)          self.interactor.SelectLayerAndShape(layer, shape)
771    
772      def LabelShapeAt(self, x, y):      def LabelShapeAt(self, x, y):

Legend:
Removed from v.6  
changed lines
  Added in v.176

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26