Author: jbronn
Date: 2008-07-19 09:17:24 -0500 (Sat, 19 Jul 2008)
New Revision: 7980

Added:
   django/branches/gis/django/contrib/admin/media/img/gis/
   django/branches/gis/django/contrib/admin/media/img/gis/move_vertex_off.png
   django/branches/gis/django/contrib/admin/media/img/gis/move_vertex_on.png
   django/branches/gis/django/contrib/gis/admin/
   django/branches/gis/django/contrib/gis/admin/__init__.py
   django/branches/gis/django/contrib/gis/admin/options.py
   django/branches/gis/django/contrib/gis/admin/sites.py
   django/branches/gis/django/contrib/gis/admin/widgets.py
   django/branches/gis/django/contrib/gis/forms/
   django/branches/gis/django/contrib/gis/forms/__init__.py
   django/branches/gis/django/contrib/gis/forms/fields.py
   django/branches/gis/django/contrib/gis/templates/gis/admin/
   django/branches/gis/django/contrib/gis/templates/gis/admin/openlayers.html
   django/branches/gis/django/contrib/gis/templates/gis/admin/openlayers.js
   django/branches/gis/django/contrib/gis/templates/gis/admin/osm.html
   django/branches/gis/django/contrib/gis/templates/gis/admin/osm.js
Modified:
   django/branches/gis/django/contrib/gis/db/models/fields/__init__.py
Log:
gis: Added the geographic-enabled forms and admin modules.


Added: 
django/branches/gis/django/contrib/admin/media/img/gis/move_vertex_off.png
===================================================================
(Binary files differ)


Property changes on: 
django/branches/gis/django/contrib/admin/media/img/gis/move_vertex_off.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: django/branches/gis/django/contrib/admin/media/img/gis/move_vertex_on.png
===================================================================
(Binary files differ)


Property changes on: 
django/branches/gis/django/contrib/admin/media/img/gis/move_vertex_on.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream


Property changes on: django/branches/gis/django/contrib/gis/admin
___________________________________________________________________
Name: svn:ignore
   + *.pyc


Added: django/branches/gis/django/contrib/gis/admin/__init__.py
===================================================================
--- django/branches/gis/django/contrib/gis/admin/__init__.py                    
        (rev 0)
+++ django/branches/gis/django/contrib/gis/admin/__init__.py    2008-07-19 
14:17:24 UTC (rev 7980)
@@ -0,0 +1,9 @@
+from django.contrib.gis.admin.options import GeoModelAdmin
+from django.contrib.gis.admin.sites import GeoAdminSite, site
+from django.contrib.gis.admin.widgets import OpenLayersWidget
+
+try:
+    from django.contrib.gis.admin.options import OSMGeoAdmin
+    HAS_OSM = True
+except ImportError:
+    HAS_OSM = False

Added: django/branches/gis/django/contrib/gis/admin/options.py
===================================================================
--- django/branches/gis/django/contrib/gis/admin/options.py                     
        (rev 0)
