/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/map.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/map.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/thuban/Thuban/Model/map.py revision 217 by bh, Wed Jul 17 10:50:40 2002 UTC branches/WIP-pyshapelib-bramz/Thuban/Model/map.py revision 2734 by bramz, Thu Mar 1 12:42:59 2007 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002 by Intevation GmbH  # Copyright (c) 2001-2003, 2005 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4    # Jonathan Coles <[email protected]>
5  #  #
6  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
7  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
8    
9  __version__ = "$Revision$"  __version__ = "$Revision$"
10    
11  from messages import LAYERS_CHANGED, MAP_PROJECTION_CHANGED, \  from messages import MAP_LAYERS_CHANGED, MAP_PROJECTION_CHANGED, \
12       CHANGED, LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \       CHANGED, LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
13       LAYER_VISIBILITY_CHANGED       LAYER_VISIBILITY_CHANGED, LAYER_CHANGED, MAP_STACKING_CHANGED, \
14         MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
15    
16    from Thuban import _
17    
18  from base import TitledObject, Modifiable  from base import TitledObject, Modifiable
19    
20  from label import LabelLayer  from label import LabelLayer
21    
22    
   
23  class Map(TitledObject, Modifiable):  class Map(TitledObject, Modifiable):
24    
25      """Represent a map. A map is simply a list of layers.      """Represent a map.
26    
27        A map is a list of layers. Additionally
28        there is a special label layer containing all labels that
29        are defined for the map.
30    
31      Map objects send the following message types:      Map objects send the following message types:
32    
33          TITLE_CHANGED -- The title has changed. Parameter: the map.          TITLE_CHANGED -- The title has changed. Parameter: the map.
34    
35          LAYERS_CHANGED -- Layers were added, removed or rearranged.          MAP_LAYERS_CHANGED -- Layers were added, removed or rearranged.
36                          Parameters: the map                          Parameters: the map
37    
38          MAP_PROJECTION_CHANGED -- the map's projection has changed.          MAP_PROJECTION_CHANGED -- the map's projection has changed.
39                          Parameter: the map                          Parameter: the map
40      """      """
41    
42      forwarded_channels = (LAYER_PROJECTION_CHANGED,      forwarded_channels = (CHANGED,
43                              LAYER_PROJECTION_CHANGED,
44                            LAYER_LEGEND_CHANGED,                            LAYER_LEGEND_CHANGED,
45                              LAYER_CHANGED,
46                            LAYER_VISIBILITY_CHANGED)                            LAYER_VISIBILITY_CHANGED)
47    
48      def __init__(self, title, projection = None):      def __init__(self, title, projection = None):
49          """Initialize the map."""          """Initialize the map."""
50          TitledObject.__init__(self, title)          TitledObject.__init__(self, title)
51            Modifiable.__init__(self)
52          self.layers = []          self.layers = []
53          self.label_layer = LabelLayer("Labels")          self.label_layer = LabelLayer(_("Labels"))
54          self.label_layer.Subscribe(CHANGED, self.forward, LAYERS_CHANGED)          self.label_layer.Subscribe(CHANGED, self.forward, MAP_LAYERS_CHANGED)
55          self.projection = projection          self.projection = projection
56    
57      def Destroy(self):      def Destroy(self):
58          for layer in self.layers:          """Destroys the map object with all layers including the label layer.
59              layer.Destroy()  
60          self.label_layer.Unsubscribe(CHANGED, self.forward, LAYERS_CHANGED)          Calls Modifiable. Destroy first since it will call
61            Publisher.Destroy which removes all subscriptions. Otherwise
62            clearing the layers results in messages to be sent which can
63            cause problems.
64            """
65          Modifiable.Destroy(self)          Modifiable.Destroy(self)
66            self.ClearLayers()
67            self.label_layer.Unsubscribe(CHANGED, self.forward, MAP_LAYERS_CHANGED)
68            self.label_layer.Destroy()
69    
70      def AddLayer(self, layer):      def AddLayer(self, layer):
71            """Append layer to the map on top of all."""
72          self.layers.append(layer)          self.layers.append(layer)
73            self.subscribe_layer_channels(layer)
74            self.changed(MAP_LAYERS_CHANGED, self)
75            self.changed(MAP_LAYERS_ADDED, self)
76    
77        def RemoveLayer(self, layer):
78            """Remove layer from the map.
79    
80            This can not be applied for the label layer of the map.
81            """
82            self.unsubscribe_layer_channels(layer)
83            self.layers.remove(layer)
84            self.changed(MAP_LAYERS_CHANGED, self)
85            self.changed(MAP_LAYERS_REMOVED, self)
86            layer.Destroy()
87    
88        def CanRemoveLayer(self, layer):
89            """Return true if the layer can be deleted.
90    
91            The default implementation always returns 1. Derived classes
92            should override this method if they have e.g. special layers
93            that the user should not be able to remove.
94            """
95            return 1
96    
97        def ClearLayers(self):
98            """Delete all layers and also remove all labels from the label layer.
99            """
100            for layer in self.layers:
101                self.unsubscribe_layer_channels(layer)
102                layer.Destroy()
103            del self.layers[:]
104            self.label_layer.ClearLabels()
105            self.changed(MAP_LAYERS_CHANGED, self)
106            self.changed(MAP_LAYERS_REMOVED, self)
107    
108        def subscribe_layer_channels(self, layer):
109            """Subscribe to some of layer's channels."""
110          for channel in self.forwarded_channels:          for channel in self.forwarded_channels:
111              layer.Subscribe(channel, self.forward, channel)              layer.Subscribe(channel, self.forward, channel)
         self.changed(LAYERS_CHANGED, self)  
