/[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 233 - (show annotations)
Fri Jul 19 15:15:16 2002 UTC (22 years, 7 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/tree.py
File MIME type: text/x-python
File size: 7014 byte(s)
	* Thuban/UI/tree.py: We can now simply subscribe to the session's
	CHANGED channel to be informed of changes.
	(SessionTreeCtrl.session_channels): Not needed any longer.
	(SessionTreeCtrl.unsubscribe_all, SessionTreeCtrl.session_changed):
	Only have to (un)subscribe CHANGED

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