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

Legend:
Removed from v.542  
changed lines
  Added in v.1895

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26