altosui/altoslib/altosuilib: Switch altosui to shared graph code
authorKeith Packard <keithp@keithp.com>
Sun, 10 Feb 2013 08:29:29 +0000 (00:29 -0800)
committerKeith Packard <keithp@keithp.com>
Sun, 10 Feb 2013 08:30:32 +0000 (00:30 -0800)
This adds a configuration tab to the graph window to enable/disable
various plotted values.

Signed-off-by: Keith Packard <keithp@keithp.com>
21 files changed:
altoslib/AltosConvert.java
altoslib/AltosHeight.java
altoslib/AltosTemperature.java [new file with mode: 0644]
altoslib/AltosUnits.java
altoslib/Makefile.am
altosui/AltosDataPoint.java [deleted file]
altosui/AltosDataPointReader.java [deleted file]
altosui/AltosGraph.java
altosui/AltosGraphDataPoint.java [new file with mode: 0644]
altosui/AltosGraphDataSet.java [new file with mode: 0644]
altosui/AltosGraphTime.java [deleted file]
altosui/AltosGraphUI.java
altosui/Makefile.am
altosuilib/AltosUIAxis.java [new file with mode: 0644]
altosuilib/AltosUIDataMissing.java [new file with mode: 0644]
altosuilib/AltosUIDataPoint.java
altosuilib/AltosUIEnable.java
altosuilib/AltosUIGraph.java
altosuilib/AltosUIMarker.java
altosuilib/AltosUISeries.java
altosuilib/Makefile.am

index 8adec06..a42b36c 100644 (file)
@@ -258,6 +258,10 @@ public class AltosConvert {
                return meters / 9.80665;
        }
 
+       public static double c_to_f(double c) {
+               return c * 9/5 + 32;
+       }
+
        public static boolean imperial_units = false;
 
        public static AltosDistance distance = new AltosDistance();
