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

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

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

revision 668 by jonathan, Mon Apr 14 17:12:57 2003 UTC revision 2187 by jan, Sun Apr 18 20:37:45 2004 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jonathan Coles <[email protected]>  # Jonathan Coles <[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.
8    
9  __version__ = "$Revision$"  __version__ = "$Revision$"
10    
11    from  math import fabs, cos, pi
12    
13  from Thuban import _  from Thuban import _
14    
15  import resource  import resource
16    
17  from wxPython.wx import *  from wxPython.wx import *
18    
19  from Thuban.Model.layer import Layer  from Thuban.Model.layer import BaseLayer
20  from Thuban.Model.map import Map  from Thuban.Model.map import Map
 from Thuban.Model.messages import *  
21  from Thuban.Model.classification import ClassGroup  from Thuban.Model.classification import ClassGroup
22    from Thuban.Model.proj import PROJ_UNITS_DEGREES
23    
24    from Thuban.Model.messages import \
25        MAP_STACKING_CHANGED, MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED, LAYER_CHANGED,\
26        LAYER_VISIBILITY_CHANGED, TITLE_CHANGED
27    
28    from Thuban.UI.messages import SCALE_CHANGED
29    
 from Thuban.UI.messages import *  
30  from Thuban.UI.classifier import ClassDataPreviewer  from Thuban.UI.classifier import ClassDataPreviewer
31  from Thuban.UI.dock import DockPanel  from Thuban.UI.dock import DockPanel
32    from Thuban.UI.scalebar import ScaleBar
33    
34    from Thuban.UI.menu import Menu
35    
36  from Thuban.Lib.connector import ConnectorError  from Thuban.Lib.connector import ConnectorError
37    
38  ID_LEGEND_RAISE = 4001  ID_LEGEND_TOP = 4001
39  ID_LEGEND_LOWER = 4002  ID_LEGEND_RAISE = 4002
40  ID_LEGEND_TREE = 4003  ID_LEGEND_LOWER = 4003
41  ID_LEGEND_PROPS = 4004  ID_LEGEND_BOTTOM = 4004
42  ID_LEGEND_SHOWLAYER = 4005  ID_LEGEND_TREE = 4005
43  ID_LEGEND_HIDELAYER = 4006  ID_LEGEND_PROPS = 4006
44    ID_LEGEND_SHOWLAYER = 4007
45    ID_LEGEND_HIDELAYER = 4008
46    
47  BMP_SIZE_W = 30  BMP_SIZE_W = 15
48  BMP_SIZE_H = 15  BMP_SIZE_H = 15
49    
50    TOP_BMP = "top_layer"
51  RAISE_BMP = "raise_layer"  RAISE_BMP = "raise_layer"
52  LOWER_BMP = "lower_layer"  LOWER_BMP = "lower_layer"
53    BOTTOM_BMP = "bottom_layer"
54  SHOW_BMP  = "show_layer"  SHOW_BMP  = "show_layer"
55  HIDE_BMP  = "hide_layer"  HIDE_BMP  = "hide_layer"
56  PROPS_BMP = "layer_properties"  PROPS_BMP = "layer_properties"
57    
   
