Allow the + character in phone numbers. In the same time, fix a bug where other non...
[zxing.git] / zxing.appspot.com / generator / src / com / google / zxing / web / generator / client / GeoLocationGenerator.java
1 /*
2  * Copyright (C) 2008 ZXing authors
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.google.zxing.web.generator.client;
18
19 import com.google.gwt.http.client.URL;
20 import com.google.gwt.user.client.ui.Button;
21 import com.google.gwt.user.client.ui.ChangeListener;
22 import com.google.gwt.user.client.ui.ClickListener;
23 import com.google.gwt.user.client.ui.Grid;
24 import com.google.gwt.user.client.ui.TextBox;
25 import com.google.gwt.user.client.ui.Widget;
26
27 /**
28  * A generator for geo location. It also accepts a google maps links and
29  * extracts the coordinates and query from the URL.
30  * 
31  * @author Yohann Coppel
32  */
33 public class GeoLocationGenerator implements GeneratorSource {
34   private static final String LON_REGEXP = "[+-]?[0-9]+(.[0-9]+)?";
35   private static final String LAT_REGEXP = "[+-]?[0-9]+(.[0-9]+)?";
36   
37   Grid table = null;
38   TextBox latitude = new TextBox();
39   TextBox longitude = new TextBox();
40   TextBox query = new TextBox();
41   TextBox mapsLink = new TextBox();
42   
43   public GeoLocationGenerator(ChangeListener listener) {
44     latitude.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
45     longitude.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
46     latitude.addChangeListener(listener);
47     longitude.addChangeListener(listener);
48     query.addChangeListener(listener);
49   }
50   
51   public String getName() {
52     return "Geo location";
53   }
54
55   public String getText() throws GeneratorException {
56     String que = getQueryField();
57     if (null != que && que.length() > 0) {
58       if (null == getLatitudeField()) {
59         latitude.setText("0");
60       }
61       if (null == getLongitudeField()) {
62         longitude.setText("0");
63       }
64     }
65     String lat = getLatitudeField();
66     String lon = getLongitudeField();
67     
68     if (que.length() > 0) {
69       return "geo:"+lat+","+lon+"?q="+que;
70     }
71
72     return "geo:"+lat+","+lon;
73   }
74
75   private String getQueryField() {
76     String que = query.getText();
77     que = que.replace("&", "%26");
78     return que;
79   }
80
81   private String getLongitudeField() throws GeneratorException {
82     String lon = longitude.getText();
83     if (!lon.matches(LON_REGEXP)) {
84       throw new GeneratorException("Longitude is not a correct value.");
85     }
86     double val = Double.parseDouble(lon);
87     if (val < -180 || val > 180) {
88       throw new GeneratorException("Longitude must be in [-180:180]");
89     }
90     return lon;
91   }
92
93   private String getLatitudeField() throws GeneratorException {
94     String lat = latitude.getText();
95     if (!lat.matches(LAT_REGEXP)) {
96       throw new GeneratorException("Latitude is not a correct value.");
97     }
98     double val = Double.parseDouble(lat);
99     if (val < -90 || val > 90) {
100       throw new GeneratorException("Latitude must be in [-90:90]");
101     }
102     return lat;
103   }
104
105   public Grid getWidget() {
106     if (table != null) {
107       return table;
108     }
109     table = new Grid(5, 2);
110     
111     table.setText(0, 0, "Latitude");
112     table.setWidget(0, 1, latitude);
113     table.setText(1, 0, "Longitude");
114     table.setWidget(1, 1, longitude);
115     table.setText(2, 0, "Query");
116     table.setWidget(2, 1, query);
117     table.setText(3, 0, "OR");
118     table.setText(3, 1, "enter a Google Maps link and click Fill:");
119     // looks like this:
120     // http://maps.google.com/?ie=UTF8&ll=40.741404,-74.00322&spn=0.001484,0.003101&z=18
121     Button fill = new Button("Fill &uarr;");
122     fill.addClickListener(new ClickListener() {
123       public void onClick(Widget sender) {
124         fillWithMaps();
125       }
126     });
127     table.setWidget(4, 0, fill);
128     table.setWidget(4, 1, mapsLink);
129     
130     return table;
131   }
132
133   protected void fillWithMaps() {
134     String link = mapsLink.getText();
135     if (!link.matches("http://maps.google.com/.*")) {
136       return;
137     }
138     String q = "";
139     if (link.matches(".*&q=[^&]*&.*")) {
140       for (int i = link.indexOf("&q=") + 3;
141           i < link.length() && link.charAt(i) != '&'; ++i) {
142         q += link.charAt(i);
143       }
144       // special cases:
145       q = q.replace("+", " ");
146       q = q.replace("%26", "&");
147     }
148     
149     String lat = "";
150     String lon = "";
151     if (link.matches(".*&s?ll=[^&]*&.*")) {
152       boolean beforeComa = true;
153       int start = 0;
154       if (link.indexOf("&sll=") == -1) {
155         start = link.indexOf("&ll=") + 4;
156       } else {
157         start = link.indexOf("&sll=") + 5;
158       }
159       for (int i = start; i < link.length() && link.charAt(i) != '&'; ++i) {
160         if (beforeComa) {
161           if (link.charAt(i) == ',') {
162             beforeComa = false;
163           } else {
164             lat += link.charAt(i); 
165           }
166         } else {
167           lon += link.charAt(i);
168         }
169       }
170     }
171     
172     query.setText(URL.decode(q));
173     latitude.setText(lat);
174     longitude.setText(lon);
175   }
176
177   public void validate(Widget widget) throws GeneratorException {
178     if (widget == latitude) getLatitudeField();
179     if (widget == longitude) getLongitudeField();
180   }
181
182   public void setFocus() {
183     latitude.setFocus(true);
184   }
185 }