/[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 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.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    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          ##self.SetAutoLayout(True)  BMP_SIZE_W = 15
56          ##self.SetSizer(topBox)  BMP_SIZE_H = 15
57    
58      #def GetLegendPanel(self):  TOP_BMP = "top_layer"
59          #return self.panel  RAISE_BMP = "raise_layer"
60    LOWER_BMP = "lower_layer"
61    BOTTOM_BMP = "bottom_layer"
62    SHOW_BMP  = "show_layer"
63    HIDE_BMP  = "hide_layer"
64    PROPS_BMP = "layer_properties"
65    
     #def OnClose(self, event):  
         #NonModalDialog.OnClose(self, event)  
66    
         #self.panel.SetMap(None)  
       
67  class LegendPanel(DockPanel):  class LegendPanel(DockPanel):
68    
69      def __init__(self, parent, map, mainWindow):      def __init__(self, parent, map, mainWindow):
# Line 64  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)  
   
 #       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)  
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            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)
150    
151    
152      def GetMap(self):      def GetMap(self):
153          return self.tree.GetMap()          return self.tree.GetMap()
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):
160    
161            ok = isinstance(layer, BaseLayer)
162            self.__EnableButtons(ok)
163    
164            self.mainWindow.SelectLayer(layer)
165    
166        def DoOnProperties(self):
167            list = self.tree.GetSelectedHierarchy()
168    
169            ok = isinstance(list[0], BaseLayer)
170            if ok:
171                self.mainWindow.OpenLayerProperties(list[0], list[1])
172    
173      def DoOnSelChanged(self):      def Destroy(self):
174          self.__EnableButtons(self.tree.GetSelection().IsOk())          self.__Close()
175    
176      def _OnClassify(self, event):      def _OnProperties(self, event):
177          self.tree.DoOnClassify()          self.DoOnProperties()
178    
179        def _OnMoveTop(self, event):
180            self.tree.MoveCurrentItemTop()
181            
182      def _OnMoveUp(self, event):      def _OnMoveUp(self, event):
183          self.tree.MoveCurrentItemUp()          self.tree.MoveCurrentItemUp()
184    
185      def _OnMoveDown(self, event):      def _OnMoveDown(self, event):
186          self.tree.MoveCurrentItemDown()          self.tree.MoveCurrentItemDown()
187    
188        def _OnMoveBottom(self, event):
189            self.tree.MoveCurrentItemBottom()
190    
191      def _OnShowLayer(self, event):      def _OnShowLayer(self, event):
192          self.tree.DoOnShowLayer()          self.tree.DoOnShowLayer()
193          pass          pass
194    
195        #def Close(self, force = False):
196            #DockPanel.Close(self, force)
197            
198        def _OnClose(self, event):
199            self.__Close()
200    
201      def _OnHideLayer(self, event):      def _OnHideLayer(self, event):
202          self.tree.DoOnHideLayer()          self.tree.DoOnHideLayer()
203          pass          pass
204    
205      def _OnDock(self, event):      def _OnToggleVisibility(self, event):
206          self.Dock()          self.tree.ToggleVisibility()
207    
208        def _OnProjection(self, event):
209            self.tree.LayerProjection()
210    
211      def _OnUndock(self, event):      def _OnRemoveLayer(self, event):
212          self.UnDock()          self.mainWindow.RemoveLayer()
213    
214        def _OnShowTable(self, event):
215            self.mainWindow.LayerShowTable()
216    
217      def __EnableButtons(self, on):      def __EnableButtons(self, on):
218          for b in self.buttons:          self.toolBar.EnableTool(ID_LEGEND_TOP, on)
219              b.Enable(on)          self.toolBar.EnableTool(ID_LEGEND_RAISE, on)
220            self.toolBar.EnableTool(ID_LEGEND_LOWER, on)
221            self.toolBar.EnableTool(ID_LEGEND_BOTTOM, on)
222            self.toolBar.EnableTool(ID_LEGEND_SHOWLAYER,  on)
223            self.toolBar.EnableTool(ID_LEGEND_HIDELAYER,  on)
224            self.toolBar.EnableTool(ID_LEGEND_PROPS, on)
225    
226        def __Close(self):
227            self.tree.Close()
228    
229  class LegendTree(wxTreeCtrl):  class LegendTree(wxTreeCtrl):
230    
# Line 164  class LegendTree(wxTreeCtrl): Line 233  class LegendTree(wxTreeCtrl):
233                              style = wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT,                              style = wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT,
234                              size = (200, 200))                              size = (200, 200))
235    
236            self.mainWindow = mainWindow
237          self.map = None          self.map = None
238          self.parent = parent          self.parent = parent
239          self.layer2id = None          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)
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):
320            self.SetMap(None)
321    
322      def GetMap(self):      def GetMap(self):
323          return self.map          return self.map
324    
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)
333              self.__DeleteAllItems()              #self.mainWindow.application.Unsubscribe(SESSION_REPLACED,
334                    #self._OnMsgMapsChanged)
335                #try:
336                    #self.mainWindow.application.session.Unsubscribe(MAPS_CHANGED,
337                        #self._OnMsgMapsChanged)
338                #except ConnectorError:
339                    #pass
340                self.DeleteAllItems()
341                    
342          self.map = map          self.map = map
343    
344          if self.map is not None:          if self.map is not None:
345              for msg, func in sub_list: self.map.Subscribe(msg, func)              for msg, func in sub_list: self.map.Subscribe(msg, func)
346                #self.mainWindow.application.session.Subscribe(MAPS_CHANGED,
347                    #self._OnMsgMapsChanged)
348                #self.mainWindow.application.Subscribe(SESSION_REPLACED,
349                    #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):
400          self.__ShowHideLayer(True)          layer, group = self.GetSelectedHierarchy()
401            layer.SetVisible(True)
402    
403      def DoOnHideLayer(self):      def DoOnHideLayer(self):
404          self.__ShowHideLayer(False)          layer, group = self.GetSelectedHierarchy()
405            layer.SetVisible(False)
406    
407      def DoOnClassify(self):      def ToggleVisibility(self):
408          id = self.GetSelection()          layer, group = self.GetSelectedHierarchy()
         assert(id.IsOk())  
         assert(id.IsOk())  
