/[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 2700 - (hide annotations)
Mon Sep 18 14:27:02 2006 UTC (18 years, 5 months ago) by dpinte
Original Path: trunk/thuban/Thuban/UI/tree.py
File MIME type: text/x-python
File size: 8809 byte(s)
2006-09-18 Didrik Pinte <dpinte@itae.be>
    
        * wxPython 2.6 update : wx 2.4 syntax has been updated to 2.6


1 bh 535 # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2 bh 6 # Authors:
3     # Jan-Oliver Wagner <[email protected]>
4     # Bernhard Herzog <[email protected]>
5     #
6     # This program is free software under the GPL (>=v2)
7     # Read the file COPYING coming with Thuban for details.
8    
9     __version__ = "$Revision$"
10    
11 jonathan 383 from types import StringType, UnicodeType
12 bh 217
13 dpinte 2700 import wx
14 bh 6
15 jan 374 from Thuban import _
16 jonathan 882 from Thuban.UI.common import Color2wxColour
17 jan 374
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 frank 1058 from dialogs import NonModalNonParentDialog
25 bh 535 from messages import SESSION_REPLACED, LAYER_SELECTED
26 bh 6
27 jonathan 383 BMP_SIZE = 15
28 bh 6
29 dpinte 2700 class SessionTreeCtrl(wx.TreeCtrl):
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 535 def __init__(self, parent, ID, mainwindow, app):
52 jonathan 383
53 bh 6 # Use the WANTS_CHARS style so the panel doesn't eat the Return key.
54 dpinte 2700 wx.TreeCtrl.__init__(self, parent, ID)
55 bh 36
56 bh 535 self.mainwindow = mainwindow
57 bh 6 self.app = app
58 bh 14 # 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 bh 41 # Dictionary mapping layer id's to tree items
63     self.layer_to_item = {}
64    
65 jonathan 504 self.app.Subscribe(SESSION_REPLACED, self.session_changed)
66 bh 535 self.mainwindow.Subscribe(LAYER_SELECTED, self.layer_selected)
67 bh 151
68     # the session currently displayed in the tree
69     self.session = None
70    
71 jonathan 383
72 bh 6 # pretend the session has changed to build the initial tree
73     self.session_changed()
74    
75 dpinte 2700 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=self.GetId())
76 bh 6
77 bh 151 def unsubscribe_all(self):
78     if self.session is not None:
79 bh 233 self.session.Unsubscribe(CHANGED, self.update_tree)
80 bh 161 self.session = None
81 jonathan 504 self.app.Unsubscribe(SESSION_REPLACED, self.session_changed)
82 bh 535 self.mainwindow.Unsubscribe(LAYER_SELECTED, self.layer_selected)
83 bh 151
84 bh 6 def update_tree(self, *args):
85     """Clear and rebuild the tree"""
86 bh 36 self.DeleteAllItems()
87 bh 41 self.layer_to_item.clear()
88 dpinte 2700 self.image_list = wx.ImageList(BMP_SIZE, BMP_SIZE, False, 0)
89 jonathan 521
90 dpinte 2700 bmp = wx.EmptyBitmap(BMP_SIZE, BMP_SIZE)
91     dc = wx.MemoryDC()
92 jonathan 521 dc.SelectObject(bmp)
93 dpinte 2700 dc.SetBrush(wx.BLACK_BRUSH)
94 jonathan 521 dc.Clear()
95 dpinte 2700 dc.SelectObject(wx.NullBitmap)
96 jonathan 521
97     self.emptyImageIndex = \
98 dpinte 2700 self.image_list.AddWithColourMask(bmp, wx.Colour(0, 0, 0))
99 jonathan 521
100 jonathan 510 self.AssignImageList(self.image_list)
101 jan 104
102 bh 217 session = self.app.session
103     info = session.TreeInfo()
104 jonathan 521 root = self.AddRoot(info[0], -1, -1, None)
105     self.SetItemImage(root, self.emptyImageIndex)
106 bh 217 self.add_items(root, info[1])
107 bh 36 self.Expand(root)
108 bh 217 # select the selected layer
109 bh 535 selected_layer = self.mainwindow.current_layer()
110 bh 217 if selected_layer is not None:
111 bh 218 # 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 bh 535 # before the canvas's selection in which case selected_layer
116     # may be a layer of the old session.
117 bh 218 item = self.layer_to_item.get(id(selected_layer))
118     if item is not None:
119     self.SelectItem(item)
120 bh 6
121 bh 217 def add_items(self, parent, items):
122 jonathan 383
123     if items is None: return
124    
125 bh 217 for item in items:
126     if hasattr(item, "TreeInfo"):
127     # Supports the TreeInfo protocol
128     info = item.TreeInfo()
129 jonathan 521 treeitem = self.AppendItem(parent, info[0], -1, -1, None)
130     self.SetItemImage(treeitem, self.emptyImageIndex)
131 bh 217 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 jonathan 383 elif isinstance(item, StringType) or \
137     isinstance(item, UnicodeType):
138 bh 217 # it's a string
139 jonathan 521 treeitem = self.AppendItem(parent, item, -1, -1, None)
140     self.SetItemImage(treeitem, self.emptyImageIndex)
141 bh 217 else:
142     # assume its a sequence (title, items)
143 jonathan 383 if isinstance(item[1], Color):
144    
145 jonathan 417 treeitem = self.AppendItem(parent, "(%s)" % item[0])
146    
147 dpinte 2700 bmp = wx.EmptyBitmap(BMP_SIZE, BMP_SIZE)
148     brush = wx.Brush(Color2wxColour(item[1]), wx.SOLID)
149     dc = wx.MemoryDC()
150 jonathan 383 dc.SelectObject(bmp)
151     dc.SetBrush(brush)
152     dc.Clear()
153 dpinte 2700 dc.DrawRoundedRectangle(0, 0,
154 jonathan 383 bmp.GetWidth(), bmp.GetHeight(),
155     4)
156 dpinte 2700 dc.SelectObject(wx.NullBitmap)
157 jonathan 383
158     i = self.image_list.Add(bmp)
159     self.SetItemImage(treeitem, i)
160     else:
161 jonathan 521 treeitem = self.AppendItem(parent, item[0], -1, -1, None)
162     self.SetItemImage(treeitem, self.emptyImageIndex)
163 jonathan 383 self.add_items(treeitem, item[1])
164 bh 217 self.Expand(treeitem)
165 jan 198
166 bh 6 def session_changed(self, *args):
167 bh 151 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 bh 233 self.session.Unsubscribe(CHANGED, self.update_tree)
172 bh 151 if new_session is not None:
173 bh 233 new_session.Subscribe(CHANGED, self.update_tree)
174 bh 151 self.session = new_session
175 bh 6 self.update_tree()
176    
177     def normalize_selection(self):
178     """Select the layer or map containing currently selected item"""
179 bh 36 item = self.GetSelection()
180 bh 6 while item.IsOk():
181 bh 36 object = self.GetPyData(item)
182 bh 6 if isinstance(object, Layer) or isinstance(object, Map):
183     break
184 bh 36 item = self.GetItemParent(item)
185 bh 353 else:
186     # No layer or map was found in the chain of parents, so
187     # there's nothing we can do.
188     return
189 bh 6
190 bh 14 self.changing_selection = 1
191     try:
192 bh 36 self.SelectItem(item)
193 bh 14 finally:
194     self.changing_selection = 0
195 bh 6
196     def SelectedLayer(self):
197     """Return the layer object currently selected in the tree.
198     Return None if no layer is selected"""
199 bh 36 layer = self.GetPyData(self.GetSelection())
200 bh 6 if isinstance(layer, Layer):
201     return layer
202     return None
203    
204     def OnSelChanged(self, event):
205 bh 14 if self.changing_selection:
206     # we're changing the selection ourselves (probably through
207     # self.normalize_selection(). ignore the event.
208     return
209 bh 6 self.normalize_selection()
210 bh 61 # SelectedLayer returns None if no layer is selected. Since
211 bh 535 # passing None to SelectLayer deselects the layer we can simply
212     # pass the result of SelectedLayer on in all cases
213     self.mainwindow.SelectLayer(self.SelectedLayer())
214 bh 6
215     def layer_selected(self, layer):
216 bh 41 item = self.layer_to_item.get(id(layer))
217     if item is not None and item != self.GetSelection():
218     self.SelectItem(item)
219 bh 36
220    
221 frank 1058 class SessionTreeView(NonModalNonParentDialog):
222 bh 36
223     """Non modal dialog showing the session as a tree"""
224    
225     def __init__(self, parent, app, name):
226 frank 1058 NonModalNonParentDialog.__init__(self, parent, name, _("Session"))
227 bh 535 self.tree = SessionTreeCtrl(self, -1, parent, app)
228 bh 36
229 jonathan 504 def OnClose(self, event):
230 frank 1058 NonModalNonParentDialog.OnClose(self, event)
231 jonathan 504
232 bh 151 # if there were a way to get notified when the tree control
233     # itself is destroyed we could use that to unsubscribe instead
234     # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
235     # all)
236     self.tree.unsubscribe_all()
237 jonathan 488

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26