@@ -268,6 +272,8 @@ public class AltosConvert {
 
        public static AltosAccel accel = new AltosAccel();
 
+       public static AltosTemperature temperature = new AltosTemperature();
+
        public static String show_gs(String format, double a) {
                a = meters_to_g(a);
                format = format.concat(" g");
index e0fef5f..ed59081 100644 (file)
@@ -37,7 +37,7 @@ public class AltosHeight extends AltosUnits {
                return "meters";
        }
 
-       int show_fraction(int width) {
+       public int show_fraction(int width) {
                return width / 9;
        }
 }
\ No newline at end of file
diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java
new file mode 100644 (file)
index 0000000..2749eac
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2012 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_1;
+
+public class AltosTemperature extends AltosUnits {
+
+       public double value(double v) {
+               if (AltosConvert.imperial_units)
+                       return AltosConvert.c_to_f(v);
+               return v;
+       }
+
+       public String show_units() {
+               if (AltosConvert.imperial_units)
+                       return "°F";
+               return "°C";
+       }
+
+       public String say_units() {
+               if (AltosConvert.imperial_units)
+                       return "degrees farenheit";
+               return "degrees celsius";
+       }
+
+       public int show_fraction(int width) {
+               return width / 3;
+       }
+}
index 4f4278b..b8b3254 100644 (file)
@@ -25,7 +25,7 @@ public abstract class AltosUnits {
 
        public abstract String say_units();
 
-       abstract int show_fraction(int width);
+       public abstract int show_fraction(int width);
 
        int say_fraction() {
                return 0;
index 74c642d..8e5701a 100644 (file)
@@ -78,6 +78,7 @@ altoslib_JAVA = \
        AltosDistance.java \
        AltosHeight.java \
        AltosSpeed.java \
+       AltosTemperature.java \
        AltosAccel.java \
        AltosPyro.java
 
diff --git a/altosui/AltosDataPoint.java b/altosui/AltosDataPoint.java
deleted file mode 100644 (file)
index 4956e9f..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
-
-package altosui;
-
-interface AltosDataPoint {
-    int version();
-    int serial();
-    int flight();
-    String callsign();
-    double time();
-    double rssi();
-
-    int state();
-    String state_name();
-
-    double acceleration();
-    double height();
-    double speed();
-    double temperature();
-    double battery_voltage();
-    double drogue_voltage();
-    double main_voltage();
-    boolean has_accel();
-}
-
diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java
deleted file mode 100644 (file)
index 0b4bd6c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
-
-package altosui;
-
-import java.lang.UnsupportedOperationException;
-import java.util.NoSuchElementException;
-import java.util.Iterator;
-import org.altusmetrum.altoslib_1.*;
-
-class AltosDataPointReader implements Iterable<AltosDataPoint> {
-    Iterator<AltosRecord> iter;
-    AltosState state;
-    boolean has_gps;
-    boolean has_accel;
-    boolean has_ignite;
-
-    final static int MISSING = AltosRecord.MISSING;
-
-    public AltosDataPointReader(AltosRecordIterable reader) {
-        this.iter = reader.iterator();
-        this.state = null;
-       has_accel = true;
-       has_gps = reader.has_gps();
-       has_ignite = reader.has_ignite();
-    }
-
-    private void read_next_record() 
-        throws NoSuchElementException
-    {
-        state = new AltosState(iter.next(), state);
-    }
-
-    private AltosDataPoint current_dp() {
-        assert this.state != null;
-        
-        return new AltosDataPoint() {
-            public int version() { return state.data.version; }
-            public int serial() { return state.data.serial; }
-            public int flight() { return state.data.flight; }
-            public String callsign() { return state.data.callsign; }
-            public double time() { return state.data.time; }
-            public double rssi() { return state.data.rssi; }
-
-            public int state() { return state.state; }
-            public String state_name() { return state.data.state(); }
-
-            public double acceleration() { return state.acceleration; }
-           public double height() { return state.height; }
-           public double speed() { return state.speed(); }
-            public double temperature() { return state.temperature; }
-            public double battery_voltage() { return state.battery; }
-            public double drogue_voltage() { return state.drogue_sense; }
-            public double main_voltage() { return state.main_sense; }
-           public boolean has_accel() { return true; } // return state.acceleration != AltosRecord.MISSING; }
-        };
-    }
-
-    public Iterator<AltosDataPoint> iterator() {
-        return new Iterator<AltosDataPoint>() {
-            public void remove() { 
-                throw new UnsupportedOperationException(); 
-            }
-            public boolean hasNext() {
-               if (state != null && state.state == Altos.ao_flight_landed)
-                   return false;
-                return iter.hasNext();
-            }
-            public AltosDataPoint next() {
-               do {
-                   read_next_record();
-               } while (state.data.time < -1.0 && hasNext());
-                return current_dp();
-            }
-        };
-    }
-}
-
index fbcefd6..9383824 100644 (file)
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
+/*
+ * Copyright © 2013 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 altosui;
 
 import java.io.*;
+import java.util.ArrayList;
+
+import java.awt.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altosuilib_1.*;
+
+import org.jfree.ui.*;
+import org.jfree.chart.*;
+import org.jfree.chart.plot.*;
+import org.jfree.chart.axis.*;
+import org.jfree.chart.renderer.*;
+import org.jfree.chart.renderer.xy.*;
+import org.jfree.chart.labels.*;
+import org.jfree.data.xy.*;
+import org.jfree.data.*;
+
+class AltosVoltage extends AltosUnits {
+
+       public double value(double v) {
+               return v;
+       }
+
+       public String show_units() {
+               return "V";
+       }
+
+       public String say_units() {
+               return "volts";
+       }
+
+       public int show_fraction(int width) {
+               return width / 9;
+       }
+}
+
+class AltosNsat extends AltosUnits {
+
+       public double value(double v) {
+               return v;
+       }
+
+       public String show_units() {
+               return "Sats";
+       }
+
+       public String say_units() {
+               return "Satellites";
+       }
 
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.ChartUtilities;
-
-abstract class AltosGraph {
-    public String filename;
-    public abstract void addData(AltosDataPoint d);
-    public abstract JFreeChart createChart();
-    public String title;
-    public void toPNG() throws java.io.IOException { toPNG(300, 500); }
-    public void toPNG(int width, int height)
-        throws java.io.IOException
-    {
-        File pngout = new File(filename);
-        JFreeChart chart = createChart();
-        ChartUtilities.saveChartAsPNG(pngout, chart, width, height);
-        System.out.println("Created " + filename);
-    }
+       public int show_fraction(int width) {
+               return 0;
+       }
 }
+
+class AltosDbm extends AltosUnits {
+
+       public double value(double v) {
+               return v;
+       }
+
+       public String show_units() {
+               return "dBm";
+       }
+
+       public String say_units() {
+               return "d b m";
+       }
+
+       public int show_fraction(int width) {
+               return 0;
+       }
+}
+
+public class AltosGraph extends AltosUIGraph {
+
+       static final private Color height_color = new Color(194,31,31);
+       static final private Color gps_height_color = new Color(150,31,31);
+       static final private Color range_color = new Color(100, 31, 31);
+       static final private Color distance_color = new Color(100, 31, 194);
+       static final private Color speed_color = new Color(31,194,31);
+       static final private Color accel_color = new Color(31,31,194);
+       static final private Color voltage_color = new Color(194, 194, 31);
+       static final private Color battery_voltage_color = new Color(194, 194, 31);
+       static final private Color drogue_voltage_color = new Color(150, 150, 31);
+       static final private Color main_voltage_color = new Color(100, 100, 31);
+       static final private Color gps_nsat_color = new Color (194, 31, 194);
+       static final private Color gps_nsat_solution_color = new Color (194, 31, 194);
+       static final private Color gps_nsat_view_color = new Color (150, 31, 150);
+       static final private Color temperature_color = new Color (31, 194, 194);
+       static final private Color dbm_color = new Color(31, 100, 100);
+       static final private Color state_color = new Color(0,0,0);
+
+       static AltosVoltage voltage_units = new AltosVoltage();
+       static AltosNsat nsat_units = new AltosNsat();
+       static AltosDbm dbm_units = new AltosDbm();
+
+       AltosUIAxis     height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis;
+       AltosUIAxis     distance_axis;
+
+       public AltosGraph(AltosUIEnable enable) {
+               super(enable);
+
+               height_axis = newAxis("Height", AltosConvert.height, height_color);
+               speed_axis = newAxis("Speed", AltosConvert.speed, speed_color);
+               accel_axis = newAxis("Acceleration", AltosConvert.accel, accel_color);
+               voltage_axis = newAxis("Voltage", voltage_units, voltage_color);
+               temperature_axis = newAxis("Temperature", AltosConvert.temperature, temperature_color, 0);
+               nsat_axis = newAxis("Satellites", nsat_units, gps_nsat_color,
+                                   AltosUIAxis.axis_include_zero | AltosUIAxis.axis_integer);
+               dbm_axis = newAxis("Signal Strength", dbm_units, dbm_color, 0);
+               distance_axis = newAxis("Distance", AltosConvert.distance, range_color);
+
+               addMarker("State", AltosGraphDataPoint.data_state, state_color);
+               addSeries("Height",
+                         AltosGraphDataPoint.data_height,
+                         AltosConvert.height,
+                         height_color,
+                         true,
+                         height_axis);
+               addSeries("Speed",
+                         AltosGraphDataPoint.data_speed,
+                         AltosConvert.speed,
+                         speed_color,
+                         true,
+                         speed_axis);
+               addSeries("Acceleration",
+                         AltosGraphDataPoint.data_accel,
+                         AltosConvert.accel,
+                         accel_color,
+                         true,
+                         accel_axis);
+               addSeries("Range",
+                         AltosGraphDataPoint.data_range,
+                         AltosConvert.distance,
+                         range_color,
+                         false,
+                         distance_axis);
+               addSeries("Distance",
+                         AltosGraphDataPoint.data_distance,
+                         AltosConvert.distance,
+                         distance_color,
+                         false,
+                         distance_axis);
+               addSeries("GPS Height",
+                         AltosGraphDataPoint.data_gps_height,
+                         AltosConvert.height,
+                         gps_height_color,
+                         false,
+                         height_axis);
+               addSeries("GPS Satellites in Solution",
+                         AltosGraphDataPoint.data_gps_nsat_solution,
+                         nsat_units,
+                         gps_nsat_solution_color,
+                         false,
+                         nsat_axis);
+               addSeries("GPS Satellites in View",
+                         AltosGraphDataPoint.data_gps_nsat_view,
+                         nsat_units,
+                         gps_nsat_view_color,
+                         false,
+                         nsat_axis);
+               addSeries("Received Signal Strength",
+                         AltosGraphDataPoint.data_rssi,
+                         dbm_units,
+                         dbm_color,
+                         false,
+                         dbm_axis);
+               addSeries("Temperature",
+                         AltosGraphDataPoint.data_temperature,
+                         AltosConvert.temperature,
+                         temperature_color,
+                         false,
+                         temperature_axis);
+               addSeries("Battery Voltage",
+                         AltosGraphDataPoint.data_battery_voltage,
+                         voltage_units,
+                         battery_voltage_color,
+                         false,
+                         voltage_axis);
+               addSeries("Drogue Voltage",
+                         AltosGraphDataPoint.data_drogue_voltage,
+                         voltage_units,
+                         drogue_voltage_color,
+                         false,
+                         voltage_axis);
+               addSeries("Main Voltage",
+                         AltosGraphDataPoint.data_main_voltage,
+                         voltage_units,
+                         main_voltage_color,
+                         false,
+                         voltage_axis);
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosGraphDataPoint.java b/altosui/AltosGraphDataPoint.java
new file mode 100644 (file)
index 0000000..8e6d692
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2013 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 altosui;
+
+import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_1.*;
+
+public class AltosGraphDataPoint implements AltosUIDataPoint {
+
+       AltosState      state;
+
+       public static final int data_height = 0;
+       public static final int data_speed = 1;
+       public static final int data_accel = 2;
+       public static final int data_temp = 3;
+       public static final int data_battery_voltage = 4;
+       public static final int data_drogue_voltage = 5;
+       public static final int data_main_voltage = 6;
+       public static final int data_rssi = 7;
+       public static final int data_state = 8;
+       public static final int data_gps_height = 9;
+       public static final int data_gps_nsat_solution = 10;
+       public static final int data_gps_nsat_view = 11;
+       public static final int data_temperature = 12;
+       public static final int data_range = 13;
+       public static final int data_distance = 14;
+
+       public double x() throws AltosUIDataMissing {
+               if (state.data.time < -2)
+                       throw new AltosUIDataMissing(-1);
+               return state.data.time;
+       }
+
+       public double y(int index) throws AltosUIDataMissing {
+               double y = AltosRecord.MISSING;
+               switch (index) {
+               case data_height:
+                       y = state.height;
+                       break;
+               case data_speed:
+                       y = state.speed();
+                       break;
+               case data_accel:
+                       y = state.acceleration;
+                       break;
+               case data_temp:
+                       y = state.temperature;
+                       break;
+               case data_battery_voltage:
+                       y = state.battery;
+                       break;
+               case data_drogue_voltage:
+                       y = state.drogue_sense;
+                       break;
+               case data_main_voltage:
+                       y = state.main_sense;
+                       break;
+               case data_rssi:
+                       y = state.data.rssi;
+                       break;
+               case data_gps_height:
+                       y = state.gps_height;
+                       break;  
+               case data_gps_nsat_solution:
+                       if (state.gps != null)
+                               y = state.gps.nsat;
+                       break;
+               case data_gps_nsat_view:
+                       if (state.gps != null && state.gps.cc_gps_sat != null)
+                               y = state.gps.cc_gps_sat.length;
+                       break;
+               case data_temperature:
+                       y = state.temperature;
+                       break;
+               case data_range:
+                       y = state.range;
+                       break;
+               case data_distance:
+                       if (state.from_pad != null)
+                               y = state.from_pad.distance;
+                       break;
+               }
+               if (y == AltosRecord.MISSING)
+                       throw new AltosUIDataMissing(index);
+               return y;
+       }
+
+       public int id(int index) {
+               if (index == data_state) {
+                       int s = state.data.state;
+                       if (s < Altos.ao_flight_boost || s > Altos.ao_flight_landed)
+                               return -1;
+                       return s;
+               }
+               return 0;
+       }
+
+       public String id_name(int index) {
+               if (index == data_state)
+                       return state.data.state();
+               return "";
+       }
+
+       public AltosGraphDataPoint (AltosState state) {
+               this.state = state;
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosGraphDataSet.java b/altosui/AltosGraphDataSet.java
new file mode 100644 (file)
index 0000000..092b7c7
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2013 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 altosui;
+
+import java.lang.*;
+import java.io.*;
+import java.util.*;
+import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altosuilib_1.*;
+
+class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
+       AltosGraphDataSet       dataSet;
+       Iterator<AltosRecord>   iterator;
+
+       AltosState      state;
+
+       public boolean hasNext() {
+               return iterator.hasNext();
+       }
+
+       public AltosUIDataPoint next() {
+               state = new AltosState(iterator.next(), state);
+
+               if (dataSet.callsign == null && state.data.callsign != null)
+                       dataSet.callsign = state.data.callsign;
+
+               if (dataSet.serial == 0 && state.data.serial != 0)
+                       dataSet.serial = state.data.serial;
+
+               if (dataSet.flight == 0 && state.data.flight != 0)
+                       dataSet.flight = state.data.flight;
+
+               return new AltosGraphDataPoint(state);
+       }
+
+       public AltosGraphIterator (Iterator<AltosRecord> iterator, AltosGraphDataSet dataSet) {
+               this.iterator = iterator;
+               this.state = null;
+               this.dataSet = dataSet;
+       }
+
+       public void remove() {
+       }
+}
+
+class AltosGraphIterable implements Iterable<AltosUIDataPoint> {
+       AltosGraphDataSet       dataSet;
+
+       public Iterator<AltosUIDataPoint> iterator() {
+               return new AltosGraphIterator(dataSet.records.iterator(), dataSet);
+       }
+
+       public AltosGraphIterable(AltosGraphDataSet dataSet) {
+               this.dataSet = dataSet;
+       }
+}
+
+public class AltosGraphDataSet implements AltosUIDataSet {
+       String                  callsign;
+       int                     serial;
+       int                     flight;
+       AltosRecordIterable     records;
+
+       public String name() {
+               if (callsign != null)
+                       return String.format("%s - %d/%d", callsign, serial, flight);
+               else
+                       return String.format("%d/%d", serial, flight);
+       }
+
+       public Iterable<AltosUIDataPoint> dataPoints() {
+               return new AltosGraphIterable(this);
+       }
+
+       public AltosGraphDataSet (AltosRecordIterable records) {
+               this.records = records;
+               this.callsign = null;
+               this.serial = 0;
+               this.flight = 0;
+       }
+}
diff --git a/altosui/AltosGraphTime.java b/altosui/AltosGraphTime.java
deleted file mode 100644 (file)
index 62d516b..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
-
-package altosui;
-
-import java.util.*;
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.HashMap;
-import org.jfree.chart.ChartUtilities;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.axis.AxisLocation;
-import org.jfree.chart.axis.NumberAxis;
-import org.jfree.chart.labels.StandardXYToolTipGenerator;
-import org.jfree.chart.plot.PlotOrientation;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.plot.ValueMarker;
-import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
-import org.jfree.chart.renderer.xy.XYItemRenderer;
-import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
-import org.jfree.data.xy.XYSeries;
-import org.jfree.data.xy.XYSeriesCollection;
-import org.jfree.ui.RectangleAnchor;
-import org.jfree.ui.TextAnchor;
-
-class AltosGraphTime extends AltosGraph {
-    static interface Element {
-        void attachGraph(AltosGraphTime g);
-        void gotTimeData(double time, AltosDataPoint d);
-        void addToPlot(AltosGraphTime g, XYPlot plot);
-    }
-
-    static class TimeAxis implements Element {
-        private int axis;
-        private Color color;
-        private String label;
-        private AxisLocation locn;
-        private double min_y = Double.NaN;
-
-        public TimeAxis(int axis, String label, Color color, AxisLocation locn)
-        {
-            this.axis = axis;
-            this.color = color;
-            this.label = label;
-            this.locn = locn;
-        }
-
-        public void setLowerBound(double min_y) {
-            this.min_y = min_y;
-        }
-
-        public void attachGraph(AltosGraphTime g) { return; }
-        public void gotTimeData(double time, AltosDataPoint d) { return; }
-
-        public void addToPlot(AltosGraphTime g, XYPlot plot) {
-            NumberAxis numAxis = new NumberAxis(label);
-            if (!Double.isNaN(min_y))
-                numAxis.setLowerBound(min_y);
-            plot.setRangeAxis(axis, numAxis);
-            plot.setRangeAxisLocation(axis, locn);
-            numAxis.setLabelPaint(color);
-            numAxis.setTickLabelPaint(color);
-            numAxis.setAutoRangeIncludesZero(false);
-        }
-    }
-
-    abstract static class TimeSeries implements Element {
-        protected XYSeries series;
-        private String axisName;
-       private String axisUnits;
-        private Color color;
-
-        public TimeSeries(String axisName, String axisUnits, String label, Color color) {
-            this.series = new XYSeries(label);
-            this.axisName = String.format("%s (%s)", axisName, axisUnits);
-           this.axisUnits = axisUnits;
-            this.color = color;
-        }
-
-        public void attachGraph(AltosGraphTime g) {
-            g.setAxis(this, axisName, color);
-        }
-        abstract public void gotTimeData(double time, AltosDataPoint d);
-
-        public void addToPlot(AltosGraphTime g, XYPlot plot) {
-            XYSeriesCollection dataset = new XYSeriesCollection();
-            dataset.addSeries(this.series);
-
-            XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
-            renderer.setSeriesPaint(0, color);
-           StandardXYToolTipGenerator  tool_tip;
-
-           tool_tip = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", axisUnits),
-                                                     new java.text.DecimalFormat("0.00"),
-                                                     new java.text.DecimalFormat("0.00"));
-           renderer.setBaseToolTipGenerator(tool_tip);
-
-            int dataNum = g.getDataNum(this);
-            int axisNum = g.getAxisNum(this);
-
-            plot.setDataset(dataNum, dataset);
-            plot.mapDatasetToRangeAxis(dataNum, axisNum);
-            plot.setRenderer(dataNum, renderer);
-        }
-    }
-
-    static class StateMarker implements Element {
-       private LinkedList<Double> times = new LinkedList<Double>();
-        private String name;
-        private int state;
-       private int prev_state = Altos.ao_flight_startup;
-
-        StateMarker(int state, String name) {
-            this.state = state;
-            this.name = name;
-        }
-
-        public void attachGraph(AltosGraphTime g) { return; }
-        public void gotTimeData(double time, AltosDataPoint d) {
-           if (prev_state != state && d.state() == state)
-               times.add(time);
-           prev_state = d.state();
-        }
-
-        public void addToPlot(AltosGraphTime g, XYPlot plot) {
-           for (double time : times) {
-               ValueMarker m = new ValueMarker(time);
-               m.setLabel(name);
-               m.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
-               m.setLabelTextAnchor(TextAnchor.TOP_LEFT);
-               plot.addDomainMarker(m);
-           }
-        }
-    }
-
-    private String callsign = null;
-    private Integer serial = null;
-    private Integer flight = null; 
-
-    private ArrayList<Element> elements;
-    private HashMap<String,Integer> axes;
-    private HashMap<Element,Integer> datasets;
-    private ArrayList<Integer> datasetAxis;
-
-    public AltosGraphTime(String title) {
-        this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png";
-        this.title = title;
-        this.elements = new ArrayList<Element>();
-        this.axes = new HashMap<String,Integer>();
-        this.datasets = new HashMap<Element,Integer>();
-        this.datasetAxis = new ArrayList<Integer>();
-    }
-
-    public AltosGraphTime addElement(Element e) {
-        e.attachGraph(this);
-        elements.add(e);
-        return this;
-    }
-
-    public void setAxis(Element ds, String axisName, Color color) {
-        Integer axisNum = axes.get(axisName);
-        int dsNum = datasetAxis.size();
-        if (axisNum == null) {
-            axisNum = newAxis(axisName, color);
-        }
-        datasets.put(ds, dsNum);
-        datasetAxis.add(axisNum);
-    }
-
-    public int getAxisNum(Element ds) {
-        return datasetAxis.get( datasets.get(ds) ).intValue();
-    }
-    public int getDataNum(Element ds) {
-        return datasets.get(ds).intValue();
-    }
-
-    private Integer newAxis(String name, Color color) {
-        int cnt = axes.size();
-        AxisLocation locn = AxisLocation.BOTTOM_OR_LEFT;
-        if (cnt > 0) {
-            locn = AxisLocation.TOP_OR_RIGHT;
-        }
-        Integer res = new Integer(cnt);
-        axes.put(name, res);
-        this.addElement(new TimeAxis(cnt, name, color, locn));
-        return res;
-    }
-
-    public void addData(AltosDataPoint d) {
-        double time = d.time();
-        for (Element e : elements) {
-            e.gotTimeData(time, d);
-        }
-        if (callsign == null) callsign = d.callsign();
-        if (serial == null) serial = new Integer(d.serial());
-        if (flight == null) flight = new Integer(d.flight());
-    }
-
-    public JFreeChart createChart() {
-        NumberAxis xAxis = new NumberAxis("Time (s)");
-        xAxis.setAutoRangeIncludesZero(false);
-        XYPlot plot = new XYPlot();
-        plot.setDomainAxis(xAxis);
-        plot.setOrientation(PlotOrientation.VERTICAL);
-
-        if (serial != null && flight != null) {
-            title = serial + "/" + flight + ": " + title;
-        }
-        if (callsign != null) {
-            title = callsign + " - " + title;
-        }
-
-        JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
-                                plot, true);
-        ChartUtilities.applyCurrentTheme(chart);
-
-        plot.setDomainPannable(true);
-        plot.setRangePannable(true);
-   
-        for (Element e : elements) {
-            e.addToPlot(this, plot);
-        }
-
-        return chart;
-    }
-
-    public void toPNG() throws java.io.IOException {
-        if (axes.size() > 1) {
-            toPNG(800, 500);
-        } else {
-            toPNG(300, 500);
-        }
-    }
-}
index c45c112..b376f7d 100644 (file)
@@ -18,290 +18,30 @@ import org.jfree.ui.RefineryUtilities;
 
 public class AltosGraphUI extends AltosUIFrame 
 {
-    JTabbedPane        pane;
+       JTabbedPane             pane;
+       AltosGraph              graph;
+       AltosUIEnable           enable;
 
-    static final private Color red = new Color(194,31,31);
-    static final private Color green = new Color(31,194,31);
-    static final private Color blue = new Color(31,31,194);
-    //static final private Color black = new Color(31,31,31);
-    static final private Color yellow = new Color(194,194,31);
-    //static final private Color cyan = new Color(31,194,194);
-    static final private Color magenta = new Color(194,31,194);
+       AltosGraphUI(AltosRecordIterable records, String file) throws InterruptedException, IOException {
+               pane = new JTabbedPane();
 
-    static private class OverallGraphs {
-        AltosGraphTime.Element height = 
-               new AltosGraphTime.TimeSeries("Height", AltosConvert.height.show_units(), "Height (AGL)", red) {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                       double  height = d.height();
-                       if (height != AltosRecord.MISSING)
-                               series.add(time, AltosConvert.height.value(height));
-                } 
-            };
-    
-        AltosGraphTime.Element speed =
-               new AltosGraphTime.TimeSeries("Speed", AltosConvert.speed.show_units(), "Vertical Speed", green) { 
-                public void gotTimeData(double time, AltosDataPoint d) {
-                   double      speed = d.speed();
-                   if (speed != AltosRecord.MISSING)
-                           series.add(time, AltosConvert.speed.value(speed));
-                }
-            };
-    
-        AltosGraphTime.Element acceleration =
-               new AltosGraphTime.TimeSeries("Acceleration",
-                                             AltosConvert.accel.show_units(),
-                                             "Axial Acceleration", blue)
-            {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                   double acceleration = d.acceleration();
-                   if (acceleration != AltosRecord.MISSING)
-                           series.add(time, AltosConvert.accel.value(acceleration));
-                }
-            };
-    
-        AltosGraphTime.Element temperature =
-           new AltosGraphTime.TimeSeries("Temperature", "\u00B0C", 
-                                         "Board temperature", red) 
-            {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                   double temp = d.temperature();
-                   if (temp != AltosRecord.MISSING)
-                       series.add(time, d.temperature());
-                }
-            };
-    
-        AltosGraphTime.Element drogue_voltage =
-            new AltosGraphTime.TimeSeries("Voltage", "(V)", "Drogue Continuity", yellow) 
-            {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                   double v = d.drogue_voltage();
-                   if (v != AltosRecord.MISSING)
-                       series.add(time, v);
-                }
-            };
-    
-        AltosGraphTime.Element main_voltage =
-            new AltosGraphTime.TimeSeries("Voltage", "(V)", "Main Continuity", magenta) 
-            {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                   double v = d.main_voltage();
-                   if (v != AltosRecord.MISSING)
-                       series.add(time, v);
-                }
-            };
-    
-        //AltosGraphTime.Element e_pad    = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad");
-        AltosGraphTime.Element e_boost  = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost");
-        AltosGraphTime.Element e_fast   = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast");
-        AltosGraphTime.Element e_coast  = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast");
-       AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue");
-       AltosGraphTime.Element e_main   = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main");
-        AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed");
-    
-        protected AltosGraphTime myAltosGraphTime(String suffix) {
-            return (new AltosGraphTime("Overall " + suffix))
-                .addElement(e_boost)
-               .addElement(e_fast)
-               .addElement(e_coast)
-                .addElement(e_drogue)
-                .addElement(e_main)
-                .addElement(e_landed);
-        }
-    
-        public ArrayList<AltosGraph> graphs() {
-            ArrayList<AltosGraph> graphs = new ArrayList<AltosGraph>();
-    
-           graphs.add( myAltosGraphTime("Summary")
-                       .addElement(height)
-                       .addElement(speed)
-                       .addElement(acceleration) );
+               enable = new AltosUIEnable();
 
-           graphs.add( myAltosGraphTime("Summary")
-                       .addElement(height)
-                       .addElement(speed));
-    
-            graphs.add( myAltosGraphTime("Altitude")
-                    .addElement(height) );
-    
-            graphs.add( myAltosGraphTime("Speed")
-                    .addElement(speed) );
-    
-           graphs.add( myAltosGraphTime("Acceleration")
-                       .addElement(acceleration) );
-    
-            graphs.add( myAltosGraphTime("Temperature")
-                    .addElement(temperature) );
-    
-           graphs.add( myAltosGraphTime("Continuity")
-                       .addElement(drogue_voltage)
-                       .addElement(main_voltage) );
-    
-            return graphs;
-        }
-    }
+               AltosGraph graph = new AltosGraph(enable);
 
-    /*
-    static private class AscentGraphs extends OverallGraphs {
-        protected AltosGraphTime myAltosGraphTime(String suffix) {
-            return (new AltosGraphTime("Ascent " + suffix) {
-                public void addData(AltosDataPoint d) {
-                    int state = d.state();
-                    if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) {
-                        super.addData(d);
-                    }
-                }
-            }).addElement(e_boost)
-              .addElement(e_fast)
-              .addElement(e_coast);
-        }
-    }
-    */
+               graph.setDataSet(new AltosGraphDataSet(records));
 
-    /*
-    static private class DescentGraphs extends OverallGraphs {
-        protected AltosGraphTime myAltosGraphTime(String suffix) {
-            return (new AltosGraphTime("Descent " + suffix) {
-                public void addData(AltosDataPoint d) {
-                    int state = d.state();
-                    if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) {
-                        super.addData(d);
-                    }
-                }
-            }).addElement(e_drogue)
-              .addElement(e_main);
-            // ((XYGraph)graph[8]).ymin = new Double(-50);
-        }
-    }
-    */
+               pane.add("Flight Graph", graph.panel);
+               pane.add("Configure Graph", enable);
 
-       public AltosGraphUI(AltosRecordIterable records, String name) throws InterruptedException, IOException {
-               super(String.format("Altos Graph %s", name));
+               AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records));
+               pane.add("Flight Statistics", stats);
 
-               AltosDataPointReader reader = new AltosDataPointReader (records);
-        
-               if (reader.has_accel)
-                   init(reader, records, 0);
-               else
-                   init(reader, records, 1);
-       }
-
-//    public AltosGraphUI(AltosDataPointReader data, int which)
-    //  {
-//        super("Altos Graph");
-//        init(data, which);
-//    }
-
-    private void init(AltosDataPointReader data, AltosRecordIterable records, int which) throws InterruptedException, IOException {
-       pane = new JTabbedPane();
-
-        AltosGraph graph = createGraph(data, which);
-
-        JFreeChart chart = graph.createChart();
-        ChartPanel chartPanel = new ChartPanel(chart);
-        chartPanel.setMouseWheelEnabled(true);
-        chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
-        pane.add(graph.title, chartPanel);
-
-       AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records));
-       pane.add("Flight Statistics", stats);
-
-       setContentPane (pane);
-
-        pack();
-
-        RefineryUtilities.centerFrameOnScreen(this);
-
-        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
-        setVisible(true);
-    }
-
-    private static AltosGraph createGraph(Iterable<AltosDataPoint> data,
-            int which)
-    {
-        return createGraphsWhich(data, which).get(0);
-    }
-
-    /*
-    private static ArrayList<AltosGraph> createGraphs(
-            Iterable<AltosDataPoint> data)
-    {
-        return createGraphsWhich(data, -1);
-    }
-    */
-
-    private static ArrayList<AltosGraph> createGraphsWhich(
-            Iterable<AltosDataPoint> data, int which)
-    {
-        ArrayList<AltosGraph> graph = new ArrayList<AltosGraph>();
-        graph.addAll((new OverallGraphs()).graphs());
-//        graph.addAll((new AscentGraphs()).graphs());
-//        graph.addAll((new DescentGraphs()).graphs());
+               setContentPane (pane);
 
-        if (which > 0) {
-            if (which >= graph.size()) {
-                which = 0;
-            }
-            AltosGraph g = graph.get(which);
-            graph = new ArrayList<AltosGraph>();
-            graph.add(g);
-        }
+               pack();
 
-        for (AltosDataPoint dp : data) {
-            for (AltosGraph g : graph) {
-                g.addData(dp);
-            }
-        }
-
-        return graph;
-    }
+               setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+               setVisible(true);
+       }
 }
