Author: jbronn
Date: 2009-03-10 13:03:35 -0500 (Tue, 10 Mar 2009)
New Revision: 10021

Modified:
   django/trunk/django/contrib/gis/maps/google/__init__.py
   django/trunk/django/contrib/gis/maps/google/gmap.py
   django/trunk/django/contrib/gis/maps/google/overlays.py
   django/trunk/django/contrib/gis/templates/gis/google/google-base.js
Log:
Fixed #9204 -- Added `GIcon` overlay, allowing customization for icons of 
`GMarker` objects.  Thanks to qingfeng for initial ticket/patch, and to 
prairiedogg for final implementation.


Modified: django/trunk/django/contrib/gis/maps/google/__init__.py
===================================================================
--- django/trunk/django/contrib/gis/maps/google/__init__.py     2009-03-10 
12:18:39 UTC (rev 10020)
+++ django/trunk/django/contrib/gis/maps/google/__init__.py     2009-03-10 
18:03:35 UTC (rev 10021)
@@ -57,5 +57,5 @@
       version.
 """
 from django.contrib.gis.maps.google.gmap import GoogleMap, GoogleMapSet
-from django.contrib.gis.maps.google.overlays import GEvent, GMarker, GPolygon, 
GPolyline
+from django.contrib.gis.maps.google.overlays import GEvent, GIcon, GMarker, 
GPolygon, GPolyline
 from django.contrib.gis.maps.google.zoom import GoogleZoom

Modified: django/trunk/django/contrib/gis/maps/google/gmap.py
===================================================================
--- django/trunk/django/contrib/gis/maps/google/gmap.py 2009-03-10 12:18:39 UTC 
(rev 10020)
+++ django/trunk/django/contrib/gis/maps/google/gmap.py 2009-03-10 18:03:35 UTC 
(rev 10021)
@@ -4,7 +4,7 @@
 from django.utils.safestring import mark_safe
 
 class GoogleMapException(Exception): pass
-from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, 
GMarker
+from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, 
GMarker, GIcon
 
 # The default Google Maps URL (for the API javascript)
 # TODO: Internationalize for Japan, UK, etc.
@@ -18,11 +18,12 @@
     vml_css  = mark_safe('v\:* {behavior:url(#default#VML);}') # CSS for IE VML
     xmlns    = mark_safe('xmlns:v="urn:schemas-microsoft-com:vml"') # XML 
Namespace (for IE VML).
 
-    def __init__(self, key=None, api_url=None, version=None, 
+    def __init__(self, key=None, api_url=None, version=None,
                  center=None, zoom=None, dom_id='map',
-                 kml_urls=[], polygons=[], polylines=[], markers=[],
+                 kml_urls=[], polylines=None, polygons=None, markers=None,
                  template='gis/google/google-single.js',
-                 js_module='geodjango',extra_context={}):
+                 js_module='geodjango',
+                 extra_context={}):
 
         # The Google Maps API Key defined in the settings will be used
         # if not passed in as a parameter.  The use of an API key is
@@ -34,7 +35,7 @@
                 raise GoogleMapException('Google Maps API Key not found (try 
adding GOOGLE_MAPS_API_KEY to your settings).')
         else:
             self.key = key
-        
+
         # Getting the Google Maps API version, defaults to using the latest 
("2.x"),
         # this is not necessarily the most stable.
         if not version:
@@ -55,28 +56,24 @@
         self.js_module = js_module
         self.template = template
         self.kml_urls = kml_urls
-        
+
         # Does the user want any GMarker, GPolygon, and/or GPolyline overlays?
-        self.polygons, self.polylines, self.markers = [], [], []
-        if markers:
-            for point in markers:
-                if isinstance(point, GMarker): 
-                    self.markers.append(point)
-                else:
-                    self.markers.append(GMarker(point))
-        if polygons:
-            for poly in polygons:
-                if isinstance(poly, GPolygon): 
-                    self.polygons.append(poly)
-                else:
-                    self.polygons.append(GPolygon(poly))
-        if polylines:
-            for pline in polylines:
-                if isinstance(pline, GPolyline):
-                    self.polylines.append(pline)
-                else:
-                    self.polylines.append(GPolyline(pline))
-       
+        overlay_info = [[GMarker, markers, 'markers'],
+                        [GPolygon, polygons, 'polygons'],
+                        [GPolyline, polylines, 'polylines']]
+
+        for overlay_class, overlay_list, varname in overlay_info:
+            setattr(self, varname, [])
+            if overlay_list:
+                for overlay in overlay_list:
+                    if isinstance(overlay, overlay_class):
+                        getattr(self, varname).append(overlay)
+                    else:
+                        getattr(self, varname).append(overlay_class(overlay))
+
+        # Pulling any icons from the markers.
+        self.icons = [marker.icon for marker in self.markers if marker.icon]
+
         # If GMarker, GPolygons, and/or GPolylines are used the zoom will be
         # automatically calculated via the Google Maps API.  If both a zoom
         # level and a center coordinate are provided with polygons/polylines,
@@ -85,7 +82,7 @@
         if self.polygons or self.polylines  or self.markers:
             if center is None or zoom is None:
                 self.calc_zoom = True
-    
+
         # Defaults for the zoom level and center coordinates if the zoom
         # is not automatically calculated.
         if zoom is None: zoom = 4
@@ -105,6 +102,7 @@
                   'zoom' : self.zoom,
                   'polygons' : self.polygons,
                   'polylines' : self.polylines,
+                  'icons': self.icons,
                   'markers' : self.markers,
                   }
         params.update(self.extra_context)
@@ -174,7 +172,12 @@
             self.maps = args[0]
         else:
             self.maps = args
-        
+
+        # Creating the icons sequence from every map in this set.
+        self.icons = []
+        for map in self.maps:
+            self.icons.extend(map.icons)
+
         # Generating DOM ids for each of the maps in the set.
         self.dom_ids = ['map%d' % i for i in xrange(len(self.maps))]
 
@@ -205,6 +208,7 @@
         params = {'js_module' : self.js_module,
                   'dom_ids' : self.dom_ids,
                   'load_map_js' : self.load_map_js(),
+                  'icons' : self.icons,
                   }
         params.update(self.extra_context)
         return render_to_string(self.template, params)

Modified: django/trunk/django/contrib/gis/maps/google/overlays.py
===================================================================
--- django/trunk/django/contrib/gis/maps/google/overlays.py     2009-03-10 
12:18:39 UTC (rev 10020)
+++ django/trunk/django/contrib/gis/maps/google/overlays.py     2009-03-10 
18:03:35 UTC (rev 10021)
@@ -18,28 +18,28 @@
 
       def sample_request(request):
           polyline = GPolyline('LINESTRING(101 26, 112 26, 102 31)')
-          event = GEvent('click', 
+          event = GEvent('click',
             'function() { location.href = "http://www.google.com"}')
           polyline.add_event(event)
-          return render_to_response('mytemplate.html', 
+          return render_to_response('mytemplate.html',
           {'google' : GoogleMap(polylines=[polyline])})
     """
 
     def __init__(self, event, action):
         """
-        Initializes a GEvent object. 
-        
+        Initializes a GEvent object.
+
         Parameters:
 
-        event: 
+        event:
           string for the event, such as 'click'. The event must be a valid
-          event for the object in the Google Maps API. 
+          event for the object in the Google Maps API.
           There is no validation of the event type within Django.
 
         action:
-          string containing a Javascript function, such as 
+          string containing a Javascript function, such as
           'function() { location.href = "newurl";}'
-          The string must be a valid Javascript function. Again there is no 
+          The string must be a valid Javascript function. Again there is no
           validation fo the function within Django.
         """
         self.event = event