58  class LegendPanel(DockPanel):  class LegendPanel(DockPanel):
59    
60      def __init__(self, parent, map, mainWindow):      def __init__(self, parent, map, mainWindow):
# Line 56  class LegendPanel(DockPanel): Line 70  class LegendPanel(DockPanel):
70          self.toolBar = wxToolBar(self, -1)          self.toolBar = wxToolBar(self, -1)
71          self.toolBar.SetToolBitmapSize(wxSize(24, 24))          self.toolBar.SetToolBitmapSize(wxSize(24, 24))
72    
73            bmp = resource.GetBitmapResource(TOP_BMP, wxBITMAP_TYPE_XPM)
74            self.toolBar.AddTool(ID_LEGEND_TOP, bmp,
75                shortHelpString=_("Top Layer"))
76    
77          bmp = resource.GetBitmapResource(RAISE_BMP, wxBITMAP_TYPE_XPM)          bmp = resource.GetBitmapResource(RAISE_BMP, wxBITMAP_TYPE_XPM)
78          self.toolBar.AddTool(ID_LEGEND_RAISE, bmp,          self.toolBar.AddTool(ID_LEGEND_RAISE, bmp,
79              shortHelpString=_("Raise Layer"))              shortHelpString=_("Raise Layer"))
# Line 64  class LegendPanel(DockPanel): Line 82  class LegendPanel(DockPanel):
82          self.toolBar.AddTool(ID_LEGEND_LOWER, bmp,          self.toolBar.AddTool(ID_LEGEND_LOWER, bmp,
83              shortHelpString=_("Lower Layer"))              shortHelpString=_("Lower Layer"))
84    
85            bmp = resource.GetBitmapResource(BOTTOM_BMP, wxBITMAP_TYPE_XPM)
86            self.toolBar.AddTool(ID_LEGEND_BOTTOM, bmp,
87                shortHelpString=_("Bottom Layer"))
88    
89          bmp = resource.GetBitmapResource(SHOW_BMP, wxBITMAP_TYPE_XPM)          bmp = resource.GetBitmapResource(SHOW_BMP, wxBITMAP_TYPE_XPM)
90          self.toolBar.AddTool(ID_LEGEND_SHOWLAYER, bmp,          self.toolBar.AddTool(ID_LEGEND_SHOWLAYER, bmp,
91              shortHelpString=_("Show Layer"))              shortHelpString=_("Show Layer"))
# Line 79  class LegendPanel(DockPanel): Line 101  class LegendPanel(DockPanel):
101          self.toolBar.Realize()          self.toolBar.Realize()
102          panelBox.Add(self.toolBar, 0, wxGROW, 0)          panelBox.Add(self.toolBar, 0, wxGROW, 0)
103    
104            EVT_TOOL(self, ID_LEGEND_TOP, self._OnMoveTop)
105          EVT_TOOL(self, ID_LEGEND_RAISE, self._OnMoveUp)          EVT_TOOL(self, ID_LEGEND_RAISE, self._OnMoveUp)
106          EVT_TOOL(self, ID_LEGEND_LOWER, self._OnMoveDown)          EVT_TOOL(self, ID_LEGEND_LOWER, self._OnMoveDown)
107            EVT_TOOL(self, ID_LEGEND_BOTTOM, self._OnMoveBottom)
108          EVT_TOOL(self, ID_LEGEND_PROPS, self._OnProperties)          EVT_TOOL(self, ID_LEGEND_PROPS, self._OnProperties)
109          EVT_TOOL(self, ID_LEGEND_SHOWLAYER, self._OnShowLayer)          EVT_TOOL(self, ID_LEGEND_SHOWLAYER, self._OnShowLayer)
110          EVT_TOOL(self, ID_LEGEND_HIDELAYER, self._OnHideLayer)          EVT_TOOL(self, ID_LEGEND_HIDELAYER, self._OnHideLayer)
# Line 89  class LegendPanel(DockPanel): Line 113  class LegendPanel(DockPanel):
113    
114          panelBox.Add(self.tree, 1, wxGROW, 0)          panelBox.Add(self.tree, 1, wxGROW, 0)
115    
116            self.scalebarbitmap = ScaleBarBitmap(self, map, mainWindow)
117            panelBox.Add(self.scalebarbitmap, 0, wxGROW, 0)
118    
119          self.SetAutoLayout(True)          self.SetAutoLayout(True)
120          self.SetSizer(panelBox)          self.SetSizer(panelBox)
121          panelBox.SetSizeHints(self)          panelBox.SetSizeHints(self)
# Line 108  class LegendPanel(DockPanel): Line 135  class LegendPanel(DockPanel):
135    
136      def SetMap(self, map):      def SetMap(self, map):
137          self.tree.SetMap(map)          self.tree.SetMap(map)
138            self.scalebarbitmap.SetCanvas(self.mainWindow.canvas)
139    
140      def DoOnSelChanged(self, layer, group):      def DoOnSelChanged(self, layer, group):
141    
142          ok = isinstance(layer, Layer)          ok = isinstance(layer, BaseLayer)
143          self.__EnableButtons(ok)          self.__EnableButtons(ok)
144    
145          self.mainWindow.SelectLayer(layer)          self.mainWindow.SelectLayer(layer)
# Line 119  class LegendPanel(DockPanel): Line 147  class LegendPanel(DockPanel):
147      def DoOnProperties(self):      def DoOnProperties(self):
148          list = self.tree.GetSelectedHierarchy()          list = self.tree.GetSelectedHierarchy()
149    
150          ok = isinstance(list[0], Layer)          ok = isinstance(list[0], BaseLayer)
151          if ok:          if ok:
152              self.mainWindow.OpenLayerProperties(list[0], list[1])              self.mainWindow.OpenLayerProperties(list[0], list[1])
153    
# Line 129  class LegendPanel(DockPanel): Line 157  class LegendPanel(DockPanel):
157      def _OnProperties(self, event):      def _OnProperties(self, event):
158          self.DoOnProperties()          self.DoOnProperties()
159    
160        def _OnMoveTop(self, event):
161            self.tree.MoveCurrentItemTop()
162            
163      def _OnMoveUp(self, event):      def _OnMoveUp(self, event):
164          self.tree.MoveCurrentItemUp()          self.tree.MoveCurrentItemUp()
165    
166      def _OnMoveDown(self, event):      def _OnMoveDown(self, event):
167          self.tree.MoveCurrentItemDown()          self.tree.MoveCurrentItemDown()
168    
169        def _OnMoveBottom(self, event):
170            self.tree.MoveCurrentItemBottom()
171    
172      def _OnShowLayer(self, event):      def _OnShowLayer(self, event):
173          self.tree.DoOnShowLayer()          self.tree.DoOnShowLayer()
174          pass          pass
# Line 149  class LegendPanel(DockPanel): Line 183  class LegendPanel(DockPanel):
183          self.tree.DoOnHideLayer()          self.tree.DoOnHideLayer()
184          pass          pass
185    
186        def _OnToggleVisibility(self, event):
187            self.tree.ToggleVisibility()
188    
189        def _OnProjection(self, event):
190            self.tree.LayerProjection()
191    
192        def _OnRemoveLayer(self, event):
193            self.mainWindow.RemoveLayer()
194    
195        def _OnShowTable(self, event):
196            self.mainWindow.LayerShowTable()
197    
198      def __EnableButtons(self, on):      def __EnableButtons(self, on):
199            self.toolBar.EnableTool(ID_LEGEND_TOP, on)
200          self.toolBar.EnableTool(ID_LEGEND_RAISE, on)          self.toolBar.EnableTool(ID_LEGEND_RAISE, on)
201          self.toolBar.EnableTool(ID_LEGEND_LOWER, on)          self.toolBar.EnableTool(ID_LEGEND_LOWER, on)
202            self.toolBar.EnableTool(ID_LEGEND_BOTTOM, on)
203          self.toolBar.EnableTool(ID_LEGEND_SHOWLAYER,  on)          self.toolBar.EnableTool(ID_LEGEND_SHOWLAYER,  on)
204          self.toolBar.EnableTool(ID_LEGEND_HIDELAYER,  on)          self.toolBar.EnableTool(ID_LEGEND_HIDELAYER,  on)
205          self.toolBar.EnableTool(ID_LEGEND_PROPS, on)          self.toolBar.EnableTool(ID_LEGEND_PROPS, on)
# Line 169  class LegendTree(wxTreeCtrl): Line 217  class LegendTree(wxTreeCtrl):
217          self.mainWindow = mainWindow          self.mainWindow = mainWindow
218          self.map = None          self.map = None
219          self.parent = parent          self.parent = parent
220          self.layer2id = {}          self.changing_selection = 0
221    
222            #
223            # The image list used by the wxTreeCtrl causes problems when
224            # we remove layers and/or change a classification because it
225            # changes the image indices if you remove images from the list.
226            # Rather than removing unused images we use this list to keep
227            # track of which indices are available in the image list
228            # (because of a previous removal) and then  replace those indices
229            # with new images rather than appending to the end of the image
230            # list (assuming there are any that are available).
231            #
232            self.availImgListIndices = []
233    
234          self.image_list = None          self.image_list = None
235          self.emptyImageIndex = 0          self.emptyImageIndex = 0
236    
237          self.previewer = ClassDataPreviewer()          self.previewer = ClassDataPreviewer()
238    
239            self.preventExpandCollapse = False
240            self.raiseProperties = False
241    
242          EVT_TREE_ITEM_ACTIVATED(self, ID_LEGEND_TREE, self._OnItemActivated)          EVT_TREE_ITEM_ACTIVATED(self, ID_LEGEND_TREE, self._OnItemActivated)
243          EVT_TREE_SEL_CHANGED(self, ID_LEGEND_TREE, self._OnSelChanged)          EVT_TREE_SEL_CHANGED(self, ID_LEGEND_TREE, self._OnSelChanged)
244            EVT_TREE_ITEM_EXPANDING(self, ID_LEGEND_TREE, self.OnItemExpandCollapse)
245            EVT_TREE_ITEM_COLLAPSING(self, ID_LEGEND_TREE, self.OnItemExpandCollapse)
246            EVT_TREE_ITEM_RIGHT_CLICK(self, ID_LEGEND_TREE, self._OnRightClick)
247    
248          EVT_CLOSE(self, self._OnClose)          EVT_CLOSE(self, self._OnClose)
249    
250          self.SetMap(map)          self.SetMap(map)
251    
252        def _OnRightClick(self, event):
253            """Select item and pop up a context menu"""
254    
255            # The pop up menu is related to the legend tree, so we have direct
256            # access on the tree items. The events issued by the menu are handled
257            # by the legend panel, since most of the handlers are already
258            # implemented there.
259    
260            # Update item selection to the right click
261            item = event.GetItem()
262            self.SelectItem(item)
263    
264            # Define the menu
265            popup_menu = Menu("PopUp", "",
266                              [ "layer_visibility",
267                                None,
268                                "layer_properties",
269                                "layer_projection",
270                                "layer_remove",
271                                "layer_show_table",
272                                None,
273                                "layer_to_top",
274                                "layer_raise",
275                                "layer_lower",
276                                "layer_to_bottom"
277                                ])
278    
279            # Display the menu
280            pos = event.GetPoint()
281            shift = self.ClientToScreen((0,0))
282            self.PopupMenu(self.mainWindow.build_menu(popup_menu), pos)
283    
284        def find_layer(self, layer):
285            """Return the tree item for the layer"""
286            root = self.GetRootItem()
287            id, cookie = self.GetFirstChild(root, 0)
288            while id.IsOk():
289                if self.GetPyData(id) is layer:
290                    return id
291                id, cookie = self.GetNextChild(root, cookie)
292            return None
293    
294      def _OnClose(self, event):      def _OnClose(self, event):
295          self.SetMap(None)          self.SetMap(None)
296    
# Line 192  class LegendTree(wxTreeCtrl): Line 300  class LegendTree(wxTreeCtrl):
300      def SetMap(self, map):      def SetMap(self, map):
301    
302          sub_list = [(MAP_STACKING_CHANGED, self._OnMsgMapStackingChanged),          sub_list = [(MAP_STACKING_CHANGED, self._OnMsgMapStackingChanged),
303                      (MAP_LAYERS_ADDED, self._OnMsgMapLayersAddedRemoved),                      (MAP_LAYERS_ADDED, self._OnMsgMapLayersAdded),
304                      (MAP_LAYERS_REMOVED, self._OnMsgMapLayersAddedRemoved)]                      (MAP_LAYERS_REMOVED, self._OnMsgMapLayersRemoved)]
305    
306          if self.map is not None:          if self.map is not None:
307              for msg, func in sub_list: self.map.Unsubscribe(msg, func)              for msg, func in sub_list: self.map.Unsubscribe(msg, func)
# Line 204  class LegendTree(wxTreeCtrl): Line 312  class LegendTree(wxTreeCtrl):
312                      #self._OnMsgMapsChanged)                      #self._OnMsgMapsChanged)
313              #except ConnectorError:              #except ConnectorError:
314                  #pass                  #pass
315              self.__DeleteAllItems()              self.DeleteAllItems()
316                    
317          self.map = map          self.map = map
318    
# Line 216  class LegendTree(wxTreeCtrl): Line 324  class LegendTree(wxTreeCtrl):
324                  #self._OnMsgMapsChanged)                  #self._OnMsgMapsChanged)
325              self.__FillTree(self.map)              self.__FillTree(self.map)
326    
327                    def MoveCurrentItemTop(self):
328      def MoveCurrentItemUp(self):          layer, group = self.GetSelectedHierarchy()
         cur_id = self.GetSelection()  
         assert cur_id.IsOk()  
   
         cur_data = self.GetPyData(cur_id)  
