/[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 383 - (show annotations)
Tue Jan 28 18:38:03 2003 UTC (22 years, 1 month ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/tree.py
File MIME type: text/x-python
File size: 8384 byte(s)
Handle drawing Colors in the tree view.

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