112    
113      def RemoveLayer(self, layer):      def unsubscribe_layer_channels(self, layer):
114            """Unsubscribe to some of layer's channels."""
115          for channel in self.forwarded_channels:          for channel in self.forwarded_channels:
116              layer.Unsubscribe(channel, self.forward, channel)              layer.Unsubscribe(channel, self.forward, channel)
         self.layers.remove(layer)  
         self.changed(LAYERS_CHANGED, self)  
         layer.Destroy()  
117    
118      def LabelLayer(self):      def LabelLayer(self):
119          """Return the Map's label layer"""          """Return the Map's label layer"""
120          return self.label_layer          return self.label_layer
121    
122      def Layers(self):      def Layers(self):
123            """Return the list of layers contained in the map.
124    
125            The list does not include the label layer which
126            can be retrieved by a separate method."""
127          return self.layers          return self.layers
128    
129      def HasLayers(self):      def HasLayers(self):
130            """Information whether this map has layers.
131    
132            Returns true if the map has at least one layer other
133            than the label layer."""
134          return len(self.layers) > 0          return len(self.layers) > 0
135    
136        def MoveLayerToTop(self, layer):
137            """Put the layer on top of the layer stack.
138    
139            This can not be applied to the label layer.
140    
141            If the layer is already at the top do nothing. If the stacking
142            order has been changed, issue a MAP_LAYERS_CHANGED message.
143            """
144            index = self.layers.index(layer)
145            if index < len(self.layers) - 1:
146                del self.layers[index]
147                self.layers.append(layer)
148                self.changed(MAP_LAYERS_CHANGED, self)
149                self.changed(MAP_STACKING_CHANGED, self)
150    
151      def RaiseLayer(self, layer):      def RaiseLayer(self, layer):
152            """Swap the layer with the one above it.
153    
154            This does not apply to the label layer.
155    
156            If the layer is already at the top do nothing. If the stacking
157            order has been changed, issue a MAP_LAYERS_CHANGED message.
158            """
159          index = self.layers.index(layer)          index = self.layers.index(layer)
160          if index < len(self.layers) - 1:          if index < len(self.layers) - 1:
161              del self.layers[index]              del self.layers[index]
162              self.layers.insert(index + 1, layer)              self.layers.insert(index + 1, layer)
163          self.changed(LAYERS_CHANGED, self)              self.changed(MAP_LAYERS_CHANGED, self)
164                self.changed(MAP_STACKING_CHANGED, self)
165    
166      def LowerLayer(self, layer):      def LowerLayer(self, layer):
167            """Swap the layer with the one below it.
168    
169            This does not apply to the label layer.
170    
171            If the layer is already at the bottom do nothing. If the
172            stacking order has been changed, issue a MAP_LAYERS_CHANGED message.
173            """
174          index = self.layers.index(layer)          index = self.layers.index(layer)
175          if index > 0:          if index > 0:
176              del self.layers[index]              del self.layers[index]
177              self.layers.insert(index - 1, layer)              self.layers.insert(index - 1, layer)
178          self.changed(LAYERS_CHANGED, self)              self.changed(MAP_LAYERS_CHANGED, self)
179                self.changed(MAP_STACKING_CHANGED, self)
180    
181        def MoveLayerToBottom(self, layer):
182            """Put the layer at the bottom of the stack.
183    
184            This does not apply to the label layer.
185    
186            If the layer is already at the bottom do nothing. If the
187            stacking order has been changed, issue a MAP_LAYERS_CHANGED message.
188            """
189            index = self.layers.index(layer)
190            if index > 0:
191                del self.layers[index]
192                self.layers.insert(0, layer)
193                self.changed(MAP_LAYERS_CHANGED, self)
194                self.changed(MAP_STACKING_CHANGED, self)
195    
196      def BoundingBox(self):      def BoundingBox(self):
197          """Return the bounding box of the map in projected coordinates.          """Return the bounding box of the map in Lat/Lon coordinates.
198    
199            The label layer is not considered for the computation of the
200            bounding box.
201    
202          Return None if there are no layers or no layer contains any shapes.          Return None if there are no layers (except the label layer) or
203            no layer contains any shapes.
204          """          """
205          if not self.layers:          if not self.layers:
206              return None              return None
# Line 99  class Map(TitledObject, Modifiable): Line 209  class Map(TitledObject, Modifiable):
209          urx = []          urx = []
210          ury = []          ury = []
211          for layer in self.layers:          for layer in self.layers:
212              if layer is self.label_layer:              # the layer's bbox may be None if it doesn't have any shapes
                 continue  
             # the layer's bbox may be None if it doesn't have any layers  
