[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Maposmatic-dev] [PATCH] Improve the bounding box selection in 'Create n
From: |
Gaël Utard |
Subject: |
[Maposmatic-dev] [PATCH] Improve the bounding box selection in 'Create new map' form. |
Date: |
Wed, 4 Aug 2010 17:08:12 +0200 |
Do not hide the bounding box drawn just after the mouse up event.
Do not zoom out when the form is displayed again because the
validation failed.
Do not validate the form if no bounding box was drawn.
Signed-off-by: Gaël Utard <address@hidden>
---
www/locale/fr/LC_MESSAGES/django.po | 31 +++++----
www/maposmatic/forms.py | 14 +++--
www/maposmatic/widgets.py | 57 ++++++++----------
www/media/osm_map.js | 114 +++++++++++++++++++++++------------
www/templates/maposmatic/new.html | 2 +-
5 files changed, 129 insertions(+), 89 deletions(-)
diff --git a/www/locale/fr/LC_MESSAGES/django.po
b/www/locale/fr/LC_MESSAGES/django.po
index 4d0d38a..e240d76 100644
--- a/www/locale/fr/LC_MESSAGES/django.po
+++ b/www/locale/fr/LC_MESSAGES/django.po
@@ -20,14 +20,14 @@ msgid ""
msgstr ""
"Project-Id-Version: mapOSMatic 0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-07-07 15:36+0200\n"
+"POT-Creation-Date: 2010-08-04 15:56+0200\n"
"PO-Revision-Date: 2009-12-26 20:47+0100\n"
"Last-Translator: Thomas Petazzoni <address@hidden>\n"
"Language-Team: FR <address@hidden>\n"
-"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
#: settings.py:199
msgid "No localization"
@@ -70,7 +70,7 @@ msgstr "Titre de la carte obligatoire"
msgid "Required"
msgstr "Obligatoire"
-#: maposmatic/forms.py:129
+#: maposmatic/forms.py:137
msgid "Bounding Box too large"
msgstr "Zone géographique trop grande"
@@ -183,8 +183,8 @@ msgid ""
"href=\"http://www.openstreetmap.org\">OpenStreetMap</a> and free\n"
"software contributor of Rennes area, France. From his idea, a group of\n"
"crazy <a\n"
-"href=\"http://en.wikipedia.org/wiki/Hacker_%28programmer_subculture"
-"%29\">hackers</a>\n"
+"href=\"http://en.wikipedia.org/wiki/Hacker_%28programmer_subculture%29"
+"\">hackers</a>\n"
"met together during a one-week <em>Hackfest</em> in August 2009 and\n"
"brought the idea of Gilles Lamiral to life by writing the code and\n"
"named the project <strong>MapOSMatic</strong>. The group of crazy\n"
@@ -515,13 +515,11 @@ msgid "MapOSMatic maps feed"
msgstr ""
#: templates/maposmatic/all_maps.html:51
-#, python-format
-msgid "No map starts with %(current_letter)s in our database!"
+msgid "Our database does not contain any rendered maps for the moment."
msgstr ""
-"Aucune carte ne commence par %(current_letter)s dans notre base de données !"
#: templates/maposmatic/all_maps.html:53
-msgid "Our database does not contain any rendered maps for the moment."
+msgid "No map matches your query."
msgstr ""
#: templates/maposmatic/base.html:57
@@ -811,16 +809,16 @@ msgid ""
"Latitude and longitude of the top left and bottom right corners of the area "
"to render."
msgstr ""
+"Latitude et longitude des coins supérieur gauche et inférieur droit de la "
+"zone à rendre."
#: templates/maposmatic/new.html:98
msgid ""
-"You can use <tt>Shift+drag</tt> to zoom on a specific area of the map. If "
-"you only want to render part of what the slippy map shows, you can use "
-"<tt>Control+drag</tt> to draw the limits of the area to render."
+"You can use <tt>Shift+drag</tt> to zoom on a specific area of the map. You "
+"can use <tt>Control+drag</tt> to draw the limits of the area to render."
msgstr ""
"Vous pouvez utiliser <tt>Shift+cliquer-déplacer</tt> pour zoomer sur une "
-"zone spécifique de la carte. Si vous ne souhaitez le rendu que d'une partie "
-"de ce qu'affiche la mini-carte, vous pouvez utiliser <tt>Contrôle+cliquer-"
+"zone spécifique de la carte. Vous pouvez utiliser <tt>Contrôle+cliquer-"
"déplacer</tt> pour tracer les limites de la zone à rendre."
#: templates/maposmatic/new.html:103
@@ -851,6 +849,11 @@ msgstr "Précédent"
msgid "Next"
msgstr "Suivant"
+#~ msgid "No map starts with %(current_letter)s in our database!"
+#~ msgstr ""
+#~ "Aucune carte ne commence par %(current_letter)s dans notre base de "
+#~ "données !"
+
#~ msgid "Page"
#~ msgstr "Page"
diff --git a/www/maposmatic/forms.py b/www/maposmatic/forms.py
index 621fe14..88543fe 100644
--- a/www/maposmatic/forms.py
+++ b/www/maposmatic/forms.py
@@ -111,9 +111,17 @@ class MapRenderingJobForm(forms.ModelForm):
val = cleaned_data.get(f)
if val is None:
msg = _(u"Required")
- self._errors[f] = forms.util.ErrorList([msg])
+ self._errors['bbox'] = forms.util.ErrorList([msg])
del cleaned_data[f]
+ # Make sure that bbox and admin modes are exclusive
+ cleaned_data["administrative_city"] = ''
+ cleaned_data["administrative_osmid"] = None
+
+ # Don't try to instanciate a bounding box with empty coordinates
+ if self._errors:
+ return cleaned_data
+
lat_upper_left = cleaned_data.get("lat_upper_left")
lon_upper_left = cleaned_data.get("lon_upper_left")
lat_bottom_right = cleaned_data.get("lat_bottom_right")
@@ -129,10 +137,6 @@ class MapRenderingJobForm(forms.ModelForm):
msg = _(u"Bounding Box too large")
self._errors['bbox'] = forms.util.ErrorList([msg])
- # Make sure that bbox and admin modes are exclusive
- cleaned_data["administrative_city"] = ''
- cleaned_data["administrative_osmid"] = None
-
return cleaned_data
class MapRecreateForm(forms.Form):
diff --git a/www/maposmatic/widgets.py b/www/maposmatic/widgets.py
index 8c502f0..265d6d8 100644
--- a/www/maposmatic/widgets.py
+++ b/www/maposmatic/widgets.py
@@ -41,30 +41,20 @@ class AreaWidget(forms.TextInput):
def render(self, name, value, attrs=None):
"""
- Render a map
+ Render the bbox selection widget.
"""
- upper_left_lat, upper_left_lon = 0, 0
- lower_right_lat, lower_right_lon = 0, 0
-
+ # Initially the widget shows no bounding box and shows an area that
+ # contains the France
if value:
- if len(value) == 2:
- upper_left = value[0]
- lower_right = value[1]
- if hasattr(upper_left, 'x') and hasattr(upper_left, 'y'):
- upper_left_lon = str(upper_left.x)
- upper_left_lat = str(upper_left.y)
- elif len(upper_left) == 2:
- upper_left_lon = upper_left[1]
- upper_left_lat = upper_left[0]
- if hasattr(lower_right, 'x') and hasattr(lower_right, 'y'):
- lower_right_lon = str(lower_right.x)
- lower_right_lat = str(lower_right.y)
- elif len(lower_right) == 2:
- lower_right_lon = lower_right[1]
- lower_right_lat = lower_right[0]
+ upper_left_lat, upper_left_lon, \
+ lower_right_lat, lower_right_lon = value[0]
+ area_upper_left_lat, area_upper_left_lon, \
+ area_lower_right_lat, area_lower_right_lon = value[1]
else:
upper_left_lat, upper_left_lon, \
- lower_right_lat, lower_right_lon = settings.BASE_BOUNDING_BOX
+ lower_right_lat, lower_right_lon = '', '', '', ''
+ area_upper_left_lat, area_upper_left_lon, \
+ area_lower_right_lat, area_lower_right_lon =
settings.BASE_BOUNDING_BOX
tpl = u"""<div id="map"></div>
<div id="map_bb">
@@ -81,8 +71,20 @@ class AreaWidget(forms.TextInput):
<input type="text" name="lon_bottom_right" id="lon_bottom_right"
onchange="updateMap();" value="%(br_lon)s"
title="%(br_lon_help)s" />
+ <input type="hidden" name="area_lat_upper_left"
+ id="area_lat_upper_left" value="%(area_tl_lat)s">
+ <input type="hidden" name="area_lon_upper_left"
+ id="area_lon_upper_left" value="%(area_tl_lon)s">
+ <input type="hidden" name="area_lat_bottom_right"
+ id="area_lat_bottom_right" value="%(area_br_lat)s">
+ <input type="hidden" name="area_lon_bottom_right"
+ id="area_lon_bottom_right" value="%(area_br_lon)s">
</div>""" % {'tl_lat': upper_left_lat, 'tl_lon': upper_left_lon,
'br_lat': lower_right_lat, 'br_lon': lower_right_lon,
+ 'area_tl_lat': area_upper_left_lat,
+ 'area_tl_lon': area_upper_left_lon,
+ 'area_br_lat': area_lower_right_lat,
+ 'area_br_lon': area_lower_right_lon,
'tl_lat_help': _("Latitude of the top left corner"),
'tl_lon_help': _("Longitude of the top left corner"),
'br_lat_help': _("Latitude of the bottom right corner"),
@@ -94,17 +96,10 @@ class AreaWidget(forms.TextInput):
"""
Return the appropriate values
"""
- values = []
- for keys in (('lat_upper_left', 'lon_upper_left',),
- ('lat_bottom_right', 'lon_bottom_right')):
- value = []
- for key in keys:
- val = data.get(key, None)
- if not val:
- return []
- value.append(val)
- values.append(value)
- return values
+ return ((data['lat_upper_left'], data['lon_upper_left'],
+ data['lat_bottom_right'], data['lon_bottom_right']),
+ (data['area_lat_upper_left'], data['area_lon_upper_left'],
+ data['area_lat_bottom_right'], data['area_lon_bottom_right']))
class AreaField(forms.MultiValueField):
'''
diff --git a/www/media/osm_map.js b/www/media/osm_map.js
index f785a17..f3f6bc1 100644
--- a/www/media/osm_map.js
+++ b/www/media/osm_map.js
@@ -31,48 +31,74 @@ var map = null;
var update_lock = 0;
var epsg_display_projection = new OpenLayers.Projection('EPSG:4326');
var epsg_projection = new OpenLayers.Projection('EPSG:900913');
+var bbox_style = {fill: true, fillColor: "#FFFFFF", fillOpacity: 0.5,
+ stroke: true, strokeOpacity: 0.8, strokeColor: "#FF0000", strokeWidth: 2};
function getUpperLeftLat() { return document.getElementById('lat_upper_left');
}
function getUpperLeftLon() { return document.getElementById('lon_upper_left');
}
function getBottomRightLat() { return
document.getElementById('lat_bottom_right'); }
function getBottomRightLon() { return
document.getElementById('lon_bottom_right'); }
+function getAreaUpperLeftLat() { return
document.getElementById('area_lat_upper_left'); }
+function getAreaUpperLeftLon() { return
document.getElementById('area_lon_upper_left'); }
+function getAreaBottomRightLat() { return
document.getElementById('area_lat_bottom_right'); }
+function getAreaBottomRightLon() { return
document.getElementById('area_lon_bottom_right'); }
-function updateFormWithLonLats(topleft, bottomright)
+/* Update form fields on bbox drawing. */
+function updateFormBbox(bounds)
{
- topleft = topleft.transform(epsg_projection, epsg_display_projection);
- bottomright = bottomright.transform(epsg_projection,
epsg_display_projection);
+ bounds = bounds.transform(epsg_projection, epsg_display_projection);
- getUpperLeftLat().value = topleft.lat.toFixed(4);
- getUpperLeftLon().value = topleft.lon.toFixed(4);
- getBottomRightLat().value = bottomright.lat.toFixed(4);
- getBottomRightLon().value = bottomright.lon.toFixed(4);
-}
-
-/** Map Zoom/Move events callback: update form fields on zoom action. */
-function updateForm()
-{
- if (update_lock)
- return;
-
- var bounds = map.getExtent();
- updateFormWithLonLats(new OpenLayers.LonLat(bounds.left, bounds.top),
- new OpenLayers.LonLat(bounds.right, bounds.bottom));
+ getUpperLeftLat().value = bounds.top.toFixed(4);
+ getUpperLeftLon().value = bounds.left.toFixed(4);
+ getBottomRightLat().value = bounds.bottom.toFixed(4);
+ getBottomRightLon().value = bounds.right.toFixed(4);
}
/* Update the map on form field modification. */
-function updateMap()
+function updateMap(vectorLayer)
{
- var bounds = new OpenLayers.Bounds(getUpperLeftLon().value,
- getUpperLeftLat().value,
- getBottomRightLon().value,
- getBottomRightLat().value);
+ if (getUpperLeftLon().value!="" && getUpperLeftLat().value!="" &&
+ getBottomRightLon().value!="" && getBottomRightLat().value!="")
+ {
+ var bbox_bounds = new OpenLayers.Bounds(
+ getUpperLeftLon().value, getUpperLeftLat().value,
+ getBottomRightLon().value, getBottomRightLat().value);
+ bbox_bounds.transform(epsg_display_projection, epsg_projection);
+ var feature = new OpenLayers.Feature.Vector(
+ bbox_bounds.toGeometry(), {}, bbox_style);
+ vectorLayer.addFeatures(feature);
+ closest = true
+ }
+ else
+ {
+ closest = false
+ }
+
+ var bounds = new OpenLayers.Bounds(getAreaUpperLeftLon().value,
+ getAreaUpperLeftLat().value,
+ getAreaBottomRightLon().value,
+ getAreaBottomRightLat().value);
bounds.transform(epsg_display_projection, epsg_projection);
update_lock = 1;
- map.zoomToExtent(bounds);
+ map.zoomToExtent(bounds, closest);
update_lock = 0;
}
+/** Map Zoom/Move events callback: update form fields on zoom action. */
+function updateFormArea()
+{
+ if (update_lock)
+ return;
+
+ var bounds = map.getExtent();
+ bounds = bounds.transform(epsg_projection, epsg_display_projection);
+ getAreaUpperLeftLat().value = bounds.top.toFixed(4);
+ getAreaUpperLeftLon().value = bounds.left.toFixed(4);
+ getAreaBottomRightLat().value = bounds.bottom.toFixed(4);
+ getAreaBottomRightLon().value = bounds.right.toFixed(4);
+}
+
/* Main initialisation function. Must be called before the map is manipulated.
*/
function mapInit()
{
@@ -90,25 +116,37 @@ function mapInit()
layerTilesMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
map.addLayer(layerTilesMapnik);
+ var vectorLayer = new OpenLayers.Layer.Vector("Overlay");
+ map.addLayer(vectorLayer);
+
var selectControl = new OpenLayers.Control();
OpenLayers.Util.extend(selectControl, {
- draw: function() {
- this.box = new OpenLayers.Handler.Box(selectControl,
- {'done': this.notice}, {keyMask: OpenLayers.Handler.MOD_CTRL});
- this.box.activate();
- },
-
- notice: function(bounds) {
- updateFormWithLonLats(
- map.getLonLatFromPixel(new OpenLayers.Pixel(bounds.left,
bounds.top)),
- map.getLonLatFromPixel(new OpenLayers.Pixel(bounds.right,
bounds.bottom)));
- }
+ draw: function() {
+ this.box = new OpenLayers.Handler.Box(selectControl,
+ {'done': this.notice}, {keyMask: OpenLayers.Handler.MOD_CTRL});
+ this.box.activate();
+ },
+
+ notice: function(pxbounds) {
+ ltpixel = map.getLonLatFromPixel(
+ new OpenLayers.Pixel(pxbounds.left, pxbounds.top));
+ rbpixel = map.getLonLatFromPixel(
+ new OpenLayers.Pixel(pxbounds.right, pxbounds.bottom));
+ bounds = new OpenLayers.Bounds();
+ bounds.extend(ltpixel);
+ bounds.extend(rbpixel);
+ var feature = new OpenLayers.Feature.Vector(
+ bounds.toGeometry(), {}, bbox_style);
+ vectorLayer.destroyFeatures()
+ vectorLayer.addFeatures(feature);
+ updateFormBbox(bounds);
+ }
});
map.addControl(selectControl);
- map.events.register('zoomend', map, updateForm);
- map.events.register('moveend', map, updateForm);
- updateMap();
+ map.events.register('zoomend', map, updateFormArea);
+ map.events.register('moveend', map, updateFormArea);
+ updateMap(vectorLayer);
}
function setFormActivation(active) {
diff --git a/www/templates/maposmatic/new.html
b/www/templates/maposmatic/new.html
index a179c84..a883598 100644
--- a/www/templates/maposmatic/new.html
+++ b/www/templates/maposmatic/new.html
@@ -95,7 +95,7 @@ map.{% endblocktrans %}
{{ form.bbox }}
{{ form.bbox.errors }}
<p class="bbox_select_help">{% blocktrans %}Latitude and longitude of
the top left and bottom right corners of the area to render.{% endblocktrans
%}</p>
- <p class="bbox_select_help">{% blocktrans %}You can use
<tt>Shift+drag</tt> to zoom on a specific area of the map. If you only want to
render part of what the slippy map shows, you can use <tt>Control+drag</tt> to
draw the limits of the area to render.{% endblocktrans %}</p>
+ <p class="bbox_select_help">{% blocktrans %}You can use
<tt>Shift+drag</tt> to zoom on a specific area of the map. You can use
<tt>Control+drag</tt> to draw the limits of the area to render.{% endblocktrans
%}</p>
</td></tr>
<tr><td class="submit">
--
1.7.0.4
- [Maposmatic-dev] [PATCH] Improve the bounding box selection in 'Create new map' form.,
Gaël Utard <=