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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26