+++ django/branches/gis/django/contrib/gis/admin/options.py     2008-07-19 
14:17:24 UTC (rev 7980)
@@ -0,0 +1,128 @@
+from django.conf import settings
+from django.contrib.admin import ModelAdmin
+from django.contrib.gis.admin.widgets import OpenLayersWidget
+from django.contrib.gis.gdal import OGRGeomType
+from django.contrib.gis.db import models
+
+class GeoModelAdmin(ModelAdmin):
+    """
+    The administration options class for Geographic models. Map settings
+    may be overloaded from their defaults to create custom maps.
+    """
+    # The default map settings that may be overloaded -- still subject
+    # to API changes.
+    default_lon = 0
+    default_lat = 0
+    default_zoom = 4
+    display_wkt = False
+    display_srid = False
+    extra_js = []
+    num_zoom = 18
+    max_zoom = False
+    min_zoom = False
+    units = False
+    max_resolution = False
+    max_extent = False
+    modifiable = True
+    mouse_position = True
+    scale_text = True
+    layerswitcher = True
+    scrollable = True
+    admin_media_prefix = settings.ADMIN_MEDIA_PREFIX
+    map_width = 600
+    map_height = 400
+    map_srid = 4326
+    map_template = 'gis/admin/openlayers.html'
+    openlayers_url = 'http://openlayers.org/api/2.6/OpenLayers.js'
+    wms_url = 'http://labs.metacarta.com/wms/vmap0'
+    wms_layer = 'basic'
+    wms_name = 'OpenLayers WMS'
+    debug = False
+    widget = OpenLayersWidget
+
+    def _media(self):
+        "Injects OpenLayers JavaScript into the admin."
+        media = super(GeoModelAdmin, self)._media()
+        media.add_js([self.openlayers_url])
+        media.add_js(self.extra_js)
+        return media
+    media = property(_media)
+
+    def formfield_for_dbfield(self, db_field, **kwargs):
+        """
+        Overloaded from ModelAdmin so that an OpenLayersWidget is used
+        for viewing/editing GeometryFields.
+        """
+        if isinstance(db_field, models.GeometryField):
+            # Setting the widget with the newly defined widget.
+            kwargs['widget'] = self.get_map_widget(db_field)
+            return db_field.formfield(**kwargs)
+        else:
+            return super(GeoModelAdmin, self).formfield_for_dbfield(db_field, 
**kwargs)
+
+    def get_map_widget(self, db_field):
+        """
+        Returns a subclass of the OpenLayersWidget (or whatever was specified
+        in the `widget` attribute) using the settings from the attributes set 
+        in this class.
+        """
+        is_collection = db_field._geom in ('MULTIPOINT', 'MULTILINESTRING', 
'MULTIPOLYGON', 'GEOMETRYCOLLECTION')
+        if is_collection:
+            if db_field._geom == 'GEOMETRYCOLLECTION': collection_type = 'Any'
+            else: collection_type = 
OGRGeomType(db_field._geom.replace('MULTI', ''))
+        else:
+            collection_type = 'None'
+
+        class OLMap(self.widget):
+            template = self.map_template
+            geom_type = db_field._geom
+            params = {'admin_media_prefix' : self.admin_media_prefix,
+                      'default_lon' : self.default_lon,
+                      'default_lat' : self.default_lat,
+                      'default_zoom' : self.default_zoom,
+                      'display_wkt' : self.debug or self.display_wkt,
+                      'geom_type' : OGRGeomType(db_field._geom),
+                      'field_name' : db_field.name,
+                      'is_collection' : is_collection,
+                      'scrollable' : self.scrollable,
+                      'layerswitcher' : self.layerswitcher,
+                      'collection_type' : collection_type,
+                      'is_linestring' : db_field._geom in ('LINESTRING', 
'MULTILINESTRING'),
+                      'is_polygon' : db_field._geom in ('POLYGON', 
'MULTIPOLYGON'),
+                      'is_point' : db_field._geom in ('POINT', 'MULTIPOINT'),
+                      'num_zoom' : self.num_zoom,
+                      'max_zoom' : self.max_zoom,
+                      'min_zoom' : self.min_zoom,
+                      'units' : self.units, #likely shoud get from object
+                      'max_resolution' : self.max_resolution,
+                      'max_extent' : self.max_extent,
+                      'modifiable' : self.modifiable,
+                      'mouse_position' : self.mouse_position,
+                      'scale_text' : self.scale_text,
+                      'map_width' : self.map_width,
+                      'map_height' : self.map_height,
+                      'srid' : self.map_srid,
+                      'display_srid' : self.display_srid,
+                      'wms_url' : self.wms_url,
+                      'wms_layer' : self.wms_layer,
+                      'wms_name' : self.wms_name,
+                      'debug' : self.debug,
+                      }
+        return OLMap
+
+# Using the Beta OSM in the admin requires the following:
+#  (1) The Google Maps Mercator projection needs to be added
+#      to your `spatial_ref_sys` table.  You'll need at least GDAL 1.5:
+#      >>> from django.contrib.gis.gdal import SpatialReference
+#      >>> from django.contrib.gis.utils import add_postgis_srs
+#      >>> add_postgis_srs(SpatialReference(900913)) # Adding the Google 
Projection 
+from django.contrib.gis import gdal
+if gdal.HAS_GDAL:
+    class OSMGeoAdmin(GeoModelAdmin):
+        map_template = 'gis/admin/osm.html'
+        extra_js = ['http://openstreetmap.org/openlayers/OpenStreetMap.js']
+        num_zoom = 20
+        map_srid = 900913
+        max_extent = '-20037508,-20037508,20037508,20037508'
+        max_resolution = 156543.0339
+        units = 'm'

