web/lib/django/contrib/gis/maps/google/overlays.py
changeset 0 0d40e90630ef
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 from django.utils.safestring import mark_safe
       
     2 from django.contrib.gis.geos import fromstr, Point, LineString, LinearRing, Polygon
       
     3 
       
     4 class GEvent(object):
       
     5     """
       
     6     A Python wrapper for the Google GEvent object.
       
     7 
       
     8     Events can be attached to any object derived from GOverlayBase with the
       
     9     add_event() call.
       
    10 
       
    11     For more information please see the Google Maps API Reference:
       
    12      http://code.google.com/apis/maps/documentation/reference.html#GEvent
       
    13 
       
    14     Example:
       
    15 
       
    16       from django.shortcuts import render_to_response
       
    17       from django.contrib.gis.maps.google import GoogleMap, GEvent, GPolyline
       
    18 
       
    19       def sample_request(request):
       
    20           polyline = GPolyline('LINESTRING(101 26, 112 26, 102 31)')
       
    21           event = GEvent('click',
       
    22             'function() { location.href = "http://www.google.com"}')
       
    23           polyline.add_event(event)
       
    24           return render_to_response('mytemplate.html',
       
    25           {'google' : GoogleMap(polylines=[polyline])})
       
    26     """
       
    27 
       
    28     def __init__(self, event, action):
       
    29         """
       
    30         Initializes a GEvent object.
       
    31 
       
    32         Parameters:
       
    33 
       
    34         event:
       
    35           string for the event, such as 'click'. The event must be a valid
       
    36           event for the object in the Google Maps API.
       
    37           There is no validation of the event type within Django.
       
    38 
       
    39         action:
       
    40           string containing a Javascript function, such as
       
    41           'function() { location.href = "newurl";}'
       
    42           The string must be a valid Javascript function. Again there is no
       
    43           validation fo the function within Django.
       
    44         """
       
    45         self.event = event
       
    46         self.action = action
       
    47 
       
    48     def __unicode__(self):
       
    49         "Returns the parameter part of a GEvent."
       
    50         return mark_safe('"%s", %s' %(self.event, self.action))
       
    51 
       
    52 class GOverlayBase(object):
       
    53     def __init__(self):
       
    54         self.events = []
       
    55 
       
    56     def latlng_from_coords(self, coords):
       
    57         "Generates a JavaScript array of GLatLng objects for the given coordinates."
       
    58         return '[%s]' % ','.join(['new GLatLng(%s,%s)' % (y, x) for x, y in coords])
       
    59 
       
    60     def add_event(self, event):
       
    61         "Attaches a GEvent to the overlay object."
       
    62         self.events.append(event)
       
    63 
       
    64     def __unicode__(self):
       
    65         "The string representation is the JavaScript API call."
       
    66         return mark_safe('%s(%s)' % (self.__class__.__name__, self.js_params))
       
    67 
       
    68 class GPolygon(GOverlayBase):
       
    69     """
       
    70     A Python wrapper for the Google GPolygon object.  For more information
       
    71     please see the Google Maps API Reference:
       
    72      http://code.google.com/apis/maps/documentation/reference.html#GPolygon
       
    73     """
       
    74     def __init__(self, poly,
       
    75                  stroke_color='#0000ff', stroke_weight=2, stroke_opacity=1,
       
    76                  fill_color='#0000ff', fill_opacity=0.4):
       
    77         """
       
    78         The GPolygon object initializes on a GEOS Polygon or a parameter that
       
    79         may be instantiated into GEOS Polygon.  Please note that this will not
       
    80         depict a Polygon's internal rings.
       
    81 
       
    82         Keyword Options:
       
    83 
       
    84           stroke_color:
       
    85             The color of the polygon outline. Defaults to '#0000ff' (blue).
       
    86 
       
    87           stroke_weight:
       
    88             The width of the polygon outline, in pixels.  Defaults to 2.
       
    89 
       
    90           stroke_opacity:
       
    91             The opacity of the polygon outline, between 0 and 1.  Defaults to 1.
       
    92 
       
    93           fill_color:
       
    94             The color of the polygon fill.  Defaults to '#0000ff' (blue).
       
    95 
       
    96           fill_opacity:
       
    97             The opacity of the polygon fill.  Defaults to 0.4.
       
    98         """
       
    99         if isinstance(poly, basestring): poly = fromstr(poly)
       
   100         if isinstance(poly, (tuple, list)): poly = Polygon(poly)
       
   101         if not isinstance(poly, Polygon):
       
   102             raise TypeError('GPolygon may only initialize on GEOS Polygons.')
       
   103 
       
   104         # Getting the envelope of the input polygon (used for automatically
       
   105         # determining the zoom level).
       
   106         self.envelope = poly.envelope
       
   107 
       
   108         # Translating the coordinates into a JavaScript array of
       
   109         # Google `GLatLng` objects.
       
   110         self.points = self.latlng_from_coords(poly.shell.coords)
       
   111 
       
   112         # Stroke settings.
       
   113         self.stroke_color, self.stroke_opacity, self.stroke_weight = stroke_color, stroke_opacity, stroke_weight
       
   114 
       
   115         # Fill settings.
       
   116         self.fill_color, self.fill_opacity = fill_color, fill_opacity
       
   117 
       
   118         super(GPolygon, self).__init__()
       
   119 
       
   120     @property
       
   121     def js_params(self):
       
   122         return '%s, "%s", %s, %s, "%s", %s' % (self.points, self.stroke_color, self.stroke_weight, self.stroke_opacity,
       
   123                                                self.fill_color, self.fill_opacity)
       
   124 
       
   125 class GPolyline(GOverlayBase):
       
   126     """
       
   127     A Python wrapper for the Google GPolyline object.  For more information
       
   128     please see the Google Maps API Reference:
       
   129      http://code.google.com/apis/maps/documentation/reference.html#GPolyline
       
   130     """
       
   131     def __init__(self, geom, color='#0000ff', weight=2, opacity=1):
       
   132         """
       
   133         The GPolyline object may be initialized on GEOS LineStirng, LinearRing,
       
   134         and Polygon objects (internal rings not supported) or a parameter that
       
   135         may instantiated into one of the above geometries.
       
   136 
       
   137         Keyword Options:
       
   138 
       
   139           color:
       
   140             The color to use for the polyline.  Defaults to '#0000ff' (blue).
       
   141 
       
   142           weight:
       
   143             The width of the polyline, in pixels.  Defaults to 2.
       
   144 
       
   145           opacity:
       
   146             The opacity of the polyline, between 0 and 1.  Defaults to 1.
       
   147         """
       
   148         # If a GEOS geometry isn't passed in, try to contsruct one.
       
   149         if isinstance(geom, basestring): geom = fromstr(geom)
       
   150         if isinstance(geom, (tuple, list)): geom = Polygon(geom)
       
   151         # Generating the lat/lng coordinate pairs.
       
   152         if isinstance(geom, (LineString, LinearRing)):
       
   153             self.latlngs = self.latlng_from_coords(geom.coords)
       
   154         elif isinstance(geom, Polygon):
       
   155             self.latlngs = self.latlng_from_coords(geom.shell.coords)
       
   156         else:
       
   157             raise TypeError('GPolyline may only initialize on GEOS LineString, LinearRing, and/or Polygon geometries.')
       
   158 
       
   159         # Getting the envelope for automatic zoom determination.
       
   160         self.envelope = geom.envelope
       
   161         self.color, self.weight, self.opacity = color, weight, opacity
       
   162         super(GPolyline, self).__init__()
       
   163 
       
   164     @property
       
   165     def js_params(self):
       
   166         return '%s, "%s", %s, %s' % (self.latlngs, self.color, self.weight, self.opacity)
       
   167 
       
   168 
       
   169 class GIcon(object):
       
   170     """
       
   171     Creates a GIcon object to pass into a Gmarker object.
       
   172 
       
   173     The keyword arguments map to instance attributes of the same name. These,
       
   174     in turn, correspond to a subset of the attributes of the official GIcon
       
   175     javascript object:
       
   176 
       
   177     http://code.google.com/apis/maps/documentation/reference.html#GIcon
       
   178 
       
   179     Because a Google map often uses several different icons, a name field has
       
   180     been added to the required arguments.
       
   181 
       
   182     Required Arguments:
       
   183         varname:
       
   184             A string which will become the basis for the js variable name of
       
   185             the marker, for this reason, your code should assign a unique
       
   186             name for each GIcon you instantiate, otherwise there will be
       
   187             name space collisions in your javascript.
       
   188 
       
   189     Keyword Options:
       
   190         image:
       
   191             The url of the image to be used as the icon on the map defaults
       
   192             to 'G_DEFAULT_ICON'
       
   193 
       
   194         iconsize:
       
   195             a tuple representing the pixel size of the foreground (not the
       
   196             shadow) image of the icon, in the format: (width, height) ex.:
       
   197 
       
   198             GIcon('fast_food',
       
   199                   image="/media/icon/star.png",
       
   200                   iconsize=(15,10))
       
   201 
       
   202             Would indicate your custom icon was 15px wide and 10px height.
       
   203 
       
   204         shadow:
       
   205             the url of the image of the icon's shadow
       
   206 
       
   207         shadowsize:
       
   208             a tuple representing the pixel size of the shadow image, format is
       
   209             the same as ``iconsize``
       
   210 
       
   211         iconanchor:
       
   212             a tuple representing the pixel coordinate relative to the top left
       
   213             corner of the icon image at which this icon is anchored to the map.
       
   214             In (x, y) format.  x increases to the right in the Google Maps
       
   215             coordinate system and y increases downwards in the Google Maps
       
   216             coordinate system.)
       
   217 
       
   218         infowindowanchor:
       
   219             The pixel coordinate relative to the top left corner of the icon
       
   220             image at which the info window is anchored to this icon.
       
   221 
       
   222     """
       
   223     def __init__(self, varname, image=None, iconsize=None,
       
   224                  shadow=None, shadowsize=None, iconanchor=None,
       
   225                  infowindowanchor=None):
       
   226         self.varname = varname
       
   227         self.image = image
       
   228         self.iconsize = iconsize
       
   229         self.shadow = shadow
       
   230         self.shadowsize = shadowsize
       
   231         self.iconanchor = iconanchor
       
   232         self.infowindowanchor = infowindowanchor
       
   233 
       
   234     def __cmp__(self, other):
       
   235         return cmp(self.varname, other.varname)
       
   236     
       
   237     def __hash__(self):
       
   238         # XOR with hash of GIcon type so that hash('varname') won't 
       
   239         # equal hash(GIcon('varname')).
       
   240         return hash(self.__class__) ^ hash(self.varname)
       
   241 
       
   242 class GMarker(GOverlayBase):
       
   243     """
       
   244     A Python wrapper for the Google GMarker object.  For more information
       
   245     please see the Google Maps API Reference:
       
   246      http://code.google.com/apis/maps/documentation/reference.html#GMarker
       
   247 
       
   248     Example:
       
   249 
       
   250       from django.shortcuts import render_to_response
       
   251       from django.contrib.gis.maps.google.overlays import GMarker, GEvent
       
   252 
       
   253       def sample_request(request):
       
   254           marker = GMarker('POINT(101 26)')
       
   255           event = GEvent('click',
       
   256                          'function() { location.href = "http://www.google.com"}')
       
   257           marker.add_event(event)
       
   258           return render_to_response('mytemplate.html',
       
   259                  {'google' : GoogleMap(markers=[marker])})
       
   260     """
       
   261     def __init__(self, geom, title=None, draggable=False, icon=None):
       
   262         """
       
   263         The GMarker object may initialize on GEOS Points or a parameter
       
   264         that may be instantiated into a GEOS point.  Keyword options map to
       
   265         GMarkerOptions -- so far only the title option is supported.
       
   266 
       
   267         Keyword Options:
       
   268          title:
       
   269            Title option for GMarker, will be displayed as a tooltip.
       
   270 
       
   271          draggable:
       
   272            Draggable option for GMarker, disabled by default.
       
   273         """
       
   274         # If a GEOS geometry isn't passed in, try to construct one.
       
   275         if isinstance(geom, basestring): geom = fromstr(geom)
       
   276         if isinstance(geom, (tuple, list)): geom = Point(geom)
       
   277         if isinstance(geom, Point):
       
   278             self.latlng = self.latlng_from_coords(geom.coords)
       
   279         else:
       
   280             raise TypeError('GMarker may only initialize on GEOS Point geometry.')
       
   281         # Getting the envelope for automatic zoom determination.
       
   282         self.envelope = geom.envelope
       
   283         # TODO: Add support for more GMarkerOptions
       
   284         self.title = title
       
   285         self.draggable = draggable
       
   286         self.icon = icon
       
   287         super(GMarker, self).__init__()
       
   288 
       
   289     def latlng_from_coords(self, coords):
       
   290         return 'new GLatLng(%s,%s)' %(coords[1], coords[0])
       
   291 
       
   292     def options(self):
       
   293         result = []
       
   294         if self.title: result.append('title: "%s"' % self.title)
       
   295         if self.icon: result.append('icon: %s' % self.icon.varname)
       
   296         if self.draggable: result.append('draggable: true')
       
   297         return '{%s}' % ','.join(result)
       
   298 
       
   299     @property
       
   300     def js_params(self):
       
   301         return '%s, %s' % (self.latlng, self.options())