/[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 605 by jonathan, Fri Apr 4 12:16:13 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 *
18    
19  from Thuban.Model.layer import Layer  from Thuban.Model.layer import BaseLayer
20  from Thuban.Model.map import Map  from Thuban.Model.map import Map
 from Thuban.Model.messages import *  
21  from Thuban.Model.classification import ClassGroup  from Thuban.Model.classification import ClassGroup
22    from Thuban.Model.proj import PROJ_UNITS_DEGREES
23    
24    from Thuban.Model.messages import \
25        MAP_STACKING_CHANGED, MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED, LAYER_CHANGED,\
26        LAYER_VISIBILITY_CHANGED, TITLE_CHANGED
27    
28    from Thuban.UI.messages import SCALE_CHANGED
29    
 from Thuban.UI.messages import *  
30  from Thuban.UI.classifier import ClassDataPreviewer  from Thuban.UI.classifier import ClassDataPreviewer
31  from Thuban.UI.dock import DockPanel  from Thuban.UI.dock import DockPanel
32    from Thuban.UI.scalebar import ScaleBar
33    
34  from Thuban.Lib.connector import ConnectorError  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    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    
66    
67  class LegendPanel(DockPanel):  class LegendPanel(DockPanel):
68    
69      def __init__(self, parent, map, mainWindow):      def __init__(self, parent, map, mainWindow):
# Line 40  class LegendPanel(DockPanel): Line 72  class LegendPanel(DockPanel):
72          self.mainWindow = mainWindow          self.mainWindow = mainWindow
73          self.parent = parent          self.parent = parent
74    
         panelBox = wxBoxSizer(wxVERTICAL)  
   
         buttonBox = wxGridSizer(2, 3, 0, 0)  
   
75          self.buttons = []          self.buttons = []
76    
77          button = wxButton(self, ID_LEGEND_MOVEUP, _("Move Up"))          panelBox = wxBoxSizer(wxVERTICAL)
         buttonBox.Add(button, 0, wxGROW | wxLEFT | wxRIGHT, 0)  
         self.buttons.append(button)  
   
         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)  
78    
79          panelBox.Add(buttonBox, 0, 0, 4)          self.toolBar = wxToolBar(self, -1)
80            self.toolBar.SetToolBitmapSize(wxSize(24, 24))
81    
82            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)          self.tree = LegendTree(self, ID_LEGEND_TREE, map, mainWindow)
132    
133          panelBox.Add(self.tree, 1, wxGROW, 4)          panelBox.Add(self.tree, 1, wxGROW, 0)
134    
135          panelBox.Fit(self)          self.scalebarbitmap = ScaleBarBitmap(self, map, mainWindow)
136            panelBox.Add(self.scalebarbitmap, 0, wxGROW, 0)
137    
138          self.SetAutoLayout(True)          self.SetAutoLayout(True)
139          self.SetSizer(panelBox)          self.SetSizer(panelBox)
140          panelBox.SetSizeHints(self)          panelBox.SetSizeHints(self)
141    
         #panelBox.SetSizeHints(self.parent)  
142    
143          self.panelBox = panelBox          self.panelBox = panelBox
144    
145            self.__EnableButtons(False)
146    
147            self.Create()
148    
149          EVT_CLOSE(self, self._OnClose)          EVT_CLOSE(self, self._OnClose)
150    
151    
# Line 96  class LegendPanel(DockPanel): Line 154  class LegendPanel(DockPanel):
154    
155      def SetMap(self, map):      def SetMap(self, map):
156          self.tree.SetMap(map)          self.tree.SetMap(map)
157            self.scalebarbitmap.SetCanvas(self.mainWindow.canvas)
158    
159      def DoOnSelChanged(self, layer, group):      def DoOnSelChanged(self, layer, group):
160    
161          ok = isinstance(layer, Layer)          ok = isinstance(layer, BaseLayer)
162          self.__EnableButtons(ok)          self.__EnableButtons(ok)
163    
164          if ok:          self.mainWindow.SelectLayer(layer)
             self.mainWindow.SelectLayer(layer)  
