/[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 353 - (hide annotations)
Tue Dec 3 17:35:30 2002 UTC (22 years, 3 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/tree.py
File MIME type: text/x-python
File size: 7156 byte(s)
(SessionTreeCtrl.normalize_selection): Handle
the case of selected items that are not children of Layers or Maps
properly. Previously this bug would trigger an assertion in
wxWindows.

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