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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1853 - (hide 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 bh 1850 # 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 bh 1853 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 bh 1850
79 bh 1853 # 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 bh 1850 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 bh 1853 # 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 bh 1850 for i in range(len(self.projections)):
176     p = self.projections[i][1]
177 bh 1853 self.SetItemState(i, p is proj and state or 0, state)
178 bh 1850
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