/[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 568 by jonathan, Wed Mar 26 11:51:28 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.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    
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.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  BMP_SIZE_W = 30  BMP_SIZE_W = 15
46  BMP_SIZE_H = 15  BMP_SIZE_H = 15
47    
48    TOP_BMP = "top_layer"
49    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    
56    
57  class LegendPanel(DockPanel):  class LegendPanel(DockPanel):
58    
59      def __init__(self, parent, map, mainWindow):      def __init__(self, parent, map, mainWindow):
# Line 37  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)  
   
         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)  
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      def DoOnSelChanged(self, layer, group = None):          self.mainWindow.SelectLayer(layer)
         sel = self.tree.GetSelection()  
         self.__EnableButtons(sel.IsOk())  
145    
146          if sel.IsOk():      def DoOnProperties(self):
147              self.mainWindow.SelectLayer(layer)          list = self.tree.GetSelectedHierarchy()
148    
149      def _OnClassify(self, event):          ok = isinstance(list[0], BaseLayer)
150          self.tree.DoOnClassify()          if ok:
151                self.mainWindow.OpenLayerProperties(list[0], list[1])
152    
153        def Destroy(self):
154            self.__Close()
155    
156        def _OnProperties(self, event):
157            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    
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 124  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)
     def DoOnClassify(self):  
         id = self.GetSelection()  
         assert(id.IsOk())  
   
         item = self.GetPyData(id)  
         if isinstance(item, ClassGroup):  
             id = self.GetItemParent(id)  
             assert(id.IsOk())  
             item = self.GetPyData(id)  
   
         # XXX: THIS IS SUCH AWFUL STYLE! YUCK!  
         self.parent.mainWindow.OpenClassifier(item)  
         #assert(False, "XXX: FIXME HERE")  
335    
336      def Sort(self):      def Sort(self):
337          self.SortChildren(self.GetRootItem())          self.SortChildren(self.GetRootItem())
338    
339      def _OnSelChanged(self, event):      def GetSelectedHierarchy(self):
340          id = self.GetSelection()          id = self.GetSelection()
         assert(id.IsOk())  
341    
342          group = None          if not id.IsOk():
343                return (None, None)
344    
345          layer = self.GetPyData(id)          layer = self.GetPyData(id)
346            group = None
347    
348          if isinstance(layer, ClassGroup):          if isinstance(layer, ClassGroup):
349              id = self.GetItemParent(id)              id = self.GetItemParent(id)
350              assert(id.IsOk())              assert id.IsOk()
351              group = layer              group = layer
352              layer = self.GetPyData(id)              layer = self.GetPyData(id)
353    
354          self.parent.DoOnSelChanged(layer, group)          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):
361            # 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 260  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.Freeze()
484    
485                  self.layer2id[l] = id          self.DeleteAllItems()
486    
487                  self.__FillTreeLayer(id)          if map.HasLayers():
488                  self.Expand(id)              root = self.GetRootItem()
489                for l in map.Layers():
490                    self.__AddLayer(0, l)
491    
492          self.Thaw()          self.Thaw()
493    
# Line 315  class LegendTree(wxTreeCtrl): Line 498  class LegendTree(wxTreeCtrl):
498    
499          self.DeleteChildren(pid)          self.DeleteChildren(pid)
500    
501          clazz = layer.GetClassification()          if layer.HasClassification():
502    
503          shapeType = layer.ShapeType()              clazz = layer.GetClassification()
504    
505          for g in clazz:              shapeType = layer.ShapeType()
             id = self.AppendItem(pid, g.GetDisplayText())  
             self.SetPyData(id, g)  
506    
507              bmp = self.__BuildGroupImage(g, shapeType)              show = layer.Visible()
508                for g in clazz:
509                    if g.IsVisible():
510                        id = self.AppendItem(pid, g.GetDisplayText())
511                        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              if bmp is None:                          self.SetItemImage(id, i)
527                  self.SetItemImage(id, self.emptyImageIndex)                          self.SetItemSelectedImage(id, i)
             else:  
                 i = self.image_list.Add(bmp)  
                 self.SetItemImage(id, i)  
   
             #self.layer2id[g] = id  
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 348  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.568  
changed lines
  Added in v.1252

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26