Index: django/contrib/gis/admin/options.py
===================================================================
--- django/contrib/gis/admin/options.py	(revision 14851)
+++ django/contrib/gis/admin/options.py	(working copy)
@@ -37,6 +37,8 @@
     wms_url = 'http://labs.metacarta.com/wms/vmap0'
     wms_layer = 'basic'
     wms_name = 'OpenLayers WMS'
+    wms_options = {'format': 'image/jpg'}
+
     debug = False
     widget = OpenLayersWidget
 
@@ -67,47 +69,72 @@
         in the `widget` attribute) using the settings from the attributes set
         in this class.
         """
-        is_collection = db_field.geom_type in ('MULTIPOINT', 'MULTILINESTRING', 'MULTIPOLYGON', 'GEOMETRYCOLLECTION')
-        if is_collection:
-            if db_field.geom_type == 'GEOMETRYCOLLECTION': collection_type = 'Any'
-            else: collection_type = OGRGeomType(db_field.geom_type.replace('MULTI', ''))
+        is_unknown = db_field.geom_type in ('GEOMETRY',)
+        if not is_unknown:
+            #If it is not generic, get the parameters from the db_field
+            is_collection = db_field.geom_type in ('MULTIPOINT', 'MULTILINESTRING', 'MULTIPOLYGON', 'GEOMETRYCOLLECTION')
+            if is_collection:
+                if db_field.geom_type == 'GEOMETRYCOLLECTION': collection_type = 'Any'
+                else: collection_type = OGRGeomType(db_field.geom_type.upper().replace('MULTI', ''))
+            else:
+                collection_type = 'None'
+            is_linestring = db_field.geom_type in ('LINESTRING', 'MULTILINESTRING')
+            is_polygon = db_field.geom_type in ('POLYGON', 'MULTIPOLYGON')
+            is_point = db_field.geom_type in ('POINT', 'MULTIPOINT')
+            geom_type = OGRGeomType(db_field.geom_type)
         else:
+            #If it is generic, set sensible defaults
+            is_collection = False
             collection_type = 'None'
+            is_linestring = False
+            is_polygon = False
+            is_point = False
+            geom_type = OGRGeomType('Unknown')
 
         class OLMap(self.widget):
             template = self.map_template
             geom_type = db_field.geom_type
+            wms_options = ''
+            if self.wms_options:
+                wms_options = ["%s: '%s'" % pair for pair in self.wms_options.items()]
+                wms_options = ', '.join(wms_options)
+                wms_options = ', ' + wms_options
+
             params = {'default_lon' : self.default_lon,
+                      'collection_type' : collection_type,
+                      'debug' : self.debug,
                       'default_lat' : self.default_lat,
                       'default_zoom' : self.default_zoom,
+                      'display_srid' : self.display_srid,
                       'display_wkt' : self.debug or self.display_wkt,
-                      'geom_type' : OGRGeomType(db_field.geom_type),
                       'field_name' : db_field.name,
+                      'geom_type' : geom_type,
                       'is_collection' : is_collection,
-                      'scrollable' : self.scrollable,
+                      'is_linestring' : is_linestring,
+                      'is_point' : is_point,
+                      'is_polygon' : is_polygon,
+                      'is_unknown': is_unknown,
                       'layerswitcher' : self.layerswitcher,
-                      'collection_type' : collection_type,
-                      'is_linestring' : db_field.geom_type in ('LINESTRING', 'MULTILINESTRING'),
-                      'is_polygon' : db_field.geom_type in ('POLYGON', 'MULTIPOLYGON'),
-                      'is_point' : db_field.geom_type in ('POINT', 'MULTIPOINT'),
-                      'num_zoom' : self.num_zoom,
+                      'map_height' : self.map_height,
+                      'map_width' : self.map_width,
+                      'max_extent' : self.max_extent,
+                      'max_resolution' : self.max_resolution,
                       '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,
+                      'num_zoom' : self.num_zoom,
+                      'openlayers_url': self.openlayers_url,
+                      'openlayers_img_path': self.openlayers_img_path,
+                      'point_zoom' : self.point_zoom,
                       'scale_text' : self.scale_text,
-                      'map_width' : self.map_width,
-                      'map_height' : self.map_height,
-                      'point_zoom' : self.point_zoom,
+                      'scrollable' : self.scrollable,
                       'srid' : self.map_srid,
-                      'display_srid' : self.display_srid,
-                      'wms_url' : self.wms_url,
+                      'units' : self.units, #likely shoud get from object
                       'wms_layer' : self.wms_layer,
                       'wms_name' : self.wms_name,
-                      'debug' : self.debug,
+                      'wms_options': wms_options,
+                      'wms_url' : self.wms_url,
                       }
         return OLMap
 
Index: django/contrib/gis/admin/widgets.py
===================================================================
--- django/contrib/gis/admin/widgets.py	(revision 14851)
+++ django/contrib/gis/admin/widgets.py	(working copy)
@@ -1,5 +1,6 @@
 from django.conf import settings
 from django.contrib.gis.gdal import OGRException
+from django.contrib.gis.gdal import OGRGeomType
 from django.contrib.gis.geos import GEOSGeometry, GEOSException
 from django.forms.widgets import Textarea
 from django.template import loader, Context
@@ -15,9 +16,12 @@
     """
     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)
