/[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 2878 - (show annotations)
Tue Jun 2 11:06:15 2009 UTC (15 years, 9 months ago) by dpinte
File MIME type: text/x-python
File size: 8738 byte(s)
2009-06-02 Didrik Pinte <dpinte@dipole-consulting.com>

  * Thuban/UI/projlist.py : removed called to inexistant __del__ method on
                            wx.ListCtrl


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