/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/map.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/Model/map.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2734 - (hide annotations)
Thu Mar 1 12:42:59 2007 UTC (18 years ago) by bramz
File MIME type: text/x-python
File size: 10294 byte(s)
made a copy
1 jan 2564 # Copyright (c) 2001-2003, 2005 by Intevation GmbH
2 bh 6 # Authors:
3     # Bernhard Herzog <[email protected]>
4 jan 2564 # Jonathan Coles <[email protected]>
5 bh 6 #
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 882 from messages import MAP_LAYERS_CHANGED, MAP_PROJECTION_CHANGED, \
12     CHANGED, LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
13     LAYER_VISIBILITY_CHANGED, LAYER_CHANGED, MAP_STACKING_CHANGED, \
14     MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
15 bh 6
16 jan 374 from Thuban import _
17    
18 bh 6 from base import TitledObject, Modifiable
19    
20     from label import LabelLayer
21    
22    
23     class Map(TitledObject, Modifiable):
24    
25 jan 2569 """Represent a map.
26    
27     A map is a list of layers. Additionally
28 jan 2564 there is a special label layer containing all labels that
29     are defined for the map.
30 bh 6
31     Map objects send the following message types:
32    
33     TITLE_CHANGED -- The title has changed. Parameter: the map.
34    
35 jonathan 546 MAP_LAYERS_CHANGED -- Layers were added, removed or rearranged.
36 bh 6 Parameters: the map
37    
38     MAP_PROJECTION_CHANGED -- the map's projection has changed.
39     Parameter: the map
40     """
41    
42 bh 319 forwarded_channels = (CHANGED,
43     LAYER_PROJECTION_CHANGED,
44 bh 6 LAYER_LEGEND_CHANGED,
45 jonathan 559 LAYER_CHANGED,
46 bh 6 LAYER_VISIBILITY_CHANGED)
47    
48     def __init__(self, title, projection = None):
49     """Initialize the map."""
50     TitledObject.__init__(self, title)
51 bh 319 Modifiable.__init__(self)
52 bh 6 self.layers = []
53 jan 374 self.label_layer = LabelLayer(_("Labels"))
54 jonathan 546 self.label_layer.Subscribe(CHANGED, self.forward, MAP_LAYERS_CHANGED)
55 bh 6 self.projection = projection
56    
57     def Destroy(self):
58 jan 2569 """Destroys the map object with all layers including the label layer.
59 jan 2564
60 jan 2569 Calls Modifiable. Destroy first since it will call
61 jan 2564 Publisher.Destroy which removes all subscriptions. Otherwise
62     clearing the layers results in messages to be sent which can
63     cause problems.
64     """
65 bh 249 Modifiable.Destroy(self)
66     self.ClearLayers()
67 jonathan 546 self.label_layer.Unsubscribe(CHANGED, self.forward, MAP_LAYERS_CHANGED)
68 bh 249 self.label_layer.Destroy()
69 bh 6
70     def AddLayer(self, layer):
71 jonathan 1388 """Append layer to the map on top of all."""
72 bh 6 self.layers.append(layer)
73 bh 245 self.subscribe_layer_channels(layer)
74 jonathan 546 self.changed(MAP_LAYERS_CHANGED, self)
75     self.changed(MAP_LAYERS_ADDED, self)
76 bh 6
77     def RemoveLayer(self, layer):
78 jan 2564 """Remove layer from the map.
79 jan 2569
80 jan 2564 This can not be applied for the label layer of the map.
81     """
82 bh 245 self.unsubscribe_layer_channels(layer)
83 bh 6 self.layers.remove(layer)
84 jonathan 546 self.changed(MAP_LAYERS_CHANGED, self)
85     self.changed(MAP_LAYERS_REMOVED, self)
86 bh 6 layer.Destroy()
87    
88 bh 298 def CanRemoveLayer(self, layer):
89     """Return true if the layer can be deleted.
90    
91     The default implementation always returns 1. Derived classes
92     should override this method if they have e.g. special layers
93     that the user should not be able to remove.
94     """
95     return 1
96    
97 bh 249 def ClearLayers(self):
98 jan 2569 """Delete all layers and also remove all labels from the label layer.
99 jan 2564 """
100 bh 249 for layer in self.layers:
101     self.unsubscribe_layer_channels(layer)
102     layer.Destroy()
103     del self.layers[:]
104     self.label_layer.ClearLabels()
105 jonathan 546 self.changed(MAP_LAYERS_CHANGED, self)
106     self.changed(MAP_LAYERS_REMOVED, self)
107 bh 249
108 bh 245 def subscribe_layer_channels(self, layer):
109     """Subscribe to some of layer's channels."""
110     for channel in self.forwarded_channels:
111     layer.Subscribe(channel, self.forward, channel)
112    
113     def unsubscribe_layer_channels(self, layer):
114     """Unsubscribe to some of layer's channels."""
115     for channel in self.forwarded_channels:
116     layer.Unsubscribe(channel, self.forward, channel)
117    
118 bh 6 def LabelLayer(self):
119     """Return the Map's label layer"""
120     return self.label_layer
121    
122     def Layers(self):
123 bh 249 """Return the list of layers contained in the map.
124    
125 jan 2564 The list does not include the label layer which
126     can be retrieved by a separate method."""
127 bh 6 return self.layers
128    
129     def HasLayers(self):
130 jan 2569 """Information whether this map has layers.
131    
132     Returns true if the map has at least one layer other
133 jan 2564 than the label layer."""
134 bh 6 return len(self.layers) > 0
135    
136 jonathan 1099 def MoveLayerToTop(self, layer):
137 jan 2569 """Put the layer on top of the layer stack.
138 frank 991
139 jan 2569 This can not be applied to the label layer.
140    
141 frank 991 If the layer is already at the top do nothing. If the stacking
142     order has been changed, issue a MAP_LAYERS_CHANGED message.
143     """
144     index = self.layers.index(layer)
145     if index < len(self.layers) - 1:
146     del self.layers[index]
147     self.layers.append(layer)
148     self.changed(MAP_LAYERS_CHANGED, self)
149     self.changed(MAP_STACKING_CHANGED, self)
150    
151 bh 6 def RaiseLayer(self, layer):
152 jan 2569 """Swap the layer with the one above it.
153 bh 249
154 jan 2569 This does not apply to the label layer.
155    
156 bh 249 If the layer is already at the top do nothing. If the stacking
157 jonathan 546 order has been changed, issue a MAP_LAYERS_CHANGED message.
158 bh 249 """
159 bh 6 index = self.layers.index(layer)
160     if index < len(self.layers) - 1:
161     del self.layers[index]
162     self.layers.insert(index + 1, layer)
163 jonathan 546 self.changed(MAP_LAYERS_CHANGED, self)
164     self.changed(MAP_STACKING_CHANGED, self)
165 bh 6
166     def LowerLayer(self, layer):
167 jan 2569 """Swap the layer with the one below it.
168 bh 249
169 jan 2569 This does not apply to the label layer.
170    
171 bh 249 If the layer is already at the bottom do nothing. If the
172 jonathan 546 stacking order has been changed, issue a MAP_LAYERS_CHANGED message.
173 bh 249 """
174 bh 6 index = self.layers.index(layer)
175     if index > 0:
176     del self.layers[index]
177     self.layers.insert(index - 1, layer)
178 jonathan 546 self.changed(MAP_LAYERS_CHANGED, self)
179     self.changed(MAP_STACKING_CHANGED, self)
180 bh 6
181 jonathan 1099 def MoveLayerToBottom(self, layer):
182 jan 2569 """Put the layer at the bottom of the stack.
183 frank 991
184 jan 2569 This does not apply to the label layer.
185    
186 frank 991 If the layer is already at the bottom do nothing. If the
187     stacking order has been changed, issue a MAP_LAYERS_CHANGED message.
188     """
189     index = self.layers.index(layer)
190     if index > 0:
191     del self.layers[index]
192     self.layers.insert(0, layer)
193     self.changed(MAP_LAYERS_CHANGED, self)
194     self.changed(MAP_STACKING_CHANGED, self)
195    
196 bh 6 def BoundingBox(self):
197 bh 249 """Return the bounding box of the map in Lat/Lon coordinates.
198 jan 2569
199 jan 2564 The label layer is not considered for the computation of the
200     bounding box.
201 bh 178
202 jan 2564 Return None if there are no layers (except the label layer) or
203     no layer contains any shapes.
204 bh 178 """
205 bh 6 if not self.layers:
206     return None
207     llx = []
208     lly = []
209     urx = []
210     ury = []
211     for layer in self.layers:
212 jonathan 931 # the layer's bbox may be None if it doesn't have any shapes
213 bh 178 bbox = layer.LatLongBoundingBox()
214     if bbox is not None:
215     left, bottom, right, top = bbox
216     llx.append(left)
217     lly.append(bottom)
218     urx.append(right)
219     ury.append(top)
220 bh 6
221 bh 178 # check whether there were any empty layers.
222     if llx:
223     return (min(llx), min(lly), max(urx), max(ury))
224     else:
225     return None
226    
227 bh 6 def ProjectedBoundingBox(self):
228 bh 249 """Return the bounding box of the map in projected coordinates.
229 jan 2569
230 jan 2564 The label layer is not considered for the computation of the
231     bounding box.
232 bh 249
233 jan 2564 Return None if there are no layers (except the label layer) or
234     no layer contains any shapes.
235 bh 249 """
236 bh 6 # This simply returns the rectangle given by the projected
237     # corners of the non-projected bbox.
238     bbox = self.BoundingBox()
239     if bbox is not None and self.projection is not None:
240     bbox = self.projection.ForwardBBox(bbox)
241     return bbox
242    
243 jonathan 707 def GetProjection(self):
244 jan 2564 """Return the projection of the map."""
245 jonathan 707 return self.projection
246    
247 bh 6 def SetProjection(self, projection):
248 bh 249 """Set the projection of the map.
249    
250 jan 2569 Issue a MAP_PROJECTION_CHANGED message.
251     """
252 jonathan 1388 old_proj = self.projection
253 bh 6 self.projection = projection
254 jonathan 1388 self.changed(MAP_PROJECTION_CHANGED, self, old_proj)
255 bh 6
256     def forward(self, *args):
257     """Reissue events"""
258     if len(args) > 1:
259     args = (args[-1],) + args[:-1]
260     apply(self.issue, args)
261    
262     def WasModified(self):
263     """Return true if the map or one of the layers was modified"""
264     if self.modified:
265     return 1
266     else:
267     for layer in self.layers:
268     if layer.WasModified():
269     return 1
270     return self.label_layer.WasModified()
271    
272     def UnsetModified(self):
273     """Unset the modified flag of the map and the layers"""
274     Modifiable.UnsetModified(self)
275     for layer in self.layers:
276     layer.UnsetModified()
277     self.label_layer.UnsetModified()
278    
279 bh 217 def TreeInfo(self):
280 jan 2569 """Return a description of the object.
281    
282     A tuple of (title, tupel) describing the contents
283     of the object in a tree-structure is returned.
284 jan 2564 """
285 bh 217 items = []
286     if self.BoundingBox() != None:
287 jan 374 items.append(_("Extent (lat-lon): (%g, %g, %g, %g)")
288 bh 217 % self.BoundingBox())
289 bh 231 if self.projection and len(self.projection.params) > 0:
290 jan 374 items.append(_("Extent (projected): (%g, %g, %g, %g)")
291 bh 231 % self.ProjectedBoundingBox())
292 jan 374 items.append((_("Projection"),
293 bh 231 [str(param)
294     for param in self.projection.params]))
295 bh 6
296 bh 217 layers = self.layers[:]
297     layers.reverse()
298     items.extend(layers)
299 jan 2564 items.append(self.label_layer)
300 bh 217
301 jan 374 return (_("Map: %s") % self.title, items)

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26