Added: django/branches/gis/django/contrib/gis/admin/sites.py
===================================================================
--- django/branches/gis/django/contrib/gis/admin/sites.py                       
        (rev 0)
+++ django/branches/gis/django/contrib/gis/admin/sites.py       2008-07-19 
14:17:24 UTC (rev 7980)
@@ -0,0 +1,37 @@
+from django.contrib.admin import sites
+from django.contrib.gis.admin.options import GeoModelAdmin
+from django.db.models.loading import get_apps
+
+class GeoAdminSite(sites.AdminSite):
+    """
+    The GeoAdminSite is overloaded from the AdminSite to provide facilities
+    for editing geographic fields (using the GeoModelAdmin for the options
+    class instead of ModelAdmin).
+    """
+    def register(self, model_or_iterable, admin_class=None, **options):
+        "Overloaded register method that uses GeoModelAdmin."
+        admin_class = admin_class or GeoModelAdmin
+        try:
+            return super(GeoAdminSite, self).register(model_or_iterable, 
admin_class, **options)
+        except sites.AlreadyRegistered:
+            # Unlike the default behavior in newforms-admin we won't 
+            # raise this exception.
+            pass
+
+# `site` is an instance of GeoAdminSite
+site = GeoAdminSite()
+
+# Re-registering models that appear normally in AdminSite with the 
+# GeoAdminSite (if the user has these installed).
+APPS = get_apps()
+
+# Registering the `auth` Group & User models.
+from django.contrib.auth import models, admin
+if models in APPS:
+    site.register(models.Group, admin.GroupAdmin)
+    site.register(models.User, admin.UserAdmin)
+
+# Registering the `sites` Site model.
+from django.contrib.sites import models, admin
+if models in APPS:
+    site.register(models.Site, admin.SiteAdmin)

Added: django/branches/gis/django/contrib/gis/admin/widgets.py
===================================================================
--- django/branches/gis/django/contrib/gis/admin/widgets.py                     
        (rev 0)
+++ django/branches/gis/django/contrib/gis/admin/widgets.py     2008-07-19 
14:17:24 UTC (rev 7980)
@@ -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

Modified: django/branches/gis/django/contrib/gis/db/models/fields/__init__.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/models/fields/__init__.py 
2008-07-19 13:30:47 UTC (rev 7979)
+++ django/branches/gis/django/contrib/gis/db/models/fields/__init__.py 
2008-07-19 14:17:24 UTC (rev 7980)
@@ -1,3 +1,4 @@
+from django.contrib.gis import forms
 from django.db import connection
 # Getting the SpatialBackend container and the geographic quoting method.
 from django.contrib.gis.db.backend import SpatialBackend, gqn