329    
330          #prev_id = self.GetPrevSibling(cur_id)          if layer is not None:
331                self.map.MoveLayerToTop(layer)
332            else:
333                assert False, "Shouldn't be allowed."
334                pass
335    
336          #      def MoveCurrentItemUp(self):
337          # Get out if there's nowhere to go          layer, group = self.GetSelectedHierarchy()
         #  
         #if prev_id == INVALID_TREE_ID: return  
338    
339          if isinstance(cur_data, Layer):          if layer is not None:
340              self.map.RaiseLayer(cur_data)              self.map.RaiseLayer(layer)
         elif isinstance(cur_data, ClassGroup):  
             pass  
341          else:          else:
342              assert False, "Shouldn't be here."              assert False, "Shouldn't be allowed."
343              pass              pass
344    
345      def MoveCurrentItemDown(self):      def MoveCurrentItemDown(self):
346          cur_id = self.GetSelection()          layer, group = self.GetSelectedHierarchy()
         assert cur_id.IsOk()  
   
         cur_data = self.GetPyData(cur_id)  
347    
348          if isinstance(cur_data, Layer):          if layer is not None:
349              self.map.LowerLayer(cur_data)              self.map.LowerLayer(layer)
         elif isinstance(cur_data, ClassGroup):  
             pass  
