Ticket #14284: 14284_patch.2.diff
File 14284_patch.2.diff, 22.3 KB (added by , 14 years ago) |
---|
-
django/contrib/gis/maps/google/__init__.py
diff -r e6fd4804cf6f django/contrib/gis/maps/google/__init__.py
a b 57 57 version. 58 58 """ 59 59 from django.contrib.gis.maps.google.gmap import GoogleMap, GoogleMapSet 60 from django.contrib.gis.maps.google.overlays import GEvent, GI con, GMarker, GPolygon, GPolyline60 from django.contrib.gis.maps.google.overlays import GEvent, GImage, GMarker, GPolygon, GPolyline 61 61 from django.contrib.gis.maps.google.zoom import GoogleZoom -
django/contrib/gis/maps/google/gmap.py
diff -r e6fd4804cf6f django/contrib/gis/maps/google/gmap.py
a b from django.template.loader import rende 4 4 from django.utils.safestring import mark_safe 5 5 6 6 class GoogleMapException(Exception): pass 7 from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker, GI con7 from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker, GImage 8 8 9 9 # The default Google Maps URL (for the API javascript) 10 10 # TODO: Internationalize for Japan, UK, etc. 11 GOOGLE_MAPS_URL='http://maps.google.com/maps ?file=api&v=%s&key='11 GOOGLE_MAPS_URL='http://maps.google.com/maps/api/js?sensor=%s' 12 12 13 13 class GoogleMap(object): 14 14 "A class for generating Google Maps JavaScript." 15 15 16 16 # String constants 17 onunload = mark_safe(' onunload="GUnload()"') # Cleans up after Google Maps17 onunload = mark_safe('') # NOTE: Used to call GUnload, but google maps v3 doesn't need it so now blank 18 18 vml_css = mark_safe('v\:* {behavior:url(#default#VML);}') # CSS for IE VML 19 19 xmlns = mark_safe('xmlns:v="urn:schemas-microsoft-com:vml"') # XML Namespace (for IE VML). 20 20 21 def __init__(self, key=None, api_url=None, version=None, 22 center=None, zoom=None, dom_id='map', 21 def __init__(self, api_url=None, center=None, zoom=None, dom_id='map', 23 22 kml_urls=[], polylines=None, polygons=None, markers=None, 23 using_sensor=False, 24 24 template='gis/google/google-map.js', 25 25 js_module='geodjango', 26 26 extra_context={}): 27 27 28 # The Google Maps API Key defined in the settings will be used29 # if not passed in as a parameter. The use of an API key is30 # _required_.31 if not key:32 try:33 self.key = settings.GOOGLE_MAPS_API_KEY34 except AttributeError:35 raise GoogleMapException('Google Maps API Key not found (try adding GOOGLE_MAPS_API_KEY to your settings).')36 else:37 self.key = key38 39 # Getting the Google Maps API version, defaults to using the latest ("2.x"),40 # this is not necessarily the most stable.41 if not version:42 self.version = getattr(settings, 'GOOGLE_MAPS_API_VERSION', '2.x')43 else:44 self.version = version45 46 28 # Can specify the API URL in the `api_url` keyword. 47 29 if not api_url: 48 self.api_url = mark_safe(getattr(settings, 'GOOGLE_MAPS_URL', GOOGLE_MAPS_URL) % self.version) 30 sensor_value = 'false' # maps v3 needs to know if the device rendering the page has a gps sensor 31 if using_sensor: sensor_value = 'true' 32 self.api_url = mark_safe(getattr(settings, 'GOOGLE_MAPS_URL', GOOGLE_MAPS_URL) % sensor_value) 49 33 else: 50 34 self.api_url = api_url 51 35 … … class GoogleMap(object): 118 102 @property 119 103 def api_script(self): 120 104 "Returns the <script> tag for the Google Maps API javascript." 121 return mark_safe('<script src="%s %s" type="text/javascript"></script>' % (self.api_url, self.key))105 return mark_safe('<script src="%s" type="text/javascript"></script>' % self.api_url) 122 106 123 107 @property 124 108 def js(self): … … class GoogleMap(object): 142 126 143 127 @property 144 128 def icons(self): 145 "Returns a sequence of GI conobjects in this map."129 "Returns a sequence of GImage objects in this map." 146 130 return set([marker.icon for marker in self.markers if marker.icon]) 147 131 148 132 class GoogleMapSet(GoogleMap): -
django/contrib/gis/maps/google/overlays.py
diff -r e6fd4804cf6f django/contrib/gis/maps/google/overlays.py
a b from django.contrib.gis.geos import from 3 3 4 4 class GEvent(object): 5 5 """ 6 A Python wrapper for the Google GEvent object. 6 A Python wrapper for wiring map events using the 7 google.maps.event.addListener() function. 7 8 8 9 Events can be attached to any object derived from GOverlayBase with the 9 10 add_event() call. 10 11 11 12 For more information please see the Google Maps API Reference: 12 http://code.google.com/apis/maps/documentation/ reference.html#GEvent13 http://code.google.com/apis/maps/documentation/javascript/reference.html#event 13 14 14 15 Example: 15 16 … … class GEvent(object): 50 51 return mark_safe('"%s", %s' %(self.event, self.action)) 51 52 52 53 class GOverlayBase(object): 54 55 JS_CLASSNAME = 'Overlay' 56 53 57 def __init__(self): 54 58 self.events = [] 55 59 56 60 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])61 "Generates a JavaScript array of google.maps.LatLng objects for the given coordinates." 62 return '[%s]' % ','.join(['new google.maps.LatLng(%s,%s)' % (y, x) for x, y in coords]) 59 63 60 64 def add_event(self, event): 61 " Attaches a GEvent to the overlay object."65 "Causes the event to be applied to the overlay object" 62 66 self.events.append(event) 63 67 64 68 def __unicode__(self): 65 69 "The string representation is the JavaScript API call." 66 return mark_safe(' %s(%s)' % (self.__class__.__name__, self.js_params))70 return mark_safe('google.maps.%s(%s)' % (self.JS_CLASSNAME, self.js_params)) 67 71 68 72 class GPolygon(GOverlayBase): 69 73 """ 70 A Python wrapper for the Google GPolygon object. For more information74 A Python wrapper for the google.maps.Polygon object. For more information 71 75 please see the Google Maps API Reference: 72 http://code.google.com/apis/maps/documentation/ reference.html#GPolygon76 http://code.google.com/apis/maps/documentation/javascript/reference.html#Polygon 73 77 """ 78 79 JS_CLASSNAME = 'Polygon' 80 74 81 def __init__(self, poly, 75 82 stroke_color='#0000ff', stroke_weight=2, stroke_opacity=1, 76 83 fill_color='#0000ff', fill_opacity=0.4): 77 84 """ 78 The GPolygon object initializes on a GEOS Polygon or a parameter that79 may be instantiated into GEOS Polygon. Please note that this will not80 depict a Polygon's internal rings.85 The GPolygon object initializes on a GEOS Polygon or a 86 parameter that may be instantiated into GEOS Polygon. Please note 87 that this will not depict a Polygon's internal rings. 81 88 82 89 Keyword Options: 83 90 … … class GPolygon(GOverlayBase): 119 126 120 127 @property 121 128 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) 129 result = [] 130 result.append('paths: %s' % self.points) 131 if self.stroke_color: result.append('strokeColor: "%s"' % self.stroke_color) 132 if self.stroke_weight: result.append('strokeWeight: "%s"' % self.stroke_weight) 133 if self.stroke_opacity: result.append('strokeOpacity: "%s"' % self.stroke_opacity) 134 if self.fill_color: result.append('fillColor: "%s"' % self.fill_color) 135 if self.fill_opacity: result.append('fillOpactiy: "%s"' % self.fill_opacity) 136 return '{%s}' % ','.join(result) 124 137 125 138 class GPolyline(GOverlayBase): 126 139 """ 127 A Python wrapper for the Google GPolyline object. For more information140 A Python wrapper for the google.maps.Polyline object. For more information 128 141 please see the Google Maps API Reference: 129 http://code.google.com/apis/maps/documentation/ reference.html#GPolyline142 http://code.google.com/apis/maps/documentation/javascript/reference.html#Polyline 130 143 """ 144 145 JS_CLASSNAME = 'Polyline' 146 131 147 def __init__(self, geom, color='#0000ff', weight=2, opacity=1): 132 148 """ 133 149 The GPolyline object may be initialized on GEOS LineStirng, LinearRing, … … class GPolyline(GOverlayBase): 163 179 164 180 @property 165 181 def js_params(self): 166 return '%s, "%s", %s, %s' % (self.latlngs, self.color, self.weight, self.opacity) 182 result = [] 183 result.append('path: %s' % self.latlngs) 184 if self.color: result.append('strokeColor: "%s"' % self.color) 185 if self.weight: result.append('strokeWeight: "%s"' % self.weight) 186 if self.opacity: result.append('strokeOpacity: "%s"' % self.opacity) 187 return '{%s}' % ','.join(result) 167 188 168 189 169 class GI con(object):190 class GImage(object): 170 191 """ 171 Creates a GIcon object to pass into a Gmarker object. 192 Creates a GImage object to pass into a Gmarker object for the icon 193 and shadow arguments. The arguments are used to create a MarkerImage 194 class in the javascript: 172 195 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. 196 http://code.google.com/apis/maps/documentation/javascript/reference.html#MarkerImage 181 197 182 198 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. 199 200 url: 201 The url of the image to be used as the icon on the map 188 202 189 203 Keyword Options: 190 image:191 The url of the image to be used as the icon on the map defaults192 to 'G_DEFAULT_ICON'193 204 194 iconsize:205 size: 195 206 a tuple representing the pixel size of the foreground (not the 196 207 shadow) image of the icon, in the format: (width, height) ex.: 197 208 198 GIcon('fast_food', 199 image="/media/icon/star.png", 209 GImage("/media/icon/star.png", 200 210 iconsize=(15,10)) 201 211 202 212 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: 213 214 origin: 215 a tuple representing the pixel coordinate of the upper left corner 216 of the icon. Used in conjuction with the size option to specify 217 the sprite/subset of an image. In the format: (x,y) ex.: 218 219 3rd_marker = GImage("/media/icon/12_markers.png", 220 size=(15,10), 221 origin=(30,0)) 222 223 Would indicate the image where it's upper left corner is at (30,0) 224 and its lower right corner is (45,10). 225 226 anchor: 212 227 a tuple representing the pixel coordinate relative to the top left 213 228 corner of the icon image at which this icon is anchored to the map. 214 229 In (x, y) format. x increases to the right in the Google Maps 215 230 coordinate system and y increases downwards in the Google Maps 216 231 coordinate system.) 217 232 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. 233 """ 234 235 def __init__(self, url, size=None, origin=None, anchor=None): 236 self.url = url 237 self.size = size 238 self.origin = origin 239 self.anchor = anchor 221 240 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 def _to_param(self): 242 args = "(%s" % self.url 243 if self.size: 244 args += ", new google.maps.Size(%s)" % self.size 245 if self.origin: 246 args += ", new google.maps.Point(%s)" % self.origin 247 if self.anchor: 248 args += ", new google.maps.Point(%s)" % self.anchor 249 args += ")" 250 return "new google.maps.MarkerImage(%s)" % args 241 251 242 252 class GMarker(GOverlayBase): 243 253 """ 244 254 A Python wrapper for the Google GMarker object. For more information 245 255 please see the Google Maps API Reference: 246 http://code.google.com/apis/maps/documentation/ reference.html#GMarker256 http://code.google.com/apis/maps/documentation/javascript/reference.html#Marker 247 257 248 258 Example: 249 259 … … class GMarker(GOverlayBase): 258 268 return render_to_response('mytemplate.html', 259 269 {'google' : GoogleMap(markers=[marker])}) 260 270 """ 261 def __init__(self, geom, title=None, draggable=False, icon=None): 271 272 JS_CLASSNAME = 'Marker' 273 274 def __init__(self, geom, title=None, draggable=False, icon=None, shadow=None): 262 275 """ 263 276 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. 277 that may be instantiated into a GEOS point. 266 278 267 279 Keyword Options: 268 280 title: … … class GMarker(GOverlayBase): 270 282 271 283 draggable: 272 284 Draggable option for GMarker, disabled by default. 285 286 icon: 287 Sets the GImage used to display the marker on the map. 288 If not set google maps will use the default marker icon. 289 290 shadow: 291 Sets the GImage used to display the shadow of the marker on the map. 273 292 """ 274 293 # If a GEOS geometry isn't passed in, try to construct one. 275 294 if isinstance(geom, basestring): geom = fromstr(geom) … … class GMarker(GOverlayBase): 284 303 self.title = title 285 304 self.draggable = draggable 286 305 self.icon = icon 306 self.shadow = shadow 287 307 super(GMarker, self).__init__() 288 308 289 309 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) 310 return 'new google.maps.LatLng(%s,%s)' %(coords[1], coords[0]) 298 311 299 312 @property 300 313 def js_params(self): 301 return '%s, %s' % (self.latlng, self.options()) 314 result = [] 315 result.append('position: %s' % self.latlng) 316 if self.title: result.append('title: "%s"' % self.title) 317 if self.icon: result.append('icon: %s' % self.icon._to_param()) 318 if self.shadow: result.append('shadow: %s' % self.shadow_to_param()) 319 if self.draggable: result.append('draggable: true') 320 return '{%s}' % ','.join(result) -
django/contrib/gis/templates/gis/google/google-map.js
diff -r e6fd4804cf6f django/contrib/gis/templates/gis/google/google-map.js
a b 1 1 {% autoescape off %} 2 {% block vars %}var geodjango = {};{% for icon in icons %} 3 var {{ icon.varname }} = new GIcon(G_DEFAULT_ICON); 4 {% if icon.image %}{{ icon.varname }}.image = "{{ icon.image }}";{% endif %} 5 {% if icon.shadow %}{{ icon.varname }}.shadow = "{{ icon.shadow }}";{% endif %} {% if icon.shadowsize %}{{ icon.varname }}.shadowSize = new GSize({{ icon.shadowsize.0 }}, {{ icon.shadowsize.1 }});{% endif %} 6 {% 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 %} 7 {% if icon.infowindowanchor %}{{ icon.varname }}.infoWindowAnchor = new GPoint({{ icon.infowindowanchor.0 }}, {{ icon.infowindowanchor.1 }});{% endif %}{% endfor %} 2 {% block vars %}var geodjango = {}; 8 3 {% endblock vars %}{% block functions %} 9 4 {% block load %}{{ js_module }}.{{ dom_id }}_load = function(){ 10 if (GBrowserIsCompatible()) { 11 {{ js_module }}.{{ dom_id }} = new GMap2(document.getElementById("{{ dom_id }}")); 12 {{ js_module }}.{{ dom_id }}.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }}); 13 {% block controls %}{{ js_module }}.{{ dom_id }}.setUIToDefault();{% endblock %} 14 {% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% endif %} 15 {% for kml_url in kml_urls %}{{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }} = new GGeoXml("{{ kml_url }}"); 16 {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }});{% endfor %} 17 {% for polygon in polygons %}{{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }} = new {{ polygon }}; 18 {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }}); 19 {% for event in polygon.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %} 20 {% if calc_zoom %}tmp_bounds = {{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %} 21 {% for polyline in polylines %}{{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }} = new {{ polyline }}; 22 {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}); 23 {% for event in polyline.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %} 24 {% if calc_zoom %}tmp_bounds = {{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %} 25 {% for marker in markers %}{{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }} = new {{ marker }}; 26 {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}); 27 {% for event in marker.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %} 28 {% if calc_zoom %}bounds.extend({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}.getLatLng()); {% endif %}{% endfor %} 29 {% if calc_zoom %}{{ js_module }}.{{ dom_id }}.setCenter(bounds.getCenter(), {{ js_module }}.{{ dom_id }}.getBoundsZoomLevel(bounds));{% endif %} 30 {% block load_extra %}{% endblock %} 31 }else { 32 alert("Sorry, the Google Maps API is not compatible with this browser."); 5 var map_options = { 6 zoom: {{ zoom }}, 7 center: google.maps.LatLng({{ center.1 }}, {{ center.0 }}), 8 mapTypeId: google.maps.MapTypeId.ROADMAP 33 9 } 10 {{ js_module }}.{{ dom_id }} = new google.maps.Map(document.getElementById("{{ dom_id }}"), map_options); 11 {% block controls %}{% endblock %} 12 {% if calc_zoom %}var bounds = new google.maps.LatLngBounds(); var i; var j;{% endif %} 13 {% for kml_url in kml_urls %}{{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }} = new google.maps.KmlLayer("{{ kml_url }}"); 14 {{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }}.setMap({{ js_module }}.{{ dom_id }});{% endfor %} 15 {% for polygon in polygons %}{{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }} = new {{ polygon }}; 16 {{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }}.setMap({{ js_module }}.{{ dom_id }}); 17 {% for event in polygon.events %}google.event.addListener({{ js_module }}.{{ dom_id }}_poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %} 18 {% if calc_zoom %}paths={{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}.getPaths(); for(i=0; i<paths.length(); i++){ for(j=0; j<paths[i].length(); j++){ bounds.extend(paths[i][j]); }}{% endif %}{% endfor %} 19 {% for polyline in polylines %}{{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }} = new {{ polyline }}; 20 {{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}.setMap({{ js_module }}.{{ dom_id }}); 21 {% for event in polyline.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %} 22 {% if calc_zoom %}path={{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}.getPath(); for(i=0; i<path.length(); i++){ bounds.extend(path[i]); }{% endif %}{% endfor %} 23 {% for marker in markers %}{{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }} = new {{ marker }}; 24 {{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}.setMap({{ js_module }}.{{ dom_id }}); 25 {% for event in marker.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %} 26 {% if calc_zoom %}bounds.extend({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}.getPosition());{% endif %}{% endfor %} 27 {% if calc_zoom %}{{ js_module }}.{{ dom_id }}.fitBounds(bounds);{% endif %} 28 {% block load_extra %}{% endblock %} 34 29 } 35 30 {% endblock load %}{% endblock functions %}{% endautoescape %}