summaryrefslogtreecommitdiff
path: root/altosuilib
diff options
context:
space:
mode:
Diffstat (limited to 'altosuilib')
-rw-r--r--altosuilib/AltosDisplayThread.java3
-rw-r--r--altosuilib/AltosEepromDelete.java2
-rw-r--r--altosuilib/AltosEepromGrapher.java22
-rw-r--r--altosuilib/AltosEepromManage.java72
-rw-r--r--altosuilib/AltosEepromMonitorUI.java77
-rw-r--r--altosuilib/AltosEepromSelect.java74
-rw-r--r--altosuilib/AltosFlightStatsTable.java84
-rw-r--r--altosuilib/AltosGraph.java128
-rw-r--r--altosuilib/AltosInfoTable.java2
-rw-r--r--altosuilib/AltosShapeListener.java20
-rw-r--r--altosuilib/AltosUIAxis.java23
-rw-r--r--altosuilib/AltosUIEnable.java145
-rw-r--r--altosuilib/AltosUIFlightSeries.java52
-rw-r--r--altosuilib/AltosUIGraph.java26
-rw-r--r--altosuilib/AltosUILineStyle.java84
-rw-r--r--altosuilib/AltosUITimeSeries.java63
-rw-r--r--altosuilib/Makefile.am3
17 files changed, 666 insertions, 214 deletions
diff --git a/altosuilib/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java
index 3fcc02da..5e691ac4 100644
--- a/altosuilib/AltosDisplayThread.java
+++ b/altosuilib/AltosDisplayThread.java
@@ -159,9 +159,6 @@ public class AltosDisplayThread extends Thread {
report(false);
}
} catch (InterruptedException ie) {
- try {
- voice.drain();
- } catch (InterruptedException iie) { }
}
}
diff --git a/altosuilib/AltosEepromDelete.java b/altosuilib/AltosEepromDelete.java
index 87e80a51..d7dde6df 100644
--- a/altosuilib/AltosEepromDelete.java
+++ b/altosuilib/AltosEepromDelete.java
@@ -84,7 +84,7 @@ public class AltosEepromDelete implements Runnable {
serial_line.start_remote();
for (AltosEepromLog log : flights) {
- if (log.selected) {
+ if (log.delete_selected) {
DeleteLog(log);
}
}
diff --git a/altosuilib/AltosEepromGrapher.java b/altosuilib/AltosEepromGrapher.java
new file mode 100644
index 00000000..a29f64ea
--- /dev/null
+++ b/altosuilib/AltosEepromGrapher.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2017 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+package org.altusmetrum.altosuilib_12;
+
+import org.altusmetrum.altoslib_12.*;
+
+public interface AltosEepromGrapher {
+
+ public void graph_flights(AltosEepromList list);
+}
diff --git a/altosuilib/AltosEepromManage.java b/altosuilib/AltosEepromManage.java
index 93827139..1adf1f0a 100644
--- a/altosuilib/AltosEepromManage.java
+++ b/altosuilib/AltosEepromManage.java
@@ -33,6 +33,7 @@ public class AltosEepromManage implements ActionListener {
AltosEepromList flights;
AltosEepromDownload download;
AltosEepromDelete delete;
+ AltosEepromGrapher grapher;
public void finish() {
if (serial_line != null) {
@@ -48,7 +49,7 @@ public class AltosEepromManage implements ActionListener {
private int countDeletedFlights() {
int count = 0;
for (AltosEepromLog flight : flights) {
- if (flight.selected)
+ if (flight.delete_selected)
count++;
}
return count;
@@ -58,7 +59,7 @@ public class AltosEepromManage implements ActionListener {
String result = "";
for (AltosEepromLog flight : flights) {
- if (flight.selected) {
+ if (flight.delete_selected) {
if (result.equals(""))
result = String.format("%d", flight.flight);
else
@@ -68,38 +69,49 @@ public class AltosEepromManage implements ActionListener {
return result;
}
- public boolean download_done() {
- AltosEepromSelect select = new AltosEepromSelect(frame, flights, "Delete");
-
- if (select.run()) {
- boolean any_selected = false;
- for (AltosEepromLog flight : flights)
- any_selected = any_selected || flight.selected;
- if (any_selected) {
- delete = new AltosEepromDelete(frame,
- serial_line,
- remote,
- flights);
- delete.addActionListener(this);
- /*
- * Start flight log delete
- */
-
- delete.start();
- return true;
- }
+ public boolean delete_start() {
+
+ boolean any_selected = false;
+ for (AltosEepromLog flight : flights)
+ any_selected = any_selected || flight.delete_selected;
+ if (any_selected) {
+ delete = new AltosEepromDelete(frame,
+ serial_line,
+ remote,
+ flights);
+ delete.addActionListener(this);
+ /*
+ * Start flight log delete
+ */
+
+ delete.start();
+ return true;
}
return false;
}
+ public void graph_start() {
+ boolean any_selected = false;
+ for (AltosEepromLog flight : flights) {
+ if (!flight.download_selected)
+ flight.graph_selected = false;
+ any_selected = any_selected || flight.graph_selected;
+ }
+ if (any_selected && grapher != null)
+ grapher.graph_flights(flights);
+ }
+
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
boolean success = e.getID() != 0;
boolean running = false;
if (cmd.equals("download")) {
- if (success)
- running = download_done();
+ if (success) {
+ running = delete_start();
+ if (!running)
+ graph_start();
+ }
} else if (cmd.equals("delete")) {
if (success) {
JOptionPane.showMessageDialog(frame,
@@ -108,6 +120,7 @@ public class AltosEepromManage implements ActionListener {
showDeletedFlights()),
serial_line.device.toShortString(),
JOptionPane.INFORMATION_MESSAGE);
+ graph_start();
}
}
if (!running)
@@ -126,12 +139,12 @@ public class AltosEepromManage implements ActionListener {
serial_line.device.toShortString(),
JOptionPane.INFORMATION_MESSAGE);
} else {
- AltosEepromSelect select = new AltosEepromSelect(frame, flights, "Download");
+ AltosEepromSelect select = new AltosEepromSelect(frame, flights, grapher != null);
if (select.run()) {
boolean any_selected = false;
for (AltosEepromLog flight : flights)
- any_selected = any_selected || flight.selected;
+ any_selected = any_selected || flight.download_selected;
if (any_selected) {
AltosEepromMonitorUI monitor = new AltosEepromMonitorUI(frame);
monitor.addActionListener(this);
@@ -147,7 +160,9 @@ public class AltosEepromManage implements ActionListener {
download.start();
running = true;
} else {
- running = download_done();
+ running = delete_start();
+ if (!running)
+ graph_start();
}
}
}
@@ -205,11 +220,12 @@ public class AltosEepromManage implements ActionListener {
}
}
- public AltosEepromManage(JFrame given_frame, int product) {
+ public AltosEepromManage(JFrame given_frame, AltosEepromGrapher grapher, int product) {
//boolean running = false;
frame = given_frame;
+ this.grapher = grapher;
device = AltosDeviceUIDialog.show(frame, product);
remote = false;
diff --git a/altosuilib/AltosEepromMonitorUI.java b/altosuilib/AltosEepromMonitorUI.java
index 3427fe0f..fc6c95c6 100644
--- a/altosuilib/AltosEepromMonitorUI.java
+++ b/altosuilib/AltosEepromMonitorUI.java
@@ -18,11 +18,18 @@
package org.altusmetrum.altosuilib_12;
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.altusmetrum.altoslib_12.*;
+ class result_holder {
+ static int result;
+ }
+
public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
JFrame owner;
Container pane;
@@ -32,7 +39,6 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
JLabel file_label;
JLabel serial_value;
JLabel flight_value;
- JLabel file_value;
JButton cancel;
JProgressBar pbar;
ActionListener listener;
@@ -42,6 +48,8 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
public AltosEepromMonitorUI(JFrame owner) {
super (owner, "Download Flight Data", false);
+ setMinimumSize(new Dimension(600, 100));
+
this.owner = owner;
GridBagConstraints c;
@@ -85,30 +93,11 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
flight_value = new JLabel("");
pane.add(flight_value, c);
- c = new GridBagConstraints();
- c.fill = GridBagConstraints.NONE;
- c.gridx = 0; c.gridy = 2;
- c.anchor = GridBagConstraints.LINE_START;
- c.insets = il;
- file_label = new JLabel("File:");
- pane.add(file_label, c);
-
- c = new GridBagConstraints();
- c.fill = GridBagConstraints.HORIZONTAL;
- c.weightx = 1;
- c.gridx = 1; c.gridy = 2;
- c.anchor = GridBagConstraints.LINE_START;
- c.insets = ir;
- file_value = new JLabel("");
- pane.add(file_value, c);
-
pbar = new JProgressBar();
pbar.setMinimum(0);
pbar.setMaximum(progress_max);
- pbar.setValue(0);
- pbar.setString("startup");
pbar.setStringPainted(true);
- pbar.setPreferredSize(new Dimension(600, 20));
+ set_block_internal(0);
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.CENTER;
@@ -118,7 +107,6 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
c.insets = ib;
pane.add(pbar, c);
-
cancel = new JButton("Cancel");
c = new GridBagConstraints();
c.fill = GridBagConstraints.NONE;
@@ -141,8 +129,9 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
final Thread eeprom_thread = in_eeprom_thread;
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- if (eeprom_thread != null)
+ if (eeprom_thread != null) {
eeprom_thread.interrupt();
+ }
}
});
}
@@ -162,6 +151,7 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
s = String.format("block %d of %d", block, max_block);
pbar.setString(s);
+ pbar.setStringPainted(true);
pbar.setValue((int) (pos * progress_max));
}
@@ -216,23 +206,6 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
SwingUtilities.invokeLater(r);
}
- private void set_filename_internal(String filename) {
- file_value.setText(String.format("%s", filename));
- }
-
- public void set_filename(String in_filename) {
- final String filename = in_filename;
- Runnable r = new Runnable() {
- public void run() {
- try {
- set_filename_internal(filename);
- } catch (Exception ex) {
- }
- }
- };
- SwingUtilities.invokeLater(r);
- }
-
private void done_internal(boolean success) {
listener.actionPerformed(new ActionEvent(this,
success ? 1 : 0,
@@ -258,7 +231,6 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
set_max(1);
set_block_internal(0);
set_flight_internal(0);
- set_filename_internal("");
}
public void reset() {
@@ -293,6 +265,29 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
joption_message_type);
}
+ public Boolean check_overwrite(File in_file) {
+ final Semaphore check_overwrite_done = new Semaphore(0);
+ final File file = in_file;
+ final result_holder result = new result_holder();
+
+ Runnable r = new Runnable() {
+ public void run() {
+ result_holder.result = JOptionPane.showConfirmDialog(owner,
+ String.format("\"%s\" already exists, overwrite?",
+ file.toString()),
+ "Overwrite Existing File?",
+ JOptionPane.YES_NO_OPTION);
+ check_overwrite_done.release();
+ }
+ };
+
+ SwingUtilities.invokeLater(r);
+ try {
+ check_overwrite_done.acquire();
+ } catch (Exception e) {}
+ return result_holder.result == JOptionPane.YES_OPTION;
+ }
+
public void show_message(String in_message, String in_title, int in_message_type) {
final String message = in_message;
final String title = in_title;
diff --git a/altosuilib/AltosEepromSelect.java b/altosuilib/AltosEepromSelect.java
index 0c890c8b..f88f2bd6 100644
--- a/altosuilib/AltosEepromSelect.java
+++ b/altosuilib/AltosEepromSelect.java
@@ -27,23 +27,35 @@ import org.altusmetrum.altoslib_12.*;
class AltosEepromItem implements ActionListener {
AltosEepromLog log;
JLabel label;
- JCheckBox action;
+ JCheckBox download;
JCheckBox delete;
+ JCheckBox graph;
public void actionPerformed(ActionEvent e) {
- log.selected = action.isSelected();
+ log.download_selected = download.isSelected();
+ log.delete_selected = delete.isSelected();
+ log.graph_selected = graph.isSelected();
}
public AltosEepromItem(AltosEepromLog in_log) {
log = in_log;
String text;
- text = String.format("Flight #%02d", log.flight);
+ if (log.flight >= 0)
+ text = String.format("Flight #%02d", log.flight);
+ else
+ text = String.format("Corrupt #%02d", -log.flight);
label = new JLabel(text);
- action = new JCheckBox("", log.selected);
- action.addActionListener(this);
+ download = new JCheckBox("", log.download_selected);
+ download.addActionListener(this);
+
+ delete = new JCheckBox("", log.delete_selected);
+ delete.addActionListener(this);
+
+ graph = new JCheckBox("", log.graph_selected);
+ graph.addActionListener(this);
}
}
@@ -72,7 +84,7 @@ public class AltosEepromSelect extends AltosUIDialog implements ActionListener {
public AltosEepromSelect (JFrame in_frame,
AltosEepromList flights,
- String action) {
+ boolean has_graph) {
super(in_frame, String.format("Flight list for serial %d", flights.config_data.serial), true);
frame = in_frame;
@@ -81,7 +93,7 @@ public class AltosEepromSelect extends AltosUIDialog implements ActionListener {
Container contentPane = getContentPane();
/* First, we create a pane containing the dialog's header/title */
- JLabel selectLabel = new JLabel(String.format ("Select flights to %s", action), SwingConstants.CENTER);
+ JLabel selectLabel = new JLabel(String.format ("Select flights"), SwingConstants.CENTER);
JPanel labelPane = new JPanel();
labelPane.setLayout(new BoxLayout(labelPane, BoxLayout.X_AXIS));
@@ -118,9 +130,31 @@ public class AltosEepromSelect extends AltosUIDialog implements ActionListener {
c.weightx = 0.5;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
- JLabel downloadHeaderLabel = new JLabel(action);
+ JLabel downloadHeaderLabel = new JLabel("Download");
flightPane.add(downloadHeaderLabel, c);
+ /* Delete Header */
+ c = new GridBagConstraints();
+ c.gridx = 2; c.gridy = 0;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx = 0.5;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = i;
+ JLabel deleteHeaderLabel = new JLabel("Delete");
+ flightPane.add(deleteHeaderLabel, c);
+
+ if (has_graph) {
+ /* Graph Header */
+ c = new GridBagConstraints();
+ c.gridx = 3; c.gridy = 0;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx = 0.5;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = i;
+ JLabel graphHeaderLabel = new JLabel("Graph");
+ flightPane.add(graphHeaderLabel, c);
+ }
+
/* Add the flights to the GridBag */
AltosEepromItem item;
int itemNumber = 1;
@@ -139,14 +173,34 @@ public class AltosEepromSelect extends AltosUIDialog implements ActionListener {
c.insets = i;
flightPane.add(item.label, c);
- /* Add action checkbox for the flight */
+ /* Add download checkbox for the flight */
c = new GridBagConstraints();
c.gridx = 1; c.gridy = itemNumber;
c.fill = GridBagConstraints.NONE;
c.weightx = 0.5;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
- flightPane.add(item.action, c);
+ flightPane.add(item.download, c);
+
+ /* Add delete checkbox for the flight */
+ c = new GridBagConstraints();
+ c.gridx = 2; c.gridy = itemNumber;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx = 0.5;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = i;
+ flightPane.add(item.delete, c);
+
+ if (has_graph) {
+ /* Add graph checkbox for the flight */
+ c = new GridBagConstraints();
+ c.gridx = 3; c.gridy = itemNumber;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx = 0.5;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = i;
+ flightPane.add(item.graph, c);
+ }
itemNumber++;
}
diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java
index 415c0244..8f7e9bff 100644
--- a/altosuilib/AltosFlightStatsTable.java
+++ b/altosuilib/AltosFlightStatsTable.java
@@ -38,6 +38,11 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen
value[i].setFont(AltosUILib.value_font);
}
+ public void set(String ... values) {
+ for (int j = 0; j < values.length; j++)
+ value[j].setText(values[j]);
+ }
+
public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) {
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
@@ -87,6 +92,43 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen
return String.format("%s %4d° %9.6f'", h, deg, min);
}
+ private FlightStat max_height_stat;
+ private FlightStat max_speed_stat;
+ private FlightStat max_accel_stat;
+ private FlightStat boost_accel_stat;
+ private FlightStat drogue_descent_stat;
+ private FlightStat main_descent_stat;
+
+ public void set_values(AltosFlightStats stats) {
+ if (max_height_stat != null && stats.max_height != AltosLib.MISSING) {
+ max_height_stat.set(String.format("%6.1f m", stats.max_height),
+ String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
+ }
+ if (max_speed_stat != null && stats.max_speed != AltosLib.MISSING) {
+ max_speed_stat.set(String.format("%6.1f m/s", stats.max_speed),
+ String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
+ String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
+ }
+ if (max_accel_stat != null && stats.max_acceleration != AltosLib.MISSING) {
+ max_accel_stat.set(String.format("%6.1f m/s²", stats.max_acceleration),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
+ String.format("%6.2f G", AltosConvert.meters_to_g(stats.max_acceleration)));
+ }
+ if (boost_accel_stat != null && stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING) {
+ boost_accel_stat.set(String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
+ String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
+ }
+ if (drogue_descent_stat != null && stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING) {
+ drogue_descent_stat.set(String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_drogue]),
+ String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue])));
+ }
+ if (main_descent_stat != null && stats.state_speed[AltosLib.ao_flight_main] != AltosLib.MISSING) {
+ main_descent_stat.set(String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]),
+ String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main])));
+ }
+ }
+
public void set_stats(AltosFlightStats stats) {
int y = 0;
if (stats.serial != AltosLib.MISSING) {
@@ -113,9 +155,9 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen
String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second));
}
if (stats.max_height != AltosLib.MISSING) {
- new FlightStat(layout, y++, "Maximum height",
- String.format("%6.1f m", stats.max_height),
- String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
+ max_height_stat = new FlightStat(layout, y++, "Maximum height",
+ String.format("%6.1f m", stats.max_height),
+ String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
}
if (stats.max_gps_height != AltosLib.MISSING) {
new FlightStat(layout, y++, "Maximum GPS height",
@@ -123,21 +165,21 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen
String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_gps_height)));
}
if (stats.max_speed != AltosLib.MISSING) {
- new FlightStat(layout, y++, "Maximum speed",
- String.format("%6.1f m/s", stats.max_speed),
- String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
- String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
+ max_speed_stat = new FlightStat(layout, y++, "Maximum speed",
+ String.format("%6.1f m/s", stats.max_speed),
+ String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
+ String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
}
if (stats.max_acceleration != AltosLib.MISSING)
- new FlightStat(layout, y++, "Maximum boost acceleration",
- String.format("%6.1f m/s²", stats.max_acceleration),
- String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
- String.format("%6.2f G", AltosConvert.meters_to_g(stats.max_acceleration)));
+ max_accel_stat = new FlightStat(layout, y++, "Maximum boost acceleration",
+ String.format("%6.1f m/s²", stats.max_acceleration),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
+ String.format("%6.2f G", AltosConvert.meters_to_g(stats.max_acceleration)));
if (stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING)
- new FlightStat(layout, y++, "Average boost acceleration",
- String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
- String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
- String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
+ boost_accel_stat = new FlightStat(layout, y++, "Average boost acceleration",
+ String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
+ String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
if (stats.state_time[AltosLib.ao_flight_boost] != 0 || stats.state_time[AltosLib.ao_flight_fast] != 0 || stats.state_time[AltosLib.ao_flight_coast] != 0) {
double boost_time = stats.state_time[AltosLib.ao_flight_boost];
@@ -167,14 +209,14 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen
label = "Descent rate";
else
label = "Drogue descent rate";
- new FlightStat(layout, y++, label,
+ drogue_descent_stat = new FlightStat(layout, y++, label,
String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_drogue]),
String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue])));
}
if (stats.state_speed[AltosLib.ao_flight_main] != AltosLib.MISSING)
- new FlightStat(layout, y++, "Main descent rate",
- String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]),
- String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main])));
+ main_descent_stat = new FlightStat(layout, y++, "Main descent rate",
+ String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]),
+ String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main])));
if (stats.state_time[AltosLib.ao_flight_drogue] != 0 || stats.state_time[AltosLib.ao_flight_main] != 0) {
double drogue_duration = stats.state_time[AltosLib.ao_flight_drogue];
double main_duration = stats.state_time[AltosLib.ao_flight_main];
@@ -210,6 +252,10 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen
AltosUIPreferences.unregister_font_listener(this);
}
+ public void filter_changed(AltosFlightStats stats) {
+ set_values(stats);
+ }
+
public AltosFlightStatsTable() {
layout = new GridBagLayout();
diff --git a/altosuilib/AltosGraph.java b/altosuilib/AltosGraph.java
index 31042abb..a758bcde 100644
--- a/altosuilib/AltosGraph.java
+++ b/altosuilib/AltosGraph.java
@@ -37,49 +37,56 @@ import org.jfree.data.*;
public class AltosGraph extends AltosUIGraph {
- static final private Color height_color = new Color(194,31,31);
- static final private Color kalman_height_color = new Color(255,0,0);
- static final private Color gps_height_color = new Color(150,31,31);
- static final private Color pressure_color = new Color (225,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 kalman_speed_color = new Color(0,255,0);
- static final private Color thrust_color = new Color(31,194,31);
- static final private Color accel_color = new Color(31,31,194);
- static final private Color vert_accel_color = new Color(64,164,164);
- static final private Color kalman_accel_color = new Color(0,0,255);
- 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 igniter_voltage_color = new Color(80, 80, 31);
- static final private Color igniter_marker_color = new Color(255, 0, 0);
- 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 gps_course_color = new Color (100, 31, 112);
- static final private Color gps_ground_speed_color = new Color (31, 112, 100);
- static final private Color gps_speed_color = new Color (31, 112, 100);
- static final private Color gps_climb_rate_color = new Color (31, 31, 112);
- static final private Color gps_pdop_color = new Color(50, 194, 0);
- static final private Color gps_hdop_color = new Color(50, 0, 194);
- static final private Color gps_vdop_color = new Color(194, 0, 50);
- 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 final private Color accel_along_color = new Color(255, 0, 0);
- static final private Color accel_across_color = new Color(0, 255, 0);
- static final private Color accel_through_color = new Color(0, 0, 255);
- static final private Color gyro_roll_color = new Color(192, 0, 0);
- static final private Color gyro_pitch_color = new Color(0, 192, 0);
- static final private Color gyro_yaw_color = new Color(0, 0, 192);
- static final private Color mag_along_color = new Color(128, 0, 0);
- static final private Color mag_across_color = new Color(0, 128, 0);
- static final private Color mag_through_color = new Color(0, 0, 128);
- static final private Color orient_color = new Color(31, 31, 31);
+ /* These are in 'priority' order so that earlier ones get simpler line styles,
+ * then they are grouped so that adjacent ones get sequential colors
+ */
+ static final private AltosUILineStyle height_color = new AltosUILineStyle();
+ static final private AltosUILineStyle speed_color = new AltosUILineStyle();
+ static final private AltosUILineStyle accel_color = new AltosUILineStyle();
+ static final private AltosUILineStyle vert_accel_color = new AltosUILineStyle();
+ static final private AltosUILineStyle orient_color = new AltosUILineStyle();
+
+ static final private AltosUILineStyle gps_height_color = new AltosUILineStyle();
+ static final private AltosUILineStyle altitude_color = new AltosUILineStyle();
+
+ static final private AltosUILineStyle battery_voltage_color = new AltosUILineStyle();
+ static final private AltosUILineStyle pyro_voltage_color = new AltosUILineStyle();
+ static final private AltosUILineStyle drogue_voltage_color = new AltosUILineStyle();
+ static final private AltosUILineStyle main_voltage_color = new AltosUILineStyle();
+ static final private AltosUILineStyle igniter_marker_color = new AltosUILineStyle(1);
+
+ static final private AltosUILineStyle kalman_height_color = new AltosUILineStyle();
+ static final private AltosUILineStyle kalman_speed_color = new AltosUILineStyle();
+ static final private AltosUILineStyle kalman_accel_color = new AltosUILineStyle();
+
+ static final private AltosUILineStyle gps_nsat_color = new AltosUILineStyle ();
+ static final private AltosUILineStyle gps_nsat_solution_color = new AltosUILineStyle ();
+ static final private AltosUILineStyle gps_nsat_view_color = new AltosUILineStyle ();
+ static final private AltosUILineStyle gps_course_color = new AltosUILineStyle ();
+ static final private AltosUILineStyle gps_ground_speed_color = new AltosUILineStyle ();
+ static final private AltosUILineStyle gps_speed_color = new AltosUILineStyle ();
+ static final private AltosUILineStyle gps_climb_rate_color = new AltosUILineStyle ();
+ static final private AltosUILineStyle gps_pdop_color = new AltosUILineStyle();
+ static final private AltosUILineStyle gps_hdop_color = new AltosUILineStyle();
+ static final private AltosUILineStyle gps_vdop_color = new AltosUILineStyle();
+
+ static final private AltosUILineStyle temperature_color = new AltosUILineStyle ();
+ static final private AltosUILineStyle dbm_color = new AltosUILineStyle();
+ static final private AltosUILineStyle pressure_color = new AltosUILineStyle ();
+
+ static final private AltosUILineStyle state_color = new AltosUILineStyle(0);
+ static final private AltosUILineStyle accel_along_color = new AltosUILineStyle();
+ static final private AltosUILineStyle accel_across_color = new AltosUILineStyle();
+ static final private AltosUILineStyle accel_through_color = new AltosUILineStyle();
+ static final private AltosUILineStyle gyro_roll_color = new AltosUILineStyle();
+ static final private AltosUILineStyle gyro_pitch_color = new AltosUILineStyle();
+ static final private AltosUILineStyle gyro_yaw_color = new AltosUILineStyle();
+ static final private AltosUILineStyle mag_along_color = new AltosUILineStyle();
+ static final private AltosUILineStyle mag_across_color = new AltosUILineStyle();
+ static final private AltosUILineStyle mag_through_color = new AltosUILineStyle();
static AltosUnits dop_units = null;
+ static AltosUnits tick_units = null;
AltosUIFlightSeries flight_series;
@@ -87,24 +94,24 @@ public class AltosGraph extends AltosUIGraph {
AltosCalData cal_data = flight_series.cal_data();
AltosUIAxis height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis;
- AltosUIAxis distance_axis, pressure_axis, thrust_axis;
+ AltosUIAxis pressure_axis, thrust_axis;
AltosUIAxis gyro_axis, orient_axis, mag_axis;
- AltosUIAxis course_axis, dop_axis;
+ AltosUIAxis course_axis, dop_axis, tick_axis;
- if (stats.serial != AltosLib.MISSING && stats.product != null && stats.flight != AltosLib.MISSING)
+ if (stats != null && stats.serial != AltosLib.MISSING && stats.product != null && stats.flight != AltosLib.MISSING)
setName(String.format("%s %d flight %d\n", stats.product, stats.serial, stats.flight));
height_axis = newAxis("Height", AltosConvert.height, height_color);
pressure_axis = newAxis("Pressure", AltosConvert.pressure, pressure_color, 0);
speed_axis = newAxis("Speed", AltosConvert.speed, speed_color);
- thrust_axis = newAxis("Thrust", AltosConvert.force, thrust_color);
+ thrust_axis = newAxis("Thrust", AltosConvert.force, accel_color);
+ tick_axis = newAxis("Tick", tick_units, accel_color, 0);
accel_axis = newAxis("Acceleration", AltosConvert.accel, accel_color);
- voltage_axis = newAxis("Voltage", AltosConvert.voltage, voltage_color);
+ voltage_axis = newAxis("Voltage", AltosConvert.voltage, battery_voltage_color);
temperature_axis = newAxis("Temperature", AltosConvert.temperature, temperature_color, 0);
nsat_axis = newAxis("Satellites", null, gps_nsat_color,
AltosUIAxis.axis_include_zero | AltosUIAxis.axis_integer);
dbm_axis = newAxis("Signal Strength", null, dbm_color, 0);
- distance_axis = newAxis("Distance", AltosConvert.distance, range_color);
gyro_axis = newAxis("Rotation Rate", AltosConvert.rotation_rate, gyro_roll_color, 0);
orient_axis = newAxis("Tilt Angle", AltosConvert.orient, orient_color, 0);
@@ -129,6 +136,11 @@ public class AltosGraph extends AltosUIGraph {
plot,
false);
+ flight_series.register_axis(AltosUIFlightSeries.tick_name,
+ accel_color,
+ false,
+ tick_axis);
+
flight_series.register_axis(AltosUIFlightSeries.accel_name,
accel_color,
true,
@@ -170,7 +182,7 @@ public class AltosGraph extends AltosUIGraph {
height_axis);
flight_series.register_axis(AltosUIFlightSeries.altitude_name,
- height_color,
+ altitude_color,
false,
height_axis);
@@ -190,6 +202,11 @@ public class AltosGraph extends AltosUIGraph {
false,
voltage_axis);
+ flight_series.register_axis(AltosUIFlightSeries.pyro_voltage_name,
+ pyro_voltage_color,
+ false,
+ voltage_axis);
+
flight_series.register_axis(AltosUIFlightSeries.apogee_voltage_name,
drogue_voltage_color,
false,
@@ -305,17 +322,19 @@ public class AltosGraph extends AltosUIGraph {
false,
orient_axis);
- for (int channel = 0; channel < 26; channel++) {
+ flight_series.register_axis(AltosUIFlightSeries.thrust_name,
+ accel_color,
+ true,
+ thrust_axis);
+
+ for (int channel = 0; channel < 8; channel++) {
flight_series.register_axis(flight_series.igniter_voltage_name(channel),
- igniter_voltage_color,
+ new AltosUILineStyle(),
false,
voltage_axis);
}
- flight_series.register_axis(AltosUIFlightSeries.thrust_name,
- thrust_color,
- true,
- thrust_axis);
+ flight_series.check_axes();
return flight_series.series(cal_data);
}
@@ -330,6 +349,7 @@ public class AltosGraph extends AltosUIGraph {
public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosUIFlightSeries flight_series) {
this(enable);
+ this.flight_series = flight_series;
set_series(setup(stats, flight_series));
}
}
diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java
index 9e528b1f..e759394b 100644
--- a/altosuilib/AltosInfoTable.java
+++ b/altosuilib/AltosInfoTable.java
@@ -142,6 +142,8 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar
info_add_row(0, "Device", "%s", AltosLib.product_name(cal_data.device_type));
else if (cal_data.product != null)
info_add_row(0, "Device", "%s", cal_data.product);
+ if (state.tick() != AltosLib.MISSING)
+ info_add_row(0, "Tick", "%6d", state.tick());
if (state.altitude() != AltosLib.MISSING)
info_add_row(0, "Altitude", "%6.0f m", state.altitude());
if (cal_data.ground_altitude != AltosLib.MISSING)
diff --git a/altosuilib/AltosShapeListener.java b/altosuilib/AltosShapeListener.java
new file mode 100644
index 00000000..6bf52fd4
--- /dev/null
+++ b/altosuilib/AltosShapeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright © 2017 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+package org.altusmetrum.altosuilib_12;
+
+public interface AltosShapeListener {
+ void set_shapes_visible(boolean visible);
+ void set_line_width(float width);
+}
diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java
index fe94f161..52873363 100644
--- a/altosuilib/AltosUIAxis.java
+++ b/altosuilib/AltosUIAxis.java
@@ -36,12 +36,12 @@ 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;
+ String label;
+ AltosUnits units;
+ AltosUILineStyle line_style;
+ int ref;
+ int visible;
+ int index;
public final static int axis_integer = 1;
public final static int axis_include_zero = 2;
@@ -82,21 +82,22 @@ public class AltosUIAxis extends NumberAxis {
}
}
- public AltosUIAxis(String label, AltosUnits units, Color color, int index, int flags) {
+ public AltosUIAxis(String label, AltosUnits units, AltosUILineStyle line_style, int index, int flags) {
this.label = label;
this.units = units;
+ this.line_style = line_style;
this.index = index;
this.visible = 0;
this.ref = 0;
- setLabelPaint(color);
- setTickLabelPaint(color);
+ setLabelPaint(line_style.color);
+ setTickLabelPaint(line_style.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);
+ public AltosUIAxis(String label, AltosUnits units, AltosUILineStyle line_style, int index) {
+ this(label, units, line_style, index, axis_default);
}
}
diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java
index 0c23fa8d..851e831f 100644
--- a/altosuilib/AltosUIEnable.java
+++ b/altosuilib/AltosUIEnable.java
@@ -21,6 +21,7 @@ package org.altusmetrum.altosuilib_12;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
+import javax.swing.event.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
@@ -36,12 +37,21 @@ import org.jfree.chart.labels.*;
import org.jfree.data.xy.*;
import org.jfree.data.*;
-public class AltosUIEnable extends Container {
+public class AltosUIEnable extends Container implements ChangeListener {
Insets il, ir;
int y;
int x;
JCheckBox imperial_units;
+ JCheckBox show_shapes;
+ JLabel line_width_label;
+ JSpinner line_width;
+ JLabel speed_filter_label;
+ JSlider speed_filter;
+ JLabel accel_filter_label;
+ JSlider accel_filter;
+ AltosFilterListener filter_listener;
+ AltosShapeListener shape_listener;
static final int max_rows = 14;
@@ -69,11 +79,15 @@ public class AltosUIEnable extends Container {
}
}
+ LinkedList<GraphElement> elements = new LinkedList<GraphElement>();
+
public void add(String name, AltosUIGrapher grapher, boolean enabled) {
GraphElement e = new GraphElement(name, grapher, enabled);
GridBagConstraints c = new GridBagConstraints();
+ elements.add(e);
+
/* Add element */
c = new GridBagConstraints();
c.gridx = x; c.gridy = y;
@@ -90,6 +104,31 @@ public class AltosUIEnable extends Container {
}
}
+ public void stateChanged(ChangeEvent e) {
+ JSlider filter = (JSlider) e.getSource();
+ if (!filter.getValueIsAdjusting()) {
+ double speed_value = (int) speed_filter.getValue() / 1000.0;
+ double accel_value = (int) accel_filter.getValue() / 1000.0;
+ if (filter_listener != null) {
+ filter_listener.filter_changed(speed_value, accel_value);
+ }
+ }
+ }
+
+ public void set_shapes_visible(boolean visible) {
+ if (shape_listener != null)
+ shape_listener.set_shapes_visible(visible);
+ }
+
+ public void set_line_width(float width) {
+ if (shape_listener != null)
+ shape_listener.set_line_width(width);
+ }
+
+ public void register_shape_listener(AltosShapeListener shape_listener) {
+ this.shape_listener = shape_listener;
+ }
+
public void add_units() {
/* Imperial units setting */
@@ -109,9 +148,111 @@ public class AltosUIEnable extends Container {
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
add(imperial_units, c);
+
+ show_shapes = new JCheckBox("Show Markers", false);
+ show_shapes.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ JCheckBox item = (JCheckBox) e.getSource();
+ boolean enabled = item.isSelected();
+ set_shapes_visible(enabled);
+ }
+ });
+ show_shapes.setToolTipText("Show marker Use Imperial units instead of metric");
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 1001;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(show_shapes, c);
+
+
+ line_width_label = new JLabel("Line Width");
+ c = new GridBagConstraints();
+ c.gridx = 1; c.gridy = 1001;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(line_width_label, c);
+
+ line_width = new JSpinner();
+ line_width.setValue(new Integer(1));
+ line_width.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ int w = (Integer) line_width.getValue();
+ if (w < 1) {
+ w = 1;
+ line_width.setValue(new Integer(w));
+ }
+ System.out.printf("line width set to %d\n", w);
+ set_line_width(w);
+ }
+ });
+ c = new GridBagConstraints();
+ c.gridx = 2; c.gridy = 1001;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(line_width, c);
+
+ speed_filter_label = new JLabel("Speed Filter(ms)");
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 1002;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(speed_filter_label, c);
+
+ speed_filter = new JSlider(JSlider.HORIZONTAL, 0, 10000, (int) (filter_listener.speed_filter() * 1000.0));
+ Hashtable<Integer,JLabel> label_table = new Hashtable<Integer,JLabel>();
+ for (int i = 0; i <= 10000; i += 5000) {
+ label_table.put(new Integer(i), new JLabel(String.format("%d", i)));
+ }
+ speed_filter.setPaintTicks(true);
+ speed_filter.setMajorTickSpacing(1000);
+ speed_filter.setMinorTickSpacing(250);
+ speed_filter.setLabelTable(label_table);
+ speed_filter.setPaintTrack(false);
+ speed_filter.setSnapToTicks(true);
+ speed_filter.setPaintLabels(true);
+ speed_filter.addChangeListener(this);
+
+ c = new GridBagConstraints();
+ c.gridx = 1; c.gridy = 1002;
+ c.gridwidth = 1000; c.gridheight = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(speed_filter, c);
+
+ accel_filter_label = new JLabel("Acceleration Filter(ms)");
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 1003;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(accel_filter_label, c);
+
+ accel_filter = new JSlider(JSlider.HORIZONTAL, 0, 10000, (int) (filter_listener.accel_filter() * 1000.0));
+ accel_filter.setPaintTicks(true);
+ accel_filter.setMajorTickSpacing(1000);
+ accel_filter.setMinorTickSpacing(250);
+ accel_filter.setLabelTable(label_table);
+ accel_filter.setPaintTrack(false);
+ accel_filter.setSnapToTicks(true);
+ accel_filter.setPaintLabels(true);
+ accel_filter.addChangeListener(this);
+
+ c = new GridBagConstraints();
+ c.gridx = 1; c.gridy = 1003;
+ c.gridwidth = 1000; c.gridheight = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(accel_filter, c);
}
- public AltosUIEnable() {
+ public AltosUIEnable(AltosFilterListener filter_listener) {
+ this.filter_listener = filter_listener;
il = new Insets(4,4,4,4);
ir = new Insets(4,4,4,4);
x = 0;
diff --git a/altosuilib/AltosUIFlightSeries.java b/altosuilib/AltosUIFlightSeries.java
index 19bed609..407e5ab4 100644
--- a/altosuilib/AltosUIFlightSeries.java
+++ b/altosuilib/AltosUIFlightSeries.java
@@ -30,15 +30,16 @@ import org.jfree.data.xy.*;
import org.jfree.data.*;
class AltosUITimeSeriesAxis {
- Color color;
- boolean enabled;
- boolean marker;
- boolean marker_top;
- AltosUIAxis axis;
- XYPlot plot;
-
- public AltosUITimeSeriesAxis(Color color, boolean enabled, AltosUIAxis axis, XYPlot plot, boolean marker, boolean marker_top) {
- this.color = color;
+ AltosUILineStyle line_style;
+ boolean enabled;
+ boolean marker;
+ boolean marker_top;
+ AltosUIAxis axis;
+ XYPlot plot;
+
+ public AltosUITimeSeriesAxis(AltosUILineStyle line_style, boolean enabled,
+ AltosUIAxis axis, XYPlot plot, boolean marker, boolean marker_top) {
+ this.line_style = line_style;
this.enabled = enabled;
this.axis = axis;
this.plot = plot;
@@ -51,26 +52,34 @@ public class AltosUIFlightSeries extends AltosFlightSeries {
Hashtable<String,AltosUITimeSeriesAxis> axes;
- AltosUIFlightSeries flight_series;
-
void fill_axes(String label, AltosUITimeSeriesAxis axis) {
for (AltosTimeSeries ts : series) {
AltosUITimeSeries uts = (AltosUITimeSeries) ts;
- if (label.equals(ts.label) || (label.equals("default") && uts.color == null)) {
+ if (label.equals(ts.label) || (label.equals("default") && uts.line_style == null)) {
+ uts.custom_axis_set = true;
if (axis.marker)
- uts.set_marker(axis.color, axis.enabled, axis.plot, axis.marker_top);
+ uts.set_marker(axis.line_style, axis.enabled, axis.plot, axis.marker_top);
else
- uts.set_axis(axis.color, axis.enabled, axis.axis);
+ uts.set_axis(axis.line_style, axis.enabled, axis.axis);
}
}
}
+ void check_axes() {
+ for (AltosTimeSeries ts : series) {
+ AltosUITimeSeries uts = (AltosUITimeSeries) ts;
+
+ if (!uts.custom_axis_set)
+ System.out.printf("%s using default axis\n", ts.label);
+ }
+ }
+
public void register_axis(String label,
- Color color,
+ AltosUILineStyle line_style,
boolean enabled,
AltosUIAxis axis) {
- AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(color,
+ AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(line_style,
enabled,
axis,
null,
@@ -81,11 +90,11 @@ public class AltosUIFlightSeries extends AltosFlightSeries {
}
public void register_marker(String label,
- Color color,
+ AltosUILineStyle line_style,
boolean enabled,
XYPlot plot,
boolean marker_top) {
- AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(color,
+ AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(line_style,
enabled,
null,
plot,
@@ -97,17 +106,18 @@ public class AltosUIFlightSeries extends AltosFlightSeries {
public AltosTimeSeries make_series(String label, AltosUnits units) {
-
AltosUITimeSeries time_series = new AltosUITimeSeries(label, units);
AltosUITimeSeriesAxis tsa = axes.get(label);
if (tsa == null)
tsa = axes.get("default");
+ else
+ time_series.custom_axis_set = true;
if (tsa != null) {
if (tsa.marker)
- time_series.set_marker(tsa.color, tsa.enabled, tsa.plot, tsa.marker_top);
+ time_series.set_marker(tsa.line_style, tsa.enabled, tsa.plot, tsa.marker_top);
else
- time_series.set_axis(tsa.color, tsa.enabled, tsa.axis);
+ time_series.set_axis(tsa.line_style, tsa.enabled, tsa.axis);
}
return time_series;
}
diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java
index 0caabcfa..40f415f1 100644
--- a/altosuilib/AltosUIGraph.java
+++ b/altosuilib/AltosUIGraph.java
@@ -36,7 +36,7 @@ import org.jfree.chart.labels.*;
import org.jfree.data.xy.*;
import org.jfree.data.*;
-public class AltosUIGraph implements AltosUnitsListener {
+public class AltosUIGraph implements AltosUnitsListener, AltosShapeListener {
XYPlot plot;
JFreeChart chart;
@@ -56,14 +56,14 @@ public class AltosUIGraph implements AltosUnitsListener {
return panel;
}
- public AltosUIAxis newAxis(String label, AltosUnits units, Color color, int flags) {
- AltosUIAxis axis = new AltosUIAxis(label, units, color, axis_index++, flags);
+ public AltosUIAxis newAxis(String label, AltosUnits units, AltosUILineStyle line_style, int flags) {
+ AltosUIAxis axis = new AltosUIAxis(label, units, line_style, 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 AltosUIAxis newAxis(String label, AltosUnits units, AltosUILineStyle line_style) {
+ return newAxis(label, units, line_style, AltosUIAxis.axis_default);
}
void addAxis(AltosUIAxis axis) {
@@ -95,6 +95,20 @@ public class AltosUIGraph implements AltosUnitsListener {
s.set_units();
}
+ public void filter_changed() {
+ units_changed(false);
+ }
+
+ public void set_shapes_visible(boolean visible) {
+ for (AltosUITimeSeries s : series)
+ s.set_shapes_visible(visible);
+ }
+
+ public void set_line_width(float width) {
+ for (AltosUITimeSeries s : series)
+ s.set_line_width(width);
+ }
+
public void setName (String name) {
chart.setTitle(name);
}
@@ -123,6 +137,8 @@ public class AltosUIGraph implements AltosUnitsListener {
this.series = null;
this.axis_index = 0;
+ enable.register_shape_listener(this);
+
axes_added = new Hashtable<Integer,Boolean>();
xAxis = new NumberAxis("Time (s)");
diff --git a/altosuilib/AltosUILineStyle.java b/altosuilib/AltosUILineStyle.java
new file mode 100644
index 00000000..387281a3
--- /dev/null
+++ b/altosuilib/AltosUILineStyle.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2017 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+package org.altusmetrum.altosuilib_12;
+
+import java.io.*;
+import java.util.ArrayList;
+
+import java.awt.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_12.*;
+
+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 AltosUILineStyle {
+ public Color color;
+ public float[] dash;
+
+ static private Color color(int r, int g, int b) {
+ return new Color(r,g,b);
+ }
+
+ static final private Color[] colors = {
+ new Color(0,0,0),
+ new Color(230,0,0), // red
+ new Color(216,103,0), // orange
+ new Color(200,200,0), // yellow
+ new Color(0,180,0), // green
+ new Color(0,140,140), // cyan
+ new Color(130,0,0), // dark red
+ new Color(0,100,0), // dark green
+ new Color(0,0,255), // blue
+ new Color(140,0,140), // magenta
+ new Color(150,150,150), // gray
+ };
+
+ static final private float[][] dashes = {
+ { 0 },
+ { 2, 4 },
+ { 4, 4 },
+ { 6, 4 },
+ { 6, 4, 2, 4 }
+ };
+
+ static int color_index, dash_index;
+
+ public AltosUILineStyle () {
+ color = colors[color_index];
+ dash = dashes[dash_index];
+ color_index = (color_index + 1) % colors.length;
+ if (color_index == 0) {
+ dash_index = (dash_index + 1) % dashes.length;
+ if (dash_index == 0)
+ System.out.printf("too many line styles\n");
+ }
+ }
+
+ public AltosUILineStyle(int index) {
+ index = index % (colors.length * dashes.length);
+ int c = index % colors.length;
+ int d = index / colors.length;
+ color = colors[c];
+ dash = dashes[d];
+ }
+}
diff --git a/altosuilib/AltosUITimeSeries.java b/altosuilib/AltosUITimeSeries.java
index 08f95ca7..e85e3c17 100644
--- a/altosuilib/AltosUITimeSeries.java
+++ b/altosuilib/AltosUITimeSeries.java
@@ -61,16 +61,17 @@ class AltosXYSeries extends XYSeries {
}
public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher {
- Color color;
- boolean enable;
- AltosUIAxis axis;
- boolean marker;
- boolean marker_top;
- XYItemRenderer renderer;
- XYPlot plot;
- AltosXYSeries xy_series;
+ AltosUILineStyle line_style;
+ boolean enable;
+ boolean custom_axis_set;
+ AltosUIAxis axis;
+ boolean marker;
+ boolean marker_top;
+ XYLineAndShapeRenderer renderer;
+ XYPlot plot;
+ AltosXYSeries xy_series;
ArrayList<ValueMarker> markers;
-
+ float width;
/* AltosUIGrapher interface */
public boolean need_reset() {
@@ -89,7 +90,7 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher
public void fireSeriesChanged() {
}
- void set_data() {
+ public void set_data() {
if (marker) {
if (markers != null) {
for (ValueMarker marker : markers)
@@ -107,7 +108,8 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher
marker.setLabelAnchor(RectangleAnchor.BOTTOM_RIGHT);
marker.setLabelTextAnchor(TextAnchor.BOTTOM_LEFT);
}
- marker.setPaint(color);
+ marker.setPaint(line_style.color);
+ marker.setStroke(new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
if (enable)
plot.addDomainMarker(marker);
markers.add(marker);
@@ -124,6 +126,7 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher
}
xy_series.setNotify(true);
}
+ clear_changed();
}
public void set_units() {
@@ -164,37 +167,59 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher
}
}
- public void set_axis(Color color, boolean enable, AltosUIAxis axis) {
- this.color = color;
+ // public BasicStroke(float width, int cap, int join, float miterlimit,
+ // float dash[], float dash_phase)
+
+ public void set_line_width(float width) {
+ this.width = width;
+ if (markers != null) {
+ for (ValueMarker marker : markers) {
+ marker.setStroke(new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
+ }
+ } else {
+ if (line_style.dash[0] == 0.0)
+ renderer.setSeriesStroke(0, new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+ else
+ renderer.setSeriesStroke(0, new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, line_style.dash, 0.0f));
+ }
+ }
+
+ public void set_axis(AltosUILineStyle line_style, boolean enable, AltosUIAxis axis) {
+ this.line_style = line_style;
this.enable = enable;
this.axis = axis;
this.marker = false;
+ this.width = 1.0f;
axis.ref(this.enable);
renderer = new XYLineAndShapeRenderer(true, false);
- renderer.setSeriesPaint(0, color);
- renderer.setSeriesStroke(0, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+ renderer.setSeriesPaint(0, line_style.color);
+ set_line_width(this.width);
renderer.setSeriesVisible(0, enable);
xy_series = new AltosXYSeries(label);
}
- public void set_marker(Color color, boolean enable, XYPlot plot, boolean marker_top) {
- this.color = color;
+ public void set_marker(AltosUILineStyle line_style, boolean enable, XYPlot plot, boolean marker_top) {
+ this.line_style = line_style;
this.enable = enable;
this.marker = true;
this.plot = plot;
this.marker_top = marker_top;
}
+ public void set_shapes_visible(boolean shapes_visible) {
+ renderer.setSeriesShapesVisible(0, shapes_visible);
+ }
+
public AltosUITimeSeries(String label, AltosUnits units) {
super(label, units);
}
public AltosUITimeSeries(String label, AltosUnits units,
- Color color, boolean enable,
+ AltosUILineStyle line_style, boolean enable,
AltosUIAxis axis) {
this(label, units);
- set_axis(color, enable, axis);
+ set_axis(line_style, enable, axis);
}
}
diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am
index ce86d21e..c65a3d15 100644
--- a/altosuilib/Makefile.am
+++ b/altosuilib/Makefile.am
@@ -31,6 +31,7 @@ altosuilib_JAVA = \
AltosUIFlightSeries.java \
AltosUIGraph.java \
AltosGraph.java \
+ AltosShapeListener.java \
AltosUSBDevice.java \
AltosVoice.java \
AltosDisplayThread.java \
@@ -40,6 +41,7 @@ altosuilib_JAVA = \
AltosConfigFreqUI.java \
AltosScanUI.java \
AltosEepromDelete.java \
+ AltosEepromGrapher.java \
AltosEepromManage.java \
AltosEepromMonitorUI.java \
AltosEepromSelect.java \
@@ -56,6 +58,7 @@ altosuilib_JAVA = \
AltosBTDeviceIterator.java \
AltosBTManage.java \
AltosBTKnown.java \
+ AltosUILineStyle.java \
AltosUIMap.java \
AltosUIMapPreload.java \
AltosUIFlightTab.java \