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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1837 - (show annotations)
Tue Oct 21 09:29:52 2003 UTC (21 years, 4 months ago) by frank
Original Path: trunk/thuban/Thuban/UI/legend.py
File MIME type: text/x-python
File size: 24618 byte(s)
Popup menu for legend. Scheduled for the 1.2 release this was too
simple to implement: The popup menu is bound to the legend tree, while
the events are hanlded by its anchestor, the legend panel. This
allows reuse of all the event handlers already implemented for the
legend toolbar buttons.

* Thuban/UI/legend.py (LegendPanel.__init__): EVT_MENU macros
	to add handlers for the events issued by the popup menu.
 	(LegendPanel._OnToggleVisibility): Handler for toggling layer
	visibility event
    	(LegendPanel._OnProjection): Handler for layer projection event.
	(LegendTree.__init__): Added EVT_TREE_ITEM_RIGHT_CLICK
	(LegendTree._OnRightClick): Event handler for right click, select item
	and pop up menu.
	(LegendTree.ToggleVisibility): Toggle layer visibility
	(LegendTree.LayerProjection): Raise layer projection dialog for
	current layer.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26