/[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 882 - (show annotations)
Fri May 9 16:34:28 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/map.py
File MIME type: text/x-python
File size: 8107 byte(s)
Explicit imports.

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 RaiseLayer(self, layer):
121 """Swap the layer with the one above it.
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.insert(index + 1, layer)
130 self.changed(MAP_LAYERS_CHANGED, self)
131 self.changed(MAP_STACKING_CHANGED, self)
132
133 def LowerLayer(self, layer):
134 """Swap the layer with the one below it.
135
136 If the layer is already at the bottom do nothing. If the
137 stacking order has been changed, issue a MAP_LAYERS_CHANGED message.
138 """
139 index = self.layers.index(layer)
140 if index > 0:
141 del self.layers[index]
142 self.layers.insert(index - 1, layer)
143 self.changed(MAP_LAYERS_CHANGED, self)
144 self.changed(MAP_STACKING_CHANGED, self)
145
146 def BoundingBox(self):
147 """Return the bounding box of the map in Lat/Lon coordinates.
148
149 Return None if there are no layers or no layer contains any shapes.
150 """
151 if not self.layers:
152 return None
153 llx = []
154 lly = []
155 urx = []
156 ury = []
157 for layer in self.layers:
158 if layer is self.label_layer:
159 continue
160 # the layer's bbox may be None if it doesn't have any layers
161 bbox = layer.LatLongBoundingBox()
162 if bbox is not None:
163 left, bottom, right, top = bbox
164 llx.append(left)
165 lly.append(bottom)
166 urx.append(right)
167 ury.append(top)
168
169 # check whether there were any empty layers.
170 if llx:
171 return (min(llx), min(lly), max(urx), max(ury))
172 else:
173 return None
174
175 def ProjectedBoundingBox(self):
176 """Return the bounding box of the map in projected coordinates.
177
178 Return None if there are no layers or no layer contains any shapes.
179 """
180 # This simply returns the rectangle given by the projected
181 # corners of the non-projected bbox.
182 bbox = self.BoundingBox()
183 if bbox is not None and self.projection is not None:
184 bbox = self.projection.ForwardBBox(bbox)
185 return bbox
186
187 def GetProjection(self):
188 return self.projection
189
190 def SetProjection(self, projection):
191 """Set the projection of the map.
192
193 Issue a MAP_PROJECTION_CHANGED message."""
194 self.projection = projection
195 self.changed(MAP_PROJECTION_CHANGED, self)
196
197 def forward(self, *args):
198 """Reissue events"""
199 if len(args) > 1:
200 args = (args[-1],) + args[:-1]
201 apply(self.issue, args)
202
203 def WasModified(self):
204 """Return true if the map or one of the layers was modified"""
205 if self.modified:
206 return 1
207 else:
208 for layer in self.layers:
209 if layer.WasModified():
210 return 1
211 return self.label_layer.WasModified()
212
213 def UnsetModified(self):
214 """Unset the modified flag of the map and the layers"""
215 Modifiable.UnsetModified(self)
216 for layer in self.layers:
217 layer.UnsetModified()
218 self.label_layer.UnsetModified()
219
220 def TreeInfo(self):
221 items = []
222 if self.BoundingBox() != None:
223 items.append(_("Extent (lat-lon): (%g, %g, %g, %g)")
224 % self.BoundingBox())
225 if self.projection and len(self.projection.params) > 0:
226 items.append(_("Extent (projected): (%g, %g, %g, %g)")
227 % self.ProjectedBoundingBox())
228 items.append((_("Projection"),
229 [str(param)
230 for param in self.projection.params]))
231
232 layers = self.layers[:]
233 layers.reverse()
234 items.extend(layers)
235
236 return (_("Map: %s") % self.title, items)
237

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26