/[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

trunk/thuban/Thuban/UI/legend.py revision 652 by jonathan, Fri Apr 11 14:28:08 2003 UTC branches/WIP-pyshapelib-bramz/Thuban/UI/legend.py revision 2734 by bramz, Thu Mar 1 12:42:59 2007 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003, 2005 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 *  import wx
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 = 16
48  BMP_SIZE_H = 15  BMP_SIZE_H = 16
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):
61          DockPanel.__init__(self, parent, -1)          DockPanel.__init__(self, parent, -1)
62    
63          self.mainWindow = mainWindow          self.mainWindow = mainWindow
# Line 51  class LegendPanel(DockPanel): Line 65  class LegendPanel(DockPanel):
65    
66          self.buttons = []          self.buttons = []
67    
68          panelBox = wxBoxSizer(wxVERTICAL)          panelBox = wx.BoxSizer(wx.VERTICAL)
69    
70          self.toolBar = wxToolBar(self, -1)          self.toolBar = wx.ToolBar(self, -1)
71            self.toolBar.SetToolBitmapSize(wx.Size(24, 24))
72    
73          bmp = resource.GetBitmapResource(RAISE_BMP, wxBITMAP_TYPE_XPM)          bmp = resource.GetBitmapResource(TOP_BMP, wx.BITMAP_TYPE_XPM)
74          self.toolBar.AddTool(ID_LEGEND_RAISE, bmp,          self.toolBar.AddTool(ID_LEGEND_TOP, bmp,
75                shortHelpString=_("Top Layer"))
76    
77            bmp = resource.GetBitmapResource(RAISE_BMP, wx.BITMAP_TYPE_XPM)
78            self.toolBar.AddTool(ID_LEGEND_RAISE, bmp,
79              shortHelpString=_("Raise Layer"))              shortHelpString=_("Raise Layer"))
80    
81          bmp = resource.GetBitmapResource(LOWER_BMP, wxBITMAP_TYPE_XPM)          bmp = resource.GetBitmapResource(LOWER_BMP, wx.BITMAP_TYPE_XPM)
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(SHOW_BMP, wxBITMAP_TYPE_XPM)          bmp = resource.GetBitmapResource(BOTTOM_BMP, wx.BITMAP_TYPE_XPM)
86          self.toolBar.AddTool(ID_LEGEND_SHOWLAYER, bmp,          self.toolBar.AddTool(ID_LEGEND_BOTTOM, bmp,
87                shortHelpString=_("Bottom Layer"))
88    
89            bmp = resource.GetBitmapResource(SHOW_BMP, wx.BITMAP_TYPE_XPM)
90            self.toolBar.AddTool(ID_LEGEND_SHOWLAYER, bmp,
91              shortHelpString=_("Show Layer"))              shortHelpString=_("Show Layer"))
92    
93          bmp = resource.GetBitmapResource(HIDE_BMP, wxBITMAP_TYPE_XPM)          bmp = resource.GetBitmapResource(HIDE_BMP, wx.BITMAP_TYPE_XPM)
94          self.toolBar.AddTool(ID_LEGEND_HIDELAYER, bmp,          self.toolBar.AddTool(ID_LEGEND_HIDELAYER, bmp,
95              shortHelpString=_("Hide Layer"))              shortHelpString=_("Hide Layer"))
96    
97          bmp = resource.GetBitmapResource(PROPS_BMP, wxBITMAP_TYPE_XPM)          bmp = resource.GetBitmapResource(PROPS_BMP, wx.BITMAP_TYPE_XPM)
98          self.toolBar.AddTool(ID_LEGEND_PROPS, bmp,          self.toolBar.AddTool(ID_LEGEND_PROPS, bmp,
99              shortHelpString=_("Edit Layer Properties"))              shortHelpString=_("Edit Layer Properties"))
100    
101          self.toolBar.Realize()          self.toolBar.Realize()
102          panelBox.Add(self.toolBar, 0, wxALL, 0)          panelBox.Add(self.toolBar, 0, wx.GROW, 0)
103    
104          EVT_TOOL(self, ID_LEGEND_RAISE, self._OnMoveUp)          self.Bind(wx.EVT_TOOL, self._OnMoveTop, id=ID_LEGEND_TOP)
105          EVT_TOOL(self, ID_LEGEND_LOWER, self._OnMoveDown)          self.Bind(wx.EVT_TOOL, self._OnMoveUp, id=ID_LEGEND_RAISE)
106          EVT_TOOL(self, ID_LEGEND_PROPS, self._OnProperties)          self.Bind(wx.EVT_TOOL, self._OnMoveDown, id=ID_LEGEND_LOWER)
107          EVT_TOOL(self, ID_LEGEND_SHOWLAYER, self._OnShowLayer)          self.Bind(wx.EVT_TOOL, self._OnMoveBottom, id=ID_LEGEND_BOTTOM)
108          EVT_TOOL(self, ID_LEGEND_HIDELAYER, self._OnHideLayer)          self.Bind(wx.EVT_TOOL, self._OnProperties, id=ID_LEGEND_PROPS)
109            self.Bind(wx.EVT_TOOL, self._OnShowLayer, id=ID_LEGEND_SHOWLAYER)
110            self.Bind(wx.EVT_TOOL, self._OnHideLayer, id=ID_LEGEND_HIDELAYER)
111    
112          self.tree = LegendTree(self, ID_LEGEND_TREE, map, mainWindow)          self.tree = LegendTree(self, ID_LEGEND_TREE, map, mainWindow)
113    
114          panelBox.Add(self.tree, 1, wxGROW, 4)          panelBox.Add(self.tree, 1, wx.GROW, 0)
115    
116          panelBox.Fit(self)          self.scalebarbitmap = ScaleBarBitmap(self, map, mainWindow)
117            panelBox.Add(self.scalebarbitmap, 0, wx.GROW, 0)
118    
119          self.SetAutoLayout(True)          self.SetAutoLayout(True)
120          self.SetSizer(panelBox)          self.SetSizer(panelBox)
121          panelBox.SetSizeHints(self)          panelBox.SetSizeHints(self)
122    
123    
124          self.panelBox = panelBox          self.panelBox = panelBox
125    
126          self.__EnableButtons(False)          self.__EnableButtons(False)
127    
128          EVT_CLOSE(self, self._OnClose)          self.Create()
129    
130            self.Bind(wx.EVT_CLOSE, self._OnClose)
131    
132    
133      def GetMap(self):      def GetMap(self):
# Line 106  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          if ok:          self.mainWindow.SelectLayer(layer)
             self.mainWindow.SelectLayer(layer)  
