root/PrimaGIS/trunk/interfaces.py

Revision 781 (checked in by dokai, 2 years ago)

Implemented support for setting a maximum extent for a map. If set, users
will not be able to zoom/pan out from the maximum extent. The bounding box
fields that were using StringField/StringWidget? are now replaced with custom
BoundingBoxField/BoundingBoxWidget? implementations.

  • Property svn:keywords set to Id
Line 
1 # -*- coding: ISO-8859-1 -*-
2 ##############################################################################
3 #
4 # Copyright (c) 2005 Kai Hänninen <kai.hanninen@mbconcert.fi>
5 #
6 # This file is part of PrimaGIS.
7 #
8 # PrimaGIS is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12 #
13 # PrimaGIS is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with PrimaGIS; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 #
22 # $Id$
23 #
24 ##############################################################################
25
26 from zope.interface import Interface
27 from Products.ZCO.interfaces import IDataStoreProxy, ILayerProxy, IStyleProxy
28
29 class IGeoAware(Interface):
30     """
31     Classes implementing IGeoAware contain spatial information which may
32     be accessed through the interface methods to be used with PrimaGIS.
33
34     For an object to be geo-aware, it must provide the following
35     information:
36      - spatial data
37      - title
38      - description
39      - URL to the object
40
41     In most cases it is probably most convenient to hook the
42     getGeoTitle() and getGeoDescription() methods to their Dublin Core
43     equivalents (Title() and Description() respectively).
44
45     The reason we define separate methods is that if the object
46     requires to have more sophisticated information shown with
47     PrimaGIS, it is possible to do so without modifying the Title()
48     and Description() methods.
49     The same reasoning applies to getGeoURL() which can be hooked to
50     absolute_url() in most cases. With complex AT hierarchies with
51     multiple objects creating a sigle logical component, we might need
52     more control over the URL.
53     """
54
55
56     def getGeometry():
57         """
58         Returns a Python Cartographic Library (PCL) geometry object representing
59         the geometry of the implementing object. PCL geometry objects may be
60         instantiated either by actual data or a WKT string representation of it.
61         
62         Implementors need to import either Point, LineString or Polygon from
63         cartography.spatial and return an instance of it.
64         
65         Example:
66         
67         from cartography.spatial import Point
68         return Point(x=self.getGeoX(), y=self.getGeoY())
69         """
70
71     def getGeoTitle():
72         """
73         Returns the title for the geo-aware object.
74         
75         The title will be shown as the title of the Javascript popups.
76         """
77
78     def getGeoDescription():
79         """
80         Returns a description of the geo-aware object.
81         
82         The description will be shown as the content of the Javascript popups
83         and may contain HTML markup.
84         """
85
86     def getGeoURL():
87         """
88         Returns an URL to the object used in creating a link in
89         PrimaGIS.
90         If this method returns None, PrimaGIS will not create a link
91         in the imagemap hotspot, but assumes that the object will
92         provide necessary links within the data from
93         getGeoDescription(). In addition the JavaScript pop-up will be
94         sticky, so the user is able to use the in-content links.
95         """
96
97 class IPrimaGISMap(Interface):
98     """
99     PrimaGIS main application interface.
100     """
101    
102     def getZCOPath():
103         """
104         Returns the traversable (in acquisition sense) path to the ZCO
105         hierarchy used by this map. The path is relative to this
106         PrimaGISMap instance and points to the ZCO hierarchy container.
107         """
108    
109     def setZCOPath(zcopath):
110         """
111         Sets the traversable (in acquisition sense) path to the ZCO hierarchy
112         container. The path should be relative to this PrimaGISMap instance.
113         
114         Examples: "zco", "../path/to/somewhere/ZCO", ...
115         
116         Parameters
117         ----------
118         zcopath : string
119             Relative path expression to the ZCO hierarchy container.
120         """
121    
122     def getZCOContainer():
123         """
124         Returns the ZCO hierarchy container object.
125         """
126    
127     def getBackgroundColor():
128         """
129         Returns the background color used for this map in the RGB hexadecimal
130         representation, e.g. "#ffffff". An empty string means transparent
131         background.
132         """
133    
134     def setBackgroundColor(color):
135         """
136         Sets the background color used for this map. The color should be
137         given in the RGB hexadecimal format.
138         
139         Parameters
140         ----------
141         color : string
142             Background color in hexadecimal form (e.g. "#ff00ff") or empty
143             string for transparent background.
144         """
145    
146     def getOutputFormat():
147         """
148         Returns the extended mimetype information of the image format used for
149         this map.
150         """
151    
152     def setOutputFormat(format):
153         """
154         Sets the image format used for this map.
155         The format string is an extended mimetype declaration. See documentation
156         for cartography.engine.mapserver.rendering.render() for more details and
157         supported values.
158         
159         Parameters
160         ----------
161         format : string
162             Extended mimetype information, e.g. "image/png; mode=RGBA"
163         """
164    
165     def getSpatialReferenceCode():
166         """
167         Returns the spatial reference code defined for this map. This can
168         either be an EPSG code, e.g. "EPSG:4326", or a white-space separated list
169         of PROJ.4 parameters, e.g. "proj=latlong datum=WGS84".
170         """
171    
172     def setSpatialReferenceCode(code):
173         """
174         Sets the spatial reference code for this map. This can
175         either be an EPSG code, e.g. "EPSG:4326", or a white-space separated list
176         of PROJ.4 parameters, e.g. "proj=latlong datum=WGS84".
177         
178         Parameters
179         ----------
180         code : string
181             Either an EPSG code or PROJ.4 parameters.
182         """
183    
184     def getMapView():
185         """
186         Returns a cartography.spatial.BoundingBox object defining the current
187         map extent.
188         """
189    
190     def getDefaultExtent():
191         """ Returns a cartography.spatial.geometry.BoundingBox object defining
192         the default extent for this map.
193         """
194    
195     def setDefaultView(bbox=None):
196         """
197         Sets the default extent for this map. This extent is used for all
198         new users before they modify their session through the map UI.
199         
200         Parameters
201         ----------
202         bbox : cartography.spatial.BoundingBox | string (optional)
203             The new default extent. Can be either a BoundingBox object or a
204             string representation in the form "minx,miny,maxx,maxy".
205         """
206    
207     def getDefaultSize():
208         """
209         Returns the default map image size as (width, height) tuple in pixel
210         units.
211         """
212    
213     def setDefaultSize(width, height):
214         """
215         Sets the default map image size for this map. It is possible for
216         this value to not be included in the user selectable sizes, but that
217         means that the user will not be able to view the map at this size
218         without reseting the user session.
219         
220         See also IPrimaGISMap.setAvailableSizes()
221         
222         Parameters
223         ----------
224         width : int
225             The default width for this map in pixels.
226             
227         heigth : int
228             The default height for this map in pixels.
229         """
230    
231     def getMapSize():
232         """
233         Returns the current map size as a (width, height) tuple.
234         """
235    
236     def getAvailableSizes():
237         """
238         Returns a list of dictionaries (keys: width, height, description) of the
239         available sizes for this map.
240         """
241    
242     def setAvailableSizes(sizes):
243         """
244         Sets the user selectable sizes for this map.
245         
246         Parameters
247         ----------
248         sizes : [{}]
249             List of dictionaries with keys 'width', 'height' and 'description'.
250         """
251    
252     def getGeoAwareTypes():
253         """
254         Returns a list of content type names that are allowed to be used as data
255         for the PrimaGISDataLayers under this map.
256         """
257    
258     def setGeoAwareTypes(types):
259         """
260         Sets the content types that are allowed to be used as data for the
261         PrimaGISDataLayers under this map. All the types should implement the
262         IGeoAware interface.
263         This allows the possible content types to be controlled on a map basis.
264         """
265    
266     def view():
267         """
268         Returns a rendered map image based on the current user session.
269         """
270    
271     def getSession():
272         """
273         Returns the current user's session, a PrimaGISSession object.
274         If the user is viewing multiple maps on a single Plone site, this method
275         guarantees that the user will have a unique session for each map.
276         """
277    
278     def reprojectPoint(point, srcSRS=None, tgtSRS=None):
279         """
280         Reprojects the given point from the spatial reference system defined by
281         srcSRS to the spatial reference system defined by tgtSRS.
282         
283         Both srcSRS and tgtSRS can either be an EPSG code, e.g. "EPSG:4326" or
284         white-space separated PROJ.4 parameters, e.g. "proj=latlong datum=WGS84".
285         
286         Parameters
287         ----------
288         point : cartography.spatial.Point
289             The point that will be reprojected.
290             
291         srsSRS : string (optional)
292             Source SRS identifier. Defaults to the map spatial reference system.
293             
294         tgtSRS : string (optional)
295             Target SRS identifier. Defaults to the map spatial reference system.
296         """
297    
298     def action():
299         """
300         Performs actions on the user session based on parameters from the
301         REQUEST object.
302         """
303    
304     def getDataLayers(check_rw=False):
305         """
306         Returns a list of PrimaGISDataLayers under this map.
307         
308         Parameters
309         ----------
310         check_rw : boolean (optional)
311             Checks whether the current user has write access to the data layers'
312             data containers and filters out those that the user has inadequate
313             rights when set to True.
314         """
315    
316     def getLayers():
317         """
318         Returns a list of PrimaGISDataLayer and PrimaGISLayer objects under this
319         map.
320
321         The returned list is subject to workflow and only those layers that the
322         current user has View permission will be returned.
323
324         The ordering of the layers defined in the folder_contents page for this
325         map is honored.
326         """
327    
328     def getDefaultLayers():
329         """
330         Returns a list of ids for ZCO Layer/ZCO Style pairs that should be
331         rendered by default.
332
333         The returned list is subject to workflow and only those layers that the
334         current user has View permission will be returned.
335
336         The ordering of the layers defined in the folder_contents page for this
337         map is honored.
338         """
339    
340     def getLegendLayers():
341         """
342         Returns a list of ids for ZCO Layer/ZCO Style pairs whose symbols should
343         be shown in the legend.
344         """
345    
346     def getHidableLayers():
347         """
348         Returns a list of PrimaGISDataLayer and PrimaGISLayer objects under this
349         map that are hidable by the user.
350
351         The returned list is subject to workflow and only those layers that the
352         current user has View permission will be returned.
353
354         The ordering of the layers defined in the folder_contents page for this
355         map is honored.
356         """
357    
358     def hasHidableLayers():
359         """
360         Checks whether this map has any layers that are hidable by the user.
361         """
362    
363     def getMapRenderer():
364         """
365         Returns the ZCO Map Renderer object used for rendering this map.
366         """
367    
368     def getLayerContainer():
369         """
370         Returns the container object containing all the ZCO Layers used with
371         this map.
372         """
373    
374     def getSerial():
375         """
376         Returns a running serial number that can be used to differentiate HTTP
377         requests and avoid caching problems.
378         """
379    
380     def getImageMapData(evaluate=False):
381         """
382         Returns a JSON string representation containing the information needed
383         to create the client side image map with the overlib popups.
384         Alternatively the method can return an evaluated list of python
385         dictionaries containing the same information.
386         
387         Parameters
388         ----------
389         evaluate : boolean (optional)
390             Set to True to get list of dictionaries instead of a JSON string.
391         """
392    
393     def getLegendData(evaluate=False):
394         """
395         Returns a JSON string representation of the information needed to create
396         the map legend.
397         Alternatively the method can return an evaluated list of python
398         dictionaries containing the same information.
399         
400         Parameters
401         ----------
402         evaluate : boolean (optional)
403             Set to True to get list of dictionaries instead of a JSON string.       
404         """
405    
406     def setSessionDefaultView():
407         """
408         Saves the current map extent as the default view for the user session.
409         Returns an i18n aware message that can be displayed to the user in the
410         map UI.
411         """
412
413     def getNamedViews():
414         """
415         Returns a list of PrimaGISView objects under this map. The objects will
416         be sorted by their Title in ascending order.
417         """
418
419     def staticview(self, layers=None, width=None, height=None, bbox=None, REQUEST=None):
420         """Returns a static, non-session aware image of the map.
421         
422         This method can be used to embed map imagery within other documents as
423         static images by using a normal <img> tag such as
424         
425           <img src="primagis/staticview?layers=list,of,layers&width=600&height=600&bbox=-500,-500,500,500" />
426           
427         Calling this method does not modify the user's session. The map layers
428         will be rendered in the order defined for the map regardless of the
429         ordering of the 'layers' parameter.
430         
431         Parameters
432         ==========
433         
434         layers : string
435             A comma separated list of layer ids, e.g. "capitals,world_borders".
436             The ids correspond to the available layers within this map. The
437             default map layers will be always appended to the requested layers.
438         
439         width : int
440             The width of the map in pixels. Defaults to map default if omitted.
441         
442         height : int
443             The height of the map in pixels. Defaults to map default if omitted.
444         
445         bbox : string
446             The map extent that will be rendered. The value must be a comma
447             separated string containing the values for minx, miny, maxx and maxy
448             in that order, e.g. "-500,-500,500,500". Defaults to map default if
449             omitted.
450         """
451
452
453 class IPrimaGISLayer(ILayerProxy, IStyleProxy):
454     """
455     PrimaGIS Layer interface.
456     
457     This interface defines a relationship with a ZCO Layer/ZCO Style pair and
458     a PrimaGIS map.
459     """
460
461     def getStyledLayer():
462         """
463         Returns a ZCO Layer / ZCO Style id pair that this PrimaGISLayer
464         represents. If there is no ZCO Style object available, then "nostyle"
465         will be used as the id of the non-existing Style.
466         """
467
468     def setStyledLayer(layer):
469         """
470         Sets the ZCO Layer / ZCO Style id pair that this layer represent on
471         the map. The id pair is also a traversable path relative to the ZCO
472         layer container (see IPrimaGISMap.getLayerContainer()) and is of the
473         form "[layerid]/[styleid]".
474         
475         Parameters
476         ----------
477         
478         layer : string
479             Traversable path to a ZCO Layer / ZCO Style combination relative to
480             the layer container. If there is no corresponding Style object for
481             the Layer, then the style can be omitted and a path to the ZCO Layer
482             object used instead.
483         """
484    
485     def getDefaultVisibility():
486         """
487         Returns a boolean flag showing whether this layer should be rendered
488         by default on the map.
489         """
490
491     def setDefaultVisibility(status):
492         """
493         Sets whether this layer should be rendered on the map by default. If set
494         to False, then the user must explicitly request that this layer be
495         rendered.
496         
497         Parameters
498         ----------
499         status : boolean
500             The boolean flag for showing the layer by default or not.
501         """
502    
503     def getLegendVisibility():
504         """
505         Returns a boolean flag showing whether symbols from this layer should
506         be visible in the map legend.
507         """
508
509     def setLegendVisibility(status):
510         """
511         Sets whether the symbols from this layer should be rendered on the map.
512         
513         Parameters
514         ----------
515         status : boolean
516             The boolean flag for whether symbols should be shown in the legend
517             or not.
518         """
519        
520     def getHidability():
521         """
522         Returns a boolean flag showing whether this layer should be hidable by
523         the user through the map UI.
524         """
525    
526     def setHidability(status):
527         """
528         Sets whether this layer should be hidable by the user through the map UI.
529         
530         Parameters
531         ----------
532         status : boolean
533             The boolean flag for whether the users should be able to hide this
534             layer or not.
535         """
536    
537     def view(width=300, height=300):
538         """
539         Returns a rendered image of this layer.
540         
541         Parameters
542         ----------
543         width : int (optional)
544             Pixel width for the image. Defaults to 300.
545             
546         height : int (optional)
547             Pixel height for the image. Default to 300.
548         """
549        
550     def getAvailableStyledLayers():
551         """
552         Returns a list of ZCO Layer / ZCO Style id pairs that are not yet used
553         by other PrimaGIS[Data]Layers within the same map as this layer.
554         
555         This provides a safe and validated vocabulary for the
556         IPrimaGISLayer.setStyledLayer() method.
557         """
558    
559 class IPrimaGISDataLayer(IPrimaGISLayer, IDataStoreProxy):
560     """
561     This interface defines a relationship with a ZCO Layer/ZCO Style pair and
562     a PrimaGISMap and in addition allows the implementing object to act as a
563     ZCO data source providing data from within the Plone site.
564     """
565
566     def getDataSourcePath():
567         """
568         Returns a traversable (in acquisition sense) path relative to this layer
569         to a folderish object containing the spatial data for this layer.
570         """
571    
572     def setDataSourcePath(source):
573         """
574         Sets the traversable (in acquisition sense) path relative to this layer
575         to a folderish object containing the spatial data for this layer.
576         
577         The folderish object can be of arbitrary type as long as it behaves like
578         a folder and provides methods for accessing its contents.
579         
580         Use "." (dot) to indicate that the data is stored within this object.
581         """
582
583     def getDataSource():
584         """
585         Returns the folderish object containing the spatial data for this layer
586         or None if the object could not be acquired.
587         """
588    
589     def getGeometryType():
590         """
591         Returns the geometry type string defined for this layer.
592         """
593    
594     def setGeometryType(geometry):
595         """
596         Sets the geometry type for this layer. All the spatial data objects
597         used as data for this layer should have the same type.
598         
599         Parameters
600         ----------
601         geometry : string
602             Either 'POINT', 'LINE' or 'POLYGON'.
603             
604         """
605    
606     def getDefaultContentType():
607         """
608         Returns the name of the default content type for this layer.
609         """
610    
611     def setDefaultContentType(typename):
612         """
613         Sets the default content type for this layer.
614         
615         When a user adds a new feature to this layer through the map UI, an
616         object of this type will be created.
617         
618         Parameters
619         ----------
620         typename : string
621             Name of the default content type. This type must implement the
622             IGeoAware interface.
623         """
624    
625     def getSpatialReferenceCode():
626         """
627         Returns the spatial reference code defined for this layer. This can
628         either be an EPSG code, e.g. "EPSG:4326", or a white-space separated list
629         of PROJ.4 parameters, e.g. "proj=latlong datum=WGS84".
630         """
631    
632     def setSpatialReferenceCode(code):
633         """
634         Sets the spatial reference code for this layer. This can
635         either be an EPSG code, e.g. "EPSG:4326", or a white-space separated list
636         of PROJ.4 parameters, e.g. "proj=latlong datum=WGS84".
637         
638         Parameters
639         ----------
640         code : string
641             Either an EPSG code or PROJ.4 parameters.
642         """
643
644     def getSpatialReference():
645         """
646         Returns an instance of cartography.referencing.srs.SpatialReference
647         initialized with the values set for this layer.
648         """
649    
650     def getSpatialData():
651         """
652         Returns the spatial data for this layer as a list of objects that
653         implement the IGeoAware interface.
654         
655         Note! The list of objects is subject to the workflow state of each
656         individual object and the results may vary depending on the access
657         rights of the user accessing this method.
658         
659         See also PrimaGIS.config.ACTIVE_WORKFLOW_STATE.
660         """
661    
662 class IPrimaGISSession(Interface):
663     """
664     User session interface.
665     """
666
667     def revertView():
668         """
669         Reverts the current map extent to its previous value, saving the current
670         value in the user session.
671         
672         Calling this method in succession will oscillate between the two
673         previous map extents.
674         """
675    
676     def setDefaultView(bbox=None):
677         """
678         Sets the default map extent for the duration of this user session. This
679         does not affect the map default extent shown when users access the map
680         for the first time.
681         
682         Parameters
683         ----------
684         bbox : cartography.spatial.BoundingBox (optional)
685             The bounding box used as the new default view, if omitted then the
686             current map extent will be used.
687         """
688
689     def setPreviousView(bbox=None):
690         """
691         Stores a view in the session that can be reverted to by using the
692         IPrimaGISSession.revertView() method.
693         
694         Parameters
695         ----------
696         bbox : cartography.spatial.BoundingBox (optional)
697             The bounding box stored as the previous view, if omitted then the
698             current map extent will be used.
699         """
700        
701     def setView(bbox):
702         """
703         Sets the current map extent.
704         
705         Parameters
706         ----------
707         bbox : cartography.spatial.BoundingBox
708             The bounding box defining the new map extent.
709         """
710
711     def resetView():
712         """
713         Resets the map extent to the default value. If the user has saved a
714         session specific default value, then this will be used. Otherwise the
715         default extent for the map will be used.
716         """
717
718     def getView():
719         """
720         Returns a cartography.spatial.BoundingBox object defining the current
721         map extent.
722         """
723    
724     def isIsomorphic(bbox=None):
725         """
726         Checks whether the given bounding box and map image size are
727         isomorphic (same width to height ratio).
728         
729         Parameters
730         ----------
731         bbox : cartography.spatial.BoundingBox
732             The bounding box to check. If omitted then the current map
733             extent will be used.
734         """
735    
736     def normalizeView(bbox=None):
737         """
738         Normalizes the given bounding box so that it is isomorphic (matching
739         width / height ratio) with the current image size.
740         
741         Parameters
742         ----------
743         bbox : cartography.spatial.BoundingBox
744             The bounding box to normalize. If omitted then the current map
745             extent will be used.
746         """
747
748     def setSize(width, height):
749         """
750         Sets the map image size in pixels.
751         Maintains the isomorphism by normalizing the current map extent.
752         
753         Parameters
754         ----------
755         width : int
756             Map width in pixels.
757             
758         height : int
759             Map height in pixels.
760         """
761
762     def getSize():
763         """
764         Returns the current image pixel size as a tuple (width, height).
765         """
766    
767     def setActiveLayers(layers):
768         """
769         Sets the active layers for the session.
770         
771         Parameters
772         ----------
773         layers : []
774             List of active layers.
775         """
776    
777     def getActiveLayers():
778         """
779         Returns a list of ZCO Layer or ZCO Style objects that are active in the
780         current session. Maintains the ordering defined in the Plone UI.
781         """
782    
783     def getLegendLayers():
784         """
785         Returns a list of layers whose symbols should be drawn in the map
786         legend.
787         """
788    
789     def inView(point):
790         """
791         Checks whether the given point is contained within the current map
792         extent. Returns True if the point is within the current extent, False
793         otherwise.
794         
795         Parameters
796         ----------
797         point : cartography.spatial.Point
798             The point that is to be checked.
799         """
800    
801     def isActiveLayer(