/[thuban]/trunk/thuban/Thuban/UI/projlist.py
ViewVC logotype

Contents of /trunk/thuban/Thuban/UI/projlist.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1853 - (show annotations)
Wed Oct 22 09:38:20 2003 UTC (21 years, 4 months ago) by bh
File MIME type: text/x-python
File size: 8277 byte(s)
(ProjectionList.Destroy): Unsubscribe from
the ProjFile's messages and call the base class methods correctly
(ProjectionList.SelectProjection): Set the wxLIST_STATE_FOCUSED
flag on the newly selected item too. Otherwise some other item is
focused and the first time the focus is moved with the keyboard
the selection moves in unexpected ways.

1 # Copyright (C) 2003 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 #
5 # This program is free software under the GPL (>=v2)
6 # Read the file COPYING coming with the software for details.
7
8 """List control for projections"""
9
10 __version__ = "$Revision$"
11 # $Source$
12 # $Id$
13
14 from wxPython.wx import *
15
16 from Thuban import _
17
18 from Thuban.Lib.connector import Publisher
19
20 from Thuban.Model.messages import PROJECTION_ADDED, PROJECTION_REMOVED, \
21 PROJECTION_REPLACED
22
23
24 PROJ_SELECTION_CHANGED = "PROJ_SELECTION_CHANGED"
25
26
27 class ProjectionList(wxListCtrl, Publisher):
28
29 """A ListCtrl that shows a list of projections
30
31 The list control is effectively a view on two ProjFile instances and
32 a specific 'original' projection (e.g. the projection of the current
33 map). The list control subscribes to the change messages of the
34 ProjFile instances to update the list whenever they change.
35
36 When the selection changes the instance sends a
37 PROJ_SELECTION_CHANGED message.
38 """
39
40 def __init__(self, parent, system_projs, user_projs, orig_proj, ID = -1):
41 """Initialize the ProjectionList
42
43 Parameters:
44
45 parent -- The parent widget
46 system_projs, user_projs -- the system and user ProjFiles
47 orig_proj -- The projection originally selected in the map/layer
48 """
49 wxListCtrl.__init__(self, parent, ID, style=wxLC_REPORT|wxLC_VIRTUAL)
50
51 self.InsertColumn(0, _("Available Projections"))
52 self.system_projs = system_projs
53 self.user_projs = user_projs
54 self.orig_proj = orig_proj
55 self.projections = []
56 self.proj_map = {}
57 self.needs_update = False
58 self.update_projections()
59 EVT_SIZE(self, self.OnSize)
60 EVT_LEFT_UP(self, self.mouse_left_up)
61 EVT_LIST_ITEM_SELECTED(self, self.GetId(), self.item_selected)
62 EVT_LIST_ITEM_DESELECTED(self, self.GetId(), self.item_deselected)
63 EVT_IDLE(self, self.OnIdle)
64 for pf in (self.system_projs, self.user_projs):
65 pf.Subscribe(PROJECTION_ADDED, self.pf_projection_added)
66 pf.Subscribe(PROJECTION_REMOVED, self.pf_projection_removed)
67 pf.Subscribe(PROJECTION_REPLACED, self.pf_projection_replaced)
68
69 def __del__(self):
70 wxListCtrl.__del__()
71 Publisher.__del__()
72
73 def Destroy(self):
74 for pf in (self.system_projs, self.user_projs):
75 pf.Unsubscribe(PROJECTION_ADDED, self.pf_projection_added)
76 pf.Unsubscribe(PROJECTION_REMOVED, self.pf_projection_removed)
77 pf.Unsubscribe(PROJECTION_REPLACED, self.pf_projection_replaced)
78
79 # Call wxListCtrl's method last because afterwards self is not
80 # an instance of ProjectionList anymore as wxPython replaces
81 # self.__class__ with its dead object class
82 Publisher.Destroy(self)
83 wxListCtrl.Destroy(self)
84
85 def update_on_idle(self):
86 self.needs_update = True
87
88 def OnIdle(self, evt):
89 if self.needs_update:
90 self.needs_update = False
91 self.update_projections()
92 evt.Skip()
93
94 def update_projections(self):
95 """Update the internal list of projection information"""
96
97 # Remember which projections are selected so that we can select
98 # them again after the update
99 selection = {}
100 for p in self.selected_projections():
101 selection[id(p[0])] = 1
102 old_length = len(self.projections)
103
104 # Build the new projection list
105 projections = [(_("<None>"), None, None)]
106 for pf in (self.user_projs, self.system_projs):
107 for p in pf.GetProjections():
108 projections.append((p.Label(), p, pf))
109 if self.orig_proj is not None:
110 projections.append((_("%s (current)") % self.orig_proj.Label(),
111 self.orig_proj, None))
112 self.projections = projections
113 self.projections.sort()
114
115 # Deselect all items with indices higher than the new length
116 # before settign the new item count This is a work-around for a
117 # bug in the listctrl which doesn't updat the selection count
118 # correctly in a call to SetItemCount if items have been
119 # selected with indices higher than the new count.
120 if len(self.projections) < old_length:
121 for i in xrange(len(self.projections), old_length):
122 self.SetItemState(i, 0, wxLIST_STATE_SELECTED)
123
124 self.SetItemCount(len(self.projections))
125
126 # Reselect the projections that had been selected before.
127 get = selection.get
128 count = 0
129 for i in xrange(len(self.projections)):
130 p = self.projections[i][1]
131 if get(id(p)):
132 state = wxLIST_STATE_SELECTED
133 count += 1
134 else:
135 state = 0
136 self.SetItemState(i, state, wxLIST_STATE_SELECTED)
137
138 # If the selection changed send a PROJ_SELECTION_CHANGED message
139 if count != len(selection):
140 self._issue_proj_selection_changed()
141
142 def pf_projection_added(self, proj):
143 """Subscribed to the projfile's PROJECTION_ADDED messages
144
145 Request an update the projection list in idle time.
146 """
147 self.update_on_idle()
148
149 def pf_projection_removed(self, proj):
150 """Subscribed to the projfile's PROJECTION_REMOVED messages
151
152 Request an update the projection list in idle time.
153 """
154 self.update_on_idle()
155
156 def pf_projection_replaced(self, old, new):
157 """Subscribed to the projfile's PROJECTION_REPLACED messages
158
159 Request an update the projection list in idle time.
160 """
161 self.update_on_idle()
162
163 def OnSize(self, evt):
164 self.SetColumnWidth(0, evt.GetSize().width)
165 evt.Skip()
166
167 def SelectProjection(self, proj):
168 """Select the projection and deselect all others."""
169 # Set both the wxLIST_STATE_SELECTED and wxLIST_STATE_FOCUSED
170 # flags on the newly selected item. If only
171 # wxLIST_STATE_SELECTED is set, some other item is focused and
172 # the first time the focus is moved with the keyboard the
173 # selection moves in unexpected ways.
174 state = wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED
175 for i in range(len(self.projections)):
176 p = self.projections[i][1]
177 self.SetItemState(i, p is proj and state or 0, state)
178
179 def ClearSelection(self):
180 """Deselect all projections."""
181 for i in range(len(self.projections)):
182 self.SetItemState(i, 0, wxLIST_STATE_SELECTED)
183
184 def OnGetItemText(self, item, col):
185 """Callback for the virtual ListCtrl mode"""
186 return self.projections[item][0]
187
188 def OnGetItemAttr(self, item):
189 """Callback for the virtual ListCtrl mode"""
190 return None
191
192 def OnGetItemImage(self, item):
193 """Callback for the virtual ListCtrl mode"""
194 return -1
195
196 def selected_projections(self):
197 """Return a list with all selected projection infos
198
199 The return value is a list of (proj, proj_file) pairs. proj_file
200 is the projection file object the projection was read from, if
201 any. Both proj and proj_file may be None, but if proj_file is
202 not None proj will also not be None.
203 """
204 return [self.projections[i][1:]
205 for i in range(len(self.projections))
206 if self.GetItemState(i, wxLIST_STATE_SELECTED)]
207
208 def _issue_proj_selection_changed(self):
209 """Internal: Issue a PROJ_SELECTION_CHANGED message"""
210 self.issue(PROJ_SELECTION_CHANGED, self.selected_projections())
211
212 def item_selected(self, evt):
213 """Handler for EVT_LIST_ITEM_SELECTED"""
214 self._issue_proj_selection_changed()
215
216 def item_deselected(self, evt):
217 #"""Handler for EVT_LIST_ITEM_DESELECTED"""
218 self._issue_proj_selection_changed()
219
220 def mouse_left_up(self, evt):
221 """Handle EVT_LEFT_UP events. Issue a selection message.
222
223 It's not clear whether the selection really has changed but the
224 selection events send by the list ctrl don't cover selecting
225 ranges of items :(.
226 """
227 self._issue_proj_selection_changed()

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26