146    
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 128  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 _OnMoveUp(self, event):      def _OnMoveTop(self, event):
161            self.tree.MoveCurrentItemTop()
162    
163        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
175    
176      #def Close(self, force = False):      #def Close(self, force = False):
177          #DockPanel.Close(self, force)          #DockPanel.Close(self, force)
178            
179      def _OnClose(self, event):      def _OnClose(self, event):
180          self.__Close()          self.__Close()
181    
# Line 148  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 158  class LegendPanel(DockPanel): Line 207  class LegendPanel(DockPanel):
207      def __Close(self):      def __Close(self):
208          self.tree.Close()          self.tree.Close()
209    
210  class LegendTree(wxTreeCtrl):  class LegendTree(wx.TreeCtrl):
211    
212      def __init__(self, parent, id, map, mainWindow):      def __init__(self, parent, id, map, mainWindow):
213          wxTreeCtrl.__init__(self, parent, id,          wx.TreeCtrl.__init__(self, parent, id,
214                              style = wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT,                              style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT,
215                              size = (200, 200))                              size = (200, 200))
216    
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          EVT_TREE_ITEM_ACTIVATED(self, ID_LEGEND_TREE, self._OnItemActivated)          self.preventExpandCollapse = False
240          EVT_TREE_SEL_CHANGED(self, ID_LEGEND_TREE, self._OnSelChanged)          self.raiseProperties = False
241    
242            self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._OnItemActivated, id=ID_LEGEND_TREE)
243            self.Bind(wx.EVT_TREE_SEL_CHANGED, self._OnSelChanged, id=ID_LEGEND_TREE)
244            self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpandCollapse, id=ID_LEGEND_TREE)
245            self.Bind(wx.EVT_TREE_ITEM_COLLAPSING, self.OnItemExpandCollapse, id=ID_LEGEND_TREE)
246            self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self._OnRightClick, id=ID_LEGEND_TREE)
247    
248          EVT_CLOSE(self, self._OnClose)          self.Bind(wx.EVT_CLOSE, 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)
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 191  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 203  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    
319          if self.map is not None:          if self.map is not None:
# Line 215  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 wx.TreeCtrl.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    
393        def GetSelectedHierarchy(self):
394            id = self.GetSelection()
395    
396            if not id.IsOk():
397                return (None, None)
398    
399            layer = self.GetPyData(id)
400            group = None
401    
402            if isinstance(layer, ClassGroup):
403                id = self.GetItemParent(id)
404                assert id.IsOk()
405                group = layer
406                layer = self.GetPyData(id)
407    
408            return (layer, group)
409    
410      def _OnMsgMapsChanged(self):      def _OnMsgMapsChanged(self):
411          #print self.map is self.mainWindow.Map()          #print self.map is self.mainWindow.Map()
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()
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          layer, group = self.GetSelectedHierarchy()  
446          self.parent.DoOnSelChanged(layer, group)      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)
474          #      commented out, but there is a problem with keeping          self.__UpdateSelection()
         #      track of the images in the image list when we replace  
         #      a layer. it ends up causing a seg fault.  
         self.__FillTree(self.map)  
         #self.__FillTreeLayer(id)  