165    
166      def DoOnClassify(self):      def DoOnProperties(self):
167          list = self.tree.GetSelectedHierarchy()          list = self.tree.GetSelectedHierarchy()
168    
169          ok = isinstance(list[0], Layer)          ok = isinstance(list[0], BaseLayer)
170          if ok:          if ok:
171              self.mainWindow.OpenClassifier(list[0], list[1])              self.mainWindow.OpenLayerProperties(list[0], list[1])
172    
173      def Destroy(self):      def Destroy(self):
174          self.__Close()          self.__Close()
175    
176      def _OnClassify(self, event):      def _OnProperties(self, event):
177          self.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
# Line 138  class LegendPanel(DockPanel): Line 202  class LegendPanel(DockPanel):
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):      def __Close(self):
227          self.tree.Close()          self.tree.Close()
# Line 155  class LegendTree(wxTreeCtrl): Line 236  class LegendTree(wxTreeCtrl):
236          self.mainWindow = mainWindow          self.mainWindow = mainWindow
237          self.map = None          self.map = None
238          self.parent = parent          self.parent = parent
239          self.layer2id = {}          self.changing_selection = 0
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)          EVT_CLOSE(self, self._OnClose)
268    
269          self.SetMap(map)          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):      def _OnClose(self, event):
320          self.SetMap(None)          self.SetMap(None)
321    
# Line 178  class LegendTree(wxTreeCtrl): Line 325  class LegendTree(wxTreeCtrl):
325      def SetMap(self, map):      def SetMap(self, map):
326    
327          sub_list = [(MAP_STACKING_CHANGED, self._OnMsgMapStackingChanged),          sub_list = [(MAP_STACKING_CHANGED, self._OnMsgMapStackingChanged),
328                      (MAP_LAYERS_ADDED, self._OnMsgMapLayersAddedRemoved),                      (MAP_LAYERS_ADDED, self._OnMsgMapLayersAdded),
329                      (MAP_LAYERS_REMOVED, self._OnMsgMapLayersAddedRemoved)]                      (MAP_LAYERS_REMOVED, self._OnMsgMapLayersRemoved)]
330    
331          if self.map is not None:          if self.map is not None:
332              for msg, func in sub_list: self.map.Unsubscribe(msg, func)              for msg, func in sub_list: self.map.Unsubscribe(msg, func)
# Line 190  class LegendTree(wxTreeCtrl): Line 337  class LegendTree(wxTreeCtrl):
337                      #self._OnMsgMapsChanged)                      #self._OnMsgMapsChanged)
338              #except ConnectorError:              #except ConnectorError:
339                  #pass                  #pass
340              self.__DeleteAllItems()              self.DeleteAllItems()
341                    
342          self.map = map          self.map = map
343    
# Line 202  class LegendTree(wxTreeCtrl): Line 349  class LegendTree(wxTreeCtrl):
349                  #self._OnMsgMapsChanged)                  #self._OnMsgMapsChanged)
350              self.__FillTree(self.map)              self.__FillTree(self.map)
351    
352                    def MoveCurrentItemTop(self):
353      def MoveCurrentItemUp(self):          layer, group = self.GetSelectedHierarchy()
         cur_id = self.GetSelection()  
         assert cur_id.IsOk()  
   
         cur_data = self.GetPyData(cur_id)  
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):
         #self.__ShowHideLayer(True)  
400          layer, group = self.GetSelectedHierarchy()          layer, group = self.GetSelectedHierarchy()
401          layer.SetVisible(True)          layer.SetVisible(True)
402    
403      def DoOnHideLayer(self):      def DoOnHideLayer(self):
         #self.__ShowHideLayer(False)  