@@ -71,7 +71,7 @@
     please see the Google Maps API Reference:
      http://code.google.com/apis/maps/documentation/reference.html#GPolygon
     """
-    def __init__(self, poly, 
+    def __init__(self, poly,
                  stroke_color='#0000ff', stroke_weight=2, stroke_opacity=1,
                  fill_color='#0000ff', fill_opacity=0.4):
         """
@@ -98,25 +98,25 @@
         """
         if isinstance(poly, basestring): poly = fromstr(poly)
         if isinstance(poly, (tuple, list)): poly = Polygon(poly)
-        if not isinstance(poly, Polygon): 
+        if not isinstance(poly, Polygon):
             raise TypeError('GPolygon may only initialize on GEOS Polygons.')
 
         # Getting the envelope of the input polygon (used for automatically
         # determining the zoom level).
         self.envelope = poly.envelope
 
-        # Translating the coordinates into a JavaScript array of 
+        # Translating the coordinates into a JavaScript array of
         # Google `GLatLng` objects.
         self.points = self.latlng_from_coords(poly.shell.coords)
 
         # Stroke settings.
         self.stroke_color, self.stroke_opacity, self.stroke_weight = 
stroke_color, stroke_opacity, stroke_weight
-      
+
         # Fill settings.
         self.fill_color, self.fill_opacity = fill_color, fill_opacity
-       
+
         super(GPolygon, self).__init__()
- 
+
     @property
     def js_params(self):
         return '%s, "%s", %s, %s, "%s", %s' % (self.points, self.stroke_color, 
self.stroke_weight, self.stroke_opacity,
@@ -135,10 +135,10 @@
         may instantiated into one of the above geometries.
 
         Keyword Options:
-          
+
           color:
             The color to use for the polyline.  Defaults to '#0000ff' (blue).
-  
+
           weight:
             The width of the polyline, in pixels.  Defaults to 2.
 
@@ -160,11 +160,77 @@
         self.envelope = geom.envelope
         self.color, self.weight, self.opacity = color, weight, opacity
         super(GPolyline, self).__init__()
-        
+
     @property
     def js_params(self):
         return '%s, "%s", %s, %s' % (self.latlngs, self.color, self.weight, 
self.opacity)
 
+
+class GIcon(object):
+    """
+    Creates a GIcon object to pass into a Gmarker object.
+
+    The keyword arguments map to instance attributes of the same name. These,
+    in turn, correspond to a subset of the attributes of the official GIcon
+    javascript object:
+
+    http://code.google.com/apis/maps/documentation/reference.html#GIcon
+
+    Because a Google map often uses several different icons, a name field has
+    been added to the required arguments.
+
+    Required Arguments:
+        varname:
+            A string which will become the basis for the js variable name of
+            the marker, for this reason, your code should assign a unique
+            name for each GIcon you instantiate, otherwise there will be
+            name space collisions in your javascript.
+
+    Keyword Options:
+        image:
+            The url of the image to be used as the icon on the map defaults
+            to 'G_DEFAULT_ICON'
+
+        iconsize:
+            a tuple representing the pixel size of the foreground (not the
+            shadow) image of the icon, in the format: (width, height) ex.:
+
+            GIcon('fast_food',
+                  image="/media/icon/star.png",
+                  iconsize=(15,10))
+
+            Would indicate your custom icon was 15px wide and 10px height.
+
+        shadow:
+            the url of the image of the icon's shadow
+
+        shadowsize:
+            a tuple representing the pixel size of the shadow image, format is
+            the same as ``iconsize``
+
+        iconanchor:
+            a tuple representing the pixel coordinate relative to the top left
+            corner of the icon image at which this icon is anchored to the map.
+            In (x, y) format.  x increases to the right in the Google Maps
+            coordinate system and y increases downwards in the Google Maps
+            coordinate system.)
+
+        infowindowanchor:
+            The pixel coordinate relative to the top left corner of the icon
+            image at which the info window is anchored to this icon.
+
+    """
+    def __init__(self, varname, image=None, iconsize=None,
+                 shadow=None, shadowsize=None, iconanchor=None,
+                 infowindowanchor=None):
+        self.varname = varname
+        self.image = image
+        self.iconsize = iconsize
+        self.shadow = shadow
+        self.shadowsize = shadowsize
+        self.iconanchor = iconanchor
+        self.infowindowanchor = infowindowanchor
+
 class GMarker(GOverlayBase):
     """
     A Python wrapper for the Google GMarker object.  For more information
