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.http.client.URL;
20 import com.google.gwt.maps.client.MapWidget;
21 import com.google.gwt.maps.client.control.SmallMapControl;
22 import com.google.gwt.maps.client.event.MapClickHandler;
23 import com.google.gwt.maps.client.event.MarkerDragEndHandler;
24 import com.google.gwt.maps.client.event.MapClickHandler.MapClickEvent;
25 import com.google.gwt.maps.client.geom.LatLng;
26 import com.google.gwt.maps.client.overlay.Marker;
27 import com.google.gwt.maps.client.overlay.MarkerOptions;
28 import com.google.gwt.user.client.ui.Button;
29 import com.google.gwt.user.client.ui.ChangeListener;
30 import com.google.gwt.user.client.ui.ClickListener;
31 import com.google.gwt.user.client.ui.Grid;
32 import com.google.gwt.user.client.ui.SimplePanel;
33 import com.google.gwt.user.client.ui.TextBox;
34 import com.google.gwt.user.client.ui.Widget;
37 * A generator for geo location. It also accepts a google maps links and
38 * extracts the coordinates and query from the URL.
40 * @author Yohann Coppel
42 public class GeoLocationGenerator implements GeneratorSource, ChangeListener {
43 private static final String LON_REGEXP = "[+-]?[0-9]+(.[0-9]+)?";
44 private static final String LAT_REGEXP = "[+-]?[0-9]+(.[0-9]+)?";
47 TextBox latitude = new TextBox();
48 TextBox longitude = new TextBox();
49 TextBox query = new TextBox();
50 TextBox mapsLink = new TextBox();
51 MapWidget map = new MapWidget();
52 Marker mapMarker = null;
53 private ChangeListener changeListener;
55 public GeoLocationGenerator(ChangeListener listener) {
56 this.changeListener = listener;
57 latitude.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
58 longitude.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
59 latitude.addChangeListener(listener);
60 latitude.addChangeListener(this);
61 longitude.addChangeListener(listener);
62 longitude.addChangeListener(this);
63 query.addChangeListener(listener);
66 public String getName() {
67 return "Geo location";
70 public String getText() throws GeneratorException {
71 String que = getQueryField();
72 if (null != que && que.length() > 0) {
73 if (null == getLatitudeField()) {
74 latitude.setText("0");
76 if (null == getLongitudeField()) {
77 longitude.setText("0");
80 String lat = getLatitudeField();
81 String lon = getLongitudeField();
83 if (null != que && que.length() > 0) {
84 return "geo:"+lat+ ',' +lon+"?q="+que;
87 return "geo:"+lat+ ',' +lon;
90 private String getQueryField() {
91 String que = query.getText();
92 que = que.replace("&", "%26");
96 private String getLongitudeField() throws GeneratorException {
97 String lon = longitude.getText();
98 if (!lon.matches(LON_REGEXP)) {
99 throw new GeneratorException("Longitude is not a correct value.");
101 double val = Double.parseDouble(lon);
102 if (val < -180 || val > 180) {
103 throw new GeneratorException("Longitude must be in [-180:180]");
108 private String getLatitudeField() throws GeneratorException {
109 String lat = latitude.getText();
110 if (!lat.matches(LAT_REGEXP)) {
111 throw new GeneratorException("Latitude is not a correct value.");
113 double val = Double.parseDouble(lat);
114 if (val < -90 || val > 90) {
115 throw new GeneratorException("Latitude must be in [-90:90]");
120 public Grid getWidget() {
124 table = new Grid(7, 2);
126 table.setText(0, 0, "Latitude");
127 table.setWidget(0, 1, latitude);
128 table.setText(1, 0, "Longitude");
129 table.setWidget(1, 1, longitude);
130 table.setText(2, 0, "Query");
131 table.setWidget(2, 1, query);
132 table.setText(3, 0, "OR");
133 table.setText(3, 1, "enter a Google Maps link and click Fill:");
135 // http://maps.google.com/?ie=UTF8&ll=40.741404,-74.00322&spn=0.001484,0.003101&z=18
136 Button fill = new Button("Fill ↑");
137 fill.addClickListener(new ClickListener() {
138 public void onClick(Widget sender) {
142 table.setWidget(4, 0, fill);
143 table.setWidget(4, 1, mapsLink);
145 map.setSize("256px", "256px");
146 map.addControl(new SmallMapControl());
147 map.getElement().getStyle().setProperty("overflow", "hidden");
148 map.addMapClickHandler(new MapClickHandler() {
149 public void onClick(MapClickEvent event) {
153 table.setText(5, 0, "OR");
154 table.setText(5, 1, "use the map to select a location:");
155 SimplePanel sp = new SimplePanel();
157 table.setWidget(6, 1, sp);
161 protected void mapClick(MapClickEvent event) {
162 latitude.setText(String.valueOf(event.getLatLng().getLatitude()));
163 longitude.setText(String.valueOf(event.getLatLng().getLongitude()));
164 setMapMarker(event.getLatLng().getLatitude(), event.getLatLng().getLongitude(), false);
165 changeListener.onChange(latitude);
166 changeListener.onChange(longitude);
169 protected void mapMarkerMoved() {
170 latitude.setText(String.valueOf(mapMarker.getLatLng().getLatitude()));
171 longitude.setText(String.valueOf(mapMarker.getLatLng().getLongitude()));
172 changeListener.onChange(latitude);
173 changeListener.onChange(longitude);
176 protected void setMapMarker(double lat, double lon, boolean zoomAndCenter) {
177 if (mapMarker != null) {
178 map.removeOverlay(mapMarker);
180 LatLng ll = LatLng.newInstance(lat, lon);
183 map.setZoomLevel(12);
185 if (mapMarker != null) {
186 mapMarker.setLatLng(ll);
188 MarkerOptions opt = MarkerOptions.newInstance();
189 opt.setDraggable(true);
190 mapMarker = new Marker(ll, opt);
191 mapMarker.addMarkerDragEndHandler(new MarkerDragEndHandler() {
192 public void onDragEnd(MarkerDragEndEvent event) {
197 map.addOverlay(mapMarker);
200 protected void fillWithMaps() {
201 String link = mapsLink.getText();
202 if (!link.matches("http://maps.google.com/.*")) {
206 if (link.matches(".*&q=[^&]*&.*")) {
207 for (int i = link.indexOf("&q=") + 3;
208 i < link.length() && link.charAt(i) != '&'; ++i) {
212 q = q.replace("+", " ");
213 q = q.replace("%26", "&");
218 if (link.matches(".*&s?ll=[^&]*&.*")) {
220 if (link.indexOf("&sll=") == -1) {
221 start = link.indexOf("&ll=") + 4;
223 start = link.indexOf("&sll=") + 5;
225 boolean beforeComma = true;
226 for (int i = start; i < link.length() && link.charAt(i) != '&'; ++i) {
228 if (link.charAt(i) == ',') {
231 lat += link.charAt(i);
234 lon += link.charAt(i);
239 query.setText(URL.decode(q));
240 latitude.setText(lat);
241 longitude.setText(lon);
242 changeListener.onChange(latitude);
243 changeListener.onChange(longitude);
244 this.onChange(latitude);
247 public void validate(Widget widget) throws GeneratorException {
248 if (widget == latitude) {
251 if (widget == longitude) {
256 public void setFocus() {
257 latitude.setFocus(true);
260 public void onChange(Widget sender) {
261 if (sender == latitude || sender == longitude) {
263 double lat = Double.parseDouble(getLatitudeField());
264 double lon = Double.parseDouble(getLongitudeField());
265 setMapMarker(lat, lon, true);
266 } catch (NumberFormatException e) {
267 } catch (GeneratorException e) {