350          else:          else:
351              assert False, "Shouldn't be here."              assert False, "Shouldn't be allowed."
352              pass              pass
353    
354        def MoveCurrentItemBottom(self):
355            layer, group = self.GetSelectedHierarchy()
356    
357            if layer is not None:
358                self.map.MoveLayerToBottom(layer)
359            else:
360                assert False, "Shouldn't be allowed."
361                pass
362    
363      def OnCompareItems(self, item1, item2):      def OnCompareItems(self, item1, item2):
364    
365          data1 = self.GetPyData(item1)          data1 = self.GetPyData(item1)
366          data2 = self.GetPyData(item2)          data2 = self.GetPyData(item2)
367    
368          if isinstance(data1, Layer):          if isinstance(data1, BaseLayer):
369              layers = self.map.Layers()              layers = self.map.Layers()
370              return layers.index(data2) - layers.index(data1)              return layers.index(data2) - layers.index(data1)
371          else:          else:
372              return wxTreeCtrl.OnCompareItems(self, item1, item2)              return wxTreeCtrl.OnCompareItems(self, item1, item2)
373    
   
374      def DoOnShowLayer(self):      def DoOnShowLayer(self):
         #self.__ShowHideLayer(True)  
375          layer, group = self.GetSelectedHierarchy()          layer, group = self.GetSelectedHierarchy()
376          layer.SetVisible(True)          layer.SetVisible(True)
377    
378      def DoOnHideLayer(self):      def DoOnHideLayer(self):
         #self.__ShowHideLayer(False)  
