/[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 504 - (show annotations)
Mon Mar 10 15:12:24 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/tree.py
File MIME type: text/x-python
File size: 8141 byte(s)
Changed SESSION_CHANGED to SESSION_REPLACED.  Go back to using OnClose()
instead of Shutdown().

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26