/[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 2187 - (show annotations)
Sun Apr 18 20:37:45 2004 UTC (20 years, 10 months ago) by jan
Original Path: trunk/thuban/Thuban/UI/legend.py
File MIME type: text/x-python
File size: 24149 byte(s)
ID_POP_xxx: removed.
(LegendPanel.__init__): Removed EVT_MENU bindings.
(LegendTree._OnRightClick): Replace direct creation of
menu via wx Classes by applying the menu definition
as of Menu class of menu.py.

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.UI.menu import Menu
35
36 from Thuban.Lib.connector import ConnectorError
37
38 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
47 BMP_SIZE_W = 15
48 BMP_SIZE_H = 15
49
50 TOP_BMP = "top_layer"
51 RAISE_BMP = "raise_layer"
52 LOWER_BMP = "lower_layer"
53 BOTTOM_BMP = "bottom_layer"
54 SHOW_BMP = "show_layer"
55 HIDE_BMP = "hide_layer"
56 PROPS_BMP = "layer_properties"
57
58 class LegendPanel(DockPanel):
59
60 def __init__(self, parent, map, mainWindow):
61 DockPanel.__init__(self, parent, -1)
62
63 self.mainWindow = mainWindow
64 self.parent = parent
65
66 self.buttons = []
67
68 panelBox = wxBoxSizer(wxVERTICAL)
69
70 self.toolBar = wxToolBar(self, -1)
71 self.toolBar.SetToolBitmapSize(wxSize(24, 24))
72
73 bmp = resource.GetBitmapResource(TOP_BMP, wxBITMAP_TYPE_XPM)
74 self.toolBar.AddTool(ID_LEGEND_TOP, bmp,
75 shortHelpString=_("Top Layer"))
76
77 bmp = resource.GetBitmapResource(RAISE_BMP, wxBITMAP_TYPE_XPM)
78 self.toolBar.AddTool(ID_LEGEND_RAISE, bmp,
79 shortHelpString=_("Raise Layer"))
80
81 bmp = resource.GetBitmapResource(LOWER_BMP, wxBITMAP_TYPE_XPM)
82 self.toolBar.AddTool(ID_LEGEND_LOWER, bmp,
83 shortHelpString=_("Lower Layer"))
84
85 bmp = resource.GetBitmapResource(BOTTOM_BMP, wxBITMAP_TYPE_XPM)
86 self.toolBar.AddTool(ID_LEGEND_BOTTOM, bmp,
87 shortHelpString=_("Bottom Layer"))
88
89 bmp = resource.GetBitmapResource(SHOW_BMP, wxBITMAP_TYPE_XPM)
90 self.toolBar.AddTool(ID_LEGEND_SHOWLAYER, bmp,
91 shortHelpString=_("Show Layer"))
92
93 bmp = resource.GetBitmapResource(HIDE_BMP, wxBITMAP_TYPE_XPM)
94 self.toolBar.AddTool(ID_LEGEND_HIDELAYER, bmp,
95 shortHelpString=_("Hide Layer"))
96
97 bmp = resource.GetBitmapResource(PROPS_BMP, wxBITMAP_TYPE_XPM)
98 self.toolBar.AddTool(ID_LEGEND_PROPS, bmp,
99 shortHelpString=_("Edit Layer Properties"))
100
101 self.toolBar.Realize()
102 panelBox.Add(self.toolBar, 0, wxGROW, 0)
103
104 EVT_TOOL(self, ID_LEGEND_TOP, self._OnMoveTop)
105 EVT_TOOL(self, ID_LEGEND_RAISE, self._OnMoveUp)
106 EVT_TOOL(self, ID_LEGEND_LOWER, self._OnMoveDown)
107 EVT_TOOL(self, ID_LEGEND_BOTTOM, self._OnMoveBottom)
108 EVT_TOOL(self, ID_LEGEND_PROPS, self._OnProperties)
109 EVT_TOOL(self, ID_LEGEND_SHOWLAYER, self._OnShowLayer)
110 EVT_TOOL(self, ID_LEGEND_HIDELAYER, self._OnHideLayer)
111
112 self.tree = LegendTree(self, ID_LEGEND_TREE, map, mainWindow)
113
114 panelBox.Add(self.tree, 1, wxGROW, 0)
115
116 self.scalebarbitmap = ScaleBarBitmap(self, map, mainWindow)
117 panelBox.Add(self.scalebarbitmap, 0, wxGROW, 0)
118
119 self.SetAutoLayout(True)
120 self.SetSizer(panelBox)
121 panelBox.SetSizeHints(self)
122
123
124 self.panelBox = panelBox
125
126 self.__EnableButtons(False)
127
128 self.Create()
129
130 EVT_CLOSE(self, self._OnClose)
131
132
133 def GetMap(self):
134 return self.tree.GetMap()
135
136 def SetMap(self, map):
137 self.tree.SetMap(map)
138 self.scalebarbitmap.SetCanvas(self.mainWindow.canvas)
139
140 def DoOnSelChanged(self, layer, group):
141
142 ok = isinstance(layer, BaseLayer)
143 self.__EnableButtons(ok)
144
145 self.mainWindow.SelectLayer(layer)
146
147 def DoOnProperties(self):
148 list = self.tree.GetSelectedHierarchy()
149
150 ok = isinstance(list[0], BaseLayer)
151 if ok:
152 self.mainWindow.OpenLayerProperties(list[0], list[1])
153
154 def Destroy(self):
155 self.__Close()
156
157 def _OnProperties(self, event):
158 self.DoOnProperties()
159
160 def _OnMoveTop(self, event):
161 self.tree.MoveCurrentItemTop()
162
163 def _OnMoveUp(self, event):
164 self.tree.MoveCurrentItemUp()
165
166 def _OnMoveDown(self, event):
167 self.tree.MoveCurrentItemDown()
168
169 def _OnMoveBottom(self, event):
170 self.tree.MoveCurrentItemBottom()
171
172 def _OnShowLayer(self, event):
173 self.tree.DoOnShowLayer()
174 pass
175
176 #def Close(self, force = False):
177 #DockPanel.Close(self, force)
178
179 def _OnClose(self, event):
180 self.__Close()
181
182 def _OnHideLayer(self, event):
183 self.tree.DoOnHideLayer()
184 pass
185
186 def _OnToggleVisibility(self, event):
187 self.tree.ToggleVisibility()
188
189 def _OnProjection(self, event):
190 self.tree.LayerProjection()
191
192 def _OnRemoveLayer(self, event):
193 self.mainWindow.RemoveLayer()
194
195 def _OnShowTable(self, event):
196 self.mainWindow.LayerShowTable()
197
198 def __EnableButtons(self, on):
199 self.toolBar.EnableTool(ID_LEGEND_TOP, on)
200 self.toolBar.EnableTool(ID_LEGEND_RAISE, on)
201 self.toolBar.EnableTool(ID_LEGEND_LOWER, on)
202 self.toolBar.EnableTool(ID_LEGEND_BOTTOM, on)
203 self.toolBar.EnableTool(ID_LEGEND_SHOWLAYER, on)
204 self.toolBar.EnableTool(ID_LEGEND_HIDELAYER, on)
205 self.toolBar.EnableTool(ID_LEGEND_PROPS, on)
206
207 def __Close(self):
208 self.tree.Close()
209
210 class LegendTree(wxTreeCtrl):
211
212 def __init__(self, parent, id, map, mainWindow):
213 wxTreeCtrl.__init__(self, parent, id,
214 style = wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT,
215 size = (200, 200))
216
217 self.mainWindow = mainWindow
218 self.map = None
219 self.parent = parent
220 self.changing_selection = 0
221
222 #
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 self.image_list = None
235 self.emptyImageIndex = 0
236
237 self.previewer = ClassDataPreviewer()
238
239 self.preventExpandCollapse = False
240 self.raiseProperties = False
241
242 EVT_TREE_ITEM_ACTIVATED(self, ID_LEGEND_TREE, self._OnItemActivated)
243 EVT_TREE_SEL_CHANGED(self, ID_LEGEND_TREE, self._OnSelChanged)
244 EVT_TREE_ITEM_EXPANDING(self, ID_LEGEND_TREE, self.OnItemExpandCollapse)
245 EVT_TREE_ITEM_COLLAPSING(self, ID_LEGEND_TREE, self.OnItemExpandCollapse)
246 EVT_TREE_ITEM_RIGHT_CLICK(self, ID_LEGEND_TREE, self._OnRightClick)
247
248 EVT_CLOSE(self, self._OnClose)
249
250 self.SetMap(map)
251
252 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 # 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
279 # Display the menu
280 pos = event.GetPoint()
281 shift = self.ClientToScreen((0,0))
282 self.PopupMenu(self.mainWindow.build_menu(popup_menu), pos)
283
284 def find_layer(self, layer):
285 """Return the tree item for the layer"""
286 root = self.GetRootItem()
287 id, cookie = self.GetFirstChild(root, 0)
288 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 def _OnClose(self, event):
295 self.SetMap(None)
296
297 def GetMap(self):
298 return self.map
299
300 def SetMap(self, map):
301
302 sub_list = [(MAP_STACKING_CHANGED, self._OnMsgMapStackingChanged),
303 (MAP_LAYERS_ADDED, self._OnMsgMapLayersAdded),
304 (MAP_LAYERS_REMOVED, self._OnMsgMapLayersRemoved)]
305
306 if self.map is not None:
307 for msg, func in sub_list: self.map.Unsubscribe(msg, func)
308 #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 self.DeleteAllItems()
316
317 self.map = map
318
319 if self.map is not None:
320 for msg, func in sub_list: self.map.Subscribe(msg, func)
321 #self.mainWindow.application.session.Subscribe(MAPS_CHANGED,
322 #self._OnMsgMapsChanged)
323 #self.mainWindow.application.Subscribe(SESSION_REPLACED,
324 #self._OnMsgMapsChanged)
325 self.__FillTree(self.map)
326
327 def MoveCurrentItemTop(self):
328 layer, group = self.GetSelectedHierarchy()
329
330 if layer is not None:
331 self.map.MoveLayerToTop(layer)
332 else:
333 assert False, "Shouldn't be allowed."
334 pass
335
336 def MoveCurrentItemUp(self):
337 layer, group = self.GetSelectedHierarchy()
338
339 if layer is not None:
340 self.map.RaiseLayer(layer)
341 else:
342 assert False, "Shouldn't be allowed."
343 pass
344
345 def MoveCurrentItemDown(self):
346 layer, group = self.GetSelectedHierarchy()
347
348 if layer is not None:
349 self.map.LowerLayer(layer)
350 else:
351 assert False, "Shouldn't be allowed."
352 pass
353
354 def MoveCurrentItemBottom(self):
355 layer, group = self.GetSelectedHierarchy()
356
357 if layer is not None:
358 self.map.MoveLayerToBottom(layer)
359 else:
360 assert False, "Shouldn't be allowed."
361 pass
362
363 def OnCompareItems(self, item1, item2):
364
365 data1 = self.GetPyData(item1)
366 data2 = self.GetPyData(item2)
367
368 if isinstance(data1, BaseLayer):
369 layers = self.map.Layers()
370 return layers.index(data2) - layers.index(data1)
371 else:
372 return wxTreeCtrl.OnCompareItems(self, item1, item2)
373
374 def DoOnShowLayer(self):
375 layer, group = self.GetSelectedHierarchy()
376 layer.SetVisible(True)
377
378 def DoOnHideLayer(self):
379 layer, group = self.GetSelectedHierarchy()
380 layer.SetVisible(False)
381
382 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 def Sort(self):
391 self.SortChildren(self.GetRootItem())
392
393 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 def _OnMsgMapsChanged(self):
411 #print self.map is self.mainWindow.Map()
412 self.SetMap(self.mainWindow.Map())
413
414 def _OnSelChanged(self, event):
415 # If we change the selection from normalize_selection do nothing.
416 if self.changing_selection:
417 return
418
419 self.normalize_selection()
420 self.__UpdateSelection()
421
422 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 def OnItemExpandCollapse(self, event):
447 if self.preventExpandCollapse:
448 event.Veto()
449 self.preventExpandCollapse = False
450
451 def _OnItemActivated(self, event):
452 # 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
467 def _OnMsgLayerChanged(self, layer):
468 assert isinstance(layer, BaseLayer)
469
470 id = self.find_layer(layer)
471 assert id is not None
472
473 self.__FillTreeLayer(id)
474 self.__UpdateSelection()
475
476 def _OnMsgMapStackingChanged(self, *args):
477 self.Sort()
478 id = self.GetSelection()
479
480 if id.IsOk():
481 self.EnsureVisible(id)
482 self.__UpdateSelection()
483
484 def _OnMsgMapLayersAdded(self, map):
485 assert map is self.map
486
487 # Build a dict with all layers known by the the tree as keys
488 layers = {}
489 root = self.GetRootItem()
490 id, cookie = self.GetFirstChild(root, 0)
491 while id.IsOk():
492 layers[self.GetPyData(id)] = 1
493 id, cookie = self.GetNextChild(root, cookie)
494
495 # Add layers in the map but not in the dict
496 i = 0
497 for l in map.Layers():
498 if not l in layers:
499 self.__AddLayer(i, l)
500
501 self.__UpdateSelection()
502
503 def _OnMsgMapLayersRemoved(self, map):
504 assert map is self.map
505
506 layers = map.Layers()
507
508 root = self.GetRootItem()
509 id, cookie = self.GetFirstChild(root, 0)
510 while id.IsOk():
511 if self.GetPyData(id) not in layers:
512 self.__RemoveLayer(id)
513 id, cookie = self.GetNextChild(root, cookie)
514
515
516 self.__UpdateSelection()
517
518 def _OnMsgLayerVisibilityChanged(self, layer):
519 assert isinstance(layer, BaseLayer)
520
521 self.__ShowHideLayer(layer)
522 self.__UpdateSelection()
523
524 def _OnMsgLayerTitleChanged(self, layer):
525
526 id = self.find_layer(layer)
527 if id.IsOk():
528 self.SetItemText(id, layer.Title())
529 self.__UpdateSelection()
530
531 def __UpdateSelection(self):
532 layer, group = self.GetSelectedHierarchy()
533 self.parent.DoOnSelChanged(layer, group)
534
535 def __FillTree(self, map):
536
537 self.Freeze()
538
539 self.DeleteAllItems()
540
541 if map.HasLayers():
542 root = self.GetRootItem()
543 for l in map.Layers():
544 self.__AddLayer(0, l)
545
546 self.Thaw()
547
548 def __FillTreeLayer(self, pid):
549 layer = self.GetPyData(pid)
550
551 self.Freeze()
552
553 self.DeleteChildren(pid)
554
555 if layer.HasClassification():
556
557 clazz = layer.GetClassification()
558
559 shapeType = layer.ShapeType()
560
561 show = layer.Visible()
562 for g in clazz:
563 if g.IsVisible():
564 id = self.AppendItem(pid, g.GetDisplayText())
565 self.SetPyData(id, g)
566 self.__SetVisibilityStyle(show, id)
567
568 bmp = self.__BuildGroupImage(g, shapeType)
569
570 if bmp is None:
571 self.SetItemImage(id, -1)
572 self.SetItemSelectedImage(id, -1)
573 else:
574 if self.availImgListIndices:
575 i = self.availImgListIndices.pop(0)
576 self.image_list.Replace(i, bmp)
577 else:
578 i = self.image_list.Add(bmp)
579
580 self.SetItemImage(id, i)
581 self.SetItemSelectedImage(id, i)
582
583 self.Thaw()
584
585 def __BuildGroupImage(self, group, shapeType):
586
587 bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
588 #brush = wxBrush(Color2wxColour(item[1]), wxSOLID)
589 dc = wxMemoryDC()
590 dc.SelectObject(bmp)
591 dc.Clear()
592
593 self.previewer.Draw(dc, None, group.GetProperties(), shapeType)
594
595 return bmp
596
597 def DeleteAllItems(self):
598
599 pid = self.GetRootItem()
600
601 id, cookie = self.GetFirstChild(pid, 123)
602 while id.IsOk():
603 self.__RemoveLayer(id)
604 id, cookie = self.GetNextChild(pid, cookie)
605
606 wxTreeCtrl.DeleteAllItems(self)
607
608 def __AddLayer(self, before, l):
609 root = self.GetRootItem()
610 id = self.InsertItemBefore(root, before,
611 l.Title(),
612 self.mapImageIndex,
613 self.mapImageIndex)
614
615 self.SetPyData(id, l)
616 self.__SetVisibilityStyle(l.Visible(), id)
617
618 self.__FillTreeLayer(id)
619 self.Expand(id)
620
621 l.Subscribe(LAYER_CHANGED, self._OnMsgLayerChanged)
622 l.Subscribe(LAYER_VISIBILITY_CHANGED,
623 self._OnMsgLayerVisibilityChanged)
624 l.Subscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
625
626 def __RemoveLayer(self, id):
627 self.DeleteChildren(id)
628
629 layer = self.GetPyData(id)
630 layer.Unsubscribe(LAYER_CHANGED,
631 self._OnMsgLayerChanged)
632 layer.Unsubscribe(LAYER_VISIBILITY_CHANGED,
633 self._OnMsgLayerVisibilityChanged)
634 layer.Unsubscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
635
636 self.Delete(id)
637
638 def DeleteChildren(self, pid):
639 id, cookie = self.GetFirstChild(pid, 123)
640 while id.IsOk():
641 self.availImgListIndices.append(self.GetItemImage(id))
642 id, cookie = self.GetNextChild(pid, cookie)
643 wxTreeCtrl.DeleteChildren(self, pid)
644
645 def GetRootItem(self):
646 root = wxTreeCtrl.GetRootItem(self)
647
648 if not root.IsOk():
649 self.image_list = wxImageList(BMP_SIZE_W, BMP_SIZE_H, False, 0)
650
651 bmp = wxEmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
652 dc = wxMemoryDC()
653 dc.SelectObject(bmp)
654 dc.SetBrush(wxBLACK_BRUSH)
655 dc.Clear()
656 dc.SelectObject(wxNullBitmap)
657
658 self.emptyImageIndex = \
659 self.image_list.AddWithColourMask(bmp, wxColour(0, 0, 0))
660
661 bmp = resource.GetBitmapResource("legend_icon_layer",
662 wxBITMAP_TYPE_XPM)
663 self.mapImageIndex = \
664 self.image_list.Add(bmp)
665
666 self.AssignImageList(self.image_list)
667 self.availImgListIndices = []
668
669 root = self.AddRoot("")
670
671 return root
672
673 def __SetVisibilityStyle(self, visible, id):
674 font = self.GetItemFont(id)
675
676 if visible:
677 font.SetStyle(wxNORMAL)
678 color = wxBLACK
679 else:
680 #font.SetStyle(wxITALIC)
681 font.SetStyle(wxNORMAL)
682 color = wxLIGHT_GREY
683
684 self.SetItemTextColour(id, color)
685 self.SetItemFont(id, font)
686
687 def __ShowHideLayer(self, layer):
688 parent = self.find_layer(layer)
689 assert parent.IsOk()
690
691 visible = layer.Visible()
692
693 self.__SetVisibilityStyle(visible, parent)
694
695 id, cookie = self.GetFirstChild(parent, 123)
696
697 while id.IsOk():
698 self.__SetVisibilityStyle(visible, id)
699 id, cookie = self.GetNextChild(parent, cookie)
700
701 class ScaleBarBitmap(wxBoxSizer):
702
703 def __init__(self, parent, map, mainWindow):
704 # While the width is fixed, get the height _now_.
705 dc = wxMemoryDC()
706 textwidth, textheight = dc.GetTextExtent("%d"%0)
707 self.width = 210
708 self.height = textheight + 3*2 + 8
709
710 wxBoxSizer.__init__(self, wxVERTICAL)
711 bmp=wxEmptyBitmap(self.width, self.height)
712 self.scalebarBitmap = wxStaticBitmap(parent, -1, bmp)
713 self.Add(self.scalebarBitmap, 0, wxALIGN_CENTER|wxLEFT|wxTOP|wxRIGHT, 1)
714
715 self.mainWindow = mainWindow
716 self.parent = parent
717 self.canvas = None
718 self.SetCanvas(self.mainWindow.canvas)
719
720 def SetCanvas(self, canvas):
721 sub_list = [(SCALE_CHANGED, self._OnMsgScaleChanged)]
722
723 if self.canvas is not None:
724 for msg, func in sub_list: self.canvas.Unsubscribe(msg, func)
725
726 self.canvas = canvas
727 self.scalebar = ScaleBar(canvas.map)
728
729 if self.canvas is not None:
730 for msg, func in sub_list: self.canvas.Subscribe(msg, func)
731 self.__SetScale(self.canvas.scale)
732
733 def _OnMsgScaleChanged(self, scale):
734 self.__SetScale(scale)
735
736 def __SetScale(self, scale):
737 bmp = wxEmptyBitmap(self.width, self.height)
738 dc = wxMemoryDC()
739 dc.SelectObject(bmp)
740 dc.Clear()
741
742 if self.canvas.map is not None \
743 and self.canvas.map.projection is not None:
744
745 # if we are using a projection with geographics coordinates
746 # we need to change the scale value based on where we are
747 # on the globe.
748 if self.canvas.map.projection.GetProjectedUnits() \
749 == PROJ_UNITS_DEGREES:
750
751 width, height = self.canvas.GetSizeTuple()
752 long, lat = self.canvas.win_to_proj(width/2, height/2)
753
754 # slightly inaccurate, but if we are looking at
755 # the north/south pole we could end up dividing by zero
756 #
757 # it shouldn't matter for our purposes that we ignore
758 # the original sign of lat.
759 if fabs(lat) > 89.9: lat = 89.9
760
761 #
762 # one degree is about 111,133m at the equator
763 # we need to adjust that for latitude as
764 # we move north/south. use the center of the map
765 # as the point to scale the length to.
766 #
767 scale = scale / (111133.0 * fabs(cos(lat * pi/180)))
768
769 self.scalebar.DrawScaleBar(scale, dc, (0,0), dc.GetSizeTuple())
770
771 self.scalebarBitmap.SetBitmap(bmp)
772

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26