-
-/* gnuplot bits...
- *
-300x400
-
---------------------------------------------------------
-TOO HARD! :)
-
-"ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)"
-    5:($7 < 6 ? $24-$11 : 1/0)
-"descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)"
-    5:($7 < 6 ? 1/0 : $24-$11)
-
-set output "overall-gps-accuracy.png"
-set ylabel "distance above sea level (m)"
-plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \
-    "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1
-
-set term png tiny size 700,700 enhanced
-set xlabel "m"
-set ylabel "m"
-set polar
-set grid polar
-set rrange[*:*]
-set angles degrees
-
-set output "overall-gps-path.png"
-#:30 with yerrorlines
-plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \
-    "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \
-    "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \
-    "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \
-    "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
-    "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
-    "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
-
-set output "ascent-gps-path.png"
-plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \
-    "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \
-    "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \
-    "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast"
-
-set output "descent-gps-path.png"
-plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
-    "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
-    "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
-
- */
-
-
index f5b83ce..8ae1a72 100644 (file)
@@ -74,10 +74,9 @@ altosui_JAVA = \
        AltosSiteMapTile.java \
        AltosUI.java \
        AltosWriter.java \
-       AltosDataPointReader.java \
-       AltosDataPoint.java \
        AltosGraph.java \
