1.1 --- a/geo/pom.xml Tue Jul 09 08:08:36 2013 +0200
1.2 +++ b/geo/pom.xml Tue Jul 09 09:09:13 2013 +0200
1.3 @@ -37,5 +37,11 @@
1.4 <artifactId>org-openide-util-lookup</artifactId>
1.5 <type>jar</type>
1.6 </dependency>
1.7 + <dependency>
1.8 + <groupId>org.apidesign.html</groupId>
1.9 + <artifactId>net.java.html.boot</artifactId>
1.10 + <version>0.4-SNAPSHOT</version>
1.11 + <type>jar</type>
1.12 + </dependency>
1.13 </dependencies>
1.14 </project>
2.1 --- a/geo/src/main/java/net/java/html/geo/Position.java Tue Jul 09 08:08:36 2013 +0200
2.2 +++ b/geo/src/main/java/net/java/html/geo/Position.java Tue Jul 09 09:09:13 2013 +0200
2.3 @@ -20,32 +20,82 @@
2.4 */
2.5 package net.java.html.geo;
2.6
2.7 -/**
2.8 +import java.util.logging.Level;
2.9 +import java.util.logging.Logger;
2.10 +import org.apidesign.html.geo.impl.JsG;
2.11 +
2.12 +/** Class that represents a geolocation position provided as a callback
2.13 + * to {@link Handle#onLocation(net.java.html.geo.Position)} method. The
2.14 + * class getters mimic closely the structure of the position object as
2.15 + * specified by <a href="http://www.w3.org/TR/2012/PRgeolocationAPI20120510/">
2.16 + * W3C's Geolocation API</a>.
2.17 *
2.18 * @author Jaroslav Tulach <jtulach@netbeans.org>
2.19 */
2.20 public final class Position {
2.21 - Position() {
2.22 + static final Logger LOG = Logger.getLogger(Position.class.getName());
2.23 + private final long timestamp;
2.24 + private final Coordinates coords;
2.25 +
2.26 + Position(Object position) {
2.27 + Object obj = JsG.get(position, "timestamp");
2.28 + timestamp = obj instanceof Number ? ((Number)obj).longValue() : 0L;
2.29 + coords = new Coordinates(JsG.get(position, "coords"));
2.30 + }
2.31 +
2.32 + /** The actual location of the position.
2.33 + * @return non-null coordinates
2.34 + */
2.35 + public Coordinates getCoords() {
2.36 + return coords;
2.37 + }
2.38 +
2.39 + /** The time when the position has been recorded.
2.40 + * @return time in milliseconds since era (e.g. Jan 1, 1970).
2.41 + */
2.42 + public long getTimestamp() {
2.43 + return timestamp;
2.44 }
2.45
2.46 - public Coordinates getCoords() {
2.47 - return null;
2.48 - }
2.49 -
2.50 - public long getTimestamp() {
2.51 - return 0L;
2.52 - }
2.53 -
2.54 + /** Actual location of a {@link Position}.
2.55 + * Mimics closely <a href="http://www.w3.org/TR/2012/PRgeolocationAPI20120510/">
2.56 + * W3C's Geolocation API</a>.
2.57 + */
2.58 public static final class Coordinates {
2.59 - private double latitude;
2.60 - private double longitude;
2.61 - private double accuracy;
2.62 + private final Object data;
2.63
2.64 - private Double altitude;
2.65 - private Double altitudeAccuracy;
2.66 - private Double heading;
2.67 - private Double speed;
2.68 - }
2.69 + Coordinates(Object data) {
2.70 + this.data = data;
2.71 + }
2.72 +
2.73 + public double getLatitude() {
2.74 + return ((Number)JsG.get(data, "latitude")).doubleValue(); // NOI18N
2.75 + }
2.76 +
2.77 + public double getLongitude() {
2.78 + return ((Number)JsG.get(data, "longitude")).doubleValue(); // NOI18N
2.79 + }
2.80 +
2.81 + public double getAccuracy() {
2.82 + return ((Number)JsG.get(data, "accuracy")).doubleValue(); // NOI18N
2.83 + }
2.84 +
2.85 + public Double getAltitude() {
2.86 + return (Double)JsG.get(data, "altitude"); // NOI18N
2.87 + }
2.88 +
2.89 + public Double getAltitudeAccuracy() {
2.90 + return (Double)JsG.get(data, "altitudeAccuracy"); // NOI18N
2.91 + }
2.92 +
2.93 + public Double getHeading() {
2.94 + return (Double)JsG.get(data, "heading"); // NOI18N
2.95 + }
2.96 +
2.97 + public Double getSpeed() {
2.98 + return (Double)JsG.get(data, "speed"); // NOI18N
2.99 + }
2.100 + } // end of Coordinates
2.101
2.102 /** Rather than subclassing this class directly consider using {@link OnLocation}
2.103 * annotation. Such annotation will generate a subclass for you automatically
2.104 @@ -53,11 +103,11 @@
2.105 * which can be used to obtain instance of this class.
2.106 */
2.107 public static abstract class Handle {
2.108 -
2.109 private final boolean oneTime;
2.110 private boolean enableHighAccuracy;
2.111 private long timeout;
2.112 private long maximumAge;
2.113 + volatile JsH handle;
2.114
2.115 /** Creates new instance of this handle.
2.116 *
2.117 @@ -87,7 +137,7 @@
2.118 * W3C's Geolocation API</a>. By default the mode is disabled.
2.119 * @param enable <code>true</code> or <code>false</code>
2.120 */
2.121 - public void setHighAccuracy(boolean enable) {
2.122 + public final void setHighAccuracy(boolean enable) {
2.123 this.enableHighAccuracy = enable;
2.124 }
2.125
2.126 @@ -95,7 +145,7 @@
2.127 * By default infinity.
2.128 * @param timeout time in milliseconds to wait for a result.
2.129 */
2.130 - public void setTimeout(long timeout) {
2.131 + public final void setTimeout(long timeout) {
2.132 this.timeout = timeout;
2.133 }
2.134
2.135 @@ -103,20 +153,74 @@
2.136 * returned. By default maximum age is set to zero.
2.137 * @param age time in milliseconds of acceptable cached results
2.138 */
2.139 - public void setMaximumAge(long age) {
2.140 + public final void setMaximumAge(long age) {
2.141 this.maximumAge = age;
2.142 }
2.143
2.144 /** Initializes the <em>query</em> or <em>watch</em> request(s) and
2.145 - * returns immediately.
2.146 + * returns immediately. Has no effect if the query has already been
2.147 + * started.
2.148 */
2.149 - public void start() {
2.150 + public final void start() {
2.151 + if (handle != null) {
2.152 + return;
2.153 + }
2.154 + handle = new JsH();
2.155 + handle.start();
2.156 }
2.157
2.158 /** Stops all pending requests. After this call no further callbacks
2.159 - * can be obtained.
2.160 + * can be obtained. Does nothing if no query or watch was in progress.
2.161 */
2.162 - public void stop() {
2.163 + public final void stop() {
2.164 + JsH h = handle;
2.165 + if (h == null) {
2.166 + return;
2.167 + }
2.168 + handle = null;
2.169 + h.stop();
2.170 + }
2.171 +
2.172 + private final class JsH extends JsG {
2.173 + long watch;
2.174 +
2.175 + @Override
2.176 + public void onLocation(Object position) {
2.177 + if (handle != this) {
2.178 + return;
2.179 + }
2.180 + if (oneTime) {
2.181 + stop();
2.182 + }
2.183 + try {
2.184 + Handle.this.onLocation(new Position(position));
2.185 + } catch (Throwable ex) {
2.186 + LOG.log(Level.SEVERE, null, ex);
2.187 + }
2.188 + }
2.189 +
2.190 + @Override
2.191 + public void onError(Object error) {
2.192 + if (handle != this) {
2.193 + return;
2.194 + }
2.195 + if (oneTime) {
2.196 + stop();
2.197 + }
2.198 + try {
2.199 + Handle.this.onError(new Exception());
2.200 + } catch (Throwable ex) {
2.201 + LOG.log(Level.SEVERE, null, ex);
2.202 + }
2.203 + }
2.204 +
2.205 + final void start() {
2.206 + watch = start(oneTime, enableHighAccuracy, timeout, maximumAge);
2.207 + }
2.208 +
2.209 + protected final void stop() {
2.210 + super.stop(watch);
2.211 + }
2.212 }
2.213 }
2.214 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/geo/src/main/java/org/apidesign/html/geo/impl/JsG.java Tue Jul 09 09:09:13 2013 +0200
3.3 @@ -0,0 +1,80 @@
3.4 +/**
3.5 + * HTML via Java(tm) Language Bindings
3.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.7 + *
3.8 + * This program is free software: you can redistribute it and/or modify
3.9 + * it under the terms of the GNU General Public License as published by
3.10 + * the Free Software Foundation, version 2 of the License.
3.11 + *
3.12 + * This program is distributed in the hope that it will be useful,
3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.15 + * GNU General Public License for more details. apidesign.org
3.16 + * designates this particular file as subject to the
3.17 + * "Classpath" exception as provided by apidesign.org
3.18 + * in the License file that accompanied this code.
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License
3.21 + * along with this program. Look for COPYING file in the top folder.
3.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
3.23 + */
3.24 +package org.apidesign.html.geo.impl;
3.25 +
3.26 +import net.java.html.js.JavaScriptBody;
3.27 +
3.28 +/** Implementation class to deal with browser's <code>navigator.geolocation</code>
3.29 + * object.
3.30 + *
3.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
3.32 + */
3.33 +public abstract class JsG {
3.34 + protected JsG() {
3.35 + if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
3.36 + throw new IllegalStateException();
3.37 + }
3.38 + }
3.39 +
3.40 + public abstract void onLocation(Object position);
3.41 + public abstract void onError(Object error);
3.42 +
3.43 + @JavaScriptBody(
3.44 + args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" },
3.45 + javacall = true,
3.46 + body =
3.47 + "var self = this;" +
3.48 + "var ok = function (position) {" +
3.49 + " self.@org.apidesign.html.geo.impl.GeoImpl::onLocation(Ljava/lang/Object;)(position);" +
3.50 + "};" +
3.51 + "var fail = function (error) {" +
3.52 + " self.@org.apidesign.html.geo.impl.GeoImpl::onError(Ljava/lang/Object;)(error);" +
3.53 + "};" +
3.54 + "var options = {};" +
3.55 + "options.enableHighAccuracy = enableHighAccuracy;" +
3.56 + "if (timeout >= 0) options.timeout = timeout;" +
3.57 + "if (maximumAge >= 0) options.maximumAge = maximumAge;" +
3.58 + "if (onlyOnce) {" +
3.59 + " navigator.geolocation.getCurrentPosition(ok, fail);" +
3.60 + " return 0;" +
3.61 + "} else {" +
3.62 + " return navigator.geolocation.watchPosition(ok, fail);" +
3.63 + "}"
3.64 + )
3.65 + protected long start(
3.66 + boolean onlyOnce,
3.67 + boolean enableHighAccuracy,
3.68 + long timeout,
3.69 + long maximumAge
3.70 + ) {
3.71 + return -1;
3.72 + }
3.73 +
3.74 + @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
3.75 + protected void stop(long watch) {
3.76 + }
3.77 +
3.78 + @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
3.79 + public static Object get(Object self, String property) {
3.80 + return null;
3.81 + }
3.82 +
3.83 +}
4.1 --- a/geo/src/test/java/net/java/html/geo/OnLocationTest.java Tue Jul 09 08:08:36 2013 +0200
4.2 +++ b/geo/src/test/java/net/java/html/geo/OnLocationTest.java Tue Jul 09 09:09:13 2013 +0200
4.3 @@ -44,7 +44,7 @@
4.4 @Test public void onLocationHandleCallback() throws Throwable {
4.5 net.java.html.geo.Position.Handle h = OnLocationHandle.createQuery();
4.6 cnt = 0;
4.7 - h.onLocation(new Position());
4.8 + h.onLocation(new Position(null));
4.9 assertEquals(cnt, 1, "The callback has been made");
4.10 }
4.11
4.12 @@ -82,7 +82,7 @@
4.13 @Test public void onInstanceCallback() throws Throwable {
4.14 OnLocationTest t = new OnLocationTest();
4.15 net.java.html.geo.Position.Handle h = InstanceHandle.createWatch(t);
4.16 - h.onLocation(new Position());
4.17 + h.onLocation(new Position(null));
4.18 assertEquals(t.instCnt, 1, "One callback made");
4.19 }
4.20