/[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 298 - (show annotations)
Fri Aug 30 17:40:52 2002 UTC (22 years, 6 months ago) by bh
Original Path: trunk/thuban/Thuban/Model/map.py
File MIME type: text/x-python
File size: 7529 byte(s)
(Map.CanRemoveLayer): New method to
determine whether a given layer can be deleted.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26