+        # If value is None, that means we haven't saved anything yet.
+        if attrs:
+            self.params.update(attrs)
 
         # Defaulting the WKT value to a blank string -- this
         # will be tested in the JavaScript and the appropriate
@@ -31,8 +35,7 @@
                 value = GEOSGeometry(value)
             except (GEOSException, ValueError):
                 value = None
-
-        if value and value.geom_type.upper() != self.geom_type:
+        if value and value.geom_type.upper() != self.geom_type and self.geom_type != 'GEOMETRY':
             value = None
 
         # Constructing the dictionary of the map options.
@@ -65,6 +68,37 @@
             # geometry.
             self.params['wkt'] = wkt
 
+            # Check if the field is generic so the proper values are overriden
+            if self.params['is_unknown']:
+                self.params['geom_type'] = OGRGeomType(value.geom_type)
+                if value.geom_type.upper() in ('LINESTRING', 'MULTILINESTRING'):
+                    self.params['is_linestring'] = True
+                elif value.geom_type.upper() in ('POLYGON', 'MULTIPOLYGON'):
+                    self.params['is_polygon'] = True
+                elif value.geom_type.upper() in ('POINT', 'MULTIPOINT'):
+                    self.params['is_point'] = True
+                elif value.geom_type.upper() in ('MULTIPOINT', 'MULTILINESTRING', 'MULTIPOLYGON'):
+                    self.params['is_collection'] = True
+                    self.params['collection_type'] = OGRGeomType(value.geom_type.upper().replace('MULTI', ''))
+                elif value.geom_type.upper() == 'GEOMETRYCOLLECTION':
+                    self.params['is_collection'] = True
+                    self.params['collection_type'] = 'Any'
+                    self.params['geom_type'] = 'Collection'
+
+
+        else:
+            if self.params['is_unknown']:
+                # If the geometry is unknown and the value is not set,
+                # make it as flexible as possible.
+                self.params['geom_type'] = 'Collection'
+                self.params['is_collection']=True
+                self.params['collection_type'] = 'Any'
+
+        # If we don't already have a camelcase geom_type,
+        # make one using str(OGRGeomType).
+        # Works for most things but not 'GeometryCollection'.
+        if str(self.params['geom_type']) == str(self.params['geom_type']).upper():
+            self.params['geom_type'] = str(OGRGeomType(self.params['geom_type']))
         return loader.render_to_string(self.template, self.params,
                                        context_instance=geo_context)
 