@@ -175,25 +241,25 @@
 
       from django.shortcuts import render_to_response
       from django.contrib.gis.maps.google.overlays import GMarker, GEvent
-     
+
       def sample_request(request):
           marker = GMarker('POINT(101 26)')
-          event = GEvent('click', 
+          event = GEvent('click',
                          'function() { location.href = 
"http://www.google.com"}')
           marker.add_event(event)
-          return render_to_response('mytemplate.html', 
+          return render_to_response('mytemplate.html',
                  {'google' : GoogleMap(markers=[marker])})
     """
-    def __init__(self, geom, title=None, draggable=False):
+    def __init__(self, geom, title=None, draggable=False, icon=None):
         """
         The GMarker object may initialize on GEOS Points or a parameter
         that may be instantiated into a GEOS point.  Keyword options map to
         GMarkerOptions -- so far only the title option is supported.
 
         Keyword Options:
-         title: 
+         title:
            Title option for GMarker, will be displayed as a tooltip.
-         
+
          draggable:
            Draggable option for GMarker, disabled by default.
         """
@@ -209,15 +275,17 @@
         # TODO: Add support for more GMarkerOptions
         self.title = title
         self.draggable = draggable
+        self.icon = icon
         super(GMarker, self).__init__()
 
     def latlng_from_coords(self, coords):
         return 'new GLatLng(%s,%s)' %(coords[1], coords[0])
-    
+
     def options(self):
         result = []
         if self.title: result.append('title: "%s"' % self.title)
-        if self.draggable: result.append('draggable: true') 
+        if self.icon: result.append('icon: %s' % self.icon.varname)
+        if self.draggable: result.append('draggable: true')
         return '{%s}' % ','.join(result)
 
     @property

Modified: django/trunk/django/contrib/gis/templates/gis/google/google-base.js
===================================================================
--- django/trunk/django/contrib/gis/templates/gis/google/google-base.js 
2009-03-10 12:18:39 UTC (rev 10020)
+++ django/trunk/django/contrib/gis/templates/gis/google/google-base.js 
2009-03-10 18:03:35 UTC (rev 10021)
@@ -1,2 +1,7 @@
-{% block vars %}var geodjango = {};{% endblock %}
+{% block vars %}var geodjango = {};{% for icon in icons %} 
+var {{ icon.varname }} = new GIcon(G_DEFAULT_ICON); 
+{% if icon.image %}{{ icon.varname }}.image = "{{ icon.image }}";{% endif %}
+{% if icon.shadow %}{{ icon.varname }}.shadow = "{{ icon.shadow }}";{% endif 
%} {% if icon.shadowsize %}{{ icon.varname }}.shadowSize = new GSize({{ 
icon.shadowsize.0 }}, {{ icon.shadowsize.1 }});{% endif %}
+{% if icon.iconanchor %}{{ icon.varname }}.iconAnchor = new GPoint({{ 
icon.iconanchor.0 }}, {{ icon.iconanchor.1 }});{% endif %} {% if icon.iconsize 
%}{{ icon.varname }}.iconSize = new GSize({{ icon.iconsize.0 }}, {{ 
icon.iconsize.1 }});{% endif %}
+{% if icon.infowindowanchor %}{{ icon.varname }}.infoWindowAnchor = new 
GPoint({{ icon.infowindowanchor.0 }}, {{ icon.infowindowanchor.1 }});{% endif 
%}{% endfor %}{% endblock %}
 {% block functions %}{% endblock %}
\ No newline at end of file


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