409    
410          item = self.GetPyData(id)          layer.SetVisible(not layer.Visible())
         if isinstance(item, ClassGroup):  
             id = self.GetItemParent(id)  
             assert(id.IsOk())  
             item = self.GetPyData(id)  
411    
412          # XXX: THIS IS SUCH AWFUL STYLE! YUCK!      def LayerProjection(self):
413          self.parent.mainWindow.OpenClassifier(item)          self.parent.mainWindow.LayerProjection()
         #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):
436            #print self.map is self.mainWindow.Map()
437            self.SetMap(self.mainWindow.Map())
438            
439      def _OnSelChanged(self, event):      def _OnSelChanged(self, event):
440          self.parent.DoOnSelChanged()          # If we change the selection from normalize_selection do nothing.
441            if self.changing_selection:
442                return
443    
444            self.normalize_selection()
445            self.__UpdateSelection()
446    
447        def normalize_selection(self):
448            """Select the layer containing currently selected item"""
449            # This is really a workaround for a bug in wx where deleting a
450            # subtree with DeleteChildren does not update the selection
451            # properly and can lead to segfaults later because the return
452            # value of GetSelection points to invalid data.
453            item = self.GetSelection()
454            while item.IsOk():
455                object = self.GetPyData(item)
456                if isinstance(object, BaseLayer):
457                    break
458                item = self.GetItemParent(item)
459            else:
460                # No layer was found in the chain of parents, so there's
461                # nothing we can do.
462                return
463    
464            self.changing_selection = 1
465            try:
466                self.SelectItem(item)
467            finally:
468                self.changing_selection = 0
469    
470    
471        def OnItemExpandCollapse(self, event):
472            if self.preventExpandCollapse:
473                event.Veto()
474                self.preventExpandCollapse = False
475    
476      def _OnItemActivated(self, event):      def _OnItemActivated(self, event):
477          self.DoOnClassify()          # The following looks strange but is need under Windows to
478            # raise the Properties on double-click: The tree control
479            # always gets an Expanded / Collapsed event after the ItemActivated
480            # on double click, which raises the main window again. We add a second
481            # ItemActivated event to the queue, which simply raises the already
482            # displayed window.
483            if self.raiseProperties:
484                self.parent.DoOnProperties()
485                self.raiseProperties = False
486            else:
487                self.raiseProperties = True
488                self.preventExpandCollapse = True
489                self.parent.DoOnProperties()
490                self.AddPendingEvent(event)
491    
492      def _OnMsgLayerChanged(self, layer):      def _OnMsgLayerChanged(self, layer):
493          assert(isinstance(layer, Layer))          assert isinstance(layer, BaseLayer)
494    
495          id = self.layer2id[layer]          id = self.find_layer(layer)
496            assert id is not None
497    
498          self.__FillTreeLayer(id)          self.__FillTreeLayer(id)
499            self.__UpdateSelection()
500    
501      def _OnMsgMapStackingChanged(self, *args):      def _OnMsgMapStackingChanged(self, *args):
502          self.Sort()          self.Sort()
# Line 290  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(id(map) == id(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 __FillTree(self, map):          # Add layers in the map but not in the dict
521            i = 0
522            for l in map.Layers():
523                if not l in layers:
524                    self.__AddLayer(i, l)
525    
526          assert(isinstance(map, Map))          self.__UpdateSelection()
527    
528          self.Freeze()      def _OnMsgMapLayersRemoved(self, map):
529            assert map is self.map
530    
531          self.__DeleteAllItems()          layers = map.Layers()
532    
533          if map.HasLayers():          root = self.GetRootItem()
534            id, cookie = self.GetFirstChild(root, 0)
535            while id.IsOk():
536                if self.GetPyData(id) not in layers:
537                    self.__RemoveLayer(id)
538                id, cookie = self.GetNextChild(root, cookie)
539    
             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)  
