Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Osm license #52

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
6 changes: 5 additions & 1 deletion maps/src/main/java/com/gluonhq/impl/maps/BaseMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import com.gluonhq.maps.MapPoint;
import com.gluonhq.maps.MapView;
import com.gluonhq.maps.tile.TileRetriever;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
Expand Down Expand Up @@ -95,7 +96,10 @@ public class BaseMap extends Group {
private final ChangeListener<Number> resizeListener = (o, oldValue, newValue) -> markDirty();
private ChangeListener<Scene> sceneListener;

public BaseMap() {
public TileRetriever tileRetriever;

public BaseMap(TileRetriever tileRetriever) {
this.tileRetriever = tileRetriever;
for (int i = 0; i < tiles.length; i++) {
tiles[i] = new HashMap<>();
}
Expand Down
4 changes: 2 additions & 2 deletions maps/src/main/java/com/gluonhq/impl/maps/MapTile.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public boolean isCovering() {
getTransforms().add(scale);
debug("[JVDBG] load image [" + myZoom + "], i = " + i + ", j = " + j);

final TileImageView imageView = new TileImageView(myZoom, i, j);
final TileImageView imageView = new TileImageView(baseMap.tileRetriever,myZoom, i, j);
imageView.exceptionProperty().addListener((obs, ov, nv) -> logger.info("Error: " + nv.getMessage()));
imageView.setMouseTransparent(true);
progress = imageView.progressProperty();
Expand Down Expand Up @@ -165,4 +165,4 @@ public void invalidated(Observable o) {
private void debug(String s) {
logger.fine("LOG " + System.currentTimeMillis() % 10000 + ": " + s);
}
}
}
10 changes: 5 additions & 5 deletions maps/src/main/java/com/gluonhq/impl/maps/TileImageView.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
package com.gluonhq.impl.maps;

import com.gluonhq.maps.tile.TileRetriever;
import com.gluonhq.maps.tile.TileRetrieverProvider;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.ReadOnlyDoubleProperty;
Expand All @@ -46,14 +46,14 @@
public class TileImageView extends ImageView {

private static final Logger logger = Logger.getLogger(TileImageView.class.getName());
private static final TileRetriever TILE_RETRIEVER = TileRetrieverProvider.getInstance().load();


public TileImageView(int zoom, long i, long j) {
public TileImageView(TileRetriever tileRetriever,int zoom, long i, long j) {
setFitHeight(256);
setFitWidth(256);
setPreserveRatio(true);
setProgress(0);
CompletableFuture<Image> future = TILE_RETRIEVER.loadTile(zoom, i, j);
CompletableFuture<Image> future = tileRetriever.loadTile(zoom, i, j);
if (!future.isDone()) {
Optional.ofNullable(placeholderImageSupplier).ifPresent(s -> setImage(s.get()));
logger.fine("start downloading tile " + zoom + "/" + i + "/" + j);
Expand Down Expand Up @@ -137,4 +137,4 @@ private ReadOnlyDoubleWrapper progressPropertyImpl() {
return progress;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,17 @@
import java.util.logging.Level;
import java.util.logging.Logger;

public class CachedOsmTileRetriever extends OsmTileRetriever {
public abstract class CachedOsmTileRetriever extends OsmTileRetriever {

private static final Logger logger = Logger.getLogger(CachedOsmTileRetriever.class.getName());
private static final int TIMEOUT = 10000;
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(2, new DaemonThreadFactory());

static File cacheRoot;
static boolean hasFileCache;
static {
File cacheRoot;
boolean hasFileCache;
CacheThread cacheThread = null;

public CachedOsmTileRetriever() {
try {
File storageRoot = StorageService.create()
.flatMap(StorageService::getPrivateStorage)
Expand All @@ -65,6 +67,9 @@ public class CachedOsmTileRetriever extends OsmTileRetriever {
} else {
hasFileCache = true;
}
if (hasFileCache) {
cacheThread = new CacheThread();
}
logger.fine("hasfilecache = " + hasFileCache);
} catch (IOException ex) {
hasFileCache = false;
Expand All @@ -81,15 +86,15 @@ public CompletableFuture<Image> loadTile(int zoom, long i, long j) {
return CompletableFuture.supplyAsync(() -> {
logger.fine("start downloading tile " + zoom + "/" + i + "/" + j);
try {
return CacheThread.cacheImage(zoom, i, j);
return cacheThread.cacheImage(zoom, i, j);
} catch (IOException e) {
throw new RuntimeException("Error " + e.getMessage());
}
}, EXECUTOR);
}


static private Image fromFileCache(int zoom, long i, long j) {
private Image fromFileCache(int zoom, long i, long j) {
if (!hasFileCache) {
return null;
}
Expand All @@ -98,14 +103,14 @@ static private Image fromFileCache(int zoom, long i, long j) {
return f.exists() ? new Image(f.toURI().toString(), true) : null;
}

private static class CacheThread {
private class CacheThread {

public static Image cacheImage(int zoom, long i, long j) throws IOException {
public Image cacheImage(int zoom, long i, long j) throws IOException {
File file = doCache(buildImageUrlString(zoom, i, j), zoom, i, j);
return new Image(new FileInputStream(file));
}

private static File doCache(String urlString, int zoom, long i, long j) throws IOException {
private File doCache(String urlString, int zoom, long i, long j) throws IOException {
final URLConnection openConnection;
URL url = new URL(urlString);
openConnection = url.openConnection();
Expand All @@ -115,7 +120,7 @@ private static File doCache(String urlString, int zoom, long i, long j) throws I
try (InputStream inputStream = openConnection.getInputStream()) {
String enc = File.separator + zoom + File.separator + i + File.separator + j + ".png";
logger.fine("retrieve " + urlString + " and store " + enc);
File candidate = new File(cacheRoot, enc);
File candidate = new File(cacheRoot.getPath(), enc);
candidate.getParentFile().mkdirs();
try (FileOutputStream fos = new FileOutputStream(candidate)) {
byte[] buff = new byte[4096];
Expand All @@ -140,4 +145,4 @@ public Thread newThread(final Runnable r) {
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,10 @@

import com.gluonhq.maps.tile.TileRetriever;
import javafx.scene.image.Image;

import java.util.concurrent.CompletableFuture;

public class OsmTileRetriever implements TileRetriever {

private static final String host = "http://tile.openstreetmap.org/";
public abstract class OsmTileRetriever implements TileRetriever {

static final String httpAgent;

static {
Expand All @@ -46,10 +44,8 @@ public class OsmTileRetriever implements TileRetriever {
System.setProperty("http.agent", httpAgent);
}

static String buildImageUrlString(int zoom, long i, long j) {
return host + zoom + "/" + i + "/" + j + ".png";
}

public abstract String buildImageUrlString(int zoom, long i, long j);

@Override
public CompletableFuture<Image> loadTile(int zoom, long i, long j) {
String urlString = buildImageUrlString(zoom, i, j);
Expand Down
22 changes: 19 additions & 3 deletions maps/src/main/java/com/gluonhq/maps/MapView.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,23 @@

import com.gluonhq.attach.util.Platform;
import com.gluonhq.impl.maps.BaseMap;
import com.gluonhq.maps.tile.TileRetriever;
import com.gluonhq.impl.maps.TileImageView;
import javafx.animation.Animation.Status;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.geometry.Point2D;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.layout.Region;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.util.Duration;

import javafx.scene.layout.BackgroundFill;
import javafx.scene.paint.Color;
import javafx.scene.layout.Background;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Supplier;
Expand All @@ -61,12 +66,19 @@ public class MapView extends Region {
private boolean zooming = false;
private boolean enableDragging = false;

private Label label;

/**
* Create a MapView component.
*/
public MapView() {
baseMap = new BaseMap();
public MapView(TileRetriever tileRetriever) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the sake of compatibility, we could keep the no-args constructor, and default to a possible implementation of CachedOsmTileRetriever (see comment below)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it... I would prefer to not have a no-args constructor actually, for the reasons in comment above.

baseMap = new BaseMap(tileRetriever);
getChildren().add(baseMap);
label = new Label(tileRetriever.copyright());
label.getStyleClass().add("label-license");
getChildren().add(label);
getStylesheets().add(MapView.class.getResource("maps.css").toExternalForm());

registerInputListeners();

baseMap.centerLat().addListener(o -> markDirty());
Expand Down Expand Up @@ -252,6 +264,10 @@ protected void layoutChildren() {
}
}
super.layoutChildren();

label.setLayoutX(w - label.getWidth());
label.setLayoutY(h - label.getHeight());

dirty = false;

// we need to get these values or we won't be notified on new changes
Expand Down
8 changes: 6 additions & 2 deletions maps/src/main/java/com/gluonhq/maps/tile/TileRetriever.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
import java.util.concurrent.CompletableFuture;

public interface TileRetriever {


/**
* @return Copyright/Attribution info to be overlayed on the map
*/
String copyright();
brunesto marked this conversation as resolved.
Show resolved Hide resolved

/**
* Loads a tile at the specified zoom level and coordinates and returns it
* as an {@link Image}.
Expand All @@ -43,5 +48,4 @@ public interface TileRetriever {
* @return a completableFuture with the image representing the tile
*/
CompletableFuture<Image> loadTile(int zoom, long i, long j);

}

This file was deleted.

1 change: 1 addition & 0 deletions maps/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@

exports com.gluonhq.maps;
exports com.gluonhq.maps.tile;
exports com.gluonhq.impl.maps.tile.osm;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we are going to export this package, it shouldn't be under impl, so osm should be under com.gluonhq.maps.tile ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see the original comment: "...Instead of moving CachedOsmTileRetriever around I just modified module-info.java ..."

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a look at it but I don't see a simple way to split the CachedOsmTileRetriever between impl and exported packaged, so I prefer not to make any changes for that in the PR.

}
4 changes: 4 additions & 0 deletions maps/src/main/resources/com/gluonhq/maps/maps.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.label-license {
-fx-background-color: rgba(126, 126, 126, 0.5);
-fx-font-size: 0.9em;
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

import com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever;
import com.gluonhq.maps.tile.TileRetriever;
public class MobileSample extends Application {

private static final Logger LOGGER = Logger.getLogger(MobileSample.class.getName());
Expand All @@ -68,7 +70,49 @@ public class MobileSample extends Application {

@Override
public void start(Stage stage) {
MapView view = new MapView();

/*
* In order to display OSM tiles you have to choose a tile provider. Here are some lists:
*
* -http://leaflet-extras.github.io/leaflet-providers/preview/ (fairly complete list with previews)
* -https://wiki.openstreetmap.org/wiki/Tile_servers
* -https://switch2osm.org/providers/#tile-hosting (both free tiers and commercial only)
*/

/*
* Here is an example for accessing OpenStreetMap server's tiles.
* Please only use for "very limited testing purposes" - @see https://operations.osmfoundation.org/policies/tiles/
*
*/
TileRetriever osm = new CachedOsmTileRetriever() {
public String buildImageUrlString(int zoom, long i, long j) {
return "http://tile.openstreetmap.org/" +zoom+"/"+ i + "/" + j + ".png";
}
public String copyright() {
return "Map data © OpenStreetMap contributors, CC-BY-SA. Imagery © OpenStreetMap, for demo only.";
}
};
/*
* Another example, using MapBox tiles free tier.
* To access MapBox you will need to create an account at https://www.mapbox.com/maps/ and generate an access token.
*
* Please note that the access token here is for demo only and will be replaced at some point - you need to get your own
*
* Styles known to work: satellite-v9,streets-v8
*/
TileRetriever mapBox = new CachedOsmTileRetriever() {
public String buildImageUrlString(int zoom, long i, long j) {
brunesto marked this conversation as resolved.
Show resolved Hide resolved
String token = "pk.eyJ1IjoiYnJ1bmVzdG8iLCJhIjoiY2tpYjRpcWVrMDk3bDJ5azBibGZmYjJ2NyJ9.5mKw_JV1w9-VoAxjn2f9LA";
String url = "https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/256/"+zoom+"/"+i+"/"+j+"?access_token="+token;
return url;
}
public String copyright() {
return "Map data © OpenStreetMap contributors CC-BY-SA, Imagery © Mapbox";
}
};

MapView view = new MapView(mapBox);

brunesto marked this conversation as resolved.
Show resolved Hide resolved
view.addLayer(positionLayer());
view.setZoom(3);
Scene scene;
Expand Down