/[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 23 by bh, Wed Sep 5 13:35:22 2001 UTC revision 1552 by bh, Wed Aug 6 17:21:32 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4    # Frank Koormann <[email protected]>
5  #  #
6  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
7  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
# Line 11  Classes for display of a map and interac Line 12  Classes for display of a map and interac
12    
13  __version__ = "$Revision$"  __version__ = "$Revision$"
14    
15  from math import hypot  from Thuban import _
16    
17  from wxPython.wx import wxWindow,\  import os.path
      wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\  
      EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION  
18    
19    from wxPython.wx import wxWindow, \
20         wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\
21         EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION, EVT_LEAVE_WINDOW, \
22         wxPlatform, wxBeginBusyCursor, wxEndBusyCursor, wxFileDialog, wxSAVE, \
23         wxOVERWRITE_PROMPT, wxID_OK
24    
25    # Export related stuff
26    if wxPlatform == '__WXMSW__':
27        from wxPython.wx import wxMetaFileDC
28    
29  from wxPython import wx  from wxPython import wx
30    
31  from wxproj import point_in_polygon_shape, shape_centroid  from Thuban.Model.messages import MAP_LAYERS_CHANGED, LAYER_CHANGED, \
32         LAYER_VISIBILITY_CHANGED
   
 from Thuban.Model.messages import MAP_PROJECTION_CHANGED, \  
      LAYERS_CHANGED, LAYER_LEGEND_CHANGED, LAYER_VISIBILITY_CHANGED  
 from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \  
      SHAPETYPE_POINT  
 from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \  
      ALIGN_LEFT, ALIGN_RIGHT  
   
33    
34  from renderer import ScreenRenderer, PrinterRender  from renderer import ScreenRenderer, ExportRenderer, PrinterRenderer
35    
36  import labeldialog  import labeldialog
37    
38  from messages import SELECTED_SHAPE  from viewport import ViewPort, PanTool, output_transform
   
   
 #  
 #   The tools  
 #  
   
 class Tool:  
   
     """  
     Base class for the interactive tools  
     """  
   
     def __init__(self, view):  
         """Intitialize the tool. The view is the canvas displaying the map"""  
         self.view = view  
         self.start = self.current = None  
         self.dragging = 0  
         self.drawn = 0  
   
     def Name(self):  
         """Return the tool's name"""  
         return ''  
   
     def drag_start(self, x, y):  
         self.start = self.current = x, y  
         self.dragging = 1  
   
     def drag_move(self, x, y):  
         self.current = x, y  
   
     def drag_stop(self, x, y):  
         self.current = x, y  
         self.dragging = 0  
   
     def Show(self, dc):  
         if not self.drawn:  
             self.draw(dc)  
         self.drawn = 1  
   
     def Hide(self, dc):  
         if self.drawn:  
             self.draw(dc)  
         self.drawn = 0  
39    
40      def draw(self, dc):  class CanvasPanTool(PanTool):
         pass  
41    
42      def MouseDown(self, event):      """The Canvas Pan Tool"""
         self.drag_start(event.m_x, event.m_y)  
43    
44      def MouseMove(self, event):      def MouseMove(self, event):
45          if self.dragging:          if self.dragging:
46              self.drag_move(event.m_x, event.m_y)              PanTool.MouseMove(self, event)
   
     def MouseUp(self, event):  
         if self.dragging:  
             self.drag_move(event.m_x, event.m_y)  
   
     def Cancel(self):  
         self.dragging = 0  
   
   
 class RectTool(Tool):  
   
     """Base class for tools that draw rectangles while dragging"""  
   
     def draw(self, dc):  
         sx, sy = self.start  
         cx, cy = self.current  
         dc.DrawRectangle(sx, sy, cx - sx, cy - sy)  
   
 class ZoomInTool(RectTool):  
   
     """The Zoom-In Tool"""  
   
     def Name(self):  
         return "ZoomInTool"  
   
     def proj_rect(self):  
         """return the rectangle given by start and current in projected  
         coordinates"""  
         sx, sy = self.start  
         cx, cy = self.current  
         left, top = self.view.win_to_proj(sx, sy)  
         right, bottom = self.view.win_to_proj(cx, cy)  
         return (min(left, right), min(top, bottom),  
                 max(left, right), max(top, bottom))  
   
     def MouseUp(self, event):  
         if self.dragging:  
             Tool.MouseUp(self, event)  
             self.view.FitRectToWindow(self.proj_rect())  
   
   
 class ZoomOutTool(RectTool):  
   
     """The Zoom-Out Tool"""  
       
     def Name(self):  
         return "ZoomOutTool"  
   
     def MouseUp(self, event):  
         if self.dragging:  
             Tool.MouseUp(self, event)  
47              sx, sy = self.start              sx, sy = self.start
             cx, cy = self.current  
             self.view.ZoomOutToRect((min(sx, cx), min(sy, cy),  
                                      max(sx, cx), max(sy, cy)))  
   
   
 class PanTool(Tool):  
   
     """The Pan Tool"""  
   
     def Name(self):  
         return "PanTool"  
   
     def MouseMove(self, event):  
         if self.dragging:  
             x0, y0 = self.current  
             Tool.MouseMove(self, event)  
48              x, y = self.current              x, y = self.current
49              width, height = self.view.GetSizeTuple()              width, height = self.view.GetSizeTuple()
             dc = self.view.drag_dc  
             dc.Blit(0, 0, width, height, dc, x0 - x, y0 - y)  
   
     def MouseUp(self, event):  
         if self.dragging:  
             Tool.MouseUp(self, event)  
             sx, sy = self.start  
             cx, cy = self.current  
             self.view.Translate(cx - sx, cy - sy)  
           
 class IdentifyTool(Tool):  
   
     """The "Identify" Tool"""  
       
     def Name(self):  
         return "IdentifyTool"  
   
     def MouseUp(self, event):  
         self.view.SelectShapeAt(event.m_x, event.m_y)  
   
   
 class LabelTool(Tool):  
   
     """The "Label" Tool"""  
   
     def Name(self):  
         return "LabelTool"  
   
     def MouseUp(self, event):  
         self.view.LabelShapeAt(event.m_x, event.m_y)  
   
50    
51                bitmapdc = wx.wxMemoryDC()
52                bitmapdc.SelectObject(self.view.bitmap)
53    
54                dc = self.view.drag_dc
55                dc.Blit(0, 0, width, height, bitmapdc, sx - x, sy - y)
56    
57  class MapPrintout(wx.wxPrintout):  class MapPrintout(wx.wxPrintout):
58    
# Line 199  class MapPrintout(wx.wxPrintout): Line 60  class MapPrintout(wx.wxPrintout):
60      wxPrintout class for printing Thuban maps      wxPrintout class for printing Thuban maps
61      """      """
62    
63      def __init__(self, map):      def __init__(self, canvas, map, region, selected_layer, selected_shapes):
64          wx.wxPrintout.__init__(self)          wx.wxPrintout.__init__(self)
65            self.canvas = canvas
66          self.map = map          self.map = map
67            self.region = region
68            self.selected_layer = selected_layer
69            self.selected_shapes = selected_shapes
70    
71      def GetPageInfo(self):      def GetPageInfo(self):
72          return (1, 1, 1, 1)          return (1, 1, 1, 1)
# Line 215  class MapPrintout(wx.wxPrintout): Line 80  class MapPrintout(wx.wxPrintout):
80    
81      def draw_on_dc(self, dc):      def draw_on_dc(self, dc):
82          width, height = self.GetPageSizePixels()          width, height = self.GetPageSizePixels()
83          llx, lly, urx, ury = self.map.ProjectedBoundingBox()          scale, offset, mapregion = output_transform(self.canvas.scale,
84          scalex = width / (urx - llx)                                                      self.canvas.offset,
85          scaley = height / (ury - lly)                                                      self.canvas.GetSizeTuple(),
86          scale = min(scalex, scaley)                                                      self.GetPageSizePixels())
         offx = 0.5 * (width - (urx + llx) * scale)  
         offy = 0.5 * (height + (ury + lly) * scale)  
   
87          resx, resy = self.GetPPIPrinter()          resx, resy = self.GetPPIPrinter()
88          renderer = PrinterRender(dc, scale, (offx, offy), resolution = resx)          renderer = PrinterRenderer(dc, scale, offset, resolution = resy)
89          renderer.RenderMap(self.map)          x, y, width, height = self.region
90          return wx.true          canvas_scale = self.canvas.scale
91                    renderer.RenderMap(self.map,
92                               (0,0,
93                                    (width/canvas_scale)*scale,
94                                    (height/canvas_scale)*scale),
95                                    mapregion,
96                               self.selected_layer, self.selected_shapes)
97            return True
98    
99  class MapCanvas(wxWindow):  class MapCanvas(wxWindow, ViewPort):
100    
101      """A widget that displays a map and offers some interaction"""      """A widget that displays a map and offers some interaction"""
102    
103      def __init__(self, parent, winid, interactor):      def __init__(self, parent, winid):
104          wxWindow.__init__(self, parent, winid)          wxWindow.__init__(self, parent, winid)
105            ViewPort.__init__(self)
106    
107          self.SetBackgroundColour(wxColour(255, 255, 255))          self.SetBackgroundColour(wxColour(255, 255, 255))
108          self.map = None  
109          self.scale = 1.0          # the bitmap serving as backing store
110          self.offset = (0, 0)          self.bitmap = None
111          self.dragging = 0  
112          self.tool = None          self.backgroundColor = wx.wxWHITE_BRUSH
113          self.redraw_on_idle = 0  
114            # Set to true if there ever is an error during redraw. There
115            # should never be errors, but unfortunately bugs happen.
116            self.error_on_redraw = 0
117    
118            # subscribe the WX events we're interested in
119          EVT_PAINT(self, self.OnPaint)          EVT_PAINT(self, self.OnPaint)
120          EVT_LEFT_DOWN(self, self.OnLeftDown)          EVT_LEFT_DOWN(self, self.OnLeftDown)
121          EVT_LEFT_UP(self, self.OnLeftUp)          EVT_LEFT_UP(self, self.OnLeftUp)
122          EVT_MOTION(self, self.OnMotion)          EVT_MOTION(self, self.OnMotion)
123            EVT_LEAVE_WINDOW(self, self.OnLeaveWindow)
124            wx.EVT_SIZE(self, self.OnSize)
125          wx.EVT_IDLE(self, self.OnIdle)          wx.EVT_IDLE(self, self.OnIdle)
         self.interactor = interactor  
         self.interactor.Subscribe(SELECTED_SHAPE, self.shape_selected)  
126    
127      def OnPaint(self, event):      def __del__(self):
128          dc = wxPaintDC(self)          wxWindow.__del__(self)
129          if self.map is None or not self.map.HasLayers():          ViewPort.__del__(self)
             return  
         self.redraw_on_idle = 1  
   
     def do_redraw(self):  
         width, height = self.GetSizeTuple()  
         bitmap = wx.wxEmptyBitmap(width, height)  
   
         dc = wx.wxMemoryDC()  
         dc.SelectObject(bitmap)  
130    
131          dc.BeginDrawing()      def PanTool(self):
132            """Start the canvas pan tool"""
133          dc.SetBrush(wx.wxWHITE_BRUSH)          self.SelectTool(CanvasPanTool(self))
         dc.SetPen(wx.wxTRANSPARENT_PEN)  
         dc.DrawRectangle(0, 0, width, height)  
   
         if 1: #self.interactor.selected_map is self.map:  
             selected_layer = self.interactor.selected_layer  
             selected_shape = self.interactor.selected_shape  
         else:  
             selected_layer = None  
             selected_shape = None  
               
         renderer = ScreenRenderer(dc, self.scale, self.offset)  
         renderer.RenderMap(self.map, selected_layer, selected_shape)  
   
         clientdc = wxClientDC(self)  
         clientdc.BeginDrawing()  
         clientdc.Blit(0, 0, width, height, dc, 0, 0)  
         clientdc.EndDrawing()  
   
   
     def Print(self):  
         printer = wx.wxPrinter()  
         printout = MapPrintout(self.map)  
         printer.Print(self, printout, wx.true)  
         printout.Destroy()  
134                    
135      def SetMap(self, map):      def SetMap(self, map):
136          redraw_channels = (LAYERS_CHANGED, LAYER_LEGEND_CHANGED,          redraw_channels = (MAP_LAYERS_CHANGED, LAYER_CHANGED,
137                             LAYER_VISIBILITY_CHANGED)                             LAYER_VISIBILITY_CHANGED)
138          if self.map is not None:          if self.Map() is not None:
139              for channel in redraw_channels:              for channel in redraw_channels:
140                  self.map.Unsubscribe(channel, self.redraw)                  self.Map().Unsubscribe(channel, self.full_redraw)
141              self.map.Unsubscribe(MAP_PROJECTION_CHANGED,  
142                                   self.projection_changed)          ViewPort.SetMap(self, map)
143          self.map = map  
144          if self.map is not None:          if self.Map() is not None:
145              for channel in redraw_channels:              for channel in redraw_channels:
146                  self.map.Subscribe(channel, self.redraw)                  self.Map().Subscribe(channel, self.full_redraw)
             self.map.Subscribe(MAP_PROJECTION_CHANGED, self.projection_changed)  
         self.FitMapToWindow()  
147    
148      def Map(self):          # force a redraw. If map is not empty, it's already been called
149          return self.map          # by FitMapToWindow but if map is empty it hasn't been called
150            # yet so we have to explicitly call it.
151            self.full_redraw()
152    
153      def redraw(self, *args):      def OnPaint(self, event):
154          self.Refresh(0)          dc = wxPaintDC(self)
155    
156      def projection_changed(self, *args):          if self.Map() is not None and self.Map().HasLayers():
157          self.FitMapToWindow()              if self.bitmap in (None, -1):
158          self.redraw()                  # set the flag that we should redraw the
159                    # bitmap in idle time
160                    self.bitmap = -1
161                else:
162                    # blit the bitmap to the screen
163                    dc.BeginDrawing()
164                    dc.DrawBitmap(self.bitmap, 0, 0)
165                    dc.EndDrawing()
166            else:
167                # If we've got no map or if the map is empty, simply clear
168                # the screen.
169    
170      def set_view_transform(self, scale, offset):              # XXX it's probably possible to get rid of this. The
171          self.scale = scale              # background color of the window is already white and the
172          self.offset = offset              # only thing we may have to do is to call self.Refresh()
173          self.redraw()              # with a true argument in the right places.
174                dc.BeginDrawing()
175                dc.SetBackground(self.backgroundColor)
176                dc.Clear()
177                dc.EndDrawing()
178    
179      def proj_to_win(self, x, y):      def OnIdle(self, event):
180          """\          """Idle handler. Redraw the bitmap if necessary"""
         Return the point in  window coords given by projected coordinates x y  
         """  
         offx, offy = self.offset  
         return (self.scale * x + offx, -self.scale * y + offy)  
181    
182      def win_to_proj(self, x, y):          if self.bitmap != -1:
183          """\              return
184          Return the point in projected coordinates given by window coords x y          if self.error_on_redraw:
185          """              return
         offx, offy = self.offset  
         return ((x - offx) / self.scale, (offy - y) / self.scale)  
186    
187      def FitRectToWindow(self, rect):          wxBeginBusyCursor()
188          width, height = self.GetSizeTuple()          try:
189          llx, lly, urx, ury = rect              try:
190          scalex = width / (urx - llx)                  self._do_redraw()
191          scaley = height / (ury - lly)              except:
192          scale = min(scalex, scaley)                  self.error_on_redraw = True
193          offx = 0.5 * (width - (urx + llx) * scale)                  raise
194          offy = 0.5 * (height + (ury + lly) * scale)          finally:
195          self.set_view_transform(scale, (offx, offy))              wxEndBusyCursor()
   
     def FitMapToWindow(self):  
         """\  
         Set the scale and offset so that the map is centered in the  
         window  
         """  
         bbox = self.map.ProjectedBoundingBox()  
         if bbox is not None:  
             self.FitRectToWindow(bbox)  
196    
197      def ZoomFactor(self, factor):      def _do_redraw(self):
198            """Called by OnIdle to do the actual redraw.
199            """
200          width, height = self.GetSizeTuple()          width, height = self.GetSizeTuple()
         scale = self.scale * factor  
         offx, offy = self.offset  
         offset = (factor * (offx - width / 2) + width / 2,  
                   factor * (offy - height / 2) + height / 2)  
         self.set_view_transform(scale, offset)  
201    
202      def ZoomOutToRect(self, rect):          bitmap = wx.wxEmptyBitmap(width, height)
203          # rect is given in window coordinates          dc = wx.wxMemoryDC()
204            dc.SelectObject(bitmap)
205            dc.BeginDrawing()
206    
207          # determine the bbox of the displayed region in projected          dc.SetBackground(self.backgroundColor)
208          # coordinates          dc.Clear()
         width, height = self.GetSizeTuple()  
         llx, lly = self.win_to_proj(0, height - 1)  
         urx, ury = self.win_to_proj(width - 1, 0)  
209    
210          sx, sy, ex, ey = rect          selected_layer = self.selection.SelectedLayer()
211          scalex = (ex - sx) / (urx - llx)          selected_shapes = self.selection.SelectedShapes()
         scaley = (ey - sy) / (ury - lly)  
         scale = min(scalex, scaley)  
   
         offx = 0.5 * ((ex + sx) - (urx + llx) * scale)  
         offy = 0.5 * ((ey + sy) + (ury + lly) * scale)  
         self.set_view_transform(scale, (offx, offy))  
   
     def Translate(self, dx, dy):  
         offx, offy = self.offset  
         self.set_view_transform(self.scale, (offx + dx, offy + dy))  
212    
213      def ZoomInTool(self):          # draw the map into the bitmap
214          self.tool = ZoomInTool(self)          renderer = ScreenRenderer(dc, self.scale, self.offset)
215    
216      def ZoomOutTool(self):          # Pass the entire bitmap as update region to the renderer.
217          self.tool = ZoomOutTool(self)          # We're redrawing the whole bitmap, after all.
218            renderer.RenderMap(self.Map(), (0, 0, width, height),
219                               selected_layer, selected_shapes)
220    
221      def PanTool(self):          dc.EndDrawing()
222          self.tool = PanTool(self)          dc.SelectObject(wx.wxNullBitmap)
223    
224            self.bitmap = bitmap
225            # This causes a paint event that then draws the bitmap
226            self.redraw()
227    
228        def Export(self):
229    
230            if hasattr(self, "export_path"):
231                export_path = self.export_path
232            else:
233                export_path="."
234            dlg = wxFileDialog(self, _("Export Map"), export_path, "",
235                               "Enhanced Metafile (*.wmf)|*.wmf",
236                               wxSAVE|wxOVERWRITE_PROMPT)
237            if dlg.ShowModal() == wxID_OK:
238                self.export_path = os.path.dirname(dlg.GetPath())
239                dc = wxMetaFileDC(dlg.GetPath())
240        
241                scale, offset, mapregion = output_transform(self.scale,
242                                                            self.offset,
243                                                            self.GetSizeTuple(),
244                                                            dc.GetSizeTuple())
245    
246                selected_layer = self.selection.SelectedLayer()
247                selected_shapes = self.selection.SelectedShapes()
248    
249                renderer = ExportRenderer(dc, scale, offset)
250    
251                # Pass the entire bitmap as update region to the renderer.
252                # We're redrawing the whole bitmap, after all.
253                width, height = self.GetSizeTuple()
254                renderer.RenderMap(self.Map(),
255                                    (0,0,
256                                        (width/self.scale)*scale,
257                                        (height/self.scale)*scale),
258                                    mapregion,
259                                    selected_layer, selected_shapes)
260                dc.EndDrawing()
261                dc.Close()
262            dlg.Destroy()
263            
264        def Print(self):
265            printer = wx.wxPrinter()
266            width, height = self.GetSizeTuple()
267            selected_layer = self.selection.SelectedLayer()
268            selected_shapes = self.selection.SelectedShapes()
269            
270            printout = MapPrintout(self, self.Map(), (0, 0, width, height),
271                                   selected_layer, selected_shapes)
272            printer.Print(self, printout, True)
273            printout.Destroy()
274    
275      def IdentifyTool(self):      def redraw(self, *args):
276          self.tool = IdentifyTool(self)          self.Refresh(False)
277    
278        def full_redraw(self, *args):
279            self.bitmap = None
280            self.redraw()
281    
282      def LabelTool(self):      def map_projection_changed(self, map, old_proj):
283          self.tool = LabelTool(self)          ViewPort.map_projection_changed(self, map, old_proj)
284            self.full_redraw()
285    
286        def layer_projection_changed(self, *args):
287            ViewPort.layer_projection_changed(self, args)
288            self.full_redraw()
289    
290      def CurrentTool(self):      def set_view_transform(self, scale, offset):
291          return self.tool and self.tool.Name() or None          ViewPort.set_view_transform(self, scale, offset)
292            self.full_redraw()
293    
294        def GetPortSizeTuple(self):
295            return self.GetSizeTuple()
296    
297      def OnLeftDown(self, event):      def OnLeftDown(self, event):
298            self.MouseLeftDown(event)
299          if self.tool is not None:          if self.tool is not None:
300              self.drag_dc = wxClientDC(self)              self.drag_dc = wxClientDC(self)
301              self.drag_dc.SetLogicalFunction(wxINVERT)              self.drag_dc.SetLogicalFunction(wxINVERT)
302              self.drag_dc.SetBrush(wxTRANSPARENT_BRUSH)              self.drag_dc.SetBrush(wxTRANSPARENT_BRUSH)
             self.CaptureMouse()  
             self.tool.MouseDown(event)  
303              self.tool.Show(self.drag_dc)              self.tool.Show(self.drag_dc)
304                self.CaptureMouse()
305              self.dragging = 1              self.dragging = 1
306            
307      def OnLeftUp(self, event):      def OnLeftUp(self, event):
308          self.ReleaseMouse()          self.MouseLeftUp(event)
309          if self.dragging:          if self.dragging:
310              self.tool.Hide(self.drag_dc)              self.ReleaseMouse()
311              self.tool.MouseUp(event)              try:
312              self.drag_dc = None                  self.tool.Hide(self.drag_dc)
313          self.dragging = 0              finally:
314                    self.drag_dc = None
315                    self.dragging = 0
316    
317      def OnMotion(self, event):      def OnMotion(self, event):
318          if self.dragging:          if self.dragging:
319              self.tool.Hide(self.drag_dc)              self.tool.Hide(self.drag_dc)
             self.tool.MouseMove(event)  
             self.tool.Show(self.drag_dc)  
320    
321      def OnIdle(self, event):          self.MouseMove(event)
         if self.redraw_on_idle:  
             self.do_redraw()  
         self.redraw_on_idle = 0  
322    
323      def shape_selected(self, layer, shape):          if self.dragging:
324          self.redraw()              self.tool.Show(self.drag_dc)
   
     def find_shape_at(self, px, py, select_labels = 0):  
         """Return a tuple shape at point px, py in window coords."""  
         map_proj = self.map.projection  
         if map_proj is not None:  
             forward = map_proj.Forward  
         else:  
             forward = None  
325    
326          scale = self.scale      def OnLeaveWindow(self, event):
327          offx, offy = self.offset          self.set_current_position(None)
328    
329          if select_labels:      def OnSize(self, event):
330              labels = self.map.LabelLayer().Labels()          # the window's size has changed. We have to get a new bitmap. If
331                        # we want to be clever we could try to get by without throwing
332              if labels:          # everything away. E.g. when the window gets smaller, we could
333                  dc = wxClientDC(self)          # either keep the bitmap or create the new one from the old one.
334                  font = wxFont(10, wx.wxSWISS, wx.wxNORMAL, wx.wxNORMAL)          # Even when the window becomes larger some parts of the bitmap
335                  dc.SetFont(font)          # could be reused.
336                  for i in range(len(labels)):          self.full_redraw()
                     label = labels[i]  
                     x = label.x  
                     y = label.y  
                     text = label.text  
                     if forward:  
                         x, y = forward(x, y)  
                     x = x * scale + offx  
                     y = -y * scale + offy  
                     width, height = dc.GetTextExtent(text)  
                     if label.halign == ALIGN_LEFT:  
                         # nothing to be done  
                         pass  
                     elif label.halign == ALIGN_RIGHT:  
                         x = x - width  
                     elif label.halign == ALIGN_CENTER:  
                         x = x - width/2  
                     if label.valign == ALIGN_TOP:  
                         # nothing to be done  
                         pass  
                     elif label.valign == ALIGN_BOTTOM:  
                         y = y - height  
                     elif label.valign == ALIGN_CENTER:  
                         y = y - height/2  
                     if x <= px < x + width and y <= py <= y + height:  
                         return None, i  
                   
         layers = self.map.Layers()  
         for layer_index in range(len(layers) - 1, -1, -1):  
             layer = layers[layer_index]  
   
             # search only in visible layers  
             if not layer.Visible():  
                 continue  
   
             filled = layer.fill is not None  
             stroked = layer.stroke is not None  
                   
             layer_proj = layer.projection  
             if layer_proj is not None:  
                 inverse = layer_proj.Inverse  
             else:  
                 inverse = None  
                   
             shapetype = layer.ShapeType()  
   
             select_shape = -1  
             if shapetype == SHAPETYPE_POLYGON:  
                 for i in range(layer.NumShapes()):  
                     result = point_in_polygon_shape(layer.shapefile.cobject(),  
                                                     i,  
                                                     filled, stroked,  
                                                     map_proj, layer_proj,  
                                                     scale, -scale, offx, offy,  
                                                     px, py)  
                     if result:  
                         select_shape = i  
                         break  
             elif shapetype == SHAPETYPE_ARC:  
                 for i in range(layer.NumShapes()):  
                     result = point_in_polygon_shape(layer.shapefile.cobject(),  
                                                     i, 0, 1,  
                                                     map_proj, layer_proj,  
                                                     scale, -scale, offx, offy,  
                                                     px, py)  
                     if result < 0:  
                         select_shape = i  
                         break  
             elif shapetype == SHAPETYPE_POINT:  
                 for i in range(layer.NumShapes()):  
                     shape = layer.Shape(i)  
                     x, y = shape.Points()[0]  
                     if inverse:  
                         x, y = inverse(x, y)  
                     if forward:  
                         x, y = forward(x, y)  
                     x = x * scale + offx  
                     y = -y * scale + offy  
                     if hypot(px - x, py - y) < 5:  
                         select_shape = i  
                         break  
   
             if select_shape >= 0:  
                 return layer, select_shape  
         return None, None  
   
     def SelectShapeAt(self, x, y):  
         layer, shape = self.find_shape_at(x, y)  
         self.interactor.SelectLayerAndShape(layer, shape)  
337    
338      def LabelShapeAt(self, x, y):      def shape_selected(self, layer, shape):
339          ox = x; oy = y          """Receiver for the SHAPES_SELECTED messages. Redraw the map."""
340            # The selection object takes care that it only issues
341            # SHAPES_SELECTED messages when the set of selected shapes has
342            # actually changed, so we can do a full redraw unconditionally.
343            # FIXME: We should perhaps try to limit the redraw to the are
344            # actually covered by the shapes before and after the selection
345            # change.
346            ViewPort.shape_selected(self, layer, shape)
347            self.full_redraw()
348    
349        def GetTextExtent(self, text):
350            dc = wxClientDC(self)
351            font = wxFont(10, wx.wxSWISS, wx.wxNORMAL, wx.wxNORMAL)
352            dc.SetFont(font)
353            return dc.GetTextExtent(text)
354    
355        def LabelShapeAt(self, x, y, text=None):
356            """Add or remove a label at window position x, y.
357    
358            If there's a label at the given position, remove it. Otherwise
359            determine the shape at the position, run the label dialog and
360            unless the user cancels the dialog, add a label.
361            """
362          label_layer = self.map.LabelLayer()          label_layer = self.map.LabelLayer()
363          layer, shape_index = self.find_shape_at(x, y, select_labels = 1)          layer, shape_index = self.find_shape_at(x, y, select_labels = 1)
364          if layer is None and shape_index is not None:          if layer is None and shape_index is not None:
365              # a label was selected              ViewPort.LabelShapeAt(self, x, y)
             label_layer.RemoveLabel(shape_index)  
366          elif layer is not None:          elif layer is not None:
367              text = labeldialog.run_label_dialog(self, layer.table, shape_index)              text = labeldialog.run_label_dialog(self,
368              if text:                                                  layer.ShapeStore().Table(),
369                  proj = self.map.projection                                                  shape_index)
370                  if proj is not None:              ViewPort.LabelShapeAt(self, x, y, text)
                     map_proj = proj  
                 else:  
                     map_proj = None  
                 proj = layer.projection  
                 if proj is not None:  
                     layer_proj = proj  
                 else:  
                     layer_proj = None  
   
                 shapetype = layer.ShapeType()  
                 if shapetype == SHAPETYPE_POLYGON:  
                     x, y = shape_centroid(layer.shapefile.cobject(),  
                                           shape_index,  
                                           map_proj, layer_proj, 1, 1, 0, 0)  
                     if map_proj is not None:  
                         x, y = map_proj.Inverse(x, y)  
                 else:  
                     shape = layer.Shape(shape_index)  
                     if shapetype == SHAPETYPE_POINT:  
                         x, y = shape.Points()[0]  
                     else:  
                         # assume SHAPETYPE_ARC  
                         points = shape.Points()  
                         x, y = points[len(points) / 2]  
                     if layer_proj is not None:  
                         x, y = layer_proj.Inverse(x, y)  
                 if shapetype == SHAPETYPE_POINT:  
                     halign = ALIGN_LEFT  
                     valign = ALIGN_CENTER  
                 elif shapetype == SHAPETYPE_POLYGON:  
                     halign = ALIGN_CENTER  
                     valign = ALIGN_CENTER  
                 elif shapetype == SHAPETYPE_ARC:  
                     halign = ALIGN_LEFT  
                     valign = ALIGN_CENTER  
                 label_layer.AddLabel(x, y, text,  
                                      halign = halign, valign = valign)  

Legend:
Removed from v.23  
changed lines
  Added in v.1552

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26