/[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 991 - (show annotations)
Thu May 22 16:51:44 2003 UTC (21 years, 9 months ago) by frank
Original Path: trunk/thuban/Thuban/Model/map.py
File MIME type: text/x-python
File size: 9097 byte(s)
(Map.TopLayer(), Map.BottomLayer()): New, place
	layer at top/bottom of layer stack.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26