379          layer, group = self.GetSelectedHierarchy()          layer, group = self.GetSelectedHierarchy()
380          layer.SetVisible(False)          layer.SetVisible(False)
381    
382        def ToggleVisibility(self):
383            layer, group = self.GetSelectedHierarchy()
384    
385            layer.SetVisible(not layer.Visible())
386    
387        def LayerProjection(self):
388            self.parent.mainWindow.LayerProjection()
389    
390      def Sort(self):      def Sort(self):
391          self.SortChildren(self.GetRootItem())          self.SortChildren(self.GetRootItem())
392    
# Line 300  class LegendTree(wxTreeCtrl): Line 412  class LegendTree(wxTreeCtrl):
412          self.SetMap(self.mainWindow.Map())          self.SetMap(self.mainWindow.Map())
413                    
414      def _OnSelChanged(self, event):      def _OnSelChanged(self, event):
415            # If we change the selection from normalize_selection do nothing.
416            if self.changing_selection:
417                return
418    
419            self.normalize_selection()
420          self.__UpdateSelection()          self.__UpdateSelection()
421    
422        def normalize_selection(self):
423            """Select the layer containing currently selected item"""
424            # This is really a workaround for a bug in wx where deleting a
425            # subtree with DeleteChildren does not update the selection
426            # properly and can lead to segfaults later because the return
427            # value of GetSelection points to invalid data.
428            item = self.GetSelection()
429            while item.IsOk():
430                object = self.GetPyData(item)
431                if isinstance(object, BaseLayer):
432                    break
433                item = self.GetItemParent(item)
434            else:
435                # No layer was found in the chain of parents, so there's
436                # nothing we can do.
437                return
438    
439            self.changing_selection = 1
440            try:
441                self.SelectItem(item)
442            finally:
443                self.changing_selection = 0
444    
445    
446        def OnItemExpandCollapse(self, event):
447            if self.preventExpandCollapse:
448                event.Veto()
449                self.preventExpandCollapse = False
450    
451      def _OnItemActivated(self, event):      def _OnItemActivated(self, event):
452          self.parent.DoOnProperties()          # The following looks strange but is need under Windows to
453            # raise the Properties on double-click: The tree control
454            # always gets an Expanded / Collapsed event after the ItemActivated
455            # on double click, which raises the main window again. We add a second
456            # ItemActivated event to the queue, which simply raises the already
457            # displayed window.
458            if self.raiseProperties:
459                self.parent.DoOnProperties()
460                self.raiseProperties = False
461            else:
462                self.raiseProperties = True
463                self.preventExpandCollapse = True
464                self.parent.DoOnProperties()
465                self.AddPendingEvent(event)
466    
467      def _OnMsgLayerChanged(self, layer):      def _OnMsgLayerChanged(self, layer):
468          assert isinstance(layer, Layer)          assert isinstance(layer, BaseLayer)
469    
470          id = self.layer2id[layer]          id = self.find_layer(layer)
471          assert id.IsOk()          assert id is not None
472    
473          # XXX: yikes! this is so bad, we should be doing what is          self.__FillTreeLayer(id)
         #      commented out, but there is a problem with keeping  
         #      track of the images in the image list when we replace  
         #      a layer. it ends up causing a seg fault.  
         self.__FillTree(self.map)  
474          self.__UpdateSelection()          self.__UpdateSelection()
         #self.__FillTreeLayer(id)  
