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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26