404          layer, group = self.GetSelectedHierarchy()          layer, group = self.GetSelectedHierarchy()
405          layer.SetVisible(False)          layer.SetVisible(False)
406    
407  #   def DoOnClassify(self):      def ToggleVisibility(self):
408  #       id = self.GetSelection()          layer, group = self.GetSelectedHierarchy()
409  #       assert id.IsOk()  
410            layer.SetVisible(not layer.Visible())
411  #       item = self.GetPyData(id)  
412  #       if isinstance(item, ClassGroup):      def LayerProjection(self):
413  #           id = self.GetItemParent(id)          self.parent.mainWindow.LayerProjection()
 #           assert id.IsOk()  
 #           item = self.GetPyData(id)  
   
 #       # XXX: THIS IS SUCH AWFUL STYLE! YUCK!  
 #       self.parent.mainWindow.OpenClassifier(item)  
 #       #assert False, "XXX: FIXME HERE"  
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):      def _OnMsgMapsChanged(self):
436          print "ADfsadfsadfsadfsa"          #print self.map is self.mainWindow.Map()
         print self.map is self.mainWindow.Map()  
437          self.SetMap(self.mainWindow.Map())          self.SetMap(self.mainWindow.Map())
438                    
439      def _OnSelChanged(self, event):      def _OnSelChanged(self, event):
440            # 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          layer, group = self.GetSelectedHierarchy()  
471          self.parent.DoOnSelChanged(layer, group)      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.parent.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.IsOk()          assert id is not None
497    
498          # XXX: yikes! this is so bad, we should be doing what is          self.__FillTreeLayer(id)
499          #      commented out, but there is a problem with keeping          self.__UpdateSelection()
         #      track of the images in the image list when we replace  
         #      a layer. it ends up causing a seg fault.  
         self.__FillTree(self.map)  
         #self.__FillTreeLayer(id)  
500    
501      def _OnMsgMapStackingChanged(self, *args):      def _OnMsgMapStackingChanged(self, *args):
502          self.Sort()          self.Sort()
# Line 310  class LegendTree(wxTreeCtrl): Line 504  class LegendTree(wxTreeCtrl):
504    
505          if id.IsOk():          if id.IsOk():
506              self.EnsureVisible(id)              self.EnsureVisible(id)
507            self.__UpdateSelection()
508    
509      def _OnMsgMapLayersAddedRemoved(self, map):      def _OnMsgMapLayersAdded(self, map):
510          assert map is self.map          assert map is self.map
511    
512          self.__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      def _OnMsgLayerVisibilityChanged(self, layer):          # Add layers in the map but not in the dict
521          assert isinstance(layer, Layer)          i = 0
522            for l in map.Layers():
523                if not l in layers:
524                    self.__AddLayer(i, l)
525    
526          self.__ShowHideLayer(layer)          self.__UpdateSelection()
527    
528      def GetSelectedHierarchy(self):      def _OnMsgMapLayersRemoved(self, map):
529          id = self.GetSelection()          assert map is self.map
         assert id.IsOk()  
530    
531          layer = self.GetPyData(id)          layers = map.Layers()
         group = None  
532    
533          if isinstance(layer, ClassGroup):          root = self.GetRootItem()
534              id = self.GetItemParent(id)          id, cookie = self.GetFirstChild(root, 0)
535              assert id.IsOk()          while id.IsOk():
536              group = layer              if self.GetPyData(id) not in layers:
537              layer = self.GetPyData(id)                  self.__RemoveLayer(id)
538                id, cookie = self.GetNextChild(root, cookie)
         return (layer, group)  
539    
     def __FillTree(self, map):  
540    
541          assert isinstance(map, Map)          self.__UpdateSelection()
542    
543          self.Freeze()      def _OnMsgLayerVisibilityChanged(self, layer):
544            assert isinstance(layer, BaseLayer)
545    
546          self.__DeleteAllItems()          self.__ShowHideLayer(layer)
547            self.__UpdateSelection()
548    
549          if map.HasLayers():      def _OnMsgLayerTitleChanged(self, layer):
550    
551              self.image_list = wxImageList(BMP_SIZE_W, BMP_SIZE_H, False, 0)          id = self.find_layer(layer)
552                                                                                            if id.IsOk():
553              bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)              self.SetItemText(id, layer.Title())
554              dc = wxMemoryDC()          self.__UpdateSelection()
             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)  
