/[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 559 - (show annotations)
Wed Mar 26 11:05:33 2003 UTC (21 years, 11 months ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/map.py
File MIME type: text/x-python
File size: 7992 byte(s)
(Map): Forward LAYER_CHANGED messages.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26