diff options
author | Keith Packard <keithp@keithp.com> | 2014-05-28 21:56:52 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2014-05-28 22:02:32 -0700 |
commit | 3871b9ac036e3adfa1da089245fc7973b268c921 (patch) | |
tree | f84cee06faaf7574e81836292b67ac702b69cc1b | |
parent | 4cec35564324f909dcddeb7c0d83a2daa8223042 (diff) |
telegps: Add 'Info' tab
This contains a summary of the tracking info, including position,
speed and course.
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r-- | altoslib/AltosConvert.java | 26 | ||||
-rw-r--r-- | altoslib/AltosGreatCircle.java | 26 | ||||
-rw-r--r-- | altoslib/AltosState.java | 24 | ||||
-rw-r--r-- | altosui/Makefile.am | 15 | ||||
-rw-r--r-- | altosuilib/AltosCSVUI.java (renamed from altosui/AltosCSVUI.java) | 7 | ||||
-rw-r--r-- | altosuilib/AltosDataChooser.java (renamed from altosui/AltosDataChooser.java) | 3 | ||||
-rw-r--r-- | altosuilib/AltosLed.java (renamed from altosui/AltosLed.java) | 4 | ||||
-rw-r--r-- | altosuilib/AltosLights.java (renamed from altosui/AltosLights.java) | 4 | ||||
-rw-r--r-- | altosuilib/Makefile.am | 20 | ||||
-rw-r--r-- | icon/telegps-128.png | bin | 0 -> 8736 bytes | |||
-rw-r--r-- | icon/telegps-16.png | bin | 0 -> 507 bytes | |||
-rw-r--r-- | icon/telegps-256.png | bin | 0 -> 21589 bytes | |||
-rw-r--r-- | icon/telegps-32.png | bin | 0 -> 1475 bytes | |||
-rw-r--r-- | icon/telegps-48.png | bin | 0 -> 2507 bytes | |||
-rw-r--r-- | icon/telegps-512.png | bin | 0 -> 56581 bytes | |||
-rw-r--r-- | icon/telegps-64.png | bin | 0 -> 3678 bytes | |||
-rw-r--r-- | icon/telegps.ico | bin | 0 -> 285478 bytes | |||
-rw-r--r-- | icon/telegps.svg | 215 | ||||
-rw-r--r-- | telegps/Makefile.am | 1 | ||||
-rw-r--r-- | telegps/TeleGPS.java | 13 | ||||
-rw-r--r-- | telegps/TeleGPSInfo.java | 511 |
21 files changed, 822 insertions, 47 deletions
diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 484f6213..a65669da 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -371,4 +371,30 @@ public class AltosConvert { return 94; return (int) Math.floor (1.0/2.0 * (24.0e6/32.0) / freq + 0.5); } + + public static final int BEARING_LONG = 0; + public static final int BEARING_SHORT = 1; + public static final int BEARING_VOICE = 2; + + public static String bearing_to_words(int length, double bearing) { + String [][] bearing_string = { + { + "North", "North North East", "North East", "East North East", + "East", "East South East", "South East", "South South East", + "South", "South South West", "South West", "West South West", + "West", "West North West", "North West", "North North West" + }, { + "N", "NNE", "NE", "ENE", + "E", "ESE", "SE", "SSE", + "S", "SSW", "SW", "WSW", + "W", "WNW", "NW", "NNW" + }, { + "north", "nor nor east", "north east", "east nor east", + "east", "east sow east", "south east", "sow sow east", + "south", "sow sow west", "south west", "west sow west", + "west", "west nor west", "north west", "nor nor west " + } + }; + return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; + } } diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java index 39df4fc8..4782c34d 100644 --- a/altoslib/AltosGreatCircle.java +++ b/altoslib/AltosGreatCircle.java @@ -30,30 +30,12 @@ public class AltosGreatCircle implements Cloneable { static final double rad = Math.PI / 180; static final double earth_radius = 6371.2 * 1000; /* in meters */ - public static final int BEARING_LONG = 0; - public static final int BEARING_SHORT = 1; - public static final int BEARING_VOICE = 2; + public static final int BEARING_LONG = AltosConvert.BEARING_LONG; + public static final int BEARING_SHORT = AltosConvert.BEARING_SHORT; + public static final int BEARING_VOICE = AltosConvert.BEARING_VOICE; public String bearing_words(int length) { - String [][] bearing_string = { - { - "North", "North North East", "North East", "East North East", - "East", "East South East", "South East", "South South East", - "South", "South South West", "South West", "West South West", - "West", "West North West", "North West", "North North West" - }, { - "N", "NNE", "NE", "ENE", - "E", "ESE", "SE", "SSE", - "S", "SSW", "SW", "WSW", - "W", "WNW", "NW", "NNW" - }, { - "north", "nor nor east", "north east", "east nor east", - "east", "east sow east", "south east", "sow sow east", - "south", "sow sow west", "south west", "west sow west", - "west", "west nor west", "north west", "nor nor west " - } - }; - return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; + return AltosConvert.bearing_to_words(length, bearing); } public AltosGreatCircle (double start_lat, double start_lon, double start_alt, diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 9e8e22ac..1162e522 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -389,6 +389,10 @@ public class AltosState implements Cloneable { private AltosGpsAltitude gps_altitude; + private AltosValue gps_ground_speed; + private AltosValue gps_ascent_rate; + private AltosValue gps_course; + public double altitude() { double a = altitude.value(); if (a != AltosLib.MISSING) @@ -419,6 +423,18 @@ public class AltosState implements Cloneable { gps_altitude.set(new_gps_altitude, time); } + public double gps_ground_speed() { + return gps_ground_speed.value(); + } + + public double gps_ascent_rate() { + return gps_ascent_rate.value(); + } + + public double gps_course() { + return gps_course.value(); + } + class AltosPressure extends AltosValue { void set(double p, double time) { super.set(p, time); @@ -695,6 +711,8 @@ public class AltosState implements Cloneable { gps_altitude = new AltosGpsAltitude(); gps_ground_altitude = new AltosGpsGroundAltitude(); + gps_ground_speed = new AltosValue(); + gps_ascent_rate = new AltosValue(); speak_tick = AltosLib.MISSING; speak_altitude = AltosLib.MISSING; @@ -877,6 +895,12 @@ public class AltosState implements Cloneable { gps_ground_altitude.set(gps.alt, time); } gps_altitude.set(gps.alt, time); + if (gps.climb_rate != AltosLib.MISSING) + gps_ascent_rate.set(gps.climb_rate, time); + if (gps.ground_speed != AltosLib.MISSING) + gps_ground_speed.set(gps.ground_speed, time); + if (gps.course != AltosLib.MISSING) + gps_course.set(gps.course, time); } if (gps.lat != 0 && gps.lon != 0 && pad_lat != AltosLib.MISSING && diff --git a/altosui/Makefile.am b/altosui/Makefile.am index c834646d..9eff1614 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -20,7 +20,6 @@ altosui_JAVA = \ AltosConfigureUI.java \ AltosConfigTD.java \ AltosConfigTDUI.java \ - AltosCSVUI.java \ AltosDescent.java \ AltosFlashUI.java \ AltosFlightInfoTableModel.java \ @@ -36,8 +35,6 @@ altosui_JAVA = \ AltosLaunchUI.java \ AltosInfoTable.java \ AltosLanded.java \ - AltosLed.java \ - AltosLights.java \ AltosPad.java \ AltosUIPreferencesBackend.java \ AltosRomconfigUI.java \ @@ -45,8 +42,7 @@ altosui_JAVA = \ AltosGraph.java \ AltosGraphDataPoint.java \ AltosGraphDataSet.java \ - AltosGraphUI.java \ - AltosDataChooser.java + AltosGraphUI.java JFREECHART_CLASS= \ jfreechart.jar @@ -94,20 +90,13 @@ JAVA_ICONS=\ $(ICONDIR)/altus-metrum-128.png \ $(ICONDIR)/altus-metrum-256.png -ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \ - $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \ - $(ICONDIR)/grayled.png $(ICONDIR)/grayoff.png - # icon base names for jar ICONJAR= -C $(ICONDIR) altus-metrum-16.png \ -C $(ICONDIR) altus-metrum-32.png \ -C $(ICONDIR) altus-metrum-48.png \ -C $(ICONDIR) altus-metrum-64.png \ -C $(ICONDIR) altus-metrum-128.png \ - -C $(ICONDIR) altus-metrum-256.png \ - -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \ - -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \ - -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png + -C $(ICONDIR) altus-metrum-256.png WINDOWS_ICON=$(ICONDIR)/altus-metrum.ico diff --git a/altosui/AltosCSVUI.java b/altosuilib/AltosCSVUI.java index a0fceee5..0a5e4fa2 100644 --- a/altosui/AltosCSVUI.java +++ b/altosuilib/AltosCSVUI.java @@ -15,14 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.altosuilib_2; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; public class AltosCSVUI extends AltosUIDialog @@ -43,9 +42,9 @@ public class AltosCSVUI String selected = (String) combo_box.getSelectedItem(); if (selected.contains("CSV")) - new_name = Altos.replace_extension(current_name, ".csv"); + new_name = AltosLib.replace_extension(current_name, ".csv"); else if (selected.contains("KML")) - new_name = Altos.replace_extension(current_name, ".kml"); + new_name = AltosLib.replace_extension(current_name, ".kml"); if (new_name != null) csv_chooser.setSelectedFile(new File(new_name)); } diff --git a/altosui/AltosDataChooser.java b/altosuilib/AltosDataChooser.java index 43726a44..14d28115 100644 --- a/altosui/AltosDataChooser.java +++ b/altosuilib/AltosDataChooser.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 javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; public class AltosDataChooser extends JFileChooser { JFrame frame; diff --git a/altosui/AltosLed.java b/altosuilib/AltosLed.java index 93064f1e..2debb62a 100644 --- a/altosui/AltosLed.java +++ b/altosuilib/AltosLed.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.altosuilib_2; import javax.swing.*; @@ -23,7 +23,7 @@ public class AltosLed extends JLabel { ImageIcon on, off; ImageIcon create_icon(String path) { - java.net.URL imgURL = AltosUI.class.getResource(path); + java.net.URL imgURL = AltosUILib.class.getResource(path); if (imgURL != null) return new ImageIcon(imgURL); System.err.printf("Cannot find icon \"%s\"\n", path); diff --git a/altosui/AltosLights.java b/altosuilib/AltosLights.java index 7ad22f3e..c91b70e9 100644 --- a/altosui/AltosLights.java +++ b/altosuilib/AltosLights.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.*; @@ -27,7 +27,7 @@ public class AltosLights extends JComponent { AltosLed red, green; ImageIcon create_icon(String path, String description) { - java.net.URL imgURL = AltosUI.class.getResource(path); + java.net.URL imgURL = AltosUILib.class.getResource(path); if (imgURL != null) return new ImageIcon(imgURL, description); System.err.printf("Cannot find icon \"%s\"\n", path); diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 4dc4c47f..f554fd74 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -50,6 +50,10 @@ altosuilib_JAVA = \ AltosEepromManage.java \ AltosEepromMonitorUI.java \ AltosEepromSelect.java \ + AltosCSVUI.java \ + AltosDataChooser.java \ + AltosLights.java \ + AltosLed.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ @@ -58,6 +62,18 @@ altosuilib_JAVA = \ JAR=altosuilib_$(ALTOSUILIB_VERSION).jar +# Icons +ICONDIR=$(top_srcdir)/icon + +ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \ + $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \ + $(ICONDIR)/grayon.png $(ICONDIR)/grayled.png + +# icon base names for jar +ICONJAR= -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \ + -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \ + -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png + all-local: $(JAR) clean-local: @@ -72,5 +88,5 @@ install-altosuilibJAVA: $(JAR) $(JAVAROOT): mkdir -p $(JAVAROOT) -$(JAR): classaltosuilib.stamp - jar cf $@ -C $(JAVAROOT) . +$(JAR): classaltosuilib.stamp $(ICONS) + jar cf $@ $(ICONJAR) -C $(JAVAROOT) . diff --git a/icon/telegps-128.png b/icon/telegps-128.png Binary files differnew file mode 100644 index 00000000..f1343d9e --- /dev/null +++ b/icon/telegps-128.png diff --git a/icon/telegps-16.png b/icon/telegps-16.png Binary files differnew file mode 100644 index 00000000..5bd45999 --- /dev/null +++ b/icon/telegps-16.png diff --git a/icon/telegps-256.png b/icon/telegps-256.png Binary files differnew file mode 100644 index 00000000..46e1670a --- /dev/null +++ b/icon/telegps-256.png diff --git a/icon/telegps-32.png b/icon/telegps-32.png Binary files differnew file mode 100644 index 00000000..c8588899 --- /dev/null +++ b/icon/telegps-32.png diff --git a/icon/telegps-48.png b/icon/telegps-48.png Binary files differnew file mode 100644 index 00000000..3bee98e6 --- /dev/null +++ b/icon/telegps-48.png diff --git a/icon/telegps-512.png b/icon/telegps-512.png Binary files differnew file mode 100644 index 00000000..47c47003 --- /dev/null +++ b/icon/telegps-512.png diff --git a/icon/telegps-64.png b/icon/telegps-64.png Binary files differnew file mode 100644 index 00000000..0ee086a6 --- /dev/null +++ b/icon/telegps-64.png diff --git a/icon/telegps.ico b/icon/telegps.ico Binary files differnew file mode 100644 index 00000000..bedf04ef --- /dev/null +++ b/icon/telegps.ico diff --git a/icon/telegps.svg b/icon/telegps.svg new file mode 100644 index 00000000..256b8c5a --- /dev/null +++ b/icon/telegps.svg @@ -0,0 +1,215 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + id="svg2" + width="191.28" + height="245.28" + version="1.0" + sodipodi:version="0.32" + inkscape:version="0.48.4 r9939" + sodipodi:docname="altusmetrum-only.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png" + inkscape:export-xdpi="119.89881" + inkscape:export-ydpi="119.89881"> + <metadata + id="metadata14"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs12"> + <linearGradient + id="linearGradient3165"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3167" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3169" /> + </linearGradient> + <linearGradient + id="linearGradient3177"> + <stop + style="stop-color:#da7000;stop-opacity:1;" + offset="0" + id="stop3179" /> + <stop + id="stop3447" + offset="0.24528302" + style="stop-color:#a63852;stop-opacity:1;" /> + <stop + style="stop-color:#7200a4;stop-opacity:1;" + offset="1" + id="stop3181" /> + </linearGradient> + <linearGradient + id="linearGradient3169"> + <stop + style="stop-color:#ff8a00;stop-opacity:1;" + offset="0" + id="stop3171" /> + <stop + id="stop3445" + offset="0.71698111" + style="stop-color:#c24573;stop-opacity:0.98039216;" /> + <stop + style="stop-color:#8500e7;stop-opacity:0.96078432;" + offset="1" + id="stop3173" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 121 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="191 : 121 : 1" + inkscape:persp3d-origin="95.5 : 80.666667 : 1" + id="perspective16" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3169" + id="radialGradient3175" + cx="951.68713" + cy="2305.2668" + fx="951.68713" + fy="2305.2668" + r="951.68701" + gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3165" + id="radialGradient3171" + cx="951.68713" + cy="1205.2668" + fx="951.68713" + fy="1205.2668" + r="951.68701" + gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3169" + id="radialGradient3020" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)" + cx="951.68713" + cy="2305.2668" + fx="951.68713" + fy="2305.2668" + r="951.68701" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3165" + id="radialGradient3022" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)" + cx="951.68713" + cy="1205.2668" + fx="951.68713" + fy="1205.2668" + r="951.68701" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3169" + id="radialGradient3024" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)" + cx="951.68713" + cy="2305.2668" + fx="951.68713" + fy="2305.2668" + r="951.68701" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3165" + id="radialGradient3026" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)" + cx="951.68713" + cy="1205.2668" + fx="951.68713" + fy="1205.2668" + r="951.68701" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3169" + id="radialGradient3028" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)" + cx="951.68713" + cy="2305.2668" + fx="951.68713" + fy="2305.2668" + r="951.68701" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3165" + id="radialGradient3030" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)" + cx="951.68713" + cy="1205.2668" + fx="951.68713" + fy="1205.2668" + r="951.68701" /> + </defs> + <sodipodi:namedview + inkscape:cy="107.44765" + inkscape:cx="270.26251" + inkscape:zoom="0.86831672" + inkscape:window-height="709" + inkscape:window-width="1006" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + showgrid="false" + inkscape:window-x="266" + inkscape:window-y="43" + inkscape:current-layer="svg2" + inkscape:window-maximized="0" /> + <g + transform="matrix(0.1,0,0,0.1,1.1516425,2.6405446)" + id="g3" + style="fill:url(#radialGradient3175);fill-opacity:1;stroke:url(#radialGradient3171);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"> + <g + transform="translate(20.61545,-27.69425)" + style="fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3030);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none" + id="g5"> + <path + d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z" + id="path7" + style="fill:url(#radialGradient3020);fill-opacity:1;stroke:url(#radialGradient3022);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none" + inkscape:connector-curvature="0" /> + <path + d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z" + id="path9" + style="fill:url(#radialGradient3024);fill-opacity:1;stroke:url(#radialGradient3026);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none" + inkscape:connector-curvature="0" /> + </g> + </g> +</svg> diff --git a/telegps/Makefile.am b/telegps/Makefile.am index 280b1e40..f8e2e63c 100644 --- a/telegps/Makefile.am +++ b/telegps/Makefile.am @@ -15,6 +15,7 @@ telegps_JAVA= \ TeleGPS.java \ TeleGPSStatus.java \ TeleGPSStatusUpdate.java \ + TeleGPSInfo.java \ TeleGPSConfig.java \ TeleGPSConfigUI.java \ TeleGPSPreferences.java diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index ad46fbdd..1bb505e0 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -53,6 +53,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo JTabbedPane pane; AltosSiteMap sitemap; + TeleGPSInfo gps_info; boolean has_map; JMenuBar menu_bar; @@ -115,10 +116,12 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo public void reset() { sitemap.reset(); + gps_info.reset(); } public void set_font() { sitemap.set_font(); + gps_info.set_font(); } public void font_size_changed(int font_size) { @@ -135,6 +138,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo state = new AltosState(); sitemap.show(state, listener_state); + gps_info.show(state, listener_state); telegps_status.show(state, listener_state); } @@ -225,6 +229,12 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo } void export() { + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosStateIterable states = chooser.runDialog(); + if (states == null) + return; + new AltosCSVUI(this, states, chooser.file()); } void graph() { @@ -394,6 +404,9 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo sitemap = new AltosSiteMap(); pane.add("Site Map", sitemap); + gps_info = new TeleGPSInfo(); + pane.add("Info", gps_info); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); AltosUIPreferences.register_font_listener(this); diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java new file mode 100644 index 00000000..0fba77d5 --- /dev/null +++ b/telegps/TeleGPSInfo.java @@ -0,0 +1,511 @@ +/* + * 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.telegps; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; + +public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + JLabel cur, max; + + public class Info { + JLabel label; + JTextField value; + AltosLights lights; + + void show() { + value.setVisible(true); + lights.setVisible(true); + label.setVisible(true); + } + + void hide() { + value.setVisible(false); + lights.setVisible(false); + label.setVisible(false); + } + + void show(AltosState state, AltosListenerState listener_state) {} + + void show(String s) { + show(); + value.setText(s); + } + + void show(AltosUnits units, double v) { + show(units.show(8, v)); + } + + void show(String format, double v) { + show(String.format(format, v)); + } + + void reset() { + lights.set(false); + value.setText(""); + } + + void set_font() { + label.setFont(AltosUILib.label_font); + value.setFont(AltosUILib.value_font); + } + + public Info (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + add(lights); + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(AltosUILib.text_width); + value.setFont(AltosUILib.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.gridwidth = 2; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + + public class Value { + JLabel label; + JTextField value; + void show(AltosState state, AltosListenerState listener_state) {} + + void reset() { + value.setText(""); + } + + void show() { + label.setVisible(true); + value.setVisible(true); + } + + void show(String s) { + show(); + value.setText(s); + } + + void show(AltosUnits units, double v) { + show(units.show(8, v)); + } + + void show(String format, double v) { + show(String.format(format, v)); + } + + void hide() { + label.setVisible(false); + value.setVisible(false); + } + void set_font() { + label.setFont(AltosUILib.label_font); + value.setFont(AltosUILib.value_font); + } + + public Value (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(AltosUILib.text_width); + value.setFont(AltosUILib.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.gridwidth = 2; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + + public abstract class DualValue { + JLabel label; + JTextField value1; + JTextField value2; + + void reset() { + value1.setText(""); + value2.setText(""); + } + + void show() { + label.setVisible(true); + value1.setVisible(true); + value2.setVisible(true); + } + + void hide() { + label.setVisible(false); + value1.setVisible(false); + value2.setVisible(false); + } + + void set_font() { + label.setFont(AltosUILib.label_font); + value1.setFont(AltosUILib.value_font); + value2.setFont(AltosUILib.value_font); + } + + abstract void show(AltosState state, AltosListenerState listener_state); + + void show(String v1, String v2) { + show(); + value1.setText(v1); + value2.setText(v2); + } + void show(String f1, double v1, String f2, double v2) { + show(); + value1.setText(String.format(f1, v1)); + value2.setText(String.format(f2, v2)); + } + + public DualValue (GridBagLayout layout, int x, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = x + 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value1 = new JTextField(AltosUILib.text_width); + value1.setFont(AltosUILib.value_font); + value1.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value1, c); + add(value1); + + value2 = new JTextField(AltosUILib.text_width); + value2.setFont(AltosUILib.value_font); + value2.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 3; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.gridwidth = 1; + layout.setConstraints(value2, c); + add(value2); + } + } + + public class ValueHold { + JLabel label; + JTextField value; + JTextField max_value; + double max; + + void show(AltosState state, AltosListenerState listener_state) {} + + void reset() { + value.setText(""); + max_value.setText(""); + max = AltosLib.MISSING; + } + + void set_font() { + label.setFont(AltosUILib.label_font); + value.setFont(AltosUILib.value_font); + max_value.setFont(AltosUILib.value_font); + } + + void show(AltosUnits units, double v) { + if (v == AltosLib.MISSING) { + value.setText("Missing"); + max_value.setText("Missing"); + } else { + value.setText(units.show(8, v)); + if (v > max || max == AltosLib.MISSING) { + max_value.setText(units.show(8, v)); + max = v; + } + } + } + + void hide() { + label.setVisible(false); + value.setVisible(false); + max_value.setVisible(false); + } + + public ValueHold (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(AltosUILib.text_width); + value.setFont(AltosUILib.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + + max_value = new JTextField(AltosUILib.text_width); + max_value.setFont(AltosUILib.value_font); + max_value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 3; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(max_value, c); + add(max_value); + } + } + + + class Altitude extends ValueHold { + void show (AltosState state, AltosListenerState listener_state) { + show(AltosConvert.height, state.altitude()); + } + public Altitude (GridBagLayout layout, int y) { + super (layout, y, "Altitude"); + } + } + + Altitude altitude; + + class AscentRate extends ValueHold { + void show (AltosState state, AltosListenerState listener_state) { + show(AltosConvert.speed, state.gps_ascent_rate()); + } + public AscentRate (GridBagLayout layout, int y) { + super (layout, y, "Ascent Rate"); + } + } + + AscentRate ascent_rate; + + class GroundSpeed extends ValueHold { + void show (AltosState state, AltosListenerState listener_state) { + show(AltosConvert.speed, state.gps_ground_speed()); + } + public GroundSpeed (GridBagLayout layout, int y) { + super (layout, y, "Ground Speed"); + } + } + + GroundSpeed ground_speed; + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class Course extends DualValue { + void show (AltosState state, AltosListenerState listener_state) { + double course = state.gps_course(); + if (course != AltosLib.MISSING) + show( String.format("%3.0f°", course), + AltosConvert.bearing_to_words( + AltosConvert.BEARING_LONG, + course)); + } + public Course (GridBagLayout layout, int y) { + super (layout, 0, y, "Course"); + } + } + + Course course; + + class Lat extends Value { + void show (AltosState state, AltosListenerState listener_state) { + if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING) + show(pos(state.gps.lat,"N", "S")); + else + show("???"); + } + public Lat (GridBagLayout layout, int y) { + super (layout, y, "Latitude"); + } + } + + Lat lat; + + class Lon extends Value { + void show (AltosState state, AltosListenerState listener_state) { + if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING) + show(pos(state.gps.lon,"E", "W")); + else + show("???"); + } + public Lon (GridBagLayout layout, int y) { + super (layout, y, "Longitude"); + } + } + + Lon lon; + + class GPSLocked extends Info { + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.gps == null) + hide(); + else { + show("%4d sats", state.gps.nsat); + lights.set(state.gps.locked && state.gps.nsat >= 4); + } + } + public GPSLocked (GridBagLayout layout, int y) { + super (layout, y, "GPS Locked"); + } + } + + GPSLocked gps_locked; + + public void reset() { + lat.reset(); + lon.reset(); + altitude.reset(); + ground_speed.reset(); + ascent_rate.reset(); + course.reset(); + gps_locked.reset(); + } + + public void set_font() { + cur.setFont(AltosUILib.label_font); + max.setFont(AltosUILib.label_font); + lat.set_font(); + lon.set_font(); + altitude.set_font(); + ground_speed.set_font(); + ascent_rate.set_font(); + course.set_font(); + gps_locked.set_font(); + } + + public void show(AltosState state, AltosListenerState listener_state) { + if (state.gps != null && state.gps.connected) { + lat.show(state, listener_state); + lon.show(state, listener_state); + } else { + lat.hide(); + lon.hide(); + } + altitude.show(state, listener_state); + ground_speed.show(state, listener_state); + ascent_rate.show(state, listener_state); + course.show(state, listener_state); + gps_locked.show(state, listener_state); + } + + public void labels(GridBagLayout layout, int y) { + GridBagConstraints c; + + cur = new JLabel("Current"); + cur.setFont(AltosUILib.label_font); + c = new GridBagConstraints(); + c.gridx = 2; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + layout.setConstraints(cur, c); + add(cur); + + max = new JLabel("Maximum"); + max.setFont(AltosUILib.label_font); + c.gridx = 3; c.gridy = y; + layout.setConstraints(max, c); + add(max); + } + + public String getName() { + return "Info"; + } + + public TeleGPSInfo() { + layout = new GridBagLayout(); + + setLayout(layout); + + /* Elements in ascent display: + * + * lat + * lon + * height + */ + int y = 0; + labels(layout, y++); + altitude = new Altitude(layout, y++); + ground_speed = new GroundSpeed(layout, y++); + ascent_rate = new AscentRate(layout, y++); + course = new Course(layout, y++); + lat = new Lat(layout, y++); + lon = new Lon(layout, y++); + gps_locked = new GPSLocked(layout, y++); + } +} |