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

Legend:
Removed from v.562  
changed lines
  Added in v.1252

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26