555    
556              root = self.AddRoot("")      def __UpdateSelection(self):
557            layer, group = self.GetSelectedHierarchy()
558            self.parent.DoOnSelChanged(layer, group)
559            
560        def __FillTree(self, map):
561    
562              for l in map.Layers():          self.Freeze()
                 id = self.PrependItem(root, l.Title())  
                 l.Subscribe(LAYER_CHANGED, self._OnMsgLayerChanged)  
                 l.Subscribe(LAYER_VISIBILITY_CHANGED,  
                             self._OnMsgLayerVisibilityChanged)  
                 self.SetPyData(id, l)  
                 font = self.GetItemFont(id)  
                 if not l.Visible():  
                     font.SetStyle(wxITALIC)  
                     self.SetItemFont(id, font)  
563    
564                  self.layer2id[l] = id          self.DeleteAllItems()
565    
566                  self.__FillTreeLayer(id)          if map.HasLayers():
567                  self.Expand(id)              root = self.GetRootItem()
568                for l in map.Layers():
569                    self.__AddLayer(0, l)
570    
571          self.Thaw()          self.Thaw()
572    
# Line 387  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)  
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 418  class LegendTree(wxTreeCtrl): Line 619  class LegendTree(wxTreeCtrl):
619    
620          return bmp          return bmp
621    
622      def __DeleteAllItems(self):      def DeleteAllItems(self):
623    
624          while len(self.layer2id) > 0:          pid = self.GetRootItem()
             layer, id = self.layer2id.popitem()  
             layer.Unsubscribe(LAYER_CHANGED,  
                               self._OnMsgLayerChanged)  
             layer.Unsubscribe(LAYER_VISIBILITY_CHANGED,  
                               self._OnMsgLayerVisibilityChanged)  
625    
626          self.DeleteAllItems()          id, cookie = self.GetFirstChild(pid, 123)
627            while id.IsOk():
628                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 __ShowHideHelper(self, show, id):      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)          font = self.GetItemFont(id)
700    
701          if show:          if visible:
702              font.SetStyle(wxNORMAL)              font.SetStyle(wxNORMAL)
703              color = wxBLACK              color = wxBLACK
704          else:          else:
705              font.SetStyle(wxITALIC)              #font.SetStyle(wxITALIC)
706                font.SetStyle(wxNORMAL)
707              color = wxLIGHT_GREY              color = wxLIGHT_GREY
708    
709          self.SetItemTextColour(id, color)          self.SetItemTextColour(id, color)
710          self.SetItemFont(id, font)          self.SetItemFont(id, font)
711                    
712      def __ShowHideLayer(self, layer):      def __ShowHideLayer(self, layer):
713          parent = self.layer2id[layer]          parent = self.find_layer(layer)
714          assert parent.IsOk()          assert parent.IsOk()
715    
716          show = layer.Visible()          visible = layer.Visible()
717    
718            self.__SetVisibilityStyle(visible, parent)
         self.__ShowHideHelper(show, parent)  
719    
720          id, cookie = self.GetFirstChild(parent, 123)          id, cookie = self.GetFirstChild(parent, 123)
721    
722          while id.IsOk():          while id.IsOk():
723              self.__ShowHideHelper(show, id)              self.__SetVisibilityStyle(visible, id)
724              id, cookie = self.GetNextChild(parent, cookie)              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        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            if self.canvas.map is not None \
768                and self.canvas.map.projection is not None:
769    
770                # if we are using a projection with geographics coordinates
771                # we need to change the scale value based on where we are
772                # on the globe.
773                if self.canvas.map.projection.GetProjectedUnits() \
774                    == PROJ_UNITS_DEGREES:
775    
776                    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.605  
changed lines
  Added in v.1895

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26