| 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 |