540    
541              root = self.AddRoot("")          self.__UpdateSelection()
542    
543              for l in map.Layers():      def _OnMsgLayerVisibilityChanged(self, layer):
544                  id = self.PrependItem(root, l.Title())          assert isinstance(layer, BaseLayer)
545                  l.Subscribe(LAYER_CHANGED, self._OnMsgLayerChanged)  
546                  self.SetPyData(id, l)          self.__ShowHideLayer(layer)
547                  font = self.GetItemFont(id)          self.__UpdateSelection()
548                  if not l.Visible():  
549                      font.SetStyle(wxITALIC)      def _OnMsgLayerTitleChanged(self, layer):
550                      self.SetItemFont(id, font)  
551            id = self.find_layer(layer)
552            if id.IsOk():
553                self.SetItemText(id, layer.Title())
554            self.__UpdateSelection()
555    
556        def __UpdateSelection(self):
557            layer, group = self.GetSelectedHierarchy()
558            self.parent.DoOnSelChanged(layer, group)
559            
560        def __FillTree(self, map):
561    
562                  self.layer2id[l] = id          self.Freeze()
563    
564                  self.__FillTreeLayer(id)          self.DeleteAllItems()
565                  self.Expand(id)  
566            if map.HasLayers():
567                root = self.GetRootItem()
568                for l in map.Layers():
569                    self.__AddLayer(0, l)
570    
571          self.Thaw()          self.Thaw()
572    
# Line 345  class LegendTree(wxTreeCtrl): Line 577  class LegendTree(wxTreeCtrl):
577    
578          self.DeleteChildren(pid)          self.DeleteChildren(pid)
579    
580          clazz = layer.GetClassification()          if layer.HasClassification():
   
         shapeType = layer.ShapeType()  
581    
582          for g in clazz:              clazz = layer.GetClassification()
             id = self.AppendItem(pid, g.GetDisplayText())  
             self.SetPyData(id, g)  