@@ -111,7 +112,7 @@
             except SpatialBackend.GeometryException:
                 raise ValueError('Could not create geometry from lookup value: 
%s' % str(value))
         else:
-            raise TypeError('Cannot use parameter of `%s` type as a geometry 
lookup parameter.' % type(value))
+            raise TypeError('Cannot use parameter of `%s` type as lookup 
parameter.' % type(value))
 
         # Assigning the SRID value.
         geom.srid = self.get_srid(geom)
@@ -137,6 +138,14 @@
         # Setup for lazy-instantiated Geometry object.
         setattr(cls, self.attname, GeometryProxy(SpatialBackend.Geometry, 
self))
 
+    def formfield(self, **kwargs):
+        defaults = {'form_class' : forms.GeometryField, 
+                    'geom_type' : self._geom,
+                    'null' : self.null,
+                    }
+        defaults.update(kwargs)
+        return super(GeometryField, self).formfield(**defaults)
+
     def get_db_prep_lookup(self, lookup_type, value):
         """
         Returns the spatial WHERE clause and associated parameters for the


Property changes on: django/branches/gis/django/contrib/gis/forms
___________________________________________________________________
Name: svn:ignore
   + *.pyc


Added: django/branches/gis/django/contrib/gis/forms/__init__.py
===================================================================
--- django/branches/gis/django/contrib/gis/forms/__init__.py                    
        (rev 0)
+++ django/branches/gis/django/contrib/gis/forms/__init__.py    2008-07-19 
14:17:24 UTC (rev 7980)
@@ -0,0 +1 @@
+from django.contrib.gis.forms.fields import GeometryField

Added: django/branches/gis/django/contrib/gis/forms/fields.py
===================================================================
--- django/branches/gis/django/contrib/gis/forms/fields.py                      
        (rev 0)
+++ django/branches/gis/django/contrib/gis/forms/fields.py      2008-07-19 
14:17:24 UTC (rev 7980)
@@ -0,0 +1,37 @@
+from django import forms
+from django.contrib.gis.geos import GEOSGeometry, GEOSException
+from django.utils.translation import ugettext_lazy as _
+
+class GeometryField(forms.Field):
+    # By default a Textarea widget is used.
+    widget = forms.Textarea
+
+    default_error_messages = {
+        'no_geom' : _(u'No geometry value provided.'),
+        'invalid_geom' : _(u'Invalid Geometry value.'),
+        'invalid_geom_type' : _(u'Invalid Geometry type.'),
+    }
+    def __init__(self, **kwargs):
+        self.null = kwargs.pop('null')
+        self.geom_type = kwargs.pop('geom_type')
+        super(GeometryField, self).__init__(**kwargs)
+
+    def clean(self, value):
+        """
+        Validates that the input value can be converted to a Geometry
+        object (which is returned).  A ValidationError is raised if
+        the value cannot be instantiated as a Geometry.
+        """
+        if not value:
+            if self.null:
+                # The geometry column allows NULL, return None.
+                return None
+            else:
+                raise forms.ValidationError(self.error_messages['no_geom'])
+        try:
+            geom = GEOSGeometry(value)
+            if geom.geom_type.upper() != self.geom_type:
+                raise 
forms.ValidationError(self.error_messages['invalid_geom_type'])
+            return geom
+        except GEOSException:
+            raise forms.ValidationError(self.error_messages['invalid_geom'])

Added: 
django/branches/gis/django/contrib/gis/templates/gis/admin/openlayers.html
===================================================================
--- django/branches/gis/django/contrib/gis/templates/gis/admin/openlayers.html  
                        (rev 0)
+++ django/branches/gis/django/contrib/gis/templates/gis/admin/openlayers.html  
2008-07-19 14:17:24 UTC (rev 7980)
@@ -0,0 +1,37 @@
+{% block extrastyle %}
+<style type="text/css">
+  #{{ id }}_map { width: {{ map_width }}px; height: {{ map_height }}px; }
+  #{{ id }}_map .aligned label { float:inherit; }
+  #{{ id }}_admin_map { position: relative; vertical-align: top; float: left; }
+  {% if not display_wkt %}#{{ id }} { display: none; }{% endif %}
+  .olControlEditingToolbar .olControlModifyFeatureItemActive { 
+     background-image: url("{{ admin_media_prefix 
}}img/gis/move_vertex_on.png");
+     background-repeat: no-repeat;
+  }
+  .olControlEditingToolbar .olControlModifyFeatureItemInactive { 
+     background-image: url("{{ admin_media_prefix 
}}img/gis/move_vertex_off.png");
+     background-repeat: no-repeat;
+  }
+</style>
+<!--[if IE]>
+<style type="text/css">
+  /* This fixes the the mouse offset issues in IE. */
+  #{{ id }}_admin_map { position: static; vertical-align: top; }
+  /* `font-size: 0` fixes the 1px border between tiles, but borks 
LayerSwitcher.
+      Thus, this is disabled until a better fix is found.
+  #{{ id }}_map { width: {{ map_width }}px; height: {{ map_height }}px; 
font-size: 0; } */
+</style>
+<![endif]-->
+{% endblock %}
+<span id="{{ id }}_admin_map">
+<script type="text/javascript">
+//<![CDATA[
+{% block openlayers %}{% include "gis/admin/openlayers.js" %}{% endblock %}
+//]]>
+</script>
+<div id="{{ id }}_map"></div>
+<a href="javascript:{{ module }}.clearFeatures()">Delete all Features</a>
+{% if display_wkt %}<p> WKT debugging window:</p>{% endif %}
+<textarea id="{{ id }}" class="vWKTField required" cols="150" rows="10" 
name="{{ field_name }}">{{ wkt }}</textarea>
+<script type="text/javascript">{% block init_function %}{{ module }}.init();{% 
endblock %}</script>
+</span>

Added: django/branches/gis/django/contrib/gis/templates/gis/admin/openlayers.js
===================================================================
--- django/branches/gis/django/contrib/gis/templates/gis/admin/openlayers.js    
                        (rev 0)
+++ django/branches/gis/django/contrib/gis/templates/gis/admin/openlayers.js    
2008-07-19 14:17:24 UTC (rev 7980)
@@ -0,0 +1,157 @@
+{# Author: Justin Bronn, Travis Pinney & Dane Springmeyer #}
+{% block vars %}var {{ module }} = {};
+{{ module }}.map = null; {{ module }}.controls = null; {{ module }}.panel = 
null; {{ module }}.re = new RegExp("^SRID=\d+;(.+)", "i"); {{ module }}.layers 
= {}; 
+{{ module }}.wkt_f = new OpenLayers.Format.WKT();
+{{ module }}.is_collection = {% if is_collection %}true{% else %}false{% endif 
%};
+{{ module }}.collection_type = '{{ collection_type }}';
+{{ module }}.is_linestring = {% if is_linestring %}true{% else %}false{% endif 
%};
+{{ module }}.is_polygon = {% if is_polygon %}true{% else %}false{% endif %};
+{{ module }}.is_point = {% if is_point %}true{% else %}false{% endif %};
+{% endblock %}
+{{ module }}.get_ewkt = function(feat){return 'SRID={{ srid }};' + {{ module 
}}.wkt_f.write(feat);}
+{{ module }}.read_wkt = function(wkt){
+  // OpenLayers cannot handle EWKT -- we make sure to strip it out.
+  // EWKT is only exposed to OL if there's a validation error in the admin.
+  var match = {{ module }}.re.exec(wkt);
+  if (match){wkt = match[1];}
+  return {{ module }}.wkt_f.read(wkt);
+}
+{{ module }}.write_wkt = function(feat){
+  if ({{ module }}.is_collection){ {{ module }}.num_geom = 
feat.geometry.components.length;}
+  else { {{ module }}.num_geom = 1;}
+  document.getElementById('{{ id }}').value = {{ module }}.get_ewkt(feat);
+}
+{{ module }}.add_wkt = function(event){
+  // This function will sync the contents of the `vector` layer with the
+  // WKT in the text field.
+  if ({{ module }}.is_collection){
+    var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.{{ 
geom_type }}());
+    for (var i = 0; i < {{ module }}.layers.vector.features.length; i++){
+      feat.geometry.addComponents([{{ module 
}}.layers.vector.features[i].geometry]);
+    }
+    {{ module }}.write_wkt(feat);
+  } else {
+    // Make sure to remove any previously added features.
+    if ({{ module }}.layers.vector.features.length > 1){
+      old_feats = [{{ module }}.layers.vector.features[0]];
+      {{ module }}.layers.vector.removeFeatures(old_feats);
+      {{ module }}.layers.vector.destroyFeatures(old_feats);
+    }
+    {{ module }}.write_wkt(event.feature);
+  }
+}
+{{ module }}.modify_wkt = function(event){
+  if ({{ module }}.is_collection){
+    if ({{ module }}.is_point){
+      {{ module }}.add_wkt(event); 
+      return;
+    } else {
+      // When modifying the selected components are added to the 
+      // vector layer so we only increment to the `num_geom` value.
+      var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.{{ 
geom_type }}());
+      for (var i = 0; i < {{ module }}.num_geom; i++){
+       feat.geometry.addComponents([{{ module 
}}.layers.vector.features[i].geometry]);
+      }
+      {{ module }}.write_wkt(feat);
+    }
+  } else {
+    {{ module }}.write_wkt(event.feature);
+  }
+}
+// Function to clear vector features and purge wkt from div
+{{ module }}.deleteFeatures = function(){
+  {{ module }}.layers.vector.removeFeatures({{ module 
}}.layers.vector.features);
+  {{ module }}.layers.vector.destroyFeatures();
+}
+{{ module }}.clearFeatures = function (){
+  {{ module }}.deleteFeatures();
+  document.getElementById('{{ id }}').value = '';
+  {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ 
default_lat }}), {{ default_zoom }});
+}
+// Add Select control
+{{ module }}.addSelectControl = function(){   
+  var select = new OpenLayers.Control.SelectFeature({{ module 
}}.layers.vector, {'toggle' : true, 'clickout' : true});
+  {{ module }}.map.addControl(select);
+  select.activate();
+}
+{{ module }}.enableDrawing = function(){ {{ module 
}}.map.getControlsByClass('OpenLayers.Control.DrawFeature')[0].activate();}
+{{ module }}.enableEditing = function(){ {{ module 
}}.map.getControlsByClass('OpenLayers.Control.ModifyFeature')[0].activate();}
+// Create an array of controls based on geometry type
+{{ module }}.getControls = function(lyr){
+  {{ module }}.panel = new OpenLayers.Control.Panel({'displayClass': 
'olControlEditingToolbar'});
+  var nav = new OpenLayers.Control.Navigation();
+  var draw_ctl;
+  if ({{ module }}.is_linestring){
+    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, 
OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath'});
+  } else if ({{ module }}.is_polygon){
+    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, 
OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'});
+  } else if ({{ module }}.is_point){
+    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, 
OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'});
+  }
+  {% if modifiable %}
+  var mod = new OpenLayers.Control.ModifyFeature(lyr, {'displayClass': 
'olControlModifyFeature'});
+  {{ module }}.controls = [nav, draw_ctl, mod];
+  {% else %}
+  {{ module }}.controls = [nav, darw_ctl];
+  {% endif %}  
+}
+{{ module }}.init = function(){
+    {% block map_options %}// The options hash, w/ zoom, resolution, and 
projection settings.
+    var options = { 
+{% autoescape off %}{% for item in map_options.items %}      '{{ item.0 }}' : 
{{ item.1 }}{% if not forloop.last %},{% endif %}
+{% endfor %}{% endautoescape %}    };{% endblock %}
+    // The admin map for this geometry field.
+    {{ module }}.map = new OpenLayers.Map('{{ id }}_map', options);
+    // Base Layer
+    {{ module }}.layers.base = {% block base_layer %}new OpenLayers.Layer.WMS( 
"{{ wms_name }}", "{{ wms_url }}", {layers: '{{ wms_layer }}'} );{% endblock %}
+    {{ module }}.map.addLayer({{ module }}.layers.base);
+    {% block extra_layers %}{% endblock %}
+    {% if is_linestring 
%}OpenLayers.Feature.Vector.style["default"]["strokeWidth"] = 3; // Default too 
thin for linestrings. {% endif %}
+    {{ module }}.layers.vector = new OpenLayers.Layer.Vector(" {{ field_name 
}}");
+    {{ module }}.map.addLayer({{ module }}.layers.vector);
+    // Read WKT from the text field.
+    var wkt = document.getElementById('{{ id }}').value;
+    if (wkt){
+      // After reading into geometry, immediately write back to 
+      // WKT <textarea> as EWKT (so that SRID is included).
+      var admin_geom = {{ module }}.read_wkt(wkt);
+      {{ module }}.write_wkt(admin_geom);
+      if ({{ module }}.is_collection){
+       // If geometry collection, add each component individually so they may 
be
+       // edited individually.
+       for (var i = 0; i < {{ module }}.num_geom; i++){
+         {{ module }}.layers.vector.addFeatures([new 
OpenLayers.Feature.Vector(admin_geom.geometry.components[i].clone())]);
+       }
+      } else {
+       {{ module }}.layers.vector.addFeatures([admin_geom]);
+      }
+      // Zooming to the bounds.
+      {{ module }}.map.zoomToExtent(admin_geom.geometry.getBounds());
+    } else {
+      {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ 
default_lat }}), {{ default_zoom }});
+    }
+    // This allows editing of the geographic fields -- the modified WKT is
+    // written back to the content field (as EWKT, so that the ORM will know
+    // to transform back to original SRID). 
+    {{ module }}.layers.vector.events.on({"featuremodified" : {{ module 
}}.modify_wkt});
+    {{ module }}.layers.vector.events.on({"featureadded" : {{ module 
}}.add_wkt});
+    {% block controls %}
+    // Map controls:
+    // Add geometry specific panel of toolbar controls
+    {{ module }}.getControls({{ module }}.layers.vector);
+    {{ module }}.panel.addControls({{ module }}.controls);
+    {{ module }}.map.addControl({{ module }}.panel);
+    {{ module }}.addSelectControl();
+    // Then add optional visual controls
+    {% if mouse_position %}{{ module }}.map.addControl(new 
OpenLayers.Control.MousePosition());{% endif %}
+    {% if scale_text %}{{ module }}.map.addControl(new 
OpenLayers.Control.Scale());{% endif %}
+    {% if layerswitcher %}{{ module }}.map.addControl(new 
OpenLayers.Control.LayerSwitcher());{% endif %}
+    // Then add optional behavior controls
+    {% if scrollable %}{% else %}{{ module 
}}.map.getControlsByClass('OpenLayers.Control.Navigation')[0].disableZoomWheel();{%
 endif %}
+    {% endblock %}
+    if (wkt){
+      {{ module }}.enableEditing();
+    } else {
+      {{ module }}.enableDrawing();
+    }
+}

Added: django/branches/gis/django/contrib/gis/templates/gis/admin/osm.html
===================================================================
--- django/branches/gis/django/contrib/gis/templates/gis/admin/osm.html         
                (rev 0)
+++ django/branches/gis/django/contrib/gis/templates/gis/admin/osm.html 
2008-07-19 14:17:24 UTC (rev 7980)
@@ -0,0 +1,2 @@
+{% extends "gis/admin/openlayers.html" %}
+{% block openlayers %}{% include "gis/admin/osm.js" %}{% endblock %}
\ No newline at end of file

Added: django/branches/gis/django/contrib/gis/templates/gis/admin/osm.js
===================================================================
--- django/branches/gis/django/contrib/gis/templates/gis/admin/osm.js           
                (rev 0)
+++ django/branches/gis/django/contrib/gis/templates/gis/admin/osm.js   
2008-07-19 14:17:24 UTC (rev 7980)
@@ -0,0 +1,2 @@
+{% extends "gis/admin/openlayers.js" %}
+{% block base_layer %}new OpenLayers.Layer.OSM.Mapnik("OpenStreetMap 
(Mapnik)");{% endblock %}


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to