475    
476      def _OnMsgMapStackingChanged(self, *args):      def _OnMsgMapStackingChanged(self, *args):
477          self.Sort()          self.Sort()
# Line 308  class LegendTree(wxTreeCtrl): Line 479  class LegendTree(wxTreeCtrl):
479    
480          if id.IsOk():          if id.IsOk():
481              self.EnsureVisible(id)              self.EnsureVisible(id)
482            self.__UpdateSelection()
483    
484        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)
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 _OnMsgMapLayersAddedRemoved(self, map):      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)
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()
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()
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()
530    
531      def GetSelectedHierarchy(self):      def __UpdateSelection(self):
532          id = self.GetSelection()          layer, group = self.GetSelectedHierarchy()
533          assert id.IsOk()          self.parent.DoOnSelChanged(layer, group)
   
         layer = self.GetPyData(id)  
         group = None  
   
         if isinstance(layer, ClassGroup):  
             id = self.GetItemParent(id)  
             assert id.IsOk()  
             group = layer  
             layer = self.GetPyData(id)  
   
         return (layer, group)  
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    
548      def __FillTreeLayer(self, pid):      def __FillTreeLayer(self, pid):
549    
550          layer = self.GetPyData(pid)          layer = self.GetPyData(pid)
551    
552          self.Freeze()          self.Freeze()
553    
554          self.DeleteChildren(pid)          self.DeleteChildren(pid)
555    
556          clazz = layer.GetClassification()          if layer.HasClassification():
557    
558                clazz = layer.GetClassification()
559    
560          shapeType = layer.ShapeType()              shapeType = layer.ShapeType()
561    
562          show = layer.Visible()              show = layer.Visible()
563          for g in clazz:              for g in clazz:
564              if g.IsVisible():                  if g.IsVisible():
565                  id = self.AppendItem(pid, g.GetDisplayText())                      id = self.AppendItem(pid, g.GetDisplayText())
566                  self.SetPyData(id, g)                      self.SetPyData(id, g)
567                  self.__SetVisibilityStyle(show, id)                      self.__SetVisibilityStyle(show, id)
568    
569                  bmp = self.__BuildGroupImage(g, shapeType)                      bmp = self.__BuildGroupImage(g, shapeType)
570    
571                  if bmp is None:                      if bmp is None:
572                      self.SetItemImage(id, self.emptyImageIndex)                          self.SetItemImage(id, -1, wx.TreeItemIcon_Normal)
573                  else:                          self.SetItemImage(id, -1, wx.TreeItemIcon_Selected)
574                      i = self.image_list.Add(bmp)                          #self.SetItemSelectedImage(id, -1)
575                      self.SetItemImage(id, i)                      else:
576                            if self.availImgListIndices:
577                                i = self.availImgListIndices.pop(0)
578                                self.image_list.Replace(i, bmp)
579                            else:
580                                i = self.image_list.Add(bmp)
581    
582                            self.SetItemImage(id, i, wx.TreeItemIcon_Normal)
583                            self.SetItemImage(id, i, wx.TreeItemIcon_Selected)
584                            #self.SetItemlectedImage(id, i)
585    
586          self.Thaw()          self.Thaw()
587    
588      def __BuildGroupImage(self, group, shapeType):      def __BuildGroupImage(self, group, shapeType):
         assert isinstance(group, ClassGroup)  
