/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/legend.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/UI/legend.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2562 - (hide annotations)
Wed Feb 16 21:14:47 2005 UTC (20 years ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/legend.py
File MIME type: text/x-python
File size: 25030 byte(s)
Further wxPython 2.5 changes using patches from Daniel Calvelo Aros
so that that wxproj doesn't crash. Added GUI support for selecting
alpha channel (opacity can't be selected yet).

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

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26