475    
476      def _OnMsgMapStackingChanged(self, *args):      def _OnMsgMapStackingChanged(self, *args):
477          self.Sort()          self.Sort()
# Line 327  class LegendTree(wxTreeCtrl): Line 481  class LegendTree(wxTreeCtrl):
481              self.EnsureVisible(id)              self.EnsureVisible(id)
482          self.__UpdateSelection()          self.__UpdateSelection()
483    
484      def _OnMsgMapLayersAddedRemoved(self, map):      def _OnMsgMapLayersAdded(self, map):
485            assert map is self.map
486    
487            # Build a dict with all layers known by the the tree as keys
488            layers = {}
489            root = self.GetRootItem()
490            id, cookie = self.GetFirstChild(root, 0)
491            while id.IsOk():
492                layers[self.GetPyData(id)] = 1
493                id, cookie = self.GetNextChild(root, cookie)
494    
495            # Add layers in the map but not in the dict
496            i = 0
497            for l in map.Layers():
498                if not l in layers:
499                    self.__AddLayer(i, l)
500    
501            self.__UpdateSelection()
502    
503        def _OnMsgMapLayersRemoved(self, map):
504          assert map is self.map          assert map is self.map
505    
506          self.__FillTree(self.map)          layers = map.Layers()
507    
508            root = self.GetRootItem()
509            id, cookie = self.GetFirstChild(root, 0)
510            while id.IsOk():
511                if self.GetPyData(id) not in layers:
512                    self.__RemoveLayer(id)
513                id, cookie = self.GetNextChild(root, cookie)
514    
515    
516          self.__UpdateSelection()          self.__UpdateSelection()
517    
518      def _OnMsgLayerVisibilityChanged(self, layer):      def _OnMsgLayerVisibilityChanged(self, layer):
519          assert isinstance(layer, Layer)          assert isinstance(layer, BaseLayer)
520    
521          self.__ShowHideLayer(layer)          self.__ShowHideLayer(layer)
522          self.__UpdateSelection()          self.__UpdateSelection()
523    
524      def _OnMsgLayerTitleChanged(self, layer):      def _OnMsgLayerTitleChanged(self, layer):
525    
526          id = self.layer2id[layer]          id = self.find_layer(layer)
527          if id.IsOk():          if id.IsOk():
528              self.SetItemText(id, layer.Title())              self.SetItemText(id, layer.Title())
529          self.__UpdateSelection()          self.__UpdateSelection()
# Line 352  class LegendTree(wxTreeCtrl): Line 534  class LegendTree(wxTreeCtrl):
534                    
535      def __FillTree(self, map):      def __FillTree(self, map):
536    
         assert isinstance(map, Map)  
   
537          self.Freeze()          self.Freeze()
538    
539          self.__DeleteAllItems()          self.DeleteAllItems()
540    
541          if map.HasLayers():          if map.HasLayers():
542                root = self.GetRootItem()
             self.image_list = wxImageList(BMP_SIZE_W, BMP_SIZE_H, False, 0)  
                                                                                   
             bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)  
             dc = wxMemoryDC()  
             dc.SelectObject(bmp)  
             dc.SetBrush(wxBLACK_BRUSH)  
             dc.Clear()  
             dc.SelectObject(wxNullBitmap)  
                                                                                   
             self.emptyImageIndex = \  
                 self.image_list.AddWithColourMask(bmp, wxColour(0, 0, 0))  
                                                                                   
             self.AssignImageList(self.image_list)  
   
             root = self.AddRoot("")  
   
543              for l in map.Layers():              for l in map.Layers():
544                  id = self.PrependItem(root, l.Title())                  self.__AddLayer(0, l)
                 l.Subscribe(LAYER_CHANGED, self._OnMsgLayerChanged)  
                 l.Subscribe(LAYER_VISIBILITY_CHANGED,  
                             self._OnMsgLayerVisibilityChanged)  
                 l.Subscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)  
                 self.SetPyData(id, l)  
                 self.__SetVisibilityStyle(l.Visible(), id)  
   
                 self.layer2id[l] = id  
   
                 self.__FillTreeLayer(id)  
                 self.Expand(id)  