583    
584              bmp = self.__BuildGroupImage(g, shapeType)              shapeType = layer.ShapeType()
585    
586              if bmp is None:              show = layer.Visible()
587                  self.SetItemImage(id, self.emptyImageIndex)              for g in clazz:
588              else:                  if g.IsVisible():
589                  i = self.image_list.Add(bmp)                      id = self.AppendItem(pid, g.GetDisplayText())
590                  self.SetItemImage(id, i)                      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              #self.layer2id[g] = id                          self.SetItemImage(id, i)
606                            self.SetItemSelectedImage(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 378  class LegendTree(wxTreeCtrl): Line 619  class LegendTree(wxTreeCtrl):
619    
620          return bmp          return bmp
621    
622      def __DeleteAllItems(self):      def DeleteAllItems(self):
         self.DeleteAllItems()  
         self.layer2id = {}  
623    
624            pid = self.GetRootItem()
625    
626      def __ShowHideLayer(self, show):          id, cookie = self.GetFirstChild(pid, 123)
627          id = self.GetSelection()          while id.IsOk():
628          assert(id.IsOk())              self.__RemoveLayer(id)
629                id, cookie = self.GetNextChild(pid, cookie)
630    
631            wxTreeCtrl.DeleteAllItems(self)
632    
633        def __AddLayer(self, before, l):
634            root = self.GetRootItem()
635            id = self.InsertItemBefore(root, before,
636                                l.Title(),
637                                self.mapImageIndex,
638                                self.mapImageIndex)
639    
640            self.SetPyData(id, l)
641            self.__SetVisibilityStyle(l.Visible(), id)
642    
643            self.__FillTreeLayer(id)
644            self.Expand(id)
645    
646            l.Subscribe(LAYER_CHANGED, self._OnMsgLayerChanged)
647            l.Subscribe(LAYER_VISIBILITY_CHANGED,
648                        self._OnMsgLayerVisibilityChanged)
649            l.Subscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
650    
651        def __RemoveLayer(self, id):
652            self.DeleteChildren(id)
653    
654            layer = self.GetPyData(id)
655            layer.Unsubscribe(LAYER_CHANGED,
656                              self._OnMsgLayerChanged)
657            layer.Unsubscribe(LAYER_VISIBILITY_CHANGED,
658                              self._OnMsgLayerVisibilityChanged)
659            layer.Unsubscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
660    
661            self.Delete(id)
662    
663        def DeleteChildren(self, pid):
664            id, cookie = self.GetFirstChild(pid, 123)
665            while id.IsOk():
666                self.availImgListIndices.append(self.GetItemImage(id))
667                id, cookie = self.GetNextChild(pid, cookie)
668            wxTreeCtrl.DeleteChildren(self, pid)
669    
670        def GetRootItem(self):
671            root = wxTreeCtrl.GetRootItem(self)
672    
673            if not root.IsOk():
674                self.image_list = wxImageList(BMP_SIZE_W, BMP_SIZE_H, False, 0)
675    
676                bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
677                dc = wxMemoryDC()
678                dc.SelectObject(bmp)
679                dc.SetBrush(wxBLACK_BRUSH)
680                dc.Clear()
681                dc.SelectObject(wxNullBitmap)
682    
683                self.emptyImageIndex = \
684                    self.image_list.AddWithColourMask(bmp, wxColour(0, 0, 0))
685    
686                bmp = resource.GetBitmapResource("legend_icon_layer",
687                                                  wxBITMAP_TYPE_XPM)
688                self.mapImageIndex = \
689                    self.image_list.Add(bmp)
690    
691                self.AssignImageList(self.image_list)
692                self.availImgListIndices = []
693    
694                root = self.AddRoot("")
695    
696            return root
697    
698        def __SetVisibilityStyle(self, visible, id):
699            font = self.GetItemFont(id)
700    
701            if visible:
702                font.SetStyle(wxNORMAL)
703                color = wxBLACK
704            else:
705                #font.SetStyle(wxITALIC)
706                font.SetStyle(wxNORMAL)
707                color = wxLIGHT_GREY
708    
709            self.SetItemTextColour(id, color)
710            self.SetItemFont(id, font)
711                    
712          item = self.GetPyData(id)      def __ShowHideLayer(self, layer):
713          if isinstance(item, ClassGroup):          parent = self.find_layer(layer)
714              id = self.GetItemParent(id)          assert parent.IsOk()
715              assert(id.IsOk())  
716              item = self.GetPyData(id)          visible = layer.Visible()
717    
718            self.__SetVisibilityStyle(visible, parent)
719    
720            id, cookie = self.GetFirstChild(parent, 123)
721    
722            while id.IsOk():
723                self.__SetVisibilityStyle(visible, id)
724                id, cookie = self.GetNextChild(parent, cookie)
725                
726    class ScaleBarBitmap(wxBoxSizer):
727    
728        def __init__(self, parent, map, mainWindow):
729            # While the width is fixed, get the height _now_.
730            dc = wxMemoryDC()
731            textwidth, textheight = dc.GetTextExtent("%d"%0)
732            self.width = 210
733            self.height = textheight + 3*2 + 8
734    
735            wxBoxSizer.__init__(self, wxVERTICAL)
736            bmp=wxEmptyBitmap(self.width, self.height)
737            self.scalebarBitmap = wxStaticBitmap(parent, -1, bmp)
738            self.Add(self.scalebarBitmap, 0, wxALIGN_CENTER|wxLEFT|wxTOP|wxRIGHT, 1)
739    
740            self.mainWindow = mainWindow
741            self.parent = parent
742            self.canvas = None
743            self.SetCanvas(self.mainWindow.canvas)
744    
745        def SetCanvas(self, canvas):
746            sub_list = [(SCALE_CHANGED, self._OnMsgScaleChanged)]
747    
748            if self.canvas is not None:
749                for msg, func in sub_list: self.canvas.Unsubscribe(msg, func)
750            
751            self.canvas = canvas
752            self.scalebar = ScaleBar(canvas.map)
753    
754            if self.canvas is not None:
755                for msg, func in sub_list: self.canvas.Subscribe(msg, func)
756                self.__SetScale(self.canvas.scale)
757    
758          if show != item.Visible():      def _OnMsgScaleChanged(self, scale):
759            self.__SetScale(scale)
760    
761        def __SetScale(self, scale):
762            bmp = wxEmptyBitmap(self.width, self.height)
763            dc = wxMemoryDC()
764            dc.SelectObject(bmp)
765            dc.Clear()
766    
767              item.SetVisible(show)          if self.canvas.map is not None \
768                and self.canvas.map.projection is not None:
769    
770              font = self.GetItemFont(id)              # if we are using a projection with geographics coordinates
771              if show:              # we need to change the scale value based on where we are
772                  font.SetStyle(wxNORMAL)              # on the globe.
773                  self.SetItemFont(id, font)              if self.canvas.map.projection.GetProjectedUnits() \
774              else:                  == PROJ_UNITS_DEGREES:
775                  font.SetStyle(wxITALIC)  
776                  self.SetItemFont(id, font)                  width, height = self.canvas.GetSizeTuple()
777                    long, lat = self.canvas.win_to_proj(width/2, height/2)
778    
779                    # slightly inaccurate, but if we are looking at
780                    # the north/south pole we could end up dividing by zero
781                    #
782                    # it shouldn't matter for our purposes that we ignore
783                    # the original sign of lat.
784                    if fabs(lat) > 89.9: lat = 89.9
785    
786                    #
787                    # one degree is about 111,133m at the equator
788                    # we need to adjust that for latitude as
789                    # we move north/south. use the center of the map
790                    # as the point to scale the length to.
791                    #
792                    scale = scale / (111133.0 * fabs(cos(lat * pi/180)))
793    
794                self.scalebar.DrawScaleBar(scale, dc, (0,0), dc.GetSizeTuple())
795    
796            self.scalebarBitmap.SetBitmap(bmp)
797    

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26