diff options
| author | Keith Packard <keithp@keithp.com> | 2015-05-21 13:49:28 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2015-05-21 13:49:28 -0700 | 
| commit | 29edc37a8de56cb6eb028e3bf3f56aa70f109eba (patch) | |
| tree | ab2a1ac5a7edf706134cde3f54ed133f0efb7761 /altoslib | |
| parent | 59a28811cb19d315b483df296145a2769c445f80 (diff) | |
altoslib: Create display-independent map support code
This takes the swing-specific map code and creates a generic version.
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'altoslib')
| -rw-r--r-- | altoslib/.gitignore | 1 | ||||
| -rw-r--r-- | altoslib/AltosFlightDisplay.java | 26 | ||||
| -rw-r--r-- | altoslib/AltosFontListener.java | 22 | ||||
| -rw-r--r-- | altoslib/AltosImage.java | 25 | ||||
| -rw-r--r-- | altoslib/AltosLatLon.java | 34 | ||||
| -rw-r--r-- | altoslib/AltosMap.java | 355 | ||||
| -rw-r--r-- | altoslib/AltosMapCache.java | 207 | ||||
| -rw-r--r-- | altoslib/AltosMapCacheListener.java | 22 | ||||
| -rw-r--r-- | altoslib/AltosMapInterface.java | 47 | ||||
| -rw-r--r-- | altoslib/AltosMapLine.java | 83 | ||||
| -rw-r--r-- | altoslib/AltosMapMark.java | 38 | ||||
| -rw-r--r-- | altoslib/AltosMapPath.java | 67 | ||||
| -rw-r--r-- | altoslib/AltosMapRectangle.java | 45 | ||||
| -rw-r--r-- | altoslib/AltosMapStore.java | 196 | ||||
| -rw-r--r-- | altoslib/AltosMapStoreListener.java | 22 | ||||
| -rw-r--r-- | altoslib/AltosMapTile.java | 114 | ||||
| -rw-r--r-- | altoslib/AltosMapTileListener.java | 22 | ||||
| -rw-r--r-- | altoslib/AltosMapTransform.java | 101 | ||||
| -rw-r--r-- | altoslib/AltosMapZoomListener.java | 22 | ||||
| -rw-r--r-- | altoslib/AltosPointDouble.java | 41 | ||||
| -rw-r--r-- | altoslib/AltosPointInt.java | 31 | ||||
| -rw-r--r-- | altoslib/AltosPreferences.java | 39 | ||||
| -rw-r--r-- | altoslib/AltosVersion.java.in | 28 | ||||
| -rw-r--r-- | altoslib/Makefile.am | 23 | 
24 files changed, 1610 insertions, 1 deletions
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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <aj@erisian.com.au> + * + * 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<AltosMapMark> marks = new LinkedList<AltosMapMark>(); + +	LinkedList<AltosMapZoomListener> zoom_listeners = new LinkedList<AltosMapZoomListener>(); + +	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<AltosPointInt,AltosMapTile> tiles = new ConcurrentHashMap<AltosPointInt,AltosMapTile>(); +	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<AltosPointInt> to_remove = new LinkedList<AltosPointInt>(); + +		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 <aj@erisian.com.au> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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<PathPoint>	points = new LinkedList<PathPoint>(); +	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<PathPoint>(); +	} +} 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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<AltosMapStoreListener>	listeners = new LinkedList<AltosMapStoreListener>(); + +	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<String,AltosMapStore> stores = new HashMap<String,AltosMapStore>(); + +	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 <keithp@keithp.com> + * + * 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 <aj@erisian.com.au> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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 <keithp@keithp.com> + * + * 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<AltosMapCacheListener> 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<AltosMapCacheListener>();  	}  	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 <keithp@keithp.com> + * + * 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  | 