213              bbox = layer.LatLongBoundingBox()              bbox = layer.LatLongBoundingBox()
214              if bbox is not None:              if bbox is not None:
215                  left, bottom, right, top = bbox                  left, bottom, right, top = bbox
# Line 117  class Map(TitledObject, Modifiable): Line 225  class Map(TitledObject, Modifiable):
225              return None              return None
226    
227      def ProjectedBoundingBox(self):      def ProjectedBoundingBox(self):
228            """Return the bounding box of the map in projected coordinates.
229    
230            The label layer is not considered for the computation of the
231            bounding box.
232    
233            Return None if there are no layers (except the label layer) or
234            no layer contains any shapes.
235            """
236          # This simply returns the rectangle given by the projected          # This simply returns the rectangle given by the projected
237          # corners of the non-projected bbox.          # corners of the non-projected bbox.
238          bbox = self.BoundingBox()          bbox = self.BoundingBox()
# Line 124  class Map(TitledObject, Modifiable): Line 240  class Map(TitledObject, Modifiable):
240              bbox = self.projection.ForwardBBox(bbox)              bbox = self.projection.ForwardBBox(bbox)
241          return bbox          return bbox
242    
243        def GetProjection(self):
244            """Return the projection of the map."""
245            return self.projection
246    
247      def SetProjection(self, projection):      def SetProjection(self, projection):
248            """Set the projection of the map.
249    
250            Issue a MAP_PROJECTION_CHANGED message.
251            """
252            old_proj = self.projection
253          self.projection = projection          self.projection = projection
254          self.changed(MAP_PROJECTION_CHANGED, self)          self.changed(MAP_PROJECTION_CHANGED, self, old_proj)
255    
256      def forward(self, *args):      def forward(self, *args):
257          """Reissue events"""          """Reissue events"""
# Line 152  class Map(TitledObject, Modifiable): Line 277  class Map(TitledObject, Modifiable):
277          self.label_layer.UnsetModified()          self.label_layer.UnsetModified()
278    
279      def TreeInfo(self):      def TreeInfo(self):
280            """Return a description of the object.
281    
282            A tuple of (title, tupel) describing the contents
283            of the object in a tree-structure is returned.
284            """
285          items = []          items = []
286          if self.BoundingBox() != None:          if self.BoundingBox() != None:
287              items.append("Extent (lat-lon): (%g, %g, %g, %g)"              items.append(_("Extent (lat-lon): (%g, %g, %g, %g)")
288                           % self.BoundingBox())                           % self.BoundingBox())
289          if self.projection and len(self.projection.params) > 0:              if self.projection and len(self.projection.params) > 0:
290              items.append("Extent (projected): (%g, %g, %g, %g)"                  items.append(_("Extent (projected): (%g, %g, %g, %g)")
291                           % self.ProjectedBoundingBox())                               % self.ProjectedBoundingBox())
292              items.append(("Projection",                  items.append((_("Projection"),
293                            [str(param) for param in self.projection.params]))                                [str(param)
294                                   for param in self.projection.params]))
295    
296          layers = self.layers[:]          layers = self.layers[:]
297          layers.reverse()          layers.reverse()
298          items.extend(layers)          items.extend(layers)
299            items.append(self.label_layer)
300    
301          return ("Map: %s" % self.title, items)          return (_("Map: %s") % self.title, items)
   

Legend:
Removed from v.217  
changed lines
  Added in v.2734

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26