diff options
| -rw-r--r-- | altoslib/AltosFlightStats.java (renamed from altosui/AltosFlightStats.java) | 63 | ||||
| -rw-r--r-- | altoslib/Makefile.am | 3 | ||||
| -rw-r--r-- | altosui/AltosSiteMapTile.java | 122 | ||||
| -rw-r--r-- | altosui/Makefile.am | 12 | ||||
| -rw-r--r-- | altosuilib/AltosDisplayThread.java (renamed from altosui/AltosDisplayThread.java) | 28 | ||||
| -rw-r--r-- | altosuilib/AltosFlightDisplay.java (renamed from altosui/AltosFlightDisplay.java) | 4 | ||||
| -rw-r--r-- | altosuilib/AltosFreqList.java (renamed from altosui/AltosFreqList.java) | 7 | ||||
| -rw-r--r-- | altosuilib/AltosSiteMap.java (renamed from altosui/AltosSiteMap.java) | 56 | ||||
| -rw-r--r-- | altosuilib/AltosSiteMapCache.java (renamed from altosui/AltosSiteMapCache.java) | 115 | ||||
| -rw-r--r-- | altosuilib/AltosSiteMapPreload.java (renamed from altosui/AltosSiteMapPreload.java) | 22 | ||||
| -rw-r--r-- | altosuilib/AltosSiteMapTile.java | 142 | ||||
| -rw-r--r-- | altosuilib/AltosVoice.java (renamed from altosui/AltosVoice.java) | 3 | ||||
| -rw-r--r-- | altosuilib/GrabNDrag.java (renamed from altosui/GrabNDrag.java) | 2 | ||||
| -rw-r--r-- | altosuilib/Makefile.am | 13 | 
14 files changed, 346 insertions, 246 deletions
| diff --git a/altosui/AltosFlightStats.java b/altoslib/AltosFlightStats.java index d02a518d..87e04293 100644 --- a/altosui/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -15,41 +15,40 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altoslib_4;  import java.io.*; -import org.altusmetrum.altoslib_3.*;  public class AltosFlightStats { -	double		max_height; -	double		max_gps_height; -	double		max_speed; -	double		max_acceleration; -	double[]	state_speed = new double[Altos.ao_flight_invalid + 1]; -	double[]	state_accel = new double[Altos.ao_flight_invalid + 1]; -	int[]		state_count = new int[Altos.ao_flight_invalid + 1]; -	double[]	state_start = new double[Altos.ao_flight_invalid + 1]; -	double[]	state_end = new double[Altos.ao_flight_invalid + 1]; -	int		serial; -	int		flight; -	int		year, month, day; -	int		hour, minute, second; -	double		lat, lon; -	double		pad_lat, pad_lon; -	boolean		has_gps; -	boolean		has_other_adc; -	boolean		has_rssi; -	boolean		has_imu; -	boolean		has_mag; -	boolean		has_orient; -	int		num_ignitor; +	public double		max_height; +	public double		max_gps_height; +	public double		max_speed; +	public double		max_acceleration; +	public double[]	state_speed = new double[AltosLib.ao_flight_invalid + 1]; +	public double[]	state_accel = new double[AltosLib.ao_flight_invalid + 1]; +	public int[]		state_count = new int[AltosLib.ao_flight_invalid + 1]; +	public double[]	state_start = new double[AltosLib.ao_flight_invalid + 1]; +	public double[]	state_end = new double[AltosLib.ao_flight_invalid + 1]; +	public int		serial; +	public int		flight; +	public int		year, month, day; +	public int		hour, minute, second; +	public double		lat, lon; +	public double		pad_lat, pad_lon; +	public boolean		has_gps; +	public boolean		has_other_adc; +	public boolean		has_rssi; +	public boolean		has_imu; +	public boolean		has_mag; +	public boolean		has_orient; +	public int		num_ignitor;  	double landed_time(AltosStateIterable states) {  		AltosState state = null;  		for (AltosState s : states) {  			state = s; -			if (state.state == Altos.ao_flight_landed) +			if (state.state == AltosLib.ao_flight_landed)  				break;  		} @@ -128,10 +127,10 @@ public class AltosFlightStats {  			end_time = state.time;  			int state_id = state.state; -			if (state.time >= boost_time && state_id < Altos.ao_flight_boost) -				state_id = Altos.ao_flight_boost; -			if (state.time >= landed_time && state_id < Altos.ao_flight_landed) -				state_id = Altos.ao_flight_landed; +			if (state.time >= boost_time && state_id < AltosLib.ao_flight_boost) +				state_id = AltosLib.ao_flight_boost; +			if (state.time >= landed_time && state_id < AltosLib.ao_flight_landed) +				state_id = AltosLib.ao_flight_landed;  			if (state.gps != null && state.gps.locked) {  				year = state.gps.year;  				month = state.gps.month; @@ -140,7 +139,7 @@ public class AltosFlightStats {  				minute = state.gps.minute;  				second = state.gps.second;  			} -			if (0 <= state_id && state_id < Altos.ao_flight_invalid) { +			if (0 <= state_id && state_id < AltosLib.ao_flight_invalid) {  				double acceleration = state.acceleration();  				double speed = state.speed();  				if (acceleration != AltosLib.MISSING && speed != AltosLib.MISSING) { @@ -158,7 +157,7 @@ public class AltosFlightStats {  				max_gps_height = state.max_gps_height();  			}  			if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { -				if (state_id <= Altos.ao_flight_pad) { +				if (state_id <= AltosLib.ao_flight_pad) {  					pad_lat = state.gps.lat;  					pad_lon = state.gps.lon;  				} @@ -175,7 +174,7 @@ public class AltosFlightStats {  			if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor)  				num_ignitor = state.ignitor_voltage.length;  		} -		for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) { +		for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) {  			if (state_count[s] > 0) {  				state_speed[s] /= state_count[s];  				state_accel[s] /= state_count[s]; diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 67cc38ff..bff09704 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -1,4 +1,4 @@ -AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6 +AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6  JAVAROOT=bin @@ -51,6 +51,7 @@ altoslib_JAVA = \  	AltosFlash.java \  	AltosFlashListener.java \  	AltosFlightReader.java \ +	AltosFlightStats.java \  	AltosFrequency.java \  	AltosGPS.java \  	AltosGPSSat.java \ diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java deleted file mode 100644 index 7d5b65e1..00000000 --- a/altosui/AltosSiteMapTile.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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 altosui; - -import java.awt.*; -import java.awt.image.*; -import javax.swing.*; -import java.awt.geom.Point2D; -import java.awt.geom.Line2D; -import org.altusmetrum.altoslib_3.*; - -public class AltosSiteMapTile extends JLayeredPane { -	JLabel mapLabel; -	JLabel draw; -	Graphics2D g2d; -	int px_size; - -	public void loadMap(ImageIcon icn) { -		mapLabel.setIcon(icn); -	} - -	public void clearMap() { -		fillLabel(mapLabel, Color.GRAY, px_size); -		g2d = fillLabel(draw, new Color(127,127,127,0), px_size); -		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, -				     RenderingHints.VALUE_ANTIALIAS_ON); -		g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); -	} - -	static Color stateColors[] = { -		Color.WHITE,  // startup -		Color.WHITE,  // idle -		Color.WHITE,  // pad -		Color.RED,    // boost -		Color.PINK,   // fast -		Color.YELLOW, // coast -		Color.CYAN,   // drogue -		Color.BLUE,   // main -		Color.BLACK   // landed -	}; - -	private boolean drawn_landed_circle = false; -	private boolean drawn_boost_circle = false; -	public synchronized void show(AltosState state, AltosListenerState listener_state, -				      Point2D.Double last_pt, Point2D.Double pt) -	{ -		if (0 <= state.state && state.state < stateColors.length) { -			g2d.setColor(stateColors[state.state]); -		} -		g2d.draw(new Line2D.Double(last_pt, pt)); - -		if (state.state == 3 && !drawn_boost_circle) { -			drawn_boost_circle = true; -			g2d.setColor(Color.RED); -			g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10); -			g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40); -			g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70); -		} -		if (state.state == 8 && !drawn_landed_circle) { -			drawn_landed_circle = true; -			g2d.setColor(Color.BLACK); -			g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); -			g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); -			g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); -		} - -		repaint(); -	} - -	public void draw_circle(Point2D.Double pt) { -		g2d.setColor(Color.RED); -		g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); -		g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); -		g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); -	} - -	public static Graphics2D fillLabel(JLabel l, Color c, int px_size) { -		BufferedImage img = new BufferedImage(px_size, px_size, -						      BufferedImage.TYPE_INT_ARGB); -		Graphics2D g = img.createGraphics(); -		g.setColor(c); -		g.fillRect(0, 0, px_size, px_size); -		l.setIcon(new ImageIcon(img)); -		return g; -	} - -	public AltosSiteMapTile(int in_px_size) { -		px_size = in_px_size; -		setPreferredSize(new Dimension(px_size, px_size)); - -		mapLabel = new JLabel(); -		fillLabel(mapLabel, Color.GRAY, px_size); -		mapLabel.setOpaque(true); -		mapLabel.setBounds(0, 0, px_size, px_size); -		add(mapLabel, new Integer(0)); - -		draw = new JLabel(); -		g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size); -		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, -				     RenderingHints.VALUE_ANTIALIAS_ON); -		g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); -		draw.setBounds(0, 0, px_size, px_size); -		draw.setOpaque(false); - -		add(draw, new Integer(1)); -	} -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 76fe9961..0440b4af 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -1,6 +1,6 @@  JAVAROOT=classes -AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6 +AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6  man_MANS=altosui.1 @@ -17,7 +17,6 @@ altosui_BT = \  	AltosBTKnown.java  altosui_JAVA = \ -	GrabNDrag.java \  	AltosAscent.java \  	AltosChannelMenu.java \  	AltosCompanionInfo.java \ @@ -31,20 +30,16 @@ altosui_JAVA = \  	AltosCSVUI.java \  	AltosDescent.java \  	AltosDeviceUIDialog.java \ -	AltosDisplayThread.java \  	AltosEepromDelete.java \  	AltosEepromManage.java \  	AltosEepromMonitorUI.java \  	AltosEepromSelect.java \  	AltosFlashUI.java \ -	AltosFlightDisplay.java \  	AltosFlightInfoTableModel.java \ -	AltosFlightStats.java \  	AltosFlightStatsTable.java \  	AltosFlightStatus.java \  	AltosFlightStatusUpdate.java \  	AltosFlightUI.java \ -	AltosFreqList.java \  	Altos.java \  	AltosIdleMonitorUI.java \  	AltosIgniteUI.java \ @@ -61,17 +56,12 @@ altosui_JAVA = \  	AltosScanUI.java \  	AltosSerial.java \  	AltosSerialInUseException.java \ -	AltosSiteMap.java \ -	AltosSiteMapPreload.java \ -	AltosSiteMapCache.java \ -	AltosSiteMapTile.java \  	AltosUI.java \  	AltosGraph.java \  	AltosGraphDataPoint.java \  	AltosGraphDataSet.java \  	AltosGraphUI.java \  	AltosDataChooser.java \ -	AltosVoice.java \  	$(altosui_BT)  JFREECHART_CLASS= \ diff --git a/altosui/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java index ab85607d..e88a891e 100644 --- a/altosui/AltosDisplayThread.java +++ b/altosuilib/AltosDisplayThread.java @@ -15,13 +15,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altosuilib_2;  import java.awt.*;  import javax.swing.*;  import java.io.*;  import java.text.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*;  public class AltosDisplayThread extends Thread { @@ -78,7 +78,7 @@ public class AltosDisplayThread extends Thread {  				return;  			/* reset the landing count once we hear about a new flight */ -			if (state.state < Altos.ao_flight_drogue) +			if (state.state < AltosLib.ao_flight_drogue)  				reported_landing = 0;  			/* Shut up once the rocket is on the ground */ @@ -87,8 +87,8 @@ public class AltosDisplayThread extends Thread {  			}  			/* If the rocket isn't on the pad, then report height */ -			if (Altos.ao_flight_drogue <= state.state && -			    state.state < Altos.ao_flight_landed && +			if (AltosLib.ao_flight_drogue <= state.state && +			    state.state < AltosLib.ao_flight_landed &&  			    state.from_pad != null &&  			    state.range >= 0)  			{ @@ -99,7 +99,7 @@ public class AltosDisplayThread extends Thread {  					    (int) (state.from_pad.bearing + 0.5),  					    (int) (state.elevation + 0.5),  					    AltosConvert.distance.say(state.range)); -			} else if (state.state > Altos.ao_flight_pad) { +			} else if (state.state > AltosLib.ao_flight_pad) {  				voice.speak(AltosConvert.height.say_units(state.height()));  			} else {  				reported_landing = 0; @@ -109,10 +109,10 @@ public class AltosDisplayThread extends Thread {  			 * either we've got a landed report or we haven't heard from it in  			 * a long time  			 */ -			if (state.state >= Altos.ao_flight_drogue && +			if (state.state >= AltosLib.ao_flight_drogue &&  			    (last ||  			     System.currentTimeMillis() - state.received_time >= 15000 || -			     state.state == Altos.ao_flight_landed)) +			     state.state == AltosLib.ao_flight_landed))  			{  				if (Math.abs(state.speed()) < 20 && state.height() < 100)  					voice.speak("rocket landed safely"); @@ -123,8 +123,8 @@ public class AltosDisplayThread extends Thread {  						    (int) (state.from_pad.bearing + 0.5),  						    AltosConvert.distance.say_units(state.from_pad.distance));  				++reported_landing; -				if (state.state != Altos.ao_flight_landed) { -					state.state = Altos.ao_flight_landed; +				if (state.state != AltosLib.ao_flight_landed) { +					state.state = AltosLib.ao_flight_landed;  					show_safely();  				}  			} @@ -183,13 +183,13 @@ public class AltosDisplayThread extends Thread {  		boolean	ret = false;  		if (old_state == null || old_state.state != state.state) {  			voice.speak(state.state_name()); -			if ((old_state == null || old_state.state <= Altos.ao_flight_boost) && -			    state.state > Altos.ao_flight_boost) { +			if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) && +			    state.state > AltosLib.ao_flight_boost) {  				voice.speak("max speed: %s.",  					    AltosConvert.speed.say_units(state.max_speed() + 0.5));  				ret = true; -			} else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) && -				   state.state >= Altos.ao_flight_drogue) { +			} else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) && +				   state.state >= AltosLib.ao_flight_drogue) {  				voice.speak("max height: %s.",  					    AltosConvert.height.say_units(state.max_height() + 0.5));  				ret = true; diff --git a/altosui/AltosFlightDisplay.java b/altosuilib/AltosFlightDisplay.java index c1264259..5695a015 100644 --- a/altosui/AltosFlightDisplay.java +++ b/altosuilib/AltosFlightDisplay.java @@ -15,9 +15,9 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altosuilib_2; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*;  public interface AltosFlightDisplay {  	void reset(); diff --git a/altosui/AltosFreqList.java b/altosuilib/AltosFreqList.java index 525e5ce5..e1299aae 100644 --- a/altosui/AltosFreqList.java +++ b/altosuilib/AltosFreqList.java @@ -15,13 +15,12 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altosuilib_2;  import javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; -public class AltosFreqList extends JComboBox { +public class AltosFreqList extends JComboBox<AltosFrequency> {  	String	product;  	int	serial; diff --git a/altosui/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index 643417b5..1cfbc8b5 100644 --- a/altosui/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -15,7 +15,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altosuilib_2;  import java.awt.*;  import javax.swing.*; @@ -23,8 +23,7 @@ import java.io.*;  import java.lang.Math;  import java.awt.geom.Point2D;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*;  public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {  	// preferred vertical step in a tile in naut. miles @@ -149,13 +148,13 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {  	}  	private void loadMap(final AltosSiteMapTile tile, -			     File pngfile, String pngurl) +			     final File pngfile, String pngurl)  	{ -		final ImageIcon res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); -		if (res != null) { +		boolean loaded = AltosSiteMapCache.fetchMap(pngfile, pngurl); +		if (loaded) {  			SwingUtilities.invokeLater(new Runnable() {  					public void run() { -						tile.loadMap(res); +						tile.loadMap(pngfile);  					}  				});  		} else { @@ -164,22 +163,30 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {  		}  	} -	File pngfile; -	String pngurl; -	public int prefetchMap(int x, int y) { +	class AltosSiteMapPrefetch { +		int	x; +		int	y; +		int	result; +		File	pngfile; +		String	pngurl; +	} + +	public AltosSiteMapPrefetch prefetchMap(int x, int y) { +		AltosSiteMapPrefetch	prefetch = new AltosSiteMapPrefetch();  		LatLng map_latlng = latlng(  			-centre.x + x*px_size + px_size/2,  			-centre.y + y*px_size + px_size/2); -		pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); -		pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); -		if (pngfile.exists()) { -			return 1; -		} else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { -			return 0; +		prefetch.pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); +		prefetch.pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); +		if (prefetch.pngfile.exists()) { +			prefetch.result = 1; +		} else if (AltosSiteMapCache.fetchMap(prefetch.pngfile, prefetch.pngurl)) { +			prefetch.result = 0;  		} else { -			return -1; +			prefetch.result = -1;  		} +		return prefetch;  	}  	public static void prefetchMaps(double lat, double lng) { @@ -193,17 +200,18 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {  		int dx = -w/2, dy = -h/2;  		for (int y = dy; y < h+dy; y++) {  			for (int x = dx; x < w+dx; x++) { -				int r = asm.prefetchMap(x, y); -				switch (r) { +				AltosSiteMapPrefetch prefetch = asm.prefetchMap(x, y); +				switch (prefetch.result) {  				case 1: -					System.out.printf("Already have %s\n", asm.pngfile); +					System.out.printf("Already have %s\n", prefetch.pngfile);  					break;  				case 0: -					System.out.printf("Fetched map %s\n", asm.pngfile); +					System.out.printf("Fetched map %s\n", prefetch.pngfile);  					break;  				case -1: -					System.out.printf("# Failed to fetch file %s\n", asm.pngfile); -					System.out.printf(" wget -O '%s' ''\n", asm.pngfile, asm.pngurl); +					System.out.printf("# Failed to fetch file %s\n", prefetch.pngfile); +					System.out.printf(" wget -O '%s' ''\n", +							  prefetch.pngfile, prefetch.pngurl);  					break;  				}  			} @@ -362,7 +370,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {  		for (Point offset : mapTiles.keySet()) {  			AltosSiteMapTile tile = mapTiles.get(offset);  			Point2D.Double ref = translatePoint(pt, tileCoordOffset(offset)); -			tile.draw_circle(ref); +			tile.set_boost(ref);  		}  	} diff --git a/altosui/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index 03dc3cf5..cf93016a 100644 --- a/altosui/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -15,21 +15,79 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altosuilib_2;  import javax.swing.*;  import javax.imageio.ImageIO;  import java.awt.image.*; +import java.awt.*;  import java.io.*;  import java.net.URL;  import java.net.URLConnection; + +class AltosCacheImage { +	Component	component; +	File		file; +	VolatileImage	image; +	int		width; +	int		height; +	long		used; + +	public void load_image() throws IOException { +		BufferedImage	bimg = ImageIO.read(file); +		Graphics2D	g = image.createGraphics(); +		g.drawImage(bimg, 0, 0, null); +		bimg.flush(); +	} + +	public Image validate() { +		int	returnCode; + +		if (image != null) +			returnCode = image.validate(component.getGraphicsConfiguration()); +		else +			returnCode = VolatileImage.IMAGE_INCOMPATIBLE; +		if (returnCode == VolatileImage.IMAGE_RESTORED) { +			try { +				load_image(); +			} catch (IOException e) { +				return null; +			} +		} else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) { +			image = component.createVolatileImage(width, height); +			try { +				load_image(); +			} catch (IOException e) { +				return null; +			} +		} +		return image; +	} + +	public void flush() { +		image.flush(); +	} + +	public AltosCacheImage(Component component, File file, int w, int h) throws IOException { +		this.component = component; +		this.file = file; +		width = w; +		height = h; +		image = component.createVolatileImage(w, h); +		used = 0; +	} +} +  public class AltosSiteMapCache extends JLabel {  	static final long google_maps_ratelimit_ms = 1200;  	// Google limits static map queries to 50 per minute per IP, so  	// each query should take at least 1.2 seconds.  	public static boolean fetchMap(File file, String url) { +		if (file.exists()) +			return true; +  		URL u;  		long startTime = System.nanoTime(); @@ -88,31 +146,48 @@ public class AltosSiteMapCache extends JLabel {  		return true;  	} -	public static ImageIcon fetchAndLoadMap(File pngfile, String url) { -		if (!pngfile.exists()) { -			if (!fetchMap(pngfile, url)) { -				return null; -			} -		} -		return loadMap(pngfile, url); +	static int			cache_size = 9; + +	static AltosCacheImage[]	images; + +	static long			used; + +	public static void set_cache_size(int cache_size) { +		AltosSiteMapCache.cache_size = cache_size; +		images = null;  	} -	public static ImageIcon loadMap(File pngfile, String url) { -		if (!pngfile.exists()) { -			return null; +	public static Image get_image(Component component, File file, int width, int height) { +		int		oldest = -1; +		long		age = used; +		AltosCacheImage	image; +		if (images == null) +			images = new AltosCacheImage[cache_size]; +		for (int i = 0; i < cache_size; i++) { +			image = images[i]; + +			if (image == null) { +				oldest = i; +				break; +			} +			if (image.component == component && file.equals(image.file)) { +				image.used = used++; +				return image.validate(); +			} +			if (image.used < age) { +				oldest = i; +				age = image.used; +			}  		}  		try { -			BufferedImage	img; - -			img = ImageIO.read(pngfile); -			if (img == null) { -				System.out.printf("# Can't read pngfile %s\n", pngfile); -				return null; -			} -			return new ImageIcon(img); +			image = new AltosCacheImage(component, file, width, height); +			image.used = used++; +			if (images[oldest] != null) +				images[oldest].flush(); +			images[oldest] = image; +			return image.validate();  		} catch (IOException e) { -			System.out.printf("# IO error trying to load %s\n", pngfile);  			return null;  		}  	} diff --git a/altosui/AltosSiteMapPreload.java b/altosuilib/AltosSiteMapPreload.java index 8380b967..baa7fc37 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosuilib/AltosSiteMapPreload.java @@ -15,7 +15,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altosuilib_2;  import java.awt.*;  import java.awt.event.*; @@ -26,10 +26,10 @@ import java.text.*;  import java.lang.Math;  import java.net.URL;  import java.net.URLConnection; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*;  class AltosMapPos extends Box { -	AltosUI		owner; +	AltosUIFrame	owner;  	JLabel		label;  	JComboBox	hemi;  	JTextField	deg; @@ -87,14 +87,14 @@ class AltosMapPos extends Box {  		return v;  	} -	public AltosMapPos(AltosUI in_owner, +	public AltosMapPos(AltosUIFrame in_owner,  			   String label_value,  			   String[] hemi_names,  			   double default_value) {  		super(BoxLayout.X_AXIS);  		owner = in_owner;  		label = new JLabel(label_value); -		hemi = new JComboBox(hemi_names); +		hemi = new JComboBox<String>(hemi_names);  		hemi.setEditable(false);  		deg = new JTextField(5);  		deg.setMinimumSize(deg.getPreferredSize()); @@ -179,7 +179,7 @@ class AltosSites extends Thread {  			URLConnection uc = url.openConnection();  			//int length = uc.getContentLength(); -			InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), Altos.unicode_set); +			InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set);  			BufferedReader in = new BufferedReader(in_stream);  			for (;;) { @@ -198,7 +198,7 @@ class AltosSites extends Thread {  		sites = new LinkedList<AltosSite>();  		preload = in_preload;  		try { -			url = new URL(Altos.launch_sites_url); +			url = new URL(AltosLib.launch_sites_url);  		} catch (java.net.MalformedURLException e) {  			notify_complete();  		} @@ -207,7 +207,7 @@ class AltosSites extends Thread {  }  public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener, ItemListener { -	AltosUI		owner; +	AltosUIFrame	owner;  	AltosSiteMap	map;  	AltosMapPos	lat; @@ -221,7 +221,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener  	AltosSites	sites;  	JLabel		site_list_label; -	JComboBox	site_list; +	JComboBox<AltosSite>	site_list;  	JToggleButton	load_button;  	boolean		loading; @@ -317,7 +317,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener  		}  	} -	public AltosSiteMapPreload(AltosUI in_owner) { +	public AltosSiteMapPreload(AltosUIFrame in_owner) {  		owner = in_owner;  		Container		pane = getContentPane(); @@ -374,7 +374,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener  		pane.add(site_list_label, c); -		site_list = new JComboBox(new String[] { "Site List" }); +		site_list = new JComboBox<AltosSite>(new AltosSite[] { new AltosSite("Site List", 0, 0) });  		site_list.addItemListener(this);  		sites = new AltosSites(this); diff --git a/altosuilib/AltosSiteMapTile.java b/altosuilib/AltosSiteMapTile.java new file mode 100644 index 00000000..1046d6bd --- /dev/null +++ b/altosuilib/AltosSiteMapTile.java @@ -0,0 +1,142 @@ +/* + * 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.altosuilib_2; + +import java.awt.*; +import java.awt.image.*; +import javax.swing.*; +import javax.imageio.*; +import java.awt.geom.Point2D; +import java.awt.geom.Line2D; +import java.io.*; +import java.util.*; +import org.altusmetrum.altoslib_4.*; + +class AltosPoint { +	Point2D.Double	pt; +	int		state; + +	AltosPoint(Point2D.Double pt, int state) { +		this.pt = pt; +		this.state = state; +	} +} + +public class AltosSiteMapTile extends JComponent { +	int px_size; +	File file; + +	Point2D.Double	boost; +	Point2D.Double	landed; + +	LinkedList<AltosPoint>	points; + +	public void loadMap(File pngFile) { +		file = pngFile; +		repaint(); +	} + +	public void clearMap() { +		boost = null; +		landed = null; +		points = null; +		file = null; +	} + +	static Color stateColors[] = { +		Color.WHITE,  // startup +		Color.WHITE,  // idle +		Color.WHITE,  // pad +		Color.RED,    // boost +		Color.PINK,   // fast +		Color.YELLOW, // coast +		Color.CYAN,   // drogue +		Color.BLUE,   // main +		Color.BLACK   // landed +	}; + +	private void draw_circle(Graphics g, Point2D.Double pt) { +		g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); +		g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); +		g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); +	} + +	public void set_boost(Point2D.Double boost) { +		this.boost = boost; +		repaint(); +	} + +	public void paint(Graphics g) { +		Graphics2D	g2d = (Graphics2D) g; +		AltosPoint	prev = null; +		Image		img = null; + +		if (file != null) +			img = AltosSiteMapCache.get_image(this, file, px_size, px_size); + +		if (img != null) { +			g2d.drawImage(img, 0, 0, null); +		} else { +			g2d.setColor(Color.GRAY); +			g2d.fillRect(0, 0, getWidth(), getHeight()); +		} + +		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, +				   RenderingHints.VALUE_ANTIALIAS_ON); +		g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + +		if (points != null) { +			for (AltosPoint point : points) { +				if (prev != null) { +					if (0 <= point.state && point.state < stateColors.length) +						g2d.setColor(stateColors[point.state]); +					g2d.draw(new Line2D.Double(prev.pt, point.pt)); +				} +				prev = point; +			} +		} +		if (boost != null) { +			g2d.setColor(Color.RED); +			draw_circle(g2d, boost); +		} +		if (landed != null) { +			g2d.setColor(Color.BLACK); +			draw_circle(g2d, landed); +		} +	} + +	public synchronized void show(AltosState state, AltosListenerState listener_state, +				      Point2D.Double last_pt, Point2D.Double pt) +	{ +		if (points == null) +			points = new LinkedList<AltosPoint>(); + +		points.add(new AltosPoint(pt, state.state)); + +		if (state.state == AltosLib.ao_flight_boost && boost == null) +			boost = pt; +		if (state.state == AltosLib.ao_flight_landed && landed == null) +			landed = pt; +		repaint(); +	} + +	public AltosSiteMapTile(int in_px_size) { +		px_size = in_px_size; +		setPreferredSize(new Dimension(px_size, px_size)); +	} +} diff --git a/altosui/AltosVoice.java b/altosuilib/AltosVoice.java index 2ed6a8c2..a3995f68 100644 --- a/altosui/AltosVoice.java +++ b/altosuilib/AltosVoice.java @@ -15,12 +15,11 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altosuilib_2;  import com.sun.speech.freetts.Voice;  import com.sun.speech.freetts.VoiceManager;  import java.util.concurrent.LinkedBlockingQueue; -import org.altusmetrum.altosuilib_1.*;  public class AltosVoice implements Runnable {  	VoiceManager			voice_manager; diff --git a/altosui/GrabNDrag.java b/altosuilib/GrabNDrag.java index 2fd6c4da..5e5fdd52 100644 --- a/altosui/GrabNDrag.java +++ b/altosuilib/GrabNDrag.java @@ -15,7 +15,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package altosui; +package org.altusmetrum.altosuilib_2;  import java.awt.*;  import java.awt.event.*; diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 4b22af1f..b7d624e2 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -1,4 +1,4 @@ -AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6 +AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6  JAVAROOT=bin @@ -9,8 +9,10 @@ SRC=.  altosuilibdir = $(datadir)/java  altosuilib_JAVA = \ +	GrabNDrag.java \  	AltosDevice.java \  	AltosDeviceDialog.java \ +	AltosFlightDisplay.java \  	AltosFontListener.java \  	AltosPositionListener.java \  	AltosUIConfigure.java \ @@ -30,7 +32,14 @@ altosuilib_JAVA = \  	AltosUIPreferences.java \  	AltosUISeries.java \  	AltosUIVersion.java \ -	AltosUSBDevice.java +	AltosUSBDevice.java \ +	AltosSiteMap.java \ +	AltosSiteMapCache.java \ +	AltosSiteMapPreload.java \ +	AltosSiteMapTile.java \ +	AltosVoice.java \ +	AltosDisplayThread.java \ +	AltosFreqList.java  JAR=altosuilib_$(ALTOSUILIB_VERSION).jar | 
