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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 383 - (hide 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 bh 6 #! /usr/bin/python
2 bh 151 # Copyright (c) 2001, 2002 by Intevation GmbH
3 bh 6 # 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 jonathan 383 from types import StringType, UnicodeType
13 bh 217
14 bh 6 from wxPython.wx import *
15    
16 jan 374 from Thuban import _
17    
18 jonathan 383 from Thuban.Model.color import Color
19    
20 bh 233 from Thuban.Model.messages import CHANGED
21     from Thuban.Model.layer import Layer
22 bh 6 from Thuban.Model.map import Map
23    
24 bh 36 from dialogs import NonModalDialog
25 bh 6 from messages import SESSION_CHANGED, SELECTED_LAYER
26    
27 jonathan 383 BMP_SIZE = 15
28 bh 6
29 bh 41 class SessionTreeCtrl(wxTreeCtrl):
30 bh 36
31 bh 217 """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 bh 36 def __init__(self, parent, ID, app):
52 jonathan 383
53 bh 6 # Use the WANTS_CHARS style so the panel doesn't eat the Return key.
54 bh 36 wxTreeCtrl.__init__(self, parent, ID)
55    
56 bh 6 self.app = app
57 bh 14 # 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 bh 41 # Dictionary mapping layer id's to tree items
62     self.layer_to_item = {}
63    
64 bh 6 self.app.Subscribe(SESSION_CHANGED, self.session_changed)
65     self.app.interactor.Subscribe(SELECTED_LAYER, self.layer_selected)
66 bh 151
67     # the session currently displayed in the tree
68     self.session = None
69    
70 jonathan 383 self.image_list = wxImageList(BMP_SIZE, BMP_SIZE)
71     self.AssignImageList(self.image_list)
72    
73 bh 6 # pretend the session has changed to build the initial tree
74     self.session_changed()
75    
76 bh 36 EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
77 bh 6
78 bh 151 def unsubscribe_all(self):
79     if self.session is not None:
80 bh 233 self.session.Unsubscribe(CHANGED, self.update_tree)
81 bh 161 self.session = None
82 bh 151 self.app.Unsubscribe(SESSION_CHANGED, self.session_changed)
83     self.app.interactor.Unsubscribe(SELECTED_LAYER, self.layer_selected)
84    
85 bh 6 def update_tree(self, *args):
86     """Clear and rebuild the tree"""
87 bh 36 self.DeleteAllItems()
88 bh 41 self.layer_to_item.clear()
89 jan 104
90 bh 217 session = self.app.session
91     info = session.TreeInfo()
92     root = self.AddRoot(info[0])
93     self.add_items(root, info[1])
94 bh 36 self.Expand(root)
95 bh 217 # select the selected layer
96     selected_layer = self.app.interactor.selected_layer
97     if selected_layer is not None:
98 bh 218 # 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 bh 6
108 bh 217 def add_items(self, parent, items):
109 jonathan 383 # print "\n---\n", items
110    
111     if items is None: return
112    
113 bh 217 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 jonathan 383 elif isinstance(item, StringType) or \
124     isinstance(item, UnicodeType):
125 bh 217 # it's a string
126     self.AppendItem(parent, item)
127     else:
128     # assume its a sequence (title, items)
129 jonathan 383 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 bh 217 self.Expand(treeitem)
152 jan 198
153 bh 6 def session_changed(self, *args):
154 bh 151 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 bh 233 self.session.Unsubscribe(CHANGED, self.update_tree)
159 bh 151 if new_session is not None:
160 bh 233 new_session.Subscribe(CHANGED, self.update_tree)
161 bh 151 self.session = new_session
162 bh 6 self.update_tree()
163    
164     def normalize_selection(self):
165     """Select the layer or map containing currently selected item"""
166 bh 36 item = self.GetSelection()
167 bh 6 while item.IsOk():
168 bh 36 object = self.GetPyData(item)
169 bh 6 if isinstance(object, Layer) or isinstance(object, Map):
170     break
171 bh 36 item = self.GetItemParent(item)
172 bh 353 else:
173     # No layer or map was found in the chain of parents, so
174     # there's nothing we can do.
175     return
176 bh 6
177 bh 14 self.changing_selection = 1
178     try:
179 bh 36 self.SelectItem(item)
180 bh 14 finally:
181     self.changing_selection = 0
182 bh 6
183     def SelectedLayer(self):
184     """Return the layer object currently selected in the tree.
185     Return None if no layer is selected"""
186 bh 36 layer = self.GetPyData(self.GetSelection())
187 bh 6 if isinstance(layer, Layer):
188     return layer
189     return None
190    
191     def OnSelChanged(self, event):
192 bh 14 if self.changing_selection:
193     # we're changing the selection ourselves (probably through
194     # self.normalize_selection(). ignore the event.
195     return
196 bh 6 self.normalize_selection()
197 bh 61 # 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 bh 6
202     def layer_selected(self, layer):
203 bh 41 item = self.layer_to_item.get(id(layer))
204     if item is not None and item != self.GetSelection():
205     self.SelectItem(item)
206 bh 36
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 jan 374 NonModalDialog.__init__(self, parent, app.interactor, name,
214     _("Session"))
215 bh 41 self.tree = SessionTreeCtrl(self, -1, app)
216 bh 36
217     def OnClose(self, event):
218     #self.interactor.Unsubscribe(SELECTED_SHAPE, self.select_shape)
219     NonModalDialog.OnClose(self, event)
220    
221 bh 151 # 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