/[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 521 - (show annotations)
Wed Mar 12 13:18:50 2003 UTC (21 years, 11 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/tree.py
File MIME type: text/x-python
File size: 8775 byte(s)
Create an empty image to use when there is no special image for an item.

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
72 # pretend the session has changed to build the initial tree
73 self.session_changed()
74
75 EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
76
77 def unsubscribe_all(self):
78 if self.session is not None:
79 self.session.Unsubscribe(CHANGED, self.update_tree)
80 self.session = None
81 self.app.Unsubscribe(SESSION_REPLACED, self.session_changed)
82 self.app.interactor.Unsubscribe(SELECTED_LAYER, self.layer_selected)
83
84 def update_tree(self, *args):
85 """Clear and rebuild the tree"""
86 self.DeleteAllItems()
87 self.layer_to_item.clear()
88 self.image_list = wxImageList(BMP_SIZE, BMP_SIZE, False, 0)
89
90 bmp = wxEmptyBitmap(BMP_SIZE, BMP_SIZE)
91 dc = wxMemoryDC()
92 dc.SelectObject(bmp)
93 dc.SetBrush(wxBLACK_BRUSH)
94 dc.Clear()
95 dc.SelectObject(wxNullBitmap)
96
97 self.emptyImageIndex = \
98 self.image_list.AddWithColourMask(bmp, wxColour(0, 0, 0))
99
100 self.AssignImageList(self.image_list)
101
102 session = self.app.session
103 info = session.TreeInfo()
104 root = self.AddRoot(info[0], -1, -1, None)
105 self.SetItemImage(root, self.emptyImageIndex)
106 self.add_items(root, info[1])
107 self.Expand(root)
108 # select the selected layer
109 selected_layer = self.app.interactor.selected_layer
110 if selected_layer is not None:
111 # One would expect that the selected_layer's id is in
112 # layer_to_item at this point as we've just rebuilt that
113 # mapping completely. However, when a new session is loaded
114 # for instance, it can happen that the tree view is updated
115 # before the interactor in which case selected_layer may be
116 # a layer of the old session.
117 item = self.layer_to_item.get(id(selected_layer))
118 if item is not None:
119 self.SelectItem(item)
120
121 def add_items(self, parent, items):
122
123 if items is None: return
124
125 for item in items:
126 if hasattr(item, "TreeInfo"):
127 # Supports the TreeInfo protocol
128 info = item.TreeInfo()
129 treeitem = self.AppendItem(parent, info[0], -1, -1, None)
130 self.SetItemImage(treeitem, self.emptyImageIndex)
131 self.SetPyData(treeitem, item)
132 self.add_items(treeitem, info[1])
133 self.Expand(treeitem)
134 if isinstance(item, Layer):
135 self.layer_to_item[id(item)] = treeitem
136 elif isinstance(item, StringType) or \
137 isinstance(item, UnicodeType):
138 # it's a string
139 treeitem = self.AppendItem(parent, item, -1, -1, None)
140 self.SetItemImage(treeitem, self.emptyImageIndex)
141 else:
142 # assume its a sequence (title, items)
143 if isinstance(item[1], Color):
144
145 treeitem = self.AppendItem(parent, "(%s)" % item[0])
146
147 bmp = wxEmptyBitmap(BMP_SIZE, BMP_SIZE)
148 brush = wxBrush(Color2wxColour(item[1]), wxSOLID)
149 dc = wxMemoryDC()
150 dc.SelectObject(bmp)
151 dc.SetBrush(brush)
152 dc.Clear()
153 dc.DrawRoundedRectangle(0, 0,
154 bmp.GetWidth(), bmp.GetHeight(),
155 4)
156 dc.SelectObject(wxNullBitmap)
157
158 i = self.image_list.Add(bmp)
159 self.SetItemImage(treeitem, i)
160 else:
161 treeitem = self.AppendItem(parent, item[0], -1, -1, None)
162 self.SetItemImage(treeitem, self.emptyImageIndex)
163 self.add_items(treeitem, item[1])
164 self.Expand(treeitem)
165
166 def session_changed(self, *args):
167 new_session = self.app.session
168 # if the session has changed subscribe/unsubscribe
169 if self.session is not new_session:
170 if self.session is not None:
171 self.session.Unsubscribe(CHANGED, self.update_tree)
172 if new_session is not None:
173 new_session.Subscribe(CHANGED, self.update_tree)
174 self.session = new_session
175 self.update_tree()
176
177 def normalize_selection(self):
178 """Select the layer or map containing currently selected item"""
179 item = self.GetSelection()
180 while item.IsOk():
181 object = self.GetPyData(item)
182 if isinstance(object, Layer) or isinstance(object, Map):
183 break
184 item = self.GetItemParent(item)
185 else:
186 # No layer or map was found in the chain of parents, so
187 # there's nothing we can do.
188 return
189
190 self.changing_selection = 1
191 try:
192 self.SelectItem(item)
193 finally:
194 self.changing_selection = 0
195
196 def SelectedLayer(self):
197 """Return the layer object currently selected in the tree.
198 Return None if no layer is selected"""
199 layer = self.GetPyData(self.GetSelection())
200 if isinstance(layer, Layer):
201 return layer
202 return None
203
204 def OnSelChanged(self, event):
205 if self.changing_selection:
206 # we're changing the selection ourselves (probably through
207 # self.normalize_selection(). ignore the event.
208 return
209 self.normalize_selection()
210 # SelectedLayer returns None if no layer is selected. Since
211 # passing None to interactor.SelectLayer deselects the layer we
212 # can simply pass the result of SelectedLayer on in all cases
213 self.app.interactor.SelectLayer(self.SelectedLayer())
214
215 def layer_selected(self, layer):
216 item = self.layer_to_item.get(id(layer))
217 if item is not None and item != self.GetSelection():
218 self.SelectItem(item)
219
220
221 class SessionTreeView(NonModalDialog):
222
223 """Non modal dialog showing the session as a tree"""
224
225 def __init__(self, parent, app, name):
226 NonModalDialog.__init__(self, parent, app.interactor, name,
227 _("Session"))
228 self.tree = SessionTreeCtrl(self, -1, app)
229
230 def OnClose(self, event):
231 NonModalDialog.OnClose(self, event)
232
233 # if there were a way to get notified when the tree control
234 # itself is destroyed we could use that to unsubscribe instead
235 # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
236 # all)
237 self.tree.unsubscribe_all()
238

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26