545    
546          self.Thaw()          self.Thaw()
547    
# Line 399  class LegendTree(wxTreeCtrl): Line 552  class LegendTree(wxTreeCtrl):
552    
553          self.DeleteChildren(pid)          self.DeleteChildren(pid)
554    
555          clazz = layer.GetClassification()          if layer.HasClassification():
556    
557                clazz = layer.GetClassification()
558    
559          shapeType = layer.ShapeType()              shapeType = layer.ShapeType()
560    
561          show = layer.Visible()              show = layer.Visible()
562          for g in clazz:              for g in clazz:
563              if g.IsVisible():                  if g.IsVisible():
564                  id = self.AppendItem(pid, g.GetDisplayText())                      id = self.AppendItem(pid, g.GetDisplayText())
565                  self.SetPyData(id, g)                      self.SetPyData(id, g)
566                  self.__SetVisibilityStyle(show, id)                      self.__SetVisibilityStyle(show, id)
567    
568                  bmp = self.__BuildGroupImage(g, shapeType)                      bmp = self.__BuildGroupImage(g, shapeType)
569    
570                  if bmp is None:                      if bmp is None:
571                      self.SetItemImage(id, self.emptyImageIndex)                          self.SetItemImage(id, -1)
572                  else:                          self.SetItemSelectedImage(id, -1)
573                      i = self.image_list.Add(bmp)                      else:
574                      self.SetItemImage(id, i)                          if self.availImgListIndices:
575                                i = self.availImgListIndices.pop(0)
576                                self.image_list.Replace(i, bmp)
577                            else:
578                                i = self.image_list.Add(bmp)
579    
580                            self.SetItemImage(id, i)
581                            self.SetItemSelectedImage(id, i)
582    
583          self.Thaw()          self.Thaw()
584    
585      def __BuildGroupImage(self, group, shapeType):      def __BuildGroupImage(self, group, shapeType):
         assert isinstance(group, ClassGroup)  
586    
587          bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)          bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
588          #brush = wxBrush(Color2wxColour(item[1]), wxSOLID)          #brush = wxBrush(Color2wxColour(item[1]), wxSOLID)
# Line 433  class LegendTree(wxTreeCtrl): Line 594  class LegendTree(wxTreeCtrl):
594    
595          return bmp          return bmp
596    
597      def __DeleteAllItems(self):      def DeleteAllItems(self):
598    
599          while len(self.layer2id) > 0:          pid = self.GetRootItem()
             layer, id = self.layer2id.popitem()  
             layer.Unsubscribe(LAYER_CHANGED,  
                               self._OnMsgLayerChanged)  
             layer.Unsubscribe(LAYER_VISIBILITY_CHANGED,  
                               self._OnMsgLayerVisibilityChanged)  
             layer.Unsubscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)  