-       AltosGraphTime.java \
+       AltosGraphDataPoint.java \
+       AltosGraphDataSet.java \
        AltosGraphUI.java \
        AltosDataChooser.java \
        AltosVoice.java \
@@ -99,10 +98,10 @@ FREETTS_CLASS= \
        freetts.jar
 
 ALTOSLIB_CLASS=\
-       AltosLib.jar
+       altoslib_$(ALTOSLIB_VERSION).jar
 
 ALTOSUILIB_CLASS=\
-       altosuilib.jar
+       altosuilib_$(ALTOSUILIB_VERSION).jar
 
 LIBALTOS= \
        libaltos.so \
diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java
new file mode 100644 (file)
index 0000000..70084a0
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2013 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.altosuilib_1;
+
+import java.io.*;
+import java.util.ArrayList;
+
+import java.awt.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_1.*;
+
+import org.jfree.ui.*;
+import org.jfree.chart.*;
+import org.jfree.chart.plot.*;
+import org.jfree.chart.axis.*;
+import org.jfree.chart.renderer.*;
+import org.jfree.chart.renderer.xy.*;
+import org.jfree.chart.labels.*;
+import org.jfree.data.xy.*;
+import org.jfree.data.*;
+
+public class AltosUIAxis extends NumberAxis {
+       String          label;
+       AltosUnits      units;
+       Color           color;
+       int             ref;
+       int             visible;
+       int             index;
+
+       public final static int axis_integer = 1;
+       public final static int axis_include_zero = 2;
+
+       public final static int axis_default = axis_include_zero;
+
+       public void set_units() {
+               setLabel(String.format("%s (%s)", label, units.show_units()));
+       }
+       
+       public void set_enable(boolean enable) {
+               if (enable) {
+                       visible++;
+                       if (visible > ref)
+                               System.out.printf("too many visible\n");
+               } else {
+                       visible--;
+                       if (visible < 0)
+                               System.out.printf("too few visible\n");
+               }
+               setVisible(visible > 0);
+       }
+
+       public void ref(boolean enable) {
+               ++ref;
+               if (enable) {
+                       ++visible;
+                       setVisible(visible > 0);
+               }
+       }
+
+       public AltosUIAxis(String label, AltosUnits units, Color color, int index, int flags) {
+               this.label = label;
+               this.units = units;
+               this.index = index;
+               this.visible = 0;
+               this.ref = 0;
+               setLabelPaint(color);
+               setTickLabelPaint(color);
+               setVisible(false);
+               if ((flags & axis_integer) != 0)
+                       setStandardTickUnits(NumberAxis.createIntegerTickUnits());
+               setAutoRangeIncludesZero((flags & axis_include_zero) != 0);
+       }
+
+       public AltosUIAxis(String label, AltosUnits units, Color color, int index) {
+               this(label, units, color, index, axis_default);
+       }
+}
diff --git a/altosuilib/AltosUIDataMissing.java b/altosuilib/AltosUIDataMissing.java
new file mode 100644 (file)
index 0000000..c7b0185
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2013 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.altosuilib_1;
+
+public class AltosUIDataMissing extends Exception {
+       public int      id;
+       public AltosUIDataMissing(int id) {
+               this.id = id;
+       }
+}
\ No newline at end of file
index a98f7cd..d302041 100644 (file)
@@ -18,8 +18,8 @@
 package org.altusmetrum.altosuilib_1;
 
 public interface AltosUIDataPoint {
-       public abstract double x();
-       public abstract double y(int index);
-       public abstract int id(int index);
-       public abstract String id_name(int index);
+       public abstract double x() throws AltosUIDataMissing;
+       public abstract double y(int index) throws AltosUIDataMissing;
+       public abstract int id(int index) throws AltosUIDataMissing;
+       public abstract String id_name(int index) throws AltosUIDataMissing;
 }
