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.event.dom.client.KeyPressHandler;
20 import com.google.gwt.http.client.URL;
21 import com.google.gwt.maps.client.MapWidget;
22 import com.google.gwt.maps.client.control.SmallMapControl;
23 import com.google.gwt.maps.client.event.MapClickHandler;
24 import com.google.gwt.maps.client.event.MarkerDragEndHandler;
25 import com.google.gwt.maps.client.event.MapClickHandler.MapClickEvent;
26 import com.google.gwt.maps.client.geom.LatLng;
27 import com.google.gwt.maps.client.overlay.Marker;
28 import com.google.gwt.maps.client.overlay.MarkerOptions;
29 import com.google.gwt.user.client.ui.Button;
30 import com.google.gwt.user.client.ui.ChangeListener;
31 import com.google.gwt.user.client.ui.ClickListener;
32 import com.google.gwt.user.client.ui.Grid;
33 import com.google.gwt.user.client.ui.SimplePanel;
34 import com.google.gwt.user.client.ui.TextBox;
35 import com.google.gwt.user.client.ui.Widget;
38 * A generator for geo location. It also accepts a google maps links and
39 * extracts the coordinates and query from the URL.
41 * @author Yohann Coppel
43 public class GeoLocationGenerator implements GeneratorSource, ChangeListener {
44 private static final String LON_REGEXP = "[+-]?[0-9]+(.[0-9]+)?";
45 private static final String LAT_REGEXP = "[+-]?[0-9]+(.[0-9]+)?";
48 TextBox latitude = new TextBox();
49 TextBox longitude = new TextBox();
50 TextBox query = new TextBox();
51 TextBox mapsLink = new TextBox();
52 MapWidget map = new MapWidget();
53 Marker mapMarker = null;
54 private ChangeListener changeListener;
56 public GeoLocationGenerator(ChangeListener listener,
57 KeyPressHandler keyListener) {
58 this.changeListener = listener;
59 latitude.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
60 latitude.addChangeListener(listener);
61 latitude.addChangeListener(this);
62 latitude.addKeyPressHandler(keyListener);
63 longitude.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
64 longitude.addChangeListener(listener);
65 longitude.addChangeListener(this);
66 longitude.addKeyPressHandler(keyListener);
67 query.addChangeListener(listener);
68 query.addKeyPressHandler(keyListener);
71 public String getName() {
72 return "Geo location";
75 public String getText() throws GeneratorException {
76 String que = getQueryField();
77 if (null != que && que.length() > 0) {
78 if (null == getLatitudeField()) {
79 latitude.setText("0");
81 if (null == getLongitudeField()) {
82 longitude.setText("0");
85 String lat = getLatitudeField();
86 String lon = getLongitudeField();
88 if (null != que && que.length() > 0) {
89 return "geo:"+lat+ ',' +lon+"?q="+que;
92 return "geo:"+lat+ ',' +lon;
95 private String getQueryField() {
96 String que = query.getText();
97 que = que.replace("&", "%26");
101 private String getLongitudeField() throws GeneratorException {
102 String lon = longitude.getText();
103 if (!lon.matches(LON_REGEXP)) {
104 throw new GeneratorException("Longitude is not a correct value.");
106 double val = Double.parseDouble(lon);
107 if (val < -180 || val > 180) {
108 throw new GeneratorException("Longitude must be in [-180:180]");
113 private String getLatitudeField() throws GeneratorException {
114 String lat = latitude.getText();
115 if (!lat.matches(LAT_REGEXP)) {
116 throw new GeneratorException("Latitude is not a correct value.");
118 double val = Double.parseDouble(lat);
119 if (val < -90 || val > 90) {
120 throw new GeneratorException("Latitude must be in [-90:90]");
125 public Grid getWidget() {
129 table = new Grid(7, 2);
131 table.setText(0, 0, "Latitude");
132 table.setWidget(0, 1, latitude);
133 table.setText(1, 0, "Longitude");
134 table.setWidget(1, 1, longitude);
135 table.setText(2, 0, "Query");
136 table.setWidget(2, 1, query);
137 table.setText(3, 0, "OR");
138 table.setText(3, 1, "enter a Google Maps link and click Fill:");
140 // http://maps.google.com/?ie=UTF8&ll=40.741404,-74.00322&spn=0.001484,0.003101&z=18
141 Button fill = new Button("Fill ↑");
142 fill.addClickListener(new ClickListener() {
143 public void onClick(Widget sender) {
147 table.setWidget(4, 0, fill);
148 table.setWidget(4, 1, mapsLink);
150 map.setSize("256px", "256px");
151 map.addControl(new SmallMapControl());
152 map.getElement().getStyle().setProperty("overflow", "hidden");
153 map.addMapClickHandler(new MapClickHandler() {
154 public void onClick(MapClickEvent event) {
158 table.setText(5, 0, "OR");
159 table.setText(5, 1, "use the map to select a location:");
160 SimplePanel sp = new SimplePanel();
162 table.setWidget(6, 1, sp);
166 protected void mapClick(MapClickEvent event) {
167 latitude.setText(String.valueOf(event.getLatLng().getLatitude()));
168 longitude.setText(String.valueOf(event.getLatLng().getLongitude()));
169 setMapMarker(event.getLatLng().getLatitude(), event.getLatLng().getLongitude(), false);
170 changeListener.onChange(latitude);
171 changeListener.onChange(longitude);
174 protected void mapMarkerMoved() {
175 latitude.setText(String.valueOf(mapMarker.getLatLng().getLatitude()));
176 longitude.setText(String.valueOf(mapMarker.getLatLng().getLongitude()));
177 changeListener.onChange(latitude);
178 changeListener.onChange(longitude);
181 protected void setMapMarker(double lat, double lon, boolean zoomAndCenter) {
182 if (mapMarker != null) {
183 map.removeOverlay(mapMarker);
185 LatLng ll = LatLng.newInstance(lat, lon);
188 map.setZoomLevel(12);
190 if (mapMarker != null) {
191 mapMarker.setLatLng(ll);
193 MarkerOptions opt = MarkerOptions.newInstance();
194 opt.setDraggable(true);
195 mapMarker = new Marker(ll, opt);
196 mapMarker.addMarkerDragEndHandler(new MarkerDragEndHandler() {
197 public void onDragEnd(MarkerDragEndEvent event) {
202 map.addOverlay(mapMarker);
205 protected void fillWithMaps() {
206 String link = mapsLink.getText();
207 if (!link.matches("http://maps.google.com/.*")) {
211 if (link.matches(".*&q=[^&]*&.*")) {
212 StringBuilder qBuilder = new StringBuilder();
213 for (int i = link.indexOf("&q=") + 3;
214 i < link.length() && link.charAt(i) != '&'; ++i) {
215 qBuilder.append(link.charAt(i));
217 q = qBuilder.toString();
219 q = q.replace("+", " ");
220 q = q.replace("%26", "&");
223 StringBuilder lat = new StringBuilder();
224 StringBuilder lon = new StringBuilder();
225 if (link.matches(".*&s?ll=[^&]*&.*")) {
227 if (link.indexOf("&sll=") == -1) {
228 start = link.indexOf("&ll=") + 4;
230 start = link.indexOf("&sll=") + 5;
232 boolean beforeComma = true;
233 for (int i = start; i < link.length() && link.charAt(i) != '&'; ++i) {
234 char c = link.charAt(i);
247 query.setText(URL.decode(q));
248 latitude.setText(lat.toString());
249 longitude.setText(lon.toString());
250 changeListener.onChange(latitude);
251 changeListener.onChange(longitude);
252 this.onChange(latitude);
255 public void validate(Widget widget) throws GeneratorException {
256 if (widget == latitude) {
259 if (widget == longitude) {
264 public void setFocus() {
265 latitude.setFocus(true);
268 public void onChange(Widget sender) {
269 if (sender == latitude || sender == longitude) {
271 double lat = Double.parseDouble(getLatitudeField());
272 double lon = Double.parseDouble(getLongitudeField());
273 setMapMarker(lat, lon, true);
274 } catch (NumberFormatException e) {
275 } catch (GeneratorException e) {