/[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 374 - (show annotations)
Mon Jan 27 14:20:02 2003 UTC (22 years, 1 month ago) by jan
Original Path: trunk/thuban/Thuban/Model/map.py
File MIME type: text/x-python
File size: 7635 byte(s)
Replace user string by _() for i18n.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26