app/django/contrib/gis/admin/widgets.py
changeset 323 ff1a9aa48cfd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/contrib/gis/admin/widgets.py	Tue Oct 14 16:00:59 2008 +0000
@@ -0,0 +1,92 @@
+from django.contrib.gis.gdal import OGRException
+from django.contrib.gis.geos import GEOSGeometry, GEOSException
+from django.forms.widgets import Textarea
+from django.template.loader import render_to_string
+
+class OpenLayersWidget(Textarea):
+    """
+    Renders an OpenLayers map using the WKT of the geometry.
+    """
+    def render(self, name, value, attrs=None):
+        # Update the template parameters with any attributes passed in.
+        if attrs: self.params.update(attrs)
+
+        # Defaulting the WKT value to a blank string -- this
+        # will be tested in the JavaScript and the appropriate
+        # interfaace will be constructed.
+        self.params['wkt'] = ''
+
+        # If a string reaches here (via a validation error on another
+        # field) then just reconstruct the Geometry.
+        if isinstance(value, basestring):
+            try:
+                value = GEOSGeometry(value)
+            except (GEOSException, ValueError):
+                value = None
+
+        if value and value.geom_type.upper() != self.geom_type:
+            value = None
+
+        # Constructing the dictionary of the map options.
+        self.params['map_options'] = self.map_options()
+
+        # Constructing the JavaScript module name using the ID of
+        # the GeometryField (passed in via the `attrs` keyword).
+        self.params['module'] = 'geodjango_%s' % self.params['field_name']
+
+        if value:
+            # Transforming the geometry to the projection used on the
+            # OpenLayers map.
+            srid = self.params['srid']
+            if value.srid != srid: 
+                try:
+                    value.transform(srid)
+                    wkt = value.wkt
+                except OGRException:
+                    wkt = ''
+            else:
+                wkt = value.wkt
+               
+            # Setting the parameter WKT with that of the transformed
+            # geometry.
+            self.params['wkt'] = wkt
+
+        return render_to_string(self.template, self.params)
+    
+    def map_options(self):
+        "Builds the map options hash for the OpenLayers template."
+
+        # JavaScript construction utilities for the Bounds and Projection.
+        def ol_bounds(extent):
+            return 'new OpenLayers.Bounds(%s)' % str(extent)
+        def ol_projection(srid):
+            return 'new OpenLayers.Projection("EPSG:%s")' % srid
+
+        # An array of the parameter name, the name of their OpenLayers
+        # counterpart, and the type of variable they are.
+        map_types = [('srid', 'projection', 'srid'), 
+                     ('display_srid', 'displayProjection', 'srid'), 
+                     ('units', 'units', str),
+                     ('max_resolution', 'maxResolution', float),
+                     ('max_extent', 'maxExtent', 'bounds'),
+                     ('num_zoom', 'numZoomLevels', int),
+                     ('max_zoom', 'maxZoomLevels', int),
+                     ('min_zoom', 'minZoomLevel', int),
+                     ]
+
+        # Building the map options hash.
+        map_options = {}
+        for param_name, js_name, option_type in map_types:
+            if self.params.get(param_name, False):
+                if option_type == 'srid':
+                    value = ol_projection(self.params[param_name])
+                elif option_type == 'bounds':
+                    value = ol_bounds(self.params[param_name])
+                elif option_type in (float, int):
+                    value = self.params[param_name]
+                elif option_type in (str,):
+                    value = '"%s"' % self.params[param_name]
+                else:
+                    raise TypeError
+                map_options[js_name] = value
+        return map_options