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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2564 - (show annotations)
Wed Feb 16 23:14:35 2005 UTC (20 years ago) by jan
Original Path: trunk/thuban/Thuban/Model/map.py
File MIME type: text/x-python
File size: 10187 byte(s)
(Map, Map.Destroy, Map.RemoveLayer, Map.ClearLayers,
Map.Layers, Map.HasLayers, Map.MoveLayerToTop,
Map.RaiseLayer, Map.LowerLayer, Map.MoveLayerToBottom,
Map.ProjectedBoundingBox, Map.GetProjection): Improved/added
doc string.
(Map.BoundingBox): Removed superfluous test for label_layer
and improved doc string.
(Map.TreeInfo): Added label_layer and improved sdo string.

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