From: Keith Packard Date: Thu, 21 May 2015 20:49:28 +0000 (-0700) Subject: altoslib: Create display-independent map support code X-Git-Tag: 1.6.0.3~80 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=29edc37a8de56cb6eb028e3bf3f56aa70f109eba altoslib: Create display-independent map support code This takes the swing-specific map code and creates a generic version. Signed-off-by: Keith Packard --- diff --git a/altoslib/.gitignore b/altoslib/.gitignore index ff0fd710..dc8b7e5e 100644 --- a/altoslib/.gitignore +++ b/altoslib/.gitignore @@ -1,3 +1,4 @@ bin classaltoslib.stamp altoslib*.jar +AltosVersion.java diff --git a/altoslib/AltosFlightDisplay.java b/altoslib/AltosFlightDisplay.java new file mode 100644 index 00000000..157a0710 --- /dev/null +++ b/altoslib/AltosFlightDisplay.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener { + void reset(); + + void show(AltosState state, AltosListenerState listener_state); + + String getName(); +} diff --git a/altoslib/AltosFontListener.java b/altoslib/AltosFontListener.java new file mode 100644 index 00000000..74988139 --- /dev/null +++ b/altoslib/AltosFontListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public interface AltosFontListener { + void font_size_changed(int font_size); +} diff --git a/altoslib/AltosImage.java b/altoslib/AltosImage.java new file mode 100644 index 00000000..9a9b5777 --- /dev/null +++ b/altoslib/AltosImage.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; + +public interface AltosImage { + /* Discard storage for image */ + public abstract void flush(); +} diff --git a/altoslib/AltosLatLon.java b/altoslib/AltosLatLon.java new file mode 100644 index 00000000..f1ecfc90 --- /dev/null +++ b/altoslib/AltosLatLon.java @@ -0,0 +1,34 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public class AltosLatLon { + public double lat; + public double lon; + + public boolean equals(AltosLatLon other) { + if (other == null) + return false; + return lat == other.lat && lon == other.lon; + } + + public AltosLatLon(double lat, double lon) { + this.lat = lat; + this.lon = lon; + } +} diff --git a/altoslib/AltosMap.java b/altoslib/AltosMap.java new file mode 100644 index 00000000..b42f9f85 --- /dev/null +++ b/altoslib/AltosMap.java @@ -0,0 +1,355 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.lang.*; +import java.util.*; +import java.util.concurrent.*; + +public class AltosMap implements AltosFlightDisplay, AltosMapTileListener, AltosMapStoreListener { + + static final int px_size = 512; + + static final int maptype_hybrid = 0; + static final int maptype_roadmap = 1; + static final int maptype_satellite = 2; + static final int maptype_terrain = 3; + static final int maptype_default = maptype_hybrid; + + static final int default_zoom = 15; + static final int min_zoom = 3; + static final int max_zoom = 21; + + static final String[] maptype_names = { + "hybrid", + "roadmap", + "satellite", + "terrain" + }; + + public static final String[] maptype_labels = { + "Hybrid", + "Roadmap", + "Satellite", + "Terrain" + }; + + AltosMapInterface map_interface; + + AltosMapCache cache; + + LinkedList marks = new LinkedList(); + + LinkedList zoom_listeners = new LinkedList(); + + public void add_zoom_listener(AltosMapZoomListener listener) { + if (!zoom_listeners.contains(listener)) + zoom_listeners.add(listener); + } + + public void remove_zoom_listener(AltosMapZoomListener listener) { + zoom_listeners.remove(listener); + } + + boolean have_boost = false; + boolean have_landed = false; + + ConcurrentHashMap tiles = new ConcurrentHashMap(); + int load_radius; + AltosLatLon load_centre = null; + AltosMapTileListener load_listener; + + int zoom = AltosMap.default_zoom; + int maptype = AltosMap.maptype_default; + + long user_input_time; + + /* Milliseconds to wait after user action before auto-scrolling + */ + static final long auto_scroll_delay = 20 * 1000; + + AltosMapTransform transform; + AltosLatLon centre; + + public void reset() { + // nothing + } + + /* MapInterface wrapping functions */ + public void set_units() { + map_interface.set_units(); + } + + public void repaint(AltosMapRectangle damage, int pad) { + map_interface.repaint(damage, pad); + } + + public void repaint(double x, double y, double w, double h) { + map_interface.repaint(x, y, w, h); + } + + public void repaint() { + map_interface.repaint(); + } + + public int width() { + return map_interface.width(); + } + + public int height() { + return map_interface.height(); + } + + public AltosPointInt floor(AltosPointDouble point) { + return new AltosPointInt ((int) Math.floor(point.x / AltosMap.px_size) * AltosMap.px_size, + (int) Math.floor(point.y / AltosMap.px_size) * AltosMap.px_size); + } + + public AltosPointInt ceil(AltosPointDouble point) { + return new AltosPointInt ((int) Math.ceil(point.x / AltosMap.px_size) * AltosMap.px_size, + (int) Math.ceil(point.y / AltosMap.px_size) * AltosMap.px_size); + } + + public void notice_user_input() { + user_input_time = System.currentTimeMillis(); + } + + public boolean recent_user_input() { + return (System.currentTimeMillis() - user_input_time) < auto_scroll_delay; + } + + public boolean far_from_centre(AltosLatLon lat_lon) { + + if (centre == null || transform == null) + return true; + + AltosPointDouble screen = transform.screen(lat_lon); + + int width = width(); + int dx = Math.abs ((int) (double) screen.x - width/2); + + if (dx > width / 4) + return true; + + int height = height(); + int dy = Math.abs ((int) (double) screen.y - height/2); + + if (dy > height / 4) + return true; + + return false; + } + + public void font_size_changed(int font_size) { + map_interface.line.font_size_changed(font_size); + for (AltosMapTile tile : tiles.values()) + tile.font_size_changed(font_size); + repaint(); + } + + public void units_changed(boolean imperial_units) { + } + + private void set_transform() { + transform = new AltosMapTransform(width(), height(), zoom, centre); + repaint(); + } + + public boolean set_zoom(int zoom) { + if (AltosMap.min_zoom <= zoom && zoom <= AltosMap.max_zoom && zoom != this.zoom) { + this.zoom = zoom; + tiles.clear(); + set_transform(); + + for (AltosMapZoomListener listener : zoom_listeners) + listener.zoom_changed(this.zoom); + + return true; + } + return false; + } + + public int get_zoom() { + return zoom; + } + + public boolean set_maptype(int maptype) { + if (maptype != this.maptype) { + this.maptype = maptype; + tiles.clear(); + repaint(); + return true; + } + return false; + } + + public void show(AltosState state, AltosListenerState listener_state) { + + /* If insufficient gps data, nothing to update + */ + AltosGPS gps = state.gps; + + if (gps == null) + return; + + if (!gps.locked && gps.nsat < 4) + return; + + AltosMapRectangle damage = map_interface.path.add(gps.lat, gps.lon, state.state); + + switch (state.state) { + case AltosLib.ao_flight_boost: + if (!have_boost) { + add_mark(gps.lat, gps.lon, state.state); + have_boost = true; + } + break; + case AltosLib.ao_flight_landed: + if (!have_landed) { + add_mark(gps.lat, gps.lon, state.state); + have_landed = true; + } + break; + } + + if (damage != null) + repaint(damage, AltosMapPath.stroke_width); + maybe_centre(gps.lat, gps.lon); + } + + public void centre(AltosLatLon lat_lon) { + centre = lat_lon; + set_transform(); + } + + public void centre(double lat, double lon) { + centre(new AltosLatLon(lat, lon)); + } + + public void centre(AltosState state) { + if (!state.gps.locked && state.gps.nsat < 4) + return; + centre(state.gps.lat, state.gps.lon); + } + + public void maybe_centre(double lat, double lon) { + AltosLatLon lat_lon = new AltosLatLon(lat, lon); + if (centre == null || (!recent_user_input() && far_from_centre(lat_lon))) + centre(lat_lon); + } + + public void add_mark(double lat, double lon, int state) { + synchronized(marks) { + marks.add(map_interface.new_mark(lat, lon, state)); + } + repaint(); + } + + public void clear_marks() { + synchronized(marks) { + marks.clear(); + } + } + + private void make_tiles() { + AltosPointInt upper_left; + AltosPointInt lower_right; + + if (load_centre != null) { + AltosPointInt centre = floor(transform.point(load_centre)); + + upper_left = new AltosPointInt(centre.x - load_radius * AltosMap.px_size, + centre.y - load_radius * AltosMap.px_size); + lower_right = new AltosPointInt(centre.x + load_radius * AltosMap.px_size, + centre.y + load_radius * AltosMap.px_size); + } else { + upper_left = floor(transform.screen_point(new AltosPointDouble(0.0, 0.0))); + lower_right = floor(transform.screen_point(new AltosPointDouble(width(), height()))); + } + LinkedList to_remove = new LinkedList(); + + for (AltosPointInt point : tiles.keySet()) { + if (point.x < upper_left.x || lower_right.x < point.x || + point.y < upper_left.y || lower_right.y < point.y) { + to_remove.add(point); + } + } + + for (AltosPointInt point : to_remove) + tiles.remove(point); + + cache.set_cache_size((width() / AltosMap.px_size + 2) * (height() / AltosMap.px_size + 2)); + for (int y = (int) upper_left.y; y <= lower_right.y; y += AltosMap.px_size) { + for (int x = (int) upper_left.x; x <= lower_right.x; x += AltosMap.px_size) { + AltosPointInt point = new AltosPointInt(x, y); + + if (!tiles.containsKey(point)) { + AltosLatLon ul = transform.lat_lon(new AltosPointDouble(x, y)); + AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2)); + AltosMapTile tile = new AltosMapTile(this, ul, center, zoom, maptype, + AltosMap.px_size); + tiles.put(point, tile); + } + } + } + } + + public void set_load_params(double lat, double lon, int radius, AltosMapTileListener listener) { + load_centre = new AltosLatLon(lat, lon); + load_radius = radius; + load_listener = listener; + centre(lat, lon); + make_tiles(); + for (AltosMapTile tile : tiles.values()) { + tile.add_store_listener(this); + if (tile.store_status() != AltosMapTile.loading) + listener.notify_tile(tile, tile.store_status()); + } + repaint(); + } + + public String getName() { + return "Map"; + } + + /* AltosMapTileListener methods */ + public synchronized void notify_tile(AltosMapTile tile, int status) { + for (AltosPointInt point : tiles.keySet()) { + if (tile == tiles.get(point)) { + AltosPointInt screen = transform.screen(point); + repaint(screen.x, screen.y, AltosMap.px_size, AltosMap.px_size); + } + } + } + + /* AltosMapStoreListener methods */ + public synchronized void notify_store(AltosMapStore store, int status) { + if (load_listener != null) { + for (AltosMapTile tile : tiles.values()) + if (store.equals(tile.store)) + load_listener.notify_tile(tile, status); + } + } + + public AltosMap(AltosMapInterface map_interface) { + this.map_interface = map_interface; + cache = new AltosMapCache(map_interface); + centre(0, 0); + } +} diff --git a/altoslib/AltosMapCache.java b/altoslib/AltosMapCache.java new file mode 100644 index 00000000..d94bae6c --- /dev/null +++ b/altoslib/AltosMapCache.java @@ -0,0 +1,207 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.net.*; + +public class AltosMapCache implements AltosMapCacheListener { + + /* An entry in the MapCache */ + class MapCacheElement implements AltosMapStoreListener { + + AltosMapTile tile; /* Notify when image has been loaded */ + AltosImage image; + AltosMapStore store; + long used; + + class loader implements Runnable { + public void run() { + if (image != null) + tile.notify_image(image); + try { + image = map_interface.load_image(store.file); + } catch (Exception ex) { + } + if (image == null) + tile.set_status(AltosMapTile.failed); + else + tile.set_status(AltosMapTile.success); + tile.notify_image(image); + } + } + + private void load() { + loader l = new loader(); + Thread lt = new Thread(l); + lt.start(); + } + + public void flush() { + if (image != null) { + image.flush(); + image = null; + } + } + + public boolean has_map() { + return store.status() == AltosMapTile.success; + } + + public synchronized void notify_store(AltosMapStore store, int status) { + switch (status) { + case AltosMapTile.loading: + break; + case AltosMapTile.success: + load(); + break; + default: + tile.set_status(status); + tile.notify_image(null); + } + } + + public MapCacheElement(AltosMapTile tile, AltosMapStore store) throws IOException { + this.tile = tile; + this.image = null; + this.store = store; + this.used = 0; + + int status = store.status(); + switch (status) { + case AltosMapTile.loading: + store.add_listener(this); + break; + case AltosMapTile.success: + load(); + break; + default: + tile.set_status(status); + tile.notify_image(null); + break; + } + } + } + + int min_cache_size; /* configured minimum cache size */ + int cache_size; /* current cache size */ + int requested_cache_size; /* cache size computed by application */ + + private Object fetch_lock = new Object(); + private Object cache_lock = new Object(); + + AltosMapInterface map_interface; + + MapCacheElement[] elements = new MapCacheElement[cache_size]; + + long used; + + public void set_cache_size(int new_size) { + + requested_cache_size = new_size; + + if (new_size < min_cache_size) + new_size = min_cache_size; + + if (new_size == cache_size) + return; + + synchronized(cache_lock) { + MapCacheElement[] new_elements = new MapCacheElement[new_size]; + + for (int i = 0; i < cache_size; i++) { + if (i < new_size) + new_elements[i] = elements[i]; + else if (elements[i] != null) + elements[i].flush(); + } + elements = new_elements; + cache_size = new_size; + } + } + + public AltosImage get(AltosMapTile tile, AltosMapStore store, int width, int height) { + int oldest = -1; + long age = used; + + synchronized(cache_lock) { + MapCacheElement element = null; + for (int i = 0; i < cache_size; i++) { + element = elements[i]; + + if (element == null) { + oldest = i; + break; + } + if (store.equals(element.store)) { + element.used = used++; + return element.image; + } + if (element.used < age) { + oldest = i; + age = element.used; + } + } + + try { + element = new MapCacheElement(tile, store); + element.used = used++; + if (elements[oldest] != null) + elements[oldest].flush(); + + elements[oldest] = element; + + if (element.image == null) + tile.set_status(AltosMapTile.loading); + else + tile.set_status(AltosMapTile.success); + + return element.image; + } catch (IOException e) { + tile.set_status(AltosMapTile.failed); + return null; + } + } + } + + public void map_cache_changed(int map_cache) { + min_cache_size = map_cache; + + set_cache_size(requested_cache_size); + } + + public void dispose() { + AltosPreferences.unregister_map_cache_listener(this); + + for (int i = 0; i < cache_size; i++) { + MapCacheElement element = elements[i]; + + if (element != null) + element.flush(); + } + } + + public AltosMapCache(AltosMapInterface map_interface) { + this.map_interface = map_interface; + min_cache_size = AltosPreferences.map_cache(); + + set_cache_size(0); + + AltosPreferences.register_map_cache_listener(this); + } +} diff --git a/altoslib/AltosMapCacheListener.java b/altoslib/AltosMapCacheListener.java new file mode 100644 index 00000000..49b075dd --- /dev/null +++ b/altoslib/AltosMapCacheListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public interface AltosMapCacheListener { + public void map_cache_changed(int map_cache); +} diff --git a/altoslib/AltosMapInterface.java b/altoslib/AltosMapInterface.java new file mode 100644 index 00000000..ea5454de --- /dev/null +++ b/altoslib/AltosMapInterface.java @@ -0,0 +1,47 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.net.*; + +public abstract class AltosMapInterface { + + public AltosMapPath path; + public AltosMapLine line; + + public abstract AltosImage load_image(File file) throws Exception; + + public abstract AltosMapMark new_mark(double lat, double lon, int state); + + public abstract int width(); + public abstract int height(); + + public abstract void repaint(); + + public abstract void repaint(AltosMapRectangle damage, int pad); + + public abstract void repaint(double x, double y, double w, double h); + + public abstract void set_units(); + + public AltosMapInterface (AltosMapPath path, AltosMapLine line) { + this.path = path; + this.line = line; + } +} diff --git a/altoslib/AltosMapLine.java b/altoslib/AltosMapLine.java new file mode 100644 index 00000000..83de47f9 --- /dev/null +++ b/altoslib/AltosMapLine.java @@ -0,0 +1,83 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.lang.Math; +import java.util.*; +import java.util.concurrent.*; + +public abstract class AltosMapLine implements AltosFontListener { + AltosLatLon start, end; + + static public int stroke_width = 6; + + public abstract void font_size_changed(int font_size); + + private AltosLatLon lat_lon(AltosPointDouble pt, AltosMapTransform t) { + return t.screen_lat_lon(pt); + } + + public void dragged(AltosPointDouble pt, AltosMapTransform t) { + end = lat_lon(pt, t); + } + + public void pressed(AltosPointDouble pt, AltosMapTransform t) { + start = lat_lon(pt, t); + end = null; + } + + private String line_dist() { + String format; + AltosGreatCircle g = new AltosGreatCircle(start.lat, start.lon, + end.lat, end.lon); + double distance = g.distance; + + if (AltosConvert.imperial_units) { + distance = AltosConvert.meters_to_feet(distance); + if (distance < 10000) { + format = "%4.0fft"; + } else { + distance /= 5280; + if (distance < 10) + format = "%5.3fmi"; + else if (distance < 100) + format = "%5.2fmi"; + else if (distance < 1000) + format = "%5.1fmi"; + else + format = "%5.0fmi"; + } + } else { + if (distance < 10000) { + format = "%4.0fm"; + } else { + distance /= 1000; + if (distance < 100) + format = "%5.2fkm"; + else if (distance < 1000) + format = "%5.1fkm"; + else + format = "%5.0fkm"; + } + } + return String.format(format, distance); + } + + public abstract void paint(AltosMapTransform t); +} diff --git a/altoslib/AltosMapMark.java b/altoslib/AltosMapMark.java new file mode 100644 index 00000000..9b77d539 --- /dev/null +++ b/altoslib/AltosMapMark.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.lang.Math; +import java.util.*; +import java.util.concurrent.*; + +public abstract class AltosMapMark { + + AltosLatLon lat_lon; + int state; + + static public int stroke_width = 6; + + public abstract void paint(AltosMapTransform t); + + public AltosMapMark (double lat, double lon, int state) { + lat_lon = new AltosLatLon(lat, lon); + this.state = state; + } +} diff --git a/altoslib/AltosMapPath.java b/altoslib/AltosMapPath.java new file mode 100644 index 00000000..272a4316 --- /dev/null +++ b/altoslib/AltosMapPath.java @@ -0,0 +1,67 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.lang.Math; +import java.util.*; +import java.util.concurrent.*; + +class PathPoint { + AltosLatLon lat_lon; + int state; + + public PathPoint(AltosLatLon lat_lon, int state) { + this.lat_lon = lat_lon; + this.state = state; + } + + public boolean equals(PathPoint other) { + if (other == null) + return false; + + return lat_lon.equals(other.lat_lon) && state == other.state; + } +} + +public abstract class AltosMapPath { + + LinkedList points = new LinkedList(); + PathPoint last_point = null; + + static public int stroke_width = 6; + + public abstract void paint(AltosMapTransform t); + + public AltosMapRectangle add(double lat, double lon, int state) { + PathPoint point = new PathPoint(new AltosLatLon (lat, lon), state); + AltosMapRectangle rect = null; + + if (!point.equals(last_point)) { + if (last_point != null) + rect = new AltosMapRectangle(last_point.lat_lon, point.lat_lon); + points.add (point); + last_point = point; + } + return rect; + } + + public void clear () { + points = new LinkedList(); + } +} diff --git a/altoslib/AltosMapRectangle.java b/altoslib/AltosMapRectangle.java new file mode 100644 index 00000000..f2f30103 --- /dev/null +++ b/altoslib/AltosMapRectangle.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public class AltosMapRectangle { + AltosLatLon ul, lr; + + public AltosMapRectangle(AltosLatLon a, AltosLatLon b) { + double ul_lat, ul_lon; + double lr_lat, lr_lon; + + if (a.lat > b.lat) { + ul_lat = a.lat; + lr_lat = b.lat; + } else { + ul_lat = b.lat; + lr_lat = a.lat; + } + if (a.lon < b.lon) { + ul_lon = a.lon; + lr_lon = b.lon; + } else { + ul_lon = b.lon; + lr_lon = a.lon; + } + + ul = new AltosLatLon(ul_lat, ul_lon); + lr = new AltosLatLon(lr_lat, lr_lon); + } +} diff --git a/altoslib/AltosMapStore.java b/altoslib/AltosMapStore.java new file mode 100644 index 00000000..2f52edb6 --- /dev/null +++ b/altoslib/AltosMapStore.java @@ -0,0 +1,196 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.net.*; +import java.util.*; + +public class AltosMapStore { + String url; + public File file; + LinkedList listeners = new LinkedList(); + + int status; + + public int status() { + return status; + } + + public synchronized void add_listener(AltosMapStoreListener listener) { + if (!listeners.contains(listener)) + listeners.add(listener); + } + + public synchronized void remove_listener(AltosMapStoreListener listener) { + listeners.remove(listener); + } + + private synchronized void notify_listeners(int status) { + this.status = status; + for (AltosMapStoreListener listener : listeners) + listener.notify_store(this, status); + } + + static Object forbidden_lock = new Object(); + static long forbidden_time; + static boolean forbidden_set; + + private int fetch_url() { + URL u; + + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return AltosMapTile.bad_request; + } + + byte[] data; + URLConnection uc = null; + try { + uc = u.openConnection(); + String type = uc.getContentType(); + int contentLength = uc.getContentLength(); + if (uc instanceof HttpURLConnection) { + int response = ((HttpURLConnection) uc).getResponseCode(); + switch (response) { + case HttpURLConnection.HTTP_FORBIDDEN: + case HttpURLConnection.HTTP_PAYMENT_REQUIRED: + case HttpURLConnection.HTTP_UNAUTHORIZED: + synchronized (forbidden_lock) { + forbidden_time = System.nanoTime(); + forbidden_set = true; + return AltosMapTile.forbidden; + } + } + } + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); + + if (offset != contentLength) + return AltosMapTile.failed; + + } catch (IOException e) { + return AltosMapTile.failed; + } + + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return AltosMapTile.bad_request; + } catch (IOException e) { + if (file.exists()) + file.delete(); + return AltosMapTile.bad_request; + } + return AltosMapTile.success; + } + + static Object fetch_lock = new Object(); + + static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; + static final long google_maps_ratelimit_ms = 1200; + + class loader implements Runnable { + + public void run() { + if (file.exists()) { + notify_listeners(AltosMapTile.success); + return; + } + + synchronized(forbidden_lock) { + if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) { + notify_listeners(AltosMapTile.forbidden); + return; + } + } + + int new_status; + + if (!AltosVersion.has_google_maps_api_key()) { + synchronized (fetch_lock) { + long startTime = System.nanoTime(); + new_status = fetch_url(); + if (new_status == AltosMapTile.success) { + long duration_ms = (System.nanoTime() - startTime) / 1000000; + if (duration_ms < google_maps_ratelimit_ms) { + try { + Thread.sleep(google_maps_ratelimit_ms - duration_ms); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + } + } else { + new_status = fetch_url(); + } + notify_listeners(new_status); + } + } + + private void load() { + loader l = new loader(); + Thread lt = new Thread(l); + lt.start(); + } + + private AltosMapStore (String url, File file) { + this.url = url; + this.file = file; + + if (file.exists()) + status = AltosMapTile.success; + else { + status = AltosMapTile.loading; + load(); + } + } + + public boolean equals(AltosMapStore other) { + return url.equals(other.url); + } + + static HashMap stores = new HashMap(); + + public static AltosMapStore get(String url, File file) { + AltosMapStore store; + synchronized(stores) { + if (stores.containsKey(url)) { + store = stores.get(url); + } else { + store = new AltosMapStore(url, file); + stores.put(url, store); + } + } + return store; + } +} diff --git a/altoslib/AltosMapStoreListener.java b/altoslib/AltosMapStoreListener.java new file mode 100644 index 00000000..a272e864 --- /dev/null +++ b/altoslib/AltosMapStoreListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public interface AltosMapStoreListener { + abstract void notify_store(AltosMapStore store, int status); +} diff --git a/altoslib/AltosMapTile.java b/altoslib/AltosMapTile.java new file mode 100644 index 00000000..b5dee7a4 --- /dev/null +++ b/altoslib/AltosMapTile.java @@ -0,0 +1,114 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.util.*; + +public class AltosMapTile implements AltosFontListener { + AltosMapTileListener listener; + AltosLatLon upper_left, center; + int px_size; + int zoom; + int maptype; + AltosMapStore store; + AltosMapCache cache; + int status; + + static public final int success = 0; + static public final int loading = 1; + static public final int failed = 2; + static public final int bad_request = 3; + static public final int forbidden = 4; + + private File map_file() { + double lat = center.lat; + double lon = center.lon; + char chlat = lat < 0 ? 'S' : 'N'; + char chlon = lon < 0 ? 'W' : 'E'; + + if (lat < 0) lat = -lat; + if (lon < 0) lon = -lon; + String maptype_string = String.format("%s-", AltosMap.maptype_names[maptype]); + String format_string; + if (maptype == AltosMap.maptype_hybrid || maptype == AltosMap.maptype_satellite || maptype == AltosMap.maptype_terrain) + format_string = "jpg"; + else + format_string = "png"; + return new File(AltosPreferences.mapdir(), + String.format("map-%c%.6f,%c%.6f-%s%d.%s", + chlat, lat, chlon, lon, maptype_string, zoom, format_string)); + } + + private String map_url() { + String format_string; + if (maptype == AltosMap.maptype_hybrid || maptype == AltosMap.maptype_satellite || maptype == AltosMap.maptype_terrain) + format_string = "jpg"; + else + format_string = "png32"; + + if (AltosVersion.has_google_maps_api_key()) + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s&key=%s", + center.lat, center.lon, zoom, px_size, px_size, AltosMap.maptype_names[maptype], format_string, AltosVersion.google_maps_api_key); + else + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s", + center.lat, center.lon, zoom, px_size, px_size, AltosMap.maptype_names[maptype], format_string); + } + + public void font_size_changed(int font_size) { + } + + public void set_status(int status) { + this.status = status; + listener.notify_tile(this, status); + } + + public void notify_image(AltosImage image) { + listener.notify_tile(this, status); + } + + public int store_status() { + return store.status(); + } + + public void add_store_listener(AltosMapStoreListener listener) { + store.add_listener(listener); + } + + public void remove_store_listener(AltosMapStoreListener listener) { + store.remove_listener(listener); + } + + public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { + this.listener = listener; + this.upper_left = upper_left; + + while (center.lon < -180.0) + center.lon += 360.0; + while (center.lon > 180.0) + center.lon -= 360.0; + + this.center = center; + this.zoom = zoom; + this.maptype = maptype; + this.px_size = px_size; + + status = AltosMapTile.loading; + store = AltosMapStore.get(map_url(), map_file()); + } +} diff --git a/altoslib/AltosMapTileListener.java b/altoslib/AltosMapTileListener.java new file mode 100644 index 00000000..8abc8b5a --- /dev/null +++ b/altoslib/AltosMapTileListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public interface AltosMapTileListener { + abstract public void notify_tile(AltosMapTile tile, int status); +} diff --git a/altoslib/AltosMapTransform.java b/altoslib/AltosMapTransform.java new file mode 100644 index 00000000..f5fc5ebe --- /dev/null +++ b/altoslib/AltosMapTransform.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +import java.io.*; +import java.lang.Math; +import java.util.*; +import java.util.concurrent.*; + +public class AltosMapTransform { + + double scale_x, scale_y; + + double offset_x, offset_y; + + public AltosLatLon lat_lon (AltosPointDouble point) { + double lat, lon; + double rads; + + lon = point.x/scale_x; + rads = 2 * Math.atan(Math.exp(-point.y/scale_y)); + lat = Math.toDegrees(rads - Math.PI/2); + + return new AltosLatLon(lat,lon); + } + + public AltosPointDouble screen_point(AltosPointDouble screen) { + return new AltosPointDouble(screen.x + offset_x, screen.y + offset_y); + } + + public AltosLatLon screen_lat_lon(AltosPointDouble screen) { + return lat_lon(screen_point(screen)); + } + + public AltosPointDouble point(AltosLatLon lat_lon) { + double x, y; + double e; + + x = lat_lon.lon * scale_x; + + e = Math.sin(Math.toRadians(lat_lon.lat)); + e = Math.max(e,-(1-1.0E-15)); + e = Math.min(e, 1-1.0E-15 ); + + y = 0.5*Math.log((1+e)/(1-e))*-scale_y; + + return new AltosPointDouble(x, y); + } + + public AltosPointDouble screen(AltosPointDouble point) { + return new AltosPointDouble(point.x - offset_x, point.y - offset_y); + } + + public AltosPointInt screen(AltosPointInt point) { + return new AltosPointInt((int) (point.x - offset_x + 0.5), + (int) (point.y - offset_y + 0.5)); + } + +// public Rectangle screen(AltosMapRectangle map_rect) { +// AltosPoint2D ul = screen(map_rect.ul); +// AltosPoint2D lr = screen(map_rect.lr); +// +// return new Rectangle((int) ul.x, (int) ul.y, (int) (lr.x - ul.x), (int) (lr.y - ul.y)); +// } + + public AltosPointDouble screen(AltosLatLon lat_lon) { + return screen(point(lat_lon)); + } + + private boolean has_location; + + public boolean has_location() { + return has_location; + } + + public AltosMapTransform(int width, int height, int zoom, AltosLatLon centre_lat_lon) { + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + + AltosPointDouble centre_pt = point(centre_lat_lon); + + has_location = (centre_lat_lon.lat != 0 || centre_lat_lon.lon != 0); + offset_x = centre_pt.x - width / 2.0; + offset_y = centre_pt.y - height / 2.0; + } +} diff --git a/altoslib/AltosMapZoomListener.java b/altoslib/AltosMapZoomListener.java new file mode 100644 index 00000000..34edb19b --- /dev/null +++ b/altoslib/AltosMapZoomListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public interface AltosMapZoomListener { + abstract public void zoom_changed(int zoom); +} diff --git a/altoslib/AltosPointDouble.java b/altoslib/AltosPointDouble.java new file mode 100644 index 00000000..96fb9161 --- /dev/null +++ b/altoslib/AltosPointDouble.java @@ -0,0 +1,41 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public class AltosPointDouble { + public double x, y; + + public boolean equals(AltosPointDouble n) { + return n.x == x && n.y == y; + } + + public AltosPointDouble(double x, double y) { + this.x = x; + this.y = y; + } + + public AltosPointDouble(int x, int y) { + this.x = x; + this.y = y; + } + + public AltosPointDouble(AltosPointInt p) { + this.x = p.x; + this.y = p.y; + } +} diff --git a/altoslib/AltosPointInt.java b/altoslib/AltosPointInt.java new file mode 100644 index 00000000..6ee077ab --- /dev/null +++ b/altoslib/AltosPointInt.java @@ -0,0 +1,31 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public class AltosPointInt { + public int x, y; + + public boolean equals(AltosPointInt n) { + return n.x == x && n.y == y; + } + + public AltosPointInt(int x, int y) { + this.x = x; + this.y = y; + } +} diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 5aa45d3f..9c4cadff 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -118,6 +118,13 @@ public class AltosPreferences { public final static String unitsPreference = "IMPERIAL-UNITS"; + /* Maps cache size preference name */ + final static String mapCachePreference = "MAP-CACHE"; + + static LinkedList map_cache_listeners; + + public static int map_cache = 9; + public static AltosFrequency[] load_common_frequencies() { AltosFrequency[] frequencies = null; boolean existing = false; @@ -208,6 +215,9 @@ public class AltosPreferences { common_frequencies = load_common_frequencies(); AltosConvert.imperial_units = backend.getBoolean(unitsPreference, false); + + map_cache = backend.getInt(mapCachePreference, 9); + map_cache_listeners = new LinkedList(); } public static void flush_preferences() { @@ -548,4 +558,33 @@ public class AltosPreferences { units_listeners.remove(l); } } + + + public static void register_map_cache_listener(AltosMapCacheListener l) { + synchronized(backend) { + map_cache_listeners.add(l); + } + } + + public static void unregister_map_cache_listener(AltosMapCacheListener l) { + synchronized (backend) { + map_cache_listeners.remove(l); + } + } + + public static void set_map_cache(int new_map_cache) { + synchronized(backend) { + map_cache = new_map_cache; + backend.putInt(mapCachePreference, map_cache); + flush_preferences(); + for (AltosMapCacheListener l: map_cache_listeners) + l.map_cache_changed(map_cache); + } + } + + public static int map_cache() { + synchronized(backend) { + return map_cache; + } + } } diff --git a/altoslib/AltosVersion.java.in b/altoslib/AltosVersion.java.in new file mode 100644 index 00000000..6bfef181 --- /dev/null +++ b/altoslib/AltosVersion.java.in @@ -0,0 +1,28 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_6; + +public class AltosVersion { + public final static String version = "@VERSION@"; + + public final static String google_maps_api_key = @GOOGLEKEY@; + + static boolean has_google_maps_api_key() { + return google_maps_api_key != null && google_maps_api_key.length() > 1; + } +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index c640c69c..0ee7b935 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -128,7 +128,28 @@ altoslib_JAVA = \ AltosPyro.java \ AltosWriter.java \ AltosQuaternion.java \ - AltosRotation.java + AltosRotation.java \ + AltosImage.java \ + AltosLatLon.java \ + AltosMap.java \ + AltosMapCache.java \ + AltosMapCacheListener.java \ + AltosMapInterface.java \ + AltosMapLine.java \ + AltosMapMark.java \ + AltosMapPath.java \ + AltosMapRectangle.java \ + AltosMapStore.java \ + AltosMapStoreListener.java \ + AltosMapTile.java \ + AltosMapTileListener.java \ + AltosMapTransform.java \ + AltosMapZoomListener.java \ + AltosPointDouble.java \ + AltosPointInt.java \ + AltosFlightDisplay.java \ + AltosFontListener.java \ + AltosVersion.java JAR=altoslib_$(ALTOSLIB_VERSION).jar