/django/contrib/gis/maps/google/overlays.py

https://code.google.com/p/mango-py/ · Python · 301 lines · 195 code · 21 blank · 85 comment · 17 complexity · 84af51ba6140ec6d1bedba4d54f00525 MD5 · raw file

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