PageRenderTime 237ms CodeModel.GetById 200ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://code.google.com/p/mango-py/
Python | 301 lines | 195 code | 21 blank | 85 comment | 16 complexity | 84af51ba6140ec6d1bedba4d54f00525 MD5 | raw file
  1from django.utils.safestring import mark_safe
  2from django.contrib.gis.geos import fromstr, Point, LineString, LinearRing, Polygon
  3
  4class 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
 52class 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
 68class 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
125class 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
169class 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
242class 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())