600    
601          self.DeleteAllItems()          id, cookie = self.GetFirstChild(pid, 123)
602            while id.IsOk():
603                self.__RemoveLayer(id)
604                id, cookie = self.GetNextChild(pid, cookie)
605    
606            wxTreeCtrl.DeleteAllItems(self)
607    
608        def __AddLayer(self, before, l):
609            root = self.GetRootItem()
610            id = self.InsertItemBefore(root, before,
611                                l.Title(),
612                                self.mapImageIndex,
613                                self.mapImageIndex)
614    
615            self.SetPyData(id, l)
616            self.__SetVisibilityStyle(l.Visible(), id)
617    
618            self.__FillTreeLayer(id)
619            self.Expand(id)
620    
621            l.Subscribe(LAYER_CHANGED, self._OnMsgLayerChanged)
622            l.Subscribe(LAYER_VISIBILITY_CHANGED,
623                        self._OnMsgLayerVisibilityChanged)
624            l.Subscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
625    
626        def __RemoveLayer(self, id):
627            self.DeleteChildren(id)
628    
629            layer = self.GetPyData(id)
630            layer.Unsubscribe(LAYER_CHANGED,
631                              self._OnMsgLayerChanged)
632            layer.Unsubscribe(LAYER_VISIBILITY_CHANGED,
633                              self._OnMsgLayerVisibilityChanged)
634            layer.Unsubscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
635    
636            self.Delete(id)
637    
638        def DeleteChildren(self, pid):
639            id, cookie = self.GetFirstChild(pid, 123)
640            while id.IsOk():
641                self.availImgListIndices.append(self.GetItemImage(id))
642                id, cookie = self.GetNextChild(pid, cookie)
643            wxTreeCtrl.DeleteChildren(self, pid)
644    
645        def GetRootItem(self):
646            root = wxTreeCtrl.GetRootItem(self)
647    
648            if not root.IsOk():
649                self.image_list = wxImageList(BMP_SIZE_W, BMP_SIZE_H, False, 0)
650    
651                bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
652                dc = wxMemoryDC()
653                dc.SelectObject(bmp)
654                dc.SetBrush(wxBLACK_BRUSH)
655                dc.Clear()
656                dc.SelectObject(wxNullBitmap)
657    
658                self.emptyImageIndex = \
659                    self.image_list.AddWithColourMask(bmp, wxColour(0, 0, 0))
660    
661                bmp = resource.GetBitmapResource("legend_icon_layer",
662                                                  wxBITMAP_TYPE_XPM)
663                self.mapImageIndex = \
664                    self.image_list.Add(bmp)
665    
666                self.AssignImageList(self.image_list)
667                self.availImgListIndices = []
668    
669                root = self.AddRoot("")
670    
671            return root
672    
673      def __SetVisibilityStyle(self, visible, id):      def __SetVisibilityStyle(self, visible, id):
674          font = self.GetItemFont(id)          font = self.GetItemFont(id)
# Line 452  class LegendTree(wxTreeCtrl): Line 677  class LegendTree(wxTreeCtrl):
677              font.SetStyle(wxNORMAL)              font.SetStyle(wxNORMAL)
678              color = wxBLACK              color = wxBLACK
679          else:          else:
680              font.SetStyle(wxITALIC)              #font.SetStyle(wxITALIC)
681                font.SetStyle(wxNORMAL)
682              color = wxLIGHT_GREY              color = wxLIGHT_GREY
683    
684          self.SetItemTextColour(id, color)          self.SetItemTextColour(id, color)
685          self.SetItemFont(id, font)          self.SetItemFont(id, font)
686                    
687      def __ShowHideLayer(self, layer):      def __ShowHideLayer(self, layer):
688          parent = self.layer2id[layer]          parent = self.find_layer(layer)
689          assert parent.IsOk()          assert parent.IsOk()
690    
691          visible = layer.Visible()          visible = layer.Visible()
# Line 472  class LegendTree(wxTreeCtrl): Line 698  class LegendTree(wxTreeCtrl):
698              self.__SetVisibilityStyle(visible, id)              self.__SetVisibilityStyle(visible, id)
699              id, cookie = self.GetNextChild(parent, cookie)              id, cookie = self.GetNextChild(parent, cookie)
700                            
701    class ScaleBarBitmap(wxBoxSizer):
702    
703        def __init__(self, parent, map, mainWindow):
704            # While the width is fixed, get the height _now_.
705            dc = wxMemoryDC()
706            textwidth, textheight = dc.GetTextExtent("%d"%0)
707            self.width = 210
708            self.height = textheight + 3*2 + 8
709    
710            wxBoxSizer.__init__(self, wxVERTICAL)
711            bmp=wxEmptyBitmap(self.width, self.height)
712            self.scalebarBitmap = wxStaticBitmap(parent, -1, bmp)
713            self.Add(self.scalebarBitmap, 0, wxALIGN_CENTER|wxLEFT|wxTOP|wxRIGHT, 1)
714    
715            self.mainWindow = mainWindow
716            self.parent = parent
717            self.canvas = None
718            self.SetCanvas(self.mainWindow.canvas)
719    
720        def SetCanvas(self, canvas):
721            sub_list = [(SCALE_CHANGED, self._OnMsgScaleChanged)]
722    
723            if self.canvas is not None:
724                for msg, func in sub_list: self.canvas.Unsubscribe(msg, func)
725            
726            self.canvas = canvas
727            self.scalebar = ScaleBar(canvas.map)
728    
729            if self.canvas is not None:
730                for msg, func in sub_list: self.canvas.Subscribe(msg, func)
731                self.__SetScale(self.canvas.scale)
732    
733        def _OnMsgScaleChanged(self, scale):
734            self.__SetScale(scale)
735    
736        def __SetScale(self, scale):
737            bmp = wxEmptyBitmap(self.width, self.height)
738            dc = wxMemoryDC()
739            dc.SelectObject(bmp)
740            dc.Clear()
741    
742            if self.canvas.map is not None \
743                and self.canvas.map.projection is not None:
744    
745                # if we are using a projection with geographics coordinates
746                # we need to change the scale value based on where we are
747                # on the globe.
748                if self.canvas.map.projection.GetProjectedUnits() \
749                    == PROJ_UNITS_DEGREES:
750    
751                    width, height = self.canvas.GetSizeTuple()
752                    long, lat = self.canvas.win_to_proj(width/2, height/2)
753    
754                    # slightly inaccurate, but if we are looking at
755                    # the north/south pole we could end up dividing by zero
756                    #
757                    # it shouldn't matter for our purposes that we ignore
758                    # the original sign of lat.
759                    if fabs(lat) > 89.9: lat = 89.9
760    
761                    #
762                    # one degree is about 111,133m at the equator
763                    # we need to adjust that for latitude as
764                    # we move north/south. use the center of the map
765                    # as the point to scale the length to.
766                    #
767                    scale = scale / (111133.0 * fabs(cos(lat * pi/180)))
768    
769                self.scalebar.DrawScaleBar(scale, dc, (0,0), dc.GetSizeTuple())
770    
771            self.scalebarBitmap.SetBitmap(bmp)
772    

Legend:
Removed from v.668  
changed lines
  Added in v.2187

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26