index 297cf32..55486de 100644 (file)
@@ -84,10 +84,38 @@ public class AltosUIEnable extends Container {
                y++;
        }
 
+       public void add_units() {
+               /* Imperial units setting */
+               /* Add label */
+               GridBagConstraints c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 1000;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               add(new JLabel("Imperial Units"), c);
+
+               JRadioButton imperial_units = new JRadioButton("Enable", AltosUIPreferences.imperial_units());
+               imperial_units.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       JRadioButton item = (JRadioButton) e.getSource();
+                                       boolean enabled = item.isSelected();
+                                       AltosUIPreferences.set_imperial_units(enabled);
+                               }
+                       });
+               imperial_units.setToolTipText("Use Imperial units instead of metric");
+               c = new GridBagConstraints();
+               c.gridx = 1; c.gridy = 1000;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               add(imperial_units, c);
+       }
+
        public AltosUIEnable() {
                il = new Insets(4,4,4,4);
                ir = new Insets(4,4,4,4);
                y = 0;
                setLayout(new GridBagLayout());
+               add_units();
        }
 }
index e212093..5c589c0 100644 (file)
@@ -43,7 +43,8 @@ public class AltosUIGraph implements AltosUnitsListener {
        AltosUIEnable                   enable;
        ArrayList<AltosUIGrapher>       graphers;
        AltosUIDataSet                  dataSet;
-       int                             index;
+       int                             axis_index;
+       int                             series_index;
 
        static final private Color gridline_color = new Color(0, 0, 0);
        static final private Color border_color = new Color(255, 255, 255);
@@ -53,19 +54,33 @@ public class AltosUIGraph implements AltosUnitsListener {
                return panel;
        }
 
-       public void addSeries(String label, int fetch, AltosUnits units, Color color) {
-               AltosUISeries           series = new AltosUISeries(label, fetch, units, color);
+       public AltosUIAxis newAxis(String label, AltosUnits units, Color color, int flags) {
+               AltosUIAxis axis = new AltosUIAxis(label, units, color, axis_index++, flags);
+               plot.setRangeAxis(axis.index, axis);
+               return axis;
+       }
+
+       public AltosUIAxis newAxis(String label, AltosUnits units, Color color) {
+               return newAxis(label, units, color, AltosUIAxis.axis_default);
+       }
+
+       public void addSeries(String label, int fetch, AltosUnits units, Color color,
+                             boolean enabled, AltosUIAxis axis) {
+               AltosUISeries           series = new AltosUISeries(label, fetch, units, color, enabled, axis);
                XYSeriesCollection      dataset = new XYSeriesCollection(series);
 
                series.renderer.setPlot(plot);
-               plot.setRangeAxis(index, series.axis);
-               plot.setDataset(index, dataset);
-               plot.setRenderer(index, series.renderer);
-               plot.mapDatasetToRangeAxis(index, index);
+               plot.setDataset(series_index, dataset);
+               plot.setRenderer(series_index, series.renderer);
+               plot.mapDatasetToRangeAxis(series_index, axis.index);
                if (enable != null)
-                       enable.add(label, series, true);
+                       enable.add(label, series, enabled);
                this.graphers.add(series);
-               index++;
+               series_index++;
+       }
+
+       public void addSeries(String label, int fetch, AltosUnits units, Color color) {
+               addSeries(label, fetch, units, color, true, newAxis(label, units, color));
        }
        
        public void addMarker(String label, int fetch, Color color) {
@@ -97,16 +112,17 @@ public class AltosUIGraph implements AltosUnitsListener {
 
        public void setDataSet (AltosUIDataSet dataSet) {
                this.dataSet = dataSet;
+               resetData();
                if (dataSet != null)
                        setName(dataSet.name());
-               resetData();
        }
 
        public AltosUIGraph(AltosUIEnable enable) {
 
                this.enable = enable;
                this.graphers = new ArrayList<AltosUIGrapher>();
-               this.index = 0;
+               this.series_index = 0;
+               this.axis_index = 0;
 
                xAxis = new NumberAxis("Time (s)");
                
index 560153f..e2eb902 100644 (file)
@@ -72,20 +72,23 @@ public class AltosUIMarker implements AltosUIGrapher {
        }
 
        public void add(AltosUIDataPoint dataPoint) {
-               int id = dataPoint.id(fetch);
-               if (id < 0)
-                       return;
-               if (id == last_id)
-                       return;
-               ValueMarker marker = new ValueMarker(dataPoint.x());
-               marker.setLabel(dataPoint.id_name(fetch));
-               marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
-               marker.setLabelTextAnchor(TextAnchor.TOP_LEFT);
-               marker.setPaint(color);
-               if (enabled)
-                       plot.addDomainMarker(marker);
-               markers.add(marker);
-               last_id = id;
+               try {
+                       int id = dataPoint.id(fetch);
+                       if (id < 0)
+                               return;
+                       if (id == last_id)
+                               return;
+                       ValueMarker marker = new ValueMarker(dataPoint.x());
+                       marker.setLabel(dataPoint.id_name(fetch));
+                       marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
+                       marker.setLabelTextAnchor(TextAnchor.TOP_LEFT);
+                       marker.setPaint(color);
+                       if (enabled)
+                               plot.addDomainMarker(marker);
+                       markers.add(marker);
+                       last_id = id;
+               } catch (AltosUIDataMissing m) {
+               }
        }
 
        public AltosUIMarker (int fetch, Color color, XYPlot plot, boolean enable) {
index 2667947..ac09a3c 100644 (file)
@@ -65,7 +65,10 @@ public class AltosUISeries extends XYSeries implements AltosUIGrapher {
        }
 
        public void add(AltosUIDataPoint dataPoint) {
-               super.add(dataPoint.x(), dataPoint.y(fetch));
+               try {
+                       super.add(dataPoint.x(), units.value(dataPoint.y(fetch)));
+               } catch (AltosUIDataMissing dm) {
+               }
        }
 
        public AltosUISeries (String label, int fetch, AltosUnits units, Color color,
@@ -82,18 +85,7 @@ public class AltosUISeries extends XYSeries implements AltosUIGrapher {
 
                renderer = new XYLineAndShapeRenderer(true, false);
                renderer.setSeriesPaint(0, color);
+               renderer.setSeriesVisible(0, enable);
                set_units();
        }
-
-       public AltosUISeries (String label, int fetch, AltosUnits units, Color color, boolean enable) {
-               this(label, fetch, units, color,
-                    enable,
-                    new AltosUIAxis(label, units, color));
-       }
-
-       public AltosUISeries (String label, int fetch, AltosUnits units, Color color) {
-               this(label, fetch, units, color,
-                    true,
-                    new AltosUIAxis(label, units, color));
-       }
 }
index faf7921..0cd2aae 100644 (file)
@@ -15,6 +15,7 @@ altosuilib_JAVA = \
        AltosPositionListener.java \
        AltosUIConfigure.java \
        AltosUIAxis.java \
+       AltosUIDataMissing.java \
        AltosUIDataPoint.java \
        AltosUIDataSet.java \
        AltosUIGraph.java \