589    
590          bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)          bmp = wx.EmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
591          #brush = wxBrush(Color2wxColour(item[1]), wxSOLID)          #brush = wxBrush(Color2wxColour(item[1]), wxSOLID)
592          dc = wxMemoryDC()          dc = wx.MemoryDC()
593          dc.SelectObject(bmp)          dc.SelectObject(bmp)
594          dc.Clear()          dc.Clear()
595    
# Line 423  class LegendTree(wxTreeCtrl): Line 597  class LegendTree(wxTreeCtrl):
597    
598          return bmp          return bmp
599    
600      def __DeleteAllItems(self):      def DeleteAllItems(self):
601    
602          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)  
603    
604          self.DeleteAllItems()          id, cookie = self.GetFirstChild(pid)
605            while id.IsOk():
606                self.__RemoveLayer(id)
607                id, cookie = self.GetNextChild(pid, cookie)
608    
609            wx.TreeCtrl.DeleteAllItems(self)
610    
611        def __AddLayer(self, before, l):
612            root = self.GetRootItem()
613            id = self.InsertItemBefore(root, before,
614                                l.Title(),
615                                self.mapImageIndex,
616                                self.mapImageIndex)
617    
618            self.SetPyData(id, l)
619            self.__SetVisibilityStyle(l.Visible(), id)
620    
621            self.__FillTreeLayer(id)
622            self.Expand(id)
623    
624            l.Subscribe(LAYER_CHANGED, self._OnMsgLayerChanged)
625            l.Subscribe(LAYER_VISIBILITY_CHANGED,
626                        self._OnMsgLayerVisibilityChanged)
627            l.Subscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
628    
629        def __RemoveLayer(self, id):
630            self.DeleteChildren(id)
631    
632            layer = self.GetPyData(id)
633            layer.Unsubscribe(LAYER_CHANGED,
634                              self._OnMsgLayerChanged)
635            layer.Unsubscribe(LAYER_VISIBILITY_CHANGED,
636                              self._OnMsgLayerVisibilityChanged)
637            layer.Unsubscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
638    
639            self.Delete(id)
640    
641        def DeleteChildren(self, pid):
642            id, cookie = self.GetFirstChild(pid)
643            while id.IsOk():
644                self.availImgListIndices.append(self.GetItemImage(id))
645                id, cookie = self.GetNextChild(pid, cookie)
646            wx.TreeCtrl.DeleteChildren(self, pid)
647    
648        def GetRootItem(self):
649            root = wx.TreeCtrl.GetRootItem(self)
650    
651            if not root.IsOk():
652                self.image_list = wx.ImageList(BMP_SIZE_W, BMP_SIZE_H, False, 0)
653    
654                bmp = wx.EmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
655                dc = wx.MemoryDC()
656                dc.SelectObject(bmp)
657                dc.SetBrush(wx.BLACK_BRUSH)
658                dc.Clear()
659                dc.SelectObject(wx.NullBitmap)
660    
661                self.emptyImageIndex = \
662                    self.image_list.AddWithColourMask(bmp, wx.Colour(0, 0, 0))
663    
664                bmp = resource.GetBitmapResource("legend_icon_layer",
665                                                  wx.BITMAP_TYPE_XPM)
666                self.mapImageIndex = \
667                    self.image_list.Add(bmp)
668    
669                self.AssignImageList(self.image_list)
670                self.availImgListIndices = []
671    
672                root = self.AddRoot("")
673    
674            return root
675    
676      def __SetVisibilityStyle(self, visible, id):      def __SetVisibilityStyle(self, visible, id):
677          font = self.GetItemFont(id)          font = self.GetItemFont(id)
678    
679          if visible:          if visible:
680              font.SetStyle(wxNORMAL)              font.SetStyle(wx.NORMAL)
681              color = wxBLACK              color = wx.BLACK
682          else:          else:
683              font.SetStyle(wxITALIC)              #font.SetStyle(wxITALIC)
684              color = wxLIGHT_GREY              font.SetStyle(wx.NORMAL)
685                color = wx.LIGHT_GREY
686    
687          self.SetItemTextColour(id, color)          self.SetItemTextColour(id, color)
688          self.SetItemFont(id, font)          self.SetItemFont(id, font)
689            
690      def __ShowHideLayer(self, layer):      def __ShowHideLayer(self, layer):
691          parent = self.layer2id[layer]          parent = self.find_layer(layer)
692          assert parent.IsOk()          assert parent.IsOk()
693    
694          visible = layer.Visible()          visible = layer.Visible()
695    
696          self.__SetVisibilityStyle(visible, parent)          self.__SetVisibilityStyle(visible, parent)
697    
698          id, cookie = self.GetFirstChild(parent, 123)          id, cookie = self.GetFirstChild(parent)
699    
700          while id.IsOk():          while id.IsOk():
701              self.__SetVisibilityStyle(visible, id)              self.__SetVisibilityStyle(visible, id)
702              id, cookie = self.GetNextChild(parent, cookie)              id, cookie = self.GetNextChild(parent, cookie)
703                
704        # In wxPython 2.4 the GetFirstChild method has to be called with a
705        # second argument and in 2.5 it must not.  Reading the code of
706        # wxPython 2.4 it seems that the second parameter was intended to be
707        # optional there but due to a bug in the C++ code it doesn't work
708        # and omitting the second argument leads to a segfault.  To cope
709        # with this and to make the code usable with both 2.5 and 2.4 we
710        # overwrite the inherited method when running with 2.4 to provide a
711        # default value for the second argument.
712        if map(int, wx.__version__.split(".")[:2]) < [2, 5]:
713            def GetFirstChild(self, item):
714                return wx.TreeCtrl.GetFirstChild(self, item, 0)
715    
716    
717    class ScaleBarBitmap(wx.BoxSizer):
718    
719        def __init__(self, parent, map, mainWindow):
720            # While the width is fixed, get the height _now_.
721            dc = wx.MemoryDC()
722            textwidth, textheight = dc.GetTextExtent("%d"%0)
723            self.width = 210
724            self.height = textheight + 3*2 + 8
725    
726            wx.BoxSizer.__init__(self, wx.VERTICAL)
727            bmp=wx.EmptyBitmap(self.width, self.height)
728            self.scalebarBitmap = wx.StaticBitmap(parent, -1, bmp)
729            self.Add(self.scalebarBitmap, 0, wx.ALIGN_CENTER|wx.LEFT|wx.TOP|wx.RIGHT, 1)
730    
731            self.mainWindow = mainWindow
732            self.parent = parent
733            self.canvas = None
734            self.SetCanvas(self.mainWindow.canvas)
735    
736        def SetCanvas(self, canvas):
737            sub_list = [(SCALE_CHANGED, self._OnMsgScaleChanged)]
738    
739            if self.canvas is not None:
740                for msg, func in sub_list: self.canvas.Unsubscribe(msg, func)
741    
742            self.canvas = canvas
743            self.scalebar = ScaleBar(canvas.map)
744    
745            if self.canvas is not None:
746                for msg, func in sub_list: self.canvas.Subscribe(msg, func)
747                self.__SetScale(self.canvas.scale)
748    
749        def _OnMsgScaleChanged(self, scale):
750            self.__SetScale(scale)
751    
752        def __SetScale(self, scale):
753            bmp = wx.EmptyBitmap(self.width, self.height)
754            dc = wx.MemoryDC()
755            dc.SelectObject(bmp)
756            dc.Clear()
757    
758            if self.canvas.map is not None \
759                and self.canvas.map.projection is not None:
760    
761                # if we are using a projection with geographics coordinates
762                # we need to change the scale value based on where we are
763                # on the globe.
764                if self.canvas.map.projection.GetProjectedUnits() \
765                    == PROJ_UNITS_DEGREES:
766    
767                    width, height = self.canvas.GetSizeTuple()
768                    long, lat = self.canvas.win_to_proj(width/2, height/2)
769    
770                    # slightly inaccurate, but if we are looking at
771                    # the north/south pole we could end up dividing by zero
772                    #
773                    # it shouldn't matter for our purposes that we ignore
774                    # the original sign of lat.
775                    if fabs(lat) > 89.9: lat = 89.9
776    
777                    #
778                    # one degree is about 111,133m at the equator
779                    # we need to adjust that for latitude as
780                    # we move north/south. use the center of the map
781                    # as the point to scale the length to.
782                    #
783                    scale = scale / (111133.0 * fabs(cos(lat * pi/180)))
784    
785                self.scalebar.DrawScaleBar(scale, dc, (0,0), dc.GetSizeTuple())
786    
787            self.scalebarBitmap.SetBitmap(bmp)
788    

Legend:
Removed from v.652  
changed lines
  Added in v.2734

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26