Index: django/contrib/gis/templates/gis/admin/openlayers.js
===================================================================
--- django/contrib/gis/templates/gis/admin/openlayers.js	(revision 14851)
+++ django/contrib/gis/templates/gis/admin/openlayers.js	(working copy)
@@ -1,5 +1,6 @@
 {# Author: Justin Bronn, Travis Pinney & Dane Springmeyer #}
 {% block vars %}var {{ module }} = {};
+{% if openlayers_img_path %}OpenLayers.ImgPath = '{{ openlayers_img_path }}';{% endif %}
 {{ module }}.map = null; {{ module }}.controls = null; {{ module }}.panel = null; {{ module }}.re = new RegExp("^SRID=\d+;(.+)", "i"); {{ module }}.layers = {};
 {{ module }}.modifiable = {{ modifiable|yesno:"true,false" }};
 {{ module }}.wkt_f = new OpenLayers.Format.WKT();
@@ -9,19 +10,24 @@
 {{ module }}.is_polygon = {{ is_polygon|yesno:"true,false" }};
 {{ module }}.is_point = {{ is_point|yesno:"true,false" }};
 {% endblock %}
-{{ module }}.get_ewkt = function(feat){return 'SRID={{ srid }};' + {{ module }}.wkt_f.write(feat);}
+{{ 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;}
+  if ({{ module }}.is_collection){
+    {{ module }}.num_geom = feat.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.
@@ -40,7 +46,7 @@
     }
     {{ module }}.write_wkt(event.feature);
   }
-}
+};
 {{ module }}.modify_wkt = function(event){
   if ({{ module }}.is_collection){
     if ({{ module }}.is_point){
@@ -58,7 +64,7 @@
   } 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);
@@ -68,29 +74,41 @@
   {{ 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();}
+};
+{{ 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 nav = new OpenLayers.Control.Navigation({'title': 'Navigate'});
   var draw_ctl;
   if ({{ module }}.is_linestring){
-    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath'});
+    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath', 'title': 'Draw Lines'});
   } else if ({{ module }}.is_polygon){
-    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'});
+    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon', 'title': 'Draw Polygons'});
   } else if ({{ module }}.is_point){
-    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'});
-  }
+    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint', 'title': 'Draw Points'});
+  };
+  /* if is_collection==true and collection_type=='Any', we should
+   * provide a widget that allows choosing the type of feature to
+   * add... but that'd take a lot more work. Possible example to draw
+   * on: http://openlayers.org/dev/examples/snapping.html
+   * For now, just assume we want MultiPolygons.
+   */
+  if (draw_ctl == undefined) {
+    draw_ctl = new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon', 'title': 'Draw Polygons'});
+  };
+  if ({{module}}.is_collection )  {
+      draw_ctl.multi = true;
+  };
   if ({{ module }}.modifiable){
-    var mod = new OpenLayers.Control.ModifyFeature(lyr, {'displayClass': 'olControlModifyFeature'});
+    var mod = new OpenLayers.Control.ModifyFeature(lyr, {'displayClass': 'olControlModifyFeature', 'title': 'Modify'});
     {{ module }}.controls = [nav, draw_ctl, mod];
   } else {
     if(!lyr.features.length){
@@ -99,7 +117,7 @@
       {{ module }}.controls = [nav];
     }
   }
-}
+};
 {{ module }}.init = function(){
     {% block map_options %}// The options hash, w/ zoom, resolution, and projection settings.
     var options = {
@@ -108,7 +126,7 @@
     // 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 }}.layers.base = {% block base_layer %}new OpenLayers.Layer.WMS( "{{ wms_name }}", "{{ wms_url }}", {layers: '{{ wms_layer }}' {{ wms_options|safe }} }  );{% 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 %}
@@ -121,20 +139,21 @@
       // 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())]);
-	}
+      var bounds;
+      if ({{ module }}.is_collection) {
+        {{ module }}.layers.vector.addFeatures(admin_geom);
+        bounds = admin_geom[0].geometry.getBounds();
+        for (var i = 1; i < admin_geom.length; i++ ) {
+          bounds.extend(admin_geom[i].geometry.getBounds());
+        };
       } else {
 	{{ module }}.layers.vector.addFeatures([admin_geom]);
-      }
-      // Zooming to the bounds.
-      {{ module }}.map.zoomToExtent(admin_geom.geometry.getBounds());
+	bounds = admin_geom.geometry.getBounds();
+      };
+      {{ module }}.map.zoomToExtent(bounds);
       if ({{ module }}.is_point){
           {{ module }}.map.zoomTo({{ point_zoom }});
-      }
+      };
     } else {
       {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ default_lat }}), {{ default_zoom }});
     }
@@ -164,4 +183,4 @@
     } else {
       {{ module }}.enableDrawing();
     }
-}
+};
