/[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 319 - (show annotations)
Fri Sep 13 14:21:24 2002 UTC (22 years, 5 months ago) by bh
Original Path: trunk/thuban/Thuban/Model/map.py
File MIME type: text/x-python
File size: 7598 byte(s)
(Map.forwarded_channels): Forward the
CHANGED channel too.
(Map.__init__): Call the Modifiable constructor as well.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26