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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 374 - (show annotations)
Mon Jan 27 14:20:02 2003 UTC (22 years, 1 month ago) by jan
Original Path: trunk/thuban/Thuban/UI/tree.py
File MIME type: text/x-python
File size: 7213 byte(s)
Replace user string by _() for i18n.

1 #! /usr/bin/python
2 # Copyright (c) 2001, 2002 by Intevation GmbH
3 # Authors:
4 # Jan-Oliver Wagner <[email protected]>
5 # Bernhard Herzog <[email protected]>
6 #
7 # This program is free software under the GPL (>=v2)
8 # Read the file COPYING coming with Thuban for details.
9
10 __version__ = "$Revision$"
11
12 from types import StringType
13
14 from wxPython.wx import *
15
16 from Thuban import _
17
18 from Thuban.Model.messages import CHANGED
19 from Thuban.Model.layer import Layer
20 from Thuban.Model.map import Map
21
22 from dialogs import NonModalDialog
23 from messages import SESSION_CHANGED, SELECTED_LAYER
24
25
26 class SessionTreeCtrl(wxTreeCtrl):
27
28 """Widget to display a tree view of the session.
29
30 The tree view is created recursively from the session object. The
31 tree view calls the session's TreeInfo method which should return a
32 pair (<title>, <item>) where <title> ist the title of the session
33 item in the tree view and <items> is a list of objects to use as the
34 children of the session in the tree view.
35
36 The items list can contain three types of items:
37
38 1. a string. The string is used as the title for a leaf item in
39 the tree view.
40
41 2. an object with a TreeInfo method. This method is called and
42 should return a pair just like the session's TreeInfo method.
43
44 3. a pair (<title>, <item>) which is treated like the return
45 value of TreeInfo.
46 """
47
48 def __init__(self, parent, ID, app):
49 # Use the WANTS_CHARS style so the panel doesn't eat the Return key.
50 wxTreeCtrl.__init__(self, parent, ID)
51
52 self.app = app
53 # boolean to indicate that we manipulate the selection ourselves
54 # so that we can ignore the selection events generated
55 self.changing_selection = 0
56
57 # Dictionary mapping layer id's to tree items
58 self.layer_to_item = {}
59
60 self.app.Subscribe(SESSION_CHANGED, self.session_changed)
61 self.app.interactor.Subscribe(SELECTED_LAYER, self.layer_selected)
62
63 # the session currently displayed in the tree
64 self.session = None
65
66 # pretend the session has changed to build the initial tree
67 self.session_changed()
68
69 EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
70
71 def unsubscribe_all(self):
72 if self.session is not None:
73 self.session.Unsubscribe(CHANGED, self.update_tree)
74 self.session = None
75 self.app.Unsubscribe(SESSION_CHANGED, self.session_changed)
76 self.app.interactor.Unsubscribe(SELECTED_LAYER, self.layer_selected)
77
78 def update_tree(self, *args):
79 """Clear and rebuild the tree"""
80 self.DeleteAllItems()
81 self.layer_to_item.clear()
82
83 session = self.app.session
84 info = session.TreeInfo()
85 root = self.AddRoot(info[0])
86 self.add_items(root, info[1])
87 self.Expand(root)
88 # select the selected layer
89 selected_layer = self.app.interactor.selected_layer
90 if selected_layer is not None:
91 # One would expect that the selected_layer's id is in
92 # layer_to_item at this point as we've just rebuilt that
93 # mapping completely. However, when a new session is loaded
94 # for instance, it can happen that the tree view is updated
95 # before the interactor in which case selected_layer may be
96 # a layer of the old session.
97 item = self.layer_to_item.get(id(selected_layer))
98 if item is not None:
99 self.SelectItem(item)
100
101 def add_items(self, parent, items):
102 for item in items:
103 if hasattr(item, "TreeInfo"):
104 # Supports the TreeInfo protocol
105 info = item.TreeInfo()
106 treeitem = self.AppendItem(parent, info[0])
107 self.SetPyData(treeitem, item)
108 self.add_items(treeitem, info[1])
109 self.Expand(treeitem)
110 if isinstance(item, Layer):
111 self.layer_to_item[id(item)] = treeitem
112 elif isinstance(item, StringType):
113 # it's a string
114 # FIXME: What to do about UNICODE
115 self.AppendItem(parent, item)
116 else:
117 # assume its a sequence (title, items)
118 treeitem = self.AppendItem(parent, item[0])
119 self.add_items(treeitem, item[1])
120 self.Expand(treeitem)
121
122 def session_changed(self, *args):
123 new_session = self.app.session
124 # if the session has changed subscribe/unsubscribe
125 if self.session is not new_session:
126 if self.session is not None:
127 self.session.Unsubscribe(CHANGED, self.update_tree)
128 if new_session is not None:
129 new_session.Subscribe(CHANGED, self.update_tree)
130 self.session = new_session
131 self.update_tree()
132
133 def normalize_selection(self):
134 """Select the layer or map containing currently selected item"""
135 item = self.GetSelection()
136 while item.IsOk():
137 object = self.GetPyData(item)
138 if isinstance(object, Layer) or isinstance(object, Map):
139 break
140 item = self.GetItemParent(item)
141 else:
142 # No layer or map was found in the chain of parents, so
143 # there's nothing we can do.
144 return
145
146 self.changing_selection = 1
147 try:
148 self.SelectItem(item)
149 finally:
150 self.changing_selection = 0
151
152 def SelectedLayer(self):
153 """Return the layer object currently selected in the tree.
154 Return None if no layer is selected"""
155 layer = self.GetPyData(self.GetSelection())
156 if isinstance(layer, Layer):
157 return layer
158 return None
159
160 def OnSelChanged(self, event):
161 if self.changing_selection:
162 # we're changing the selection ourselves (probably through
163 # self.normalize_selection(). ignore the event.
164 return
165 self.normalize_selection()
166 # SelectedLayer returns None if no layer is selected. Since
167 # passing None to interactor.SelectLayer deselects the layer we
168 # can simply pass the result of SelectedLayer on in all cases
169 self.app.interactor.SelectLayer(self.SelectedLayer())
170
171 def layer_selected(self, layer):
172 item = self.layer_to_item.get(id(layer))
173 if item is not None and item != self.GetSelection():
174 self.SelectItem(item)
175
176
177 class SessionTreeView(NonModalDialog):
178
179 """Non modal dialog showing the session as a tree"""
180
181 def __init__(self, parent, app, name):
182 NonModalDialog.__init__(self, parent, app.interactor, name,
183 _("Session"))
184 self.tree = SessionTreeCtrl(self, -1, app)
185
186 def OnClose(self, event):
187 #self.interactor.Unsubscribe(SELECTED_SHAPE, self.select_shape)
188 NonModalDialog.OnClose(self, event)
189
190 # if there were a way to get notified when the tree control
191 # itself is destroyed we could use that to unsubscribe instead
192 # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
193 # all)
194 self.tree.unsubscribe_all()

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26