2 * Copyright (C) 2008 ZXing authors
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.google.zxing.web.generator.client;
19 import com.google.gwt.dom.client.Node;
20 import com.google.gwt.dom.client.NodeList;
21 import com.google.gwt.http.client.URL;
22 import com.google.gwt.maps.client.MapWidget;
23 import com.google.gwt.maps.client.control.SmallMapControl;
24 import com.google.gwt.maps.client.event.MapClickHandler;
25 import com.google.gwt.maps.client.event.MarkerDragEndHandler;
26 import com.google.gwt.maps.client.event.MapClickHandler.MapClickEvent;
27 import com.google.gwt.maps.client.geom.LatLng;
28 import com.google.gwt.maps.client.overlay.Marker;
29 import com.google.gwt.maps.client.overlay.MarkerOptions;
30 import com.google.gwt.user.client.ui.Button;
31 import com.google.gwt.user.client.ui.ChangeListener;
32 import com.google.gwt.user.client.ui.ClickListener;
33 import com.google.gwt.user.client.ui.Grid;
34 import com.google.gwt.user.client.ui.SimplePanel;
35 import com.google.gwt.user.client.ui.TextBox;
36 import com.google.gwt.user.client.ui.Widget;
39 * A generator for geo location. It also accepts a google maps links and
40 * extracts the coordinates and query from the URL.
42 * @author Yohann Coppel
44 public class GeoLocationGenerator implements GeneratorSource, ChangeListener {
45 private static final String LON_REGEXP = "[+-]?[0-9]+(.[0-9]+)?";
46 private static final String LAT_REGEXP = "[+-]?[0-9]+(.[0-9]+)?";
49 TextBox latitude = new TextBox();
50 TextBox longitude = new TextBox();
51 TextBox query = new TextBox();
52 TextBox mapsLink = new TextBox();
53 MapWidget map = new MapWidget();
54 Marker mapMarker = null;
55 private ChangeListener changeListener;
57 public GeoLocationGenerator(ChangeListener listener) {
58 this.changeListener = listener;
59 latitude.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
60 longitude.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
61 latitude.addChangeListener(listener);
62 latitude.addChangeListener(this);
63 longitude.addChangeListener(listener);
64 longitude.addChangeListener(this);
65 query.addChangeListener(listener);
68 public String getName() {
69 return "Geo location";
72 public String getText() throws GeneratorException {
73 String que = getQueryField();
74 if (null != que && que.length() > 0) {
75 if (null == getLatitudeField()) {
76 latitude.setText("0");
78 if (null == getLongitudeField()) {
79 longitude.setText("0");
82 String lat = getLatitudeField();
83 String lon = getLongitudeField();
85 if (que.length() > 0) {
86 return "geo:"+lat+","+lon+"?q="+que;
89 return "geo:"+lat+","+lon;
92 private String getQueryField() {
93 String que = query.getText();
94 que = que.replace("&", "%26");
98 private String getLongitudeField() throws GeneratorException {
99 String lon = longitude.getText();
100 if (!lon.matches(LON_REGEXP)) {
101 throw new GeneratorException("Longitude is not a correct value.");
103 double val = Double.parseDouble(lon);
104 if (val < -180 || val > 180) {
105 throw new GeneratorException("Longitude must be in [-180:180]");
110 private String getLatitudeField() throws GeneratorException {
111 String lat = latitude.getText();
112 if (!lat.matches(LAT_REGEXP)) {
113 throw new GeneratorException("Latitude is not a correct value.");
115 double val = Double.parseDouble(lat);
116 if (val < -90 || val > 90) {
117 throw new GeneratorException("Latitude must be in [-90:90]");
122 public Grid getWidget() {
126 table = new Grid(7, 2);
128 table.setText(0, 0, "Latitude");
129 table.setWidget(0, 1, latitude);
130 table.setText(1, 0, "Longitude");
131 table.setWidget(1, 1, longitude);
132 table.setText(2, 0, "Query");
133 table.setWidget(2, 1, query);
134 table.setText(3, 0, "OR");
135 table.setText(3, 1, "enter a Google Maps link and click Fill:");
137 // http://maps.google.com/?ie=UTF8&ll=40.741404,-74.00322&spn=0.001484,0.003101&z=18
138 Button fill = new Button("Fill ↑");
139 fill.addClickListener(new ClickListener() {
140 public void onClick(Widget sender) {
144 table.setWidget(4, 0, fill);
145 table.setWidget(4, 1, mapsLink);
147 map.setSize("256px", "256px");
148 map.addControl(new SmallMapControl());
149 map.addMapClickHandler(new MapClickHandler() {
150 public void onClick(MapClickEvent event) {
154 table.setText(5, 0, "OR");
155 table.setText(5, 1, "use the map to select a location:");
156 SimplePanel sp = new SimplePanel();
158 table.setWidget(6, 1, sp);
162 protected void mapClick(MapClickEvent event) {
163 latitude.setText("" + event.getLatLng().getLatitude());
164 longitude.setText("" + event.getLatLng().getLongitude());
165 setMapMarker(event.getLatLng().getLatitude(), event.getLatLng().getLongitude(), false);
166 changeListener.onChange(latitude);
167 changeListener.onChange(longitude);
170 protected void mapMarkerMoved() {
171 latitude.setText("" + mapMarker.getLatLng().getLatitude());
172 longitude.setText("" + mapMarker.getLatLng().getLongitude());
173 changeListener.onChange(latitude);
174 changeListener.onChange(longitude);
177 protected void setMapMarker(double lat, double lon, boolean zoomAndCenter) {
178 if (mapMarker != null) {
179 map.removeOverlay(mapMarker);
181 LatLng ll = LatLng.newInstance(lat, lon);
184 map.setZoomLevel(12);
186 if (mapMarker != null) {
187 mapMarker.setLatLng(ll);
189 MarkerOptions opt = MarkerOptions.newInstance();
190 opt.setDraggable(true);
191 mapMarker = new Marker(ll, opt);
192 mapMarker.addMarkerDragEndHandler(new MarkerDragEndHandler() {
193 public void onDragEnd(MarkerDragEndEvent event) {
198 map.addOverlay(mapMarker);
201 protected void fillWithMaps() {
202 String link = mapsLink.getText();
203 if (!link.matches("http://maps.google.com/.*")) {
207 if (link.matches(".*&q=[^&]*&.*")) {
208 for (int i = link.indexOf("&q=") + 3;
209 i < link.length() && link.charAt(i) != '&'; ++i) {
213 q = q.replace("+", " ");
214 q = q.replace("%26", "&");
219 if (link.matches(".*&s?ll=[^&]*&.*")) {
220 boolean beforeComa = true;
222 if (link.indexOf("&sll=") == -1) {
223 start = link.indexOf("&ll=") + 4;
225 start = link.indexOf("&sll=") + 5;
227 for (int i = start; i < link.length() && link.charAt(i) != '&'; ++i) {
229 if (link.charAt(i) == ',') {
232 lat += link.charAt(i);
235 lon += link.charAt(i);
240 query.setText(URL.decode(q));
241 latitude.setText(lat);
242 longitude.setText(lon);
243 changeListener.onChange(latitude);
244 changeListener.onChange(longitude);
245 this.onChange(latitude);
248 public void validate(Widget widget) throws GeneratorException {
249 if (widget == latitude) getLatitudeField();
250 if (widget == longitude) getLongitudeField();
253 public void setFocus() {
254 latitude.setFocus(true);
257 public void onChange(Widget sender) {
258 if (sender == latitude || sender == longitude) {
260 double lat = Double.parseDouble(getLatitudeField());
261 double lon = Double.parseDouble(getLongitudeField());
262 setMapMarker(lat, lon, true);
263 } catch (NumberFormatException e) {
264 } catch (GeneratorException e) {