Commit 6aa5aacc authored by Justin Bronn's avatar Justin Bronn
Browse files

Fixed #9204 -- Added `GIcon` overlay, allowing customization for icons of...

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.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@10021 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 326c5813
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+32 −28
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ from django.template.loader import render_to_string
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.
@@ -20,9 +20,10 @@ class GoogleMap(object):

    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
@@ -57,25 +58,21 @@ class GoogleMap(object):
        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)
        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:
                    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))
                        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
@@ -105,6 +102,7 @@ class GoogleMap(object):
                  'zoom' : self.zoom,
                  'polygons' : self.polygons,
                  'polylines' : self.polylines,
                  'icons': self.icons,
                  'markers' : self.markers,
                  }
        params.update(self.extra_context)
@@ -175,6 +173,11 @@ class GoogleMapSet(GoogleMap):
        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 @@ class GoogleMapSet(GoogleMap):
        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)
+93 −25
Original line number Diff line number Diff line
@@ -165,6 +165,72 @@ class GPolyline(GOverlayBase):
    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
@@ -184,7 +250,7 @@ class GMarker(GOverlayBase):
          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
@@ -209,6 +275,7 @@ class GMarker(GOverlayBase):
        # 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):
@@ -217,6 +284,7 @@ class GMarker(GOverlayBase):
    def options(self):
        result = []
        if self.title: result.append('title: "%s"' % self.title)
        if self.icon: result.append('icon: %s' % self.icon.varname)
        if self.draggable: result.append('draggable: true')
        return '{%s}' % ','.join(result)

+6 −1
Original line number Diff line number Diff line
{% 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