From 9e18c524fa2d1f648f265b3c3105f5ceacf06c10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Apr 2014 16:40:06 -0700 Subject: altoslib/altosui/altosuilib/libaltos: Remove trailing whitespace Just cleaning up the source code. Signed-off-by: Keith Packard --- altosuilib/AltosDeviceDialog.java | 2 +- altosuilib/AltosUIAxis.java | 2 +- altosuilib/AltosUIEnable.java | 2 +- altosuilib/AltosUIFrame.java | 10 +++++----- altosuilib/AltosUIGraph.java | 4 ++-- altosuilib/AltosUIGrapher.java | 2 +- altosuilib/AltosUIMarker.java | 2 +- altosuilib/AltosUIPreferencesBackend.java | 2 +- altosuilib/AltosUISeries.java | 4 ++-- 9 files changed, 15 insertions(+), 15 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java index 73bc0b2f..0a3ddb7b 100644 --- a/altosuilib/AltosDeviceDialog.java +++ b/altosuilib/AltosDeviceDialog.java @@ -30,7 +30,7 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL public Frame frame; public int product; public JPanel buttonPane; - + public AltosDevice getValue() { return value; } diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java index 1638ea29..7bc2def9 100644 --- a/altosuilib/AltosUIAxis.java +++ b/altosuilib/AltosUIAxis.java @@ -50,7 +50,7 @@ public class AltosUIAxis extends NumberAxis { public void set_units() { setLabel(String.format("%s (%s)", label, units.show_units())); } - + public void set_enable(boolean enable) { if (enable) { visible++; diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java index ea4bd00a..40b5f087 100644 --- a/altosuilib/AltosUIEnable.java +++ b/altosuilib/AltosUIEnable.java @@ -56,7 +56,7 @@ public class AltosUIEnable extends Container { this.name = name; this.grapher = grapher; enable = new JRadioButton(name, enabled); - grapher.set_enable(enabled); + grapher.set_enable(enabled); enable.addActionListener(this); } } diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java index 3fc99910..3dc2a0ad 100644 --- a/altosuilib/AltosUIFrame.java +++ b/altosuilib/AltosUIFrame.java @@ -45,7 +45,7 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi }; static public String[] icon_names; - + static public void set_icon_names(String[] new_icon_names) { icon_names = new_icon_names; } public String[] icon_names() { @@ -57,7 +57,7 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi public void set_icon() { ArrayList icons = new ArrayList(); String[] icon_names = icon_names(); - + for (int i = 0; i < icon_names.length; i++) { java.net.URL imgURL = AltosUIFrame.class.getResource(icon_names[i]); if (imgURL != null) @@ -65,14 +65,14 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi } setIconImages(icons); } - + private boolean location_by_platform = true; public void setLocationByPlatform(boolean lbp) { location_by_platform = lbp; super.setLocationByPlatform(lbp); } - + public void setSize() { /* Smash sizes around so that the window comes up in the right shape */ Insets i = getInsets(); @@ -153,7 +153,7 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi setPosition(position); } } - + void init() { AltosUIPreferences.register_ui_listener(this); AltosUIPreferences.register_position_listener(this); diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java index 061a7629..21e13cf6 100644 --- a/altosuilib/AltosUIGraph.java +++ b/altosuilib/AltosUIGraph.java @@ -82,7 +82,7 @@ public class AltosUIGraph implements AltosUnitsListener { 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) { AltosUIMarker marker = new AltosUIMarker(fetch, color, plot); if (enable != null) @@ -131,7 +131,7 @@ public class AltosUIGraph implements AltosUnitsListener { this.axis_index = 0; xAxis = new NumberAxis("Time (s)"); - + xAxis.setAutoRangeIncludesZero(true); plot = new XYPlot(); diff --git a/altosuilib/AltosUIGrapher.java b/altosuilib/AltosUIGrapher.java index 23e7d9f0..54f8d5a9 100644 --- a/altosuilib/AltosUIGrapher.java +++ b/altosuilib/AltosUIGrapher.java @@ -37,7 +37,7 @@ import org.jfree.data.*; interface AltosUIGrapher { public abstract void set_units(); - + public abstract void clear(); public abstract void add(AltosUIDataPoint dataPoint); diff --git a/altosuilib/AltosUIMarker.java b/altosuilib/AltosUIMarker.java index ae8eb034..efd27921 100644 --- a/altosuilib/AltosUIMarker.java +++ b/altosuilib/AltosUIMarker.java @@ -41,7 +41,7 @@ public class AltosUIMarker implements AltosUIGrapher { boolean enabled; int fetch; Color color; - + private void remove_markers() { for (ValueMarker marker : markers) plot.removeDomainMarker(marker); diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java index 64d3e3df..d6575717 100644 --- a/altosuilib/AltosUIPreferencesBackend.java +++ b/altosuilib/AltosUIPreferencesBackend.java @@ -25,7 +25,7 @@ import javax.swing.filechooser.FileSystemView; public class AltosUIPreferencesBackend implements AltosPreferencesBackend { private Preferences _preferences = null; - + public AltosUIPreferencesBackend() { _preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); } diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java index 1f2a1c3f..c17175e4 100644 --- a/altosuilib/AltosUISeries.java +++ b/altosuilib/AltosUISeries.java @@ -38,7 +38,7 @@ class AltosUITime extends AltosUnits { public double value(double v, boolean imperial_units) { return v; } public double inverse(double v, boolean imperial_unis) { return v; } - + public String show_units(boolean imperial_units) { return "s"; } public String say_units(boolean imperial_units) { return "seconds"; } @@ -60,7 +60,7 @@ public class AltosUISeries extends XYSeries implements AltosUIGrapher { XYItemRenderer renderer; int fetch; boolean enable; - + public void set_units() { axis.set_units(); StandardXYToolTipGenerator ttg; -- cgit v1.2.3 From 8628f7e02834a476d5cb3afa4cbf8d46a4b3c513 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Apr 2014 17:45:38 -0700 Subject: altosuilib: Make lines in graphs 2 units wide This makes the graphs a lot easier to read. Signed-off-by: Keith Packard --- altosuilib/AltosUISeries.java | 1 + 1 file changed, 1 insertion(+) (limited to 'altosuilib') diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java index c17175e4..10ea1614 100644 --- a/altosuilib/AltosUISeries.java +++ b/altosuilib/AltosUISeries.java @@ -104,6 +104,7 @@ public class AltosUISeries extends XYSeries implements AltosUIGrapher { renderer = new XYLineAndShapeRenderer(true, false); renderer.setSeriesPaint(0, color); + renderer.setSeriesStroke(0, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); renderer.setSeriesVisible(0, enable); set_units(); } -- cgit v1.2.3 From 4ac7797d3efb9cc2d9fae88519f55e40b1050224 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 May 2014 20:47:49 -0700 Subject: altosui/altosuilib: Cleanup -Xlint:unchecked warnings Add parametric types to avoid unchecked warnings. Signed-off-by: Keith Packard --- altosui/AltosBTManage.java | 14 ++--- altosui/AltosCSVUI.java | 4 +- altosui/AltosChannelMenu.java | 2 +- altosui/AltosConfigFreqUI.java | 6 +- altosui/AltosConfigPyroUI.java | 4 +- altosui/AltosConfigUI.java | 124 +++++++++++++++++++------------------- altosui/AltosConfigureUI.java | 4 +- altosui/AltosFlightUI.java | 4 +- altosui/AltosScanUI.java | 8 +-- altosuilib/AltosDeviceDialog.java | 16 ++--- altosuilib/AltosUIConfigure.java | 19 +++--- 11 files changed, 101 insertions(+), 104 deletions(-) (limited to 'altosuilib') diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 1015f7c3..ad1c28b6 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -31,9 +31,9 @@ public class AltosBTManage extends AltosUIDialog implements ActionListener, Iter LinkedList listeners; AltosBTKnown bt_known; - class DeviceList extends JList implements Iterable { - LinkedList devices; - DefaultListModel list_model; + class DeviceList extends JList implements Iterable { + LinkedList devices; + DefaultListModel list_model; public void add (AltosBTDevice device) { if (!devices.contains(device)) { @@ -86,16 +86,12 @@ public class AltosBTManage extends AltosUIDialog implements ActionListener, Iter } public java.util.List selected_list() throws InterruptedException { - java.util.LinkedList l = new java.util.LinkedList(); - Object[] a = getSelectedValues(); - for (int i = 0; i < a.length; i++) - l.add((AltosBTDevice)a[i]); - return l; + return getSelectedValuesList(); } public DeviceList() { devices = new LinkedList(); - list_model = new DefaultListModel(); + list_model = new DefaultListModel(); setModel(list_model); setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); setLayoutOrientation(JList.HORIZONTAL_WRAP); diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index 05cabcdf..95a8aeea 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -30,7 +30,7 @@ public class AltosCSVUI { JFileChooser csv_chooser; JPanel accessory; - JComboBox combo_box; + JComboBox combo_box; Iterable states; AltosWriter writer; @@ -73,7 +73,7 @@ public class AltosCSVUI c.gridy = 0; accessory.add(accessory_label, c); - combo_box = new JComboBox(combo_box_items); + combo_box = new JComboBox(combo_box_items); combo_box.addActionListener(this); c.gridx = 0; c.gridy = 1; diff --git a/altosui/AltosChannelMenu.java b/altosui/AltosChannelMenu.java index f90a11c0..382b6ae4 100644 --- a/altosui/AltosChannelMenu.java +++ b/altosui/AltosChannelMenu.java @@ -20,7 +20,7 @@ package altosui; import java.awt.event.*; import javax.swing.*; -public class AltosChannelMenu extends JComboBox implements ActionListener { +public class AltosChannelMenu extends JComboBox implements ActionListener { int channel; public AltosChannelMenu(int current_channel) { diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java index 58778057..663782f0 100644 --- a/altosui/AltosConfigFreqUI.java +++ b/altosui/AltosConfigFreqUI.java @@ -164,8 +164,8 @@ public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener { Frame frame; LinkedList listeners; - class FrequencyList extends JList { - DefaultListModel list_model; + class FrequencyList extends JList { + DefaultListModel list_model; public void add(AltosFrequency frequency) { int i; @@ -226,7 +226,7 @@ public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener { } public FrequencyList(AltosFrequency[] in_frequencies) { - list_model = new DefaultListModel(); + list_model = new DefaultListModel(); setModel(list_model); setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); setLayoutOrientation(JList.HORIZONTAL_WRAP); diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java index b667b15a..cd42a3b0 100644 --- a/altosui/AltosConfigPyroUI.java +++ b/altosui/AltosConfigPyroUI.java @@ -50,7 +50,7 @@ public class AltosConfigPyroUI public int flag; public JCheckBox enable; public JTextField value; - public JComboBox combo; + public JComboBox combo; AltosConfigPyroUI ui; boolean setting; @@ -159,7 +159,7 @@ public class AltosConfigPyroUI c.insets = il; if ((flag & AltosPyro.pyro_state_value) != 0) { make_state_names(); - combo = new JComboBox(state_names); + combo = new JComboBox(state_names); combo.addItemListener(this); pane.add(combo, c); } else { diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 6292f778..7f4e1eb0 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -29,98 +29,98 @@ public class AltosConfigUI implements ActionListener, ItemListener, DocumentListener, AltosConfigValues, AltosUnitsListener { - Container pane; - JLabel product_label; - JLabel version_label; - JLabel serial_label; - JLabel main_deploy_label; - JLabel apogee_delay_label; - JLabel apogee_lockout_label; - JLabel frequency_label; - JLabel radio_calibration_label; - JLabel radio_frequency_label; - JLabel radio_enable_label; - JLabel aprs_interval_label; - JLabel flight_log_max_label; - JLabel ignite_mode_label; - JLabel pad_orientation_label; - JLabel callsign_label; - JLabel beep_label; + Container pane; + JLabel product_label; + JLabel version_label; + JLabel serial_label; + JLabel main_deploy_label; + JLabel apogee_delay_label; + JLabel apogee_lockout_label; + JLabel frequency_label; + JLabel radio_calibration_label; + JLabel radio_frequency_label; + JLabel radio_enable_label; + JLabel aprs_interval_label; + JLabel flight_log_max_label; + JLabel ignite_mode_label; + JLabel pad_orientation_label; + JLabel callsign_label; + JLabel beep_label; public boolean dirty; - JFrame owner; - JLabel product_value; - JLabel version_value; - JLabel serial_value; - JComboBox main_deploy_value; - JComboBox apogee_delay_value; - JComboBox apogee_lockout_value; - AltosFreqList radio_frequency_value; - JTextField radio_calibration_value; - JRadioButton radio_enable_value; - JComboBox aprs_interval_value; - JComboBox flight_log_max_value; - JComboBox ignite_mode_value; - JComboBox pad_orientation_value; - JTextField callsign_value; - JComboBox beep_value; - - JButton pyro; - - JButton save; - JButton reset; - JButton reboot; - JButton close; - - AltosPyro[] pyros; - - ActionListener listener; - - static String[] main_deploy_values_m = { + JFrame owner; + JLabel product_value; + JLabel version_value; + JLabel serial_value; + JComboBox main_deploy_value; + JComboBox apogee_delay_value; + JComboBox apogee_lockout_value; + AltosFreqList radio_frequency_value; + JTextField radio_calibration_value; + JRadioButton radio_enable_value; + JComboBox aprs_interval_value; + JComboBox flight_log_max_value; + JComboBox ignite_mode_value; + JComboBox pad_orientation_value; + JTextField callsign_value; + JComboBox beep_value; + + JButton pyro; + + JButton save; + JButton reset; + JButton reboot; + JButton close; + + AltosPyro[] pyros; + + ActionListener listener; + + static String[] main_deploy_values_m = { "100", "150", "200", "250", "300", "350", "400", "450", "500" }; - static String[] main_deploy_values_ft = { + static String[] main_deploy_values_ft = { "250", "500", "750", "1000", "1250", "1500", "1750", "2000" }; - static String[] apogee_delay_values = { + static String[] apogee_delay_values = { "0", "1", "2", "3", "4", "5" }; - static String[] apogee_lockout_values = { + static String[] apogee_lockout_values = { "0", "5", "10", "15", "20" }; - static String[] flight_log_max_values = { + static String[] flight_log_max_values = { "64", "128", "192", "256", "320", "384", "448", "512", "576", "640", "704", "768", "832", "896", "960", }; - static String[] ignite_mode_values = { + static String[] ignite_mode_values = { "Dual Deploy", "Redundant Apogee", "Redundant Main", }; - static String[] aprs_interval_values = { + static String[] aprs_interval_values = { "Disabled", "2", "5", "10" }; - static String[] beep_values = { + static String[] beep_values = { "3750", "4000", "4250", }; - static String[] pad_orientation_values = { + static String[] pad_orientation_values = { "Antenna Up", "Antenna Down", }; @@ -319,7 +319,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - main_deploy_value = new JComboBox(main_deploy_values()); + main_deploy_value = new JComboBox(main_deploy_values()); main_deploy_value.setEditable(true); main_deploy_value.addItemListener(this); pane.add(main_deploy_value, c); @@ -345,7 +345,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - apogee_delay_value = new JComboBox(apogee_delay_values); + apogee_delay_value = new JComboBox(apogee_delay_values); apogee_delay_value.setEditable(true); apogee_delay_value.addItemListener(this); pane.add(apogee_delay_value, c); @@ -371,7 +371,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - apogee_lockout_value = new JComboBox(apogee_lockout_values); + apogee_lockout_value = new JComboBox(apogee_lockout_values); apogee_lockout_value.setEditable(true); apogee_lockout_value.addItemListener(this); pane.add(apogee_lockout_value, c); @@ -474,7 +474,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - aprs_interval_value = new JComboBox(aprs_interval_values); + aprs_interval_value = new JComboBox(aprs_interval_values); aprs_interval_value.setEditable(true); aprs_interval_value.addItemListener(this); pane.add(aprs_interval_value, c); @@ -525,7 +525,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - flight_log_max_value = new JComboBox(flight_log_max_values); + flight_log_max_value = new JComboBox(flight_log_max_values); flight_log_max_value.setEditable(true); flight_log_max_value.addItemListener(this); pane.add(flight_log_max_value, c); @@ -551,7 +551,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - ignite_mode_value = new JComboBox(ignite_mode_values); + ignite_mode_value = new JComboBox(ignite_mode_values); ignite_mode_value.setEditable(false); ignite_mode_value.addItemListener(this); pane.add(ignite_mode_value, c); @@ -577,7 +577,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - pad_orientation_value = new JComboBox(pad_orientation_values); + pad_orientation_value = new JComboBox(pad_orientation_values); pad_orientation_value.setEditable(false); pad_orientation_value.addItemListener(this); pane.add(pad_orientation_value, c); @@ -603,7 +603,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - beep_value = new JComboBox(beep_values); + beep_value = new JComboBox(beep_values); beep_value.setEditable(true); beep_value.addItemListener(this); pane.add(beep_value, c); diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 631c188d..80876959 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -31,7 +31,7 @@ public class AltosConfigureUI AltosVoice voice; public JTextField callsign_value; - public JComboBox position_value; + public JComboBox position_value; /* DocumentListener interface methods */ public void insertUpdate(DocumentEvent e) { @@ -127,7 +127,7 @@ public class AltosConfigureUI public void add_position() { pane.add(new JLabel ("Menu position"), constraints(0, 1)); - position_value = new JComboBox (position_names); + position_value = new JComboBox(position_names); position_value.setMaximumRowCount(position_names.length); int position = AltosUIPreferences.position(); position_value.setSelectedIndex(position); diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 0d21d296..b31de12c 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -179,7 +179,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A Container bag; AltosFreqList frequencies; - JComboBox telemetries; + JComboBox telemetries; JLabel telemetry; ActionListener show_timer; @@ -225,7 +225,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A // Telemetry format menu if (reader.supports_telemetry(Altos.ao_telemetry_standard)) { - telemetries = new JComboBox(); + telemetries = new JComboBox(); for (int i = 1; i <= Altos.ao_telemetry_max; i++) telemetries.addItem(Altos.telemetry_name(i)); int telemetry = AltosPreferences.telemetry(serial); diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 419fe957..5cc74a77 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -75,7 +75,7 @@ class AltosScanResult { } } -class AltosScanResults extends LinkedList implements ListModel { +class AltosScanResults extends LinkedList implements ListModel { LinkedList listeners = new LinkedList(); @@ -129,7 +129,7 @@ public class AltosScanUI AltosDevice device; AltosConfigData config_data; AltosTelemetryReader reader; - private JList list; + private JList list; private JLabel scanning_label; private JLabel frequency_label; private JLabel telemetry_label; @@ -435,7 +435,7 @@ public class AltosScanUI int y_offset = 3 + (Altos.ao_telemetry_max - Altos.ao_telemetry_min + 1); - list = new JList(results) { + list = new JList(results) { //Subclass JList to workaround bug 4832765, which can cause the //scroll pane to not let the user easily scroll up to the beginning //of the list. An alternative would be to set the unitIncrement @@ -548,4 +548,4 @@ public class AltosScanUI setVisible(true); } -} \ No newline at end of file +} diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java index 0a3ddb7b..7fb23e13 100644 --- a/altosuilib/AltosDeviceDialog.java +++ b/altosuilib/AltosDeviceDialog.java @@ -23,13 +23,13 @@ import java.awt.event.*; public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionListener { - private AltosDevice value; - private JList list; - private JButton cancel_button; - private JButton select_button; - public Frame frame; - public int product; - public JPanel buttonPane; + private AltosDevice value; + private JList list; + private JButton cancel_button; + private JButton select_button; + public Frame frame; + public int product; + public JPanel buttonPane; public AltosDevice getValue() { return value; @@ -65,7 +65,7 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL select_button.setEnabled(false); getRootPane().setDefaultButton(select_button); - list = new JList(devices) { + list = new JList(devices) { //Subclass JList to workaround bug 4832765, which can cause the //scroll pane to not let the user easily scroll up to the beginning //of the list. An alternative would be to set the unitIncrement diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java index 9e72e403..153eb8ee 100644 --- a/altosuilib/AltosUIConfigure.java +++ b/altosuilib/AltosUIConfigure.java @@ -23,10 +23,10 @@ import java.beans.*; import javax.swing.*; import javax.swing.event.*; -class DelegatingRenderer implements ListCellRenderer { +class DelegatingRenderer implements ListCellRenderer { // ... - public static void install(JComboBox comboBox) { + public static void install(JComboBox comboBox) { DelegatingRenderer renderer = new DelegatingRenderer(comboBox); renderer.initialise(); comboBox.setRenderer(renderer); @@ -36,7 +36,7 @@ class DelegatingRenderer implements ListCellRenderer { private final JComboBox comboBox; // ... - private ListCellRenderer delegate; + private ListCellRenderer delegate; // ... private DelegatingRenderer(JComboBox comboBox) { @@ -45,21 +45,22 @@ class DelegatingRenderer implements ListCellRenderer { // ... private void initialise() { - delegate = new JComboBox().getRenderer(); + JComboBox c = new JComboBox(); + delegate = c.getRenderer(); comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { - delegate = new JComboBox().getRenderer(); + delegate = new JComboBox().getRenderer(); } }); } // ... - public Component getListCellRendererComponent(JList list, + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { return delegate.getListCellRendererComponent(list, - ((UIManager.LookAndFeelInfo) value).getName(), + ((UIManager.LookAndFeelInfo)value).getName(), index, isSelected, cellHasFocus); } } @@ -139,7 +140,7 @@ public class AltosUIConfigure /* Font size setting */ pane.add(new JLabel("Font size"), constraints(0, 1)); - final JComboBox font_size_value = new JComboBox(font_size_names); + final JComboBox font_size_value = new JComboBox(font_size_names); int font_size = AltosUIPreferences.font_size(); font_size_value.setSelectedIndex(font_size - AltosUILib.font_size_small); font_size_value.addActionListener(new ActionListener() { @@ -181,7 +182,7 @@ public class AltosUIConfigure final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels(); - final JComboBox look_and_feel_value = new JComboBox(look_and_feels); + final JComboBox look_and_feel_value = new JComboBox(look_and_feels); DelegatingRenderer.install(look_and_feel_value); -- cgit v1.2.3 From 0a6c76fc0525d6588a1d88127f0085f13a02f1af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 May 2014 20:55:11 -0700 Subject: altosui/altosuilib/altoslib: Move more stuff out of autosui. Reduce site map memory Prepare to share with TeleGPS application. This also has the changes to the site map tile which cache only a few images and regenerate the flight path on the fly, saving piles of memory Signed-off-by: Keith Packard --- altoslib/AltosFlightStats.java | 188 ++++++++++++++ altoslib/Makefile.am | 3 +- altosui/AltosDisplayThread.java | 259 ------------------- altosui/AltosFlightDisplay.java | 28 --- altosui/AltosFlightStats.java | 189 -------------- altosui/AltosFreqList.java | 86 ------- altosui/AltosSiteMap.java | 476 ----------------------------------- altosui/AltosSiteMapCache.java | 119 --------- altosui/AltosSiteMapPreload.java | 467 ---------------------------------- altosui/AltosSiteMapTile.java | 122 --------- altosui/AltosVoice.java | 95 ------- altosui/GrabNDrag.java | 48 ---- altosui/Makefile.am | 12 +- altosuilib/AltosDisplayThread.java | 259 +++++++++++++++++++ altosuilib/AltosFlightDisplay.java | 28 +++ altosuilib/AltosFreqList.java | 85 +++++++ altosuilib/AltosSiteMap.java | 484 ++++++++++++++++++++++++++++++++++++ altosuilib/AltosSiteMapCache.java | 194 +++++++++++++++ altosuilib/AltosSiteMapPreload.java | 467 ++++++++++++++++++++++++++++++++++ altosuilib/AltosSiteMapTile.java | 142 +++++++++++ altosuilib/AltosVoice.java | 94 +++++++ altosuilib/GrabNDrag.java | 48 ++++ altosuilib/Makefile.am | 13 +- 23 files changed, 2003 insertions(+), 1903 deletions(-) create mode 100644 altoslib/AltosFlightStats.java delete mode 100644 altosui/AltosDisplayThread.java delete mode 100644 altosui/AltosFlightDisplay.java delete mode 100644 altosui/AltosFlightStats.java delete mode 100644 altosui/AltosFreqList.java delete mode 100644 altosui/AltosSiteMap.java delete mode 100644 altosui/AltosSiteMapCache.java delete mode 100644 altosui/AltosSiteMapPreload.java delete mode 100644 altosui/AltosSiteMapTile.java delete mode 100644 altosui/AltosVoice.java delete mode 100644 altosui/GrabNDrag.java create mode 100644 altosuilib/AltosDisplayThread.java create mode 100644 altosuilib/AltosFlightDisplay.java create mode 100644 altosuilib/AltosFreqList.java create mode 100644 altosuilib/AltosSiteMap.java create mode 100644 altosuilib/AltosSiteMapCache.java create mode 100644 altosuilib/AltosSiteMapPreload.java create mode 100644 altosuilib/AltosSiteMapTile.java create mode 100644 altosuilib/AltosVoice.java create mode 100644 altosuilib/GrabNDrag.java (limited to 'altosuilib') diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java new file mode 100644 index 00000000..87e04293 --- /dev/null +++ b/altoslib/AltosFlightStats.java @@ -0,0 +1,188 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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_4; + +import java.io.*; + +public class AltosFlightStats { + public double max_height; + public double max_gps_height; + public double max_speed; + public double max_acceleration; + public double[] state_speed = new double[AltosLib.ao_flight_invalid + 1]; + public double[] state_accel = new double[AltosLib.ao_flight_invalid + 1]; + public int[] state_count = new int[AltosLib.ao_flight_invalid + 1]; + public double[] state_start = new double[AltosLib.ao_flight_invalid + 1]; + public double[] state_end = new double[AltosLib.ao_flight_invalid + 1]; + public int serial; + public int flight; + public int year, month, day; + public int hour, minute, second; + public double lat, lon; + public double pad_lat, pad_lon; + public boolean has_gps; + public boolean has_other_adc; + public boolean has_rssi; + public boolean has_imu; + public boolean has_mag; + public boolean has_orient; + public int num_ignitor; + + double landed_time(AltosStateIterable states) { + AltosState state = null; + + for (AltosState s : states) { + state = s; + if (state.state == AltosLib.ao_flight_landed) + break; + } + + if (state == null) + return 0; + + double landed_height = state.height(); + + state = null; + + boolean above = true; + + double landed_time = -1000; + + for (AltosState s : states) { + state = s; + + if (state.height() > landed_height + 10) { + above = true; + } else { + if (above && state.height() < landed_height + 2) { + above = false; + landed_time = state.time; + } + } + } + if (landed_time == -1000) + landed_time = state.time; + return landed_time; + } + + double boost_time(AltosStateIterable states) { + double boost_time = AltosLib.MISSING; + AltosState state = null; + + for (AltosState s : states) { + state = s; + if (state.acceleration() < 1) + boost_time = state.time; + if (state.state >= AltosLib.ao_flight_boost && state.state <= AltosLib.ao_flight_landed) + break; + } + if (state == null) + return 0; + + if (boost_time == AltosLib.MISSING) + boost_time = state.time; + return boost_time; + } + + + public AltosFlightStats(AltosStateIterable states) throws InterruptedException, IOException { + double boost_time = boost_time(states); + double end_time = 0; + double landed_time = landed_time(states); + + year = month = day = AltosLib.MISSING; + hour = minute = second = AltosLib.MISSING; + serial = flight = AltosLib.MISSING; + lat = lon = AltosLib.MISSING; + has_gps = false; + has_other_adc = false; + has_rssi = false; + has_imu = false; + has_mag = false; + has_orient = false; + for (AltosState state : states) { + if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING) + serial = state.serial; + if (flight == AltosLib.MISSING && state.flight != AltosLib.MISSING) + flight = state.flight; + if (state.battery_voltage != AltosLib.MISSING) + has_other_adc = true; + if (state.rssi != AltosLib.MISSING) + has_rssi = true; + end_time = state.time; + + int state_id = state.state; + if (state.time >= boost_time && state_id < AltosLib.ao_flight_boost) + state_id = AltosLib.ao_flight_boost; + if (state.time >= landed_time && state_id < AltosLib.ao_flight_landed) + state_id = AltosLib.ao_flight_landed; + if (state.gps != null && state.gps.locked) { + year = state.gps.year; + month = state.gps.month; + day = state.gps.day; + hour = state.gps.hour; + minute = state.gps.minute; + second = state.gps.second; + } + if (0 <= state_id && state_id < AltosLib.ao_flight_invalid) { + double acceleration = state.acceleration(); + double speed = state.speed(); + if (acceleration != AltosLib.MISSING && speed != AltosLib.MISSING) { + state_accel[state_id] += acceleration; + state_speed[state_id] += speed; + state_count[state_id]++; + } + if (state_start[state_id] == 0.0) + state_start[state_id] = state.time; + if (state_end[state_id] < state.time) + state_end[state_id] = state.time; + max_height = state.max_height(); + max_speed = state.max_speed(); + max_acceleration = state.max_acceleration(); + max_gps_height = state.max_gps_height(); + } + if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { + if (state_id <= AltosLib.ao_flight_pad) { + pad_lat = state.gps.lat; + pad_lon = state.gps.lon; + } + lat = state.gps.lat; + lon = state.gps.lon; + has_gps = true; + } + if (state.imu != null) + has_imu = true; + if (state.mag != null) + has_mag = true; + if (state.orient() != AltosLib.MISSING) + has_orient = true; + if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor) + num_ignitor = state.ignitor_voltage.length; + } + for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) { + if (state_count[s] > 0) { + state_speed[s] /= state_count[s]; + state_accel[s] /= state_count[s]; + } + if (state_start[s] == 0) + state_start[s] = end_time; + if (state_end[s] == 0) + state_end[s] = end_time; + } + } +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 67cc38ff..bff09704 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -1,4 +1,4 @@ -AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6 +AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6 JAVAROOT=bin @@ -51,6 +51,7 @@ altoslib_JAVA = \ AltosFlash.java \ AltosFlashListener.java \ AltosFlightReader.java \ + AltosFlightStats.java \ AltosFrequency.java \ AltosGPS.java \ AltosGPSSat.java \ diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java deleted file mode 100644 index ab85607d..00000000 --- a/altosui/AltosDisplayThread.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import javax.swing.*; -import java.io.*; -import java.text.*; -import org.altusmetrum.altoslib_3.*; - -public class AltosDisplayThread extends Thread { - - Frame parent; - IdleThread idle_thread; - AltosVoice voice; - AltosFlightReader reader; - AltosState old_state, state; - AltosListenerState listener_state; - AltosFlightDisplay display; - - synchronized void show_safely() { - final AltosState my_state = state; - final AltosListenerState my_listener_state = listener_state; - Runnable r = new Runnable() { - public void run() { - try { - display.show(my_state, my_listener_state); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - void reading_error_internal() { - JOptionPane.showMessageDialog(parent, - String.format("Error reading from \"%s\"", reader.name), - "Telemetry Read Error", - JOptionPane.ERROR_MESSAGE); - } - - void reading_error_safely() { - Runnable r = new Runnable() { - public void run() { - try { - reading_error_internal(); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - class IdleThread extends Thread { - - boolean started; - int reported_landing; - int report_interval; - long report_time; - - public synchronized void report(boolean last) { - if (state == null) - return; - - /* reset the landing count once we hear about a new flight */ - if (state.state < Altos.ao_flight_drogue) - reported_landing = 0; - - /* Shut up once the rocket is on the ground */ - if (reported_landing > 2) { - return; - } - - /* If the rocket isn't on the pad, then report height */ - if (Altos.ao_flight_drogue <= state.state && - state.state < Altos.ao_flight_landed && - state.from_pad != null && - state.range >= 0) - { - voice.speak("Height %s, bearing %s %d, elevation %d, range %s.\n", - AltosConvert.height.say(state.height()), - state.from_pad.bearing_words( - AltosGreatCircle.BEARING_VOICE), - (int) (state.from_pad.bearing + 0.5), - (int) (state.elevation + 0.5), - AltosConvert.distance.say(state.range)); - } else if (state.state > Altos.ao_flight_pad) { - voice.speak(AltosConvert.height.say_units(state.height())); - } else { - reported_landing = 0; - } - - /* If the rocket is coming down, check to see if it has landed; - * either we've got a landed report or we haven't heard from it in - * a long time - */ - if (state.state >= Altos.ao_flight_drogue && - (last || - System.currentTimeMillis() - state.received_time >= 15000 || - state.state == Altos.ao_flight_landed)) - { - if (Math.abs(state.speed()) < 20 && state.height() < 100) - voice.speak("rocket landed safely"); - else - voice.speak("rocket may have crashed"); - if (state.from_pad != null) - voice.speak("Bearing %d degrees, range %s.", - (int) (state.from_pad.bearing + 0.5), - AltosConvert.distance.say_units(state.from_pad.distance)); - ++reported_landing; - if (state.state != Altos.ao_flight_landed) { - state.state = Altos.ao_flight_landed; - show_safely(); - } - } - } - - long now () { - return System.currentTimeMillis(); - } - - void set_report_time() { - report_time = now() + report_interval; - } - - public void run () { - try { - for (;;) { - if (reader.has_monitor_battery()) { - listener_state.battery = reader.monitor_battery(); - show_safely(); - } - set_report_time(); - for (;;) { - voice.drain(); - synchronized (this) { - long sleep_time = report_time - now(); - if (sleep_time <= 0) - break; - wait(sleep_time); - } - } - - report(false); - } - } catch (InterruptedException ie) { - try { - voice.drain(); - } catch (InterruptedException iie) { } - } - } - - public synchronized void notice(boolean spoken) { - if (old_state != null && old_state.state != state.state) { - report_time = now(); - this.notify(); - } else if (spoken) - set_report_time(); - } - - public IdleThread() { - reported_landing = 0; - report_interval = 10000; - } - } - - synchronized boolean tell() { - boolean ret = false; - if (old_state == null || old_state.state != state.state) { - voice.speak(state.state_name()); - if ((old_state == null || old_state.state <= Altos.ao_flight_boost) && - state.state > Altos.ao_flight_boost) { - voice.speak("max speed: %s.", - AltosConvert.speed.say_units(state.max_speed() + 0.5)); - ret = true; - } else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) && - state.state >= Altos.ao_flight_drogue) { - voice.speak("max height: %s.", - AltosConvert.height.say_units(state.max_height() + 0.5)); - ret = true; - } - } - if (old_state == null || old_state.gps_ready != state.gps_ready) { - if (state.gps_ready) { - voice.speak("GPS ready"); - ret = true; - } - else if (old_state != null) { - voice.speak("GPS lost"); - ret = true; - } - } - old_state = state; - return ret; - } - - public void run() { - boolean interrupted = false; - boolean told; - - idle_thread = new IdleThread(); - idle_thread.start(); - - try { - for (;;) { - try { - state = reader.read(); - if (state == null) - break; - reader.update(state); - show_safely(); - told = tell(); - idle_thread.notice(told); - } catch (ParseException pp) { - System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); - } catch (AltosCRCException ce) { - ++listener_state.crc_errors; - show_safely(); - } - } - } catch (InterruptedException ee) { - interrupted = true; - } catch (IOException ie) { - reading_error_safely(); - } finally { - if (!interrupted) - idle_thread.report(true); - reader.close(interrupted); - idle_thread.interrupt(); - try { - idle_thread.join(); - } catch (InterruptedException ie) {} - } - } - - public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) { - listener_state = new AltosListenerState(); - parent = in_parent; - voice = in_voice; - display = in_display; - reader = in_reader; - display.reset(); - } -} diff --git a/altosui/AltosFlightDisplay.java b/altosui/AltosFlightDisplay.java deleted file mode 100644 index c1264259..00000000 --- a/altosui/AltosFlightDisplay.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.altoslib_3.*; - -public interface AltosFlightDisplay { - void reset(); - - void show(AltosState state, AltosListenerState listener_state); - - void set_font(); -} diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java deleted file mode 100644 index d02a518d..00000000 --- a/altosui/AltosFlightStats.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 org.altusmetrum.altoslib_3.*; - -public class AltosFlightStats { - double max_height; - double max_gps_height; - double max_speed; - double max_acceleration; - double[] state_speed = new double[Altos.ao_flight_invalid + 1]; - double[] state_accel = new double[Altos.ao_flight_invalid + 1]; - int[] state_count = new int[Altos.ao_flight_invalid + 1]; - double[] state_start = new double[Altos.ao_flight_invalid + 1]; - double[] state_end = new double[Altos.ao_flight_invalid + 1]; - int serial; - int flight; - int year, month, day; - int hour, minute, second; - double lat, lon; - double pad_lat, pad_lon; - boolean has_gps; - boolean has_other_adc; - boolean has_rssi; - boolean has_imu; - boolean has_mag; - boolean has_orient; - int num_ignitor; - - double landed_time(AltosStateIterable states) { - AltosState state = null; - - for (AltosState s : states) { - state = s; - if (state.state == Altos.ao_flight_landed) - break; - } - - if (state == null) - return 0; - - double landed_height = state.height(); - - state = null; - - boolean above = true; - - double landed_time = -1000; - - for (AltosState s : states) { - state = s; - - if (state.height() > landed_height + 10) { - above = true; - } else { - if (above && state.height() < landed_height + 2) { - above = false; - landed_time = state.time; - } - } - } - if (landed_time == -1000) - landed_time = state.time; - return landed_time; - } - - double boost_time(AltosStateIterable states) { - double boost_time = AltosLib.MISSING; - AltosState state = null; - - for (AltosState s : states) { - state = s; - if (state.acceleration() < 1) - boost_time = state.time; - if (state.state >= AltosLib.ao_flight_boost && state.state <= AltosLib.ao_flight_landed) - break; - } - if (state == null) - return 0; - - if (boost_time == AltosLib.MISSING) - boost_time = state.time; - return boost_time; - } - - - public AltosFlightStats(AltosStateIterable states) throws InterruptedException, IOException { - double boost_time = boost_time(states); - double end_time = 0; - double landed_time = landed_time(states); - - year = month = day = AltosLib.MISSING; - hour = minute = second = AltosLib.MISSING; - serial = flight = AltosLib.MISSING; - lat = lon = AltosLib.MISSING; - has_gps = false; - has_other_adc = false; - has_rssi = false; - has_imu = false; - has_mag = false; - has_orient = false; - for (AltosState state : states) { - if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING) - serial = state.serial; - if (flight == AltosLib.MISSING && state.flight != AltosLib.MISSING) - flight = state.flight; - if (state.battery_voltage != AltosLib.MISSING) - has_other_adc = true; - if (state.rssi != AltosLib.MISSING) - has_rssi = true; - end_time = state.time; - - int state_id = state.state; - if (state.time >= boost_time && state_id < Altos.ao_flight_boost) - state_id = Altos.ao_flight_boost; - if (state.time >= landed_time && state_id < Altos.ao_flight_landed) - state_id = Altos.ao_flight_landed; - if (state.gps != null && state.gps.locked) { - year = state.gps.year; - month = state.gps.month; - day = state.gps.day; - hour = state.gps.hour; - minute = state.gps.minute; - second = state.gps.second; - } - if (0 <= state_id && state_id < Altos.ao_flight_invalid) { - double acceleration = state.acceleration(); - double speed = state.speed(); - if (acceleration != AltosLib.MISSING && speed != AltosLib.MISSING) { - state_accel[state_id] += acceleration; - state_speed[state_id] += speed; - state_count[state_id]++; - } - if (state_start[state_id] == 0.0) - state_start[state_id] = state.time; - if (state_end[state_id] < state.time) - state_end[state_id] = state.time; - max_height = state.max_height(); - max_speed = state.max_speed(); - max_acceleration = state.max_acceleration(); - max_gps_height = state.max_gps_height(); - } - if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { - if (state_id <= Altos.ao_flight_pad) { - pad_lat = state.gps.lat; - pad_lon = state.gps.lon; - } - lat = state.gps.lat; - lon = state.gps.lon; - has_gps = true; - } - if (state.imu != null) - has_imu = true; - if (state.mag != null) - has_mag = true; - if (state.orient() != AltosLib.MISSING) - has_orient = true; - if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor) - num_ignitor = state.ignitor_voltage.length; - } - for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) { - if (state_count[s] > 0) { - state_speed[s] /= state_count[s]; - state_accel[s] /= state_count[s]; - } - if (state_start[s] == 0) - state_start[s] = end_time; - if (state_end[s] == 0) - state_end[s] = end_time; - } - } -} diff --git a/altosui/AltosFreqList.java b/altosui/AltosFreqList.java deleted file mode 100644 index 525e5ce5..00000000 --- a/altosui/AltosFreqList.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; - -public class AltosFreqList extends JComboBox { - - String product; - int serial; - int calibrate; - - public void set_frequency(double new_frequency) { - int i; - - if (new_frequency < 0) { - setVisible(false); - return; - } - - for (i = 0; i < getItemCount(); i++) { - AltosFrequency f = (AltosFrequency) getItemAt(i); - - if (f.close(new_frequency)) { - setSelectedIndex(i); - return; - } - } - for (i = 0; i < getItemCount(); i++) { - AltosFrequency f = (AltosFrequency) getItemAt(i); - - if (new_frequency < f.frequency) - break; - } - String description = String.format("%s serial %d", product, serial); - AltosFrequency frequency = new AltosFrequency(new_frequency, description); - AltosUIPreferences.add_common_frequency(frequency); - insertItemAt(frequency, i); - setMaximumRowCount(getItemCount()); - } - - public void set_product(String new_product) { - product = new_product; - } - - public void set_serial(int new_serial) { - serial = new_serial; - } - - public double frequency() { - AltosFrequency f = (AltosFrequency) getSelectedItem(); - if (f != null) - return f.frequency; - return 434.550; - } - - public AltosFreqList () { - super(AltosUIPreferences.common_frequencies()); - setMaximumRowCount(getItemCount()); - setEditable(false); - product = "Unknown"; - serial = 0; - } - - public AltosFreqList(double in_frequency) { - this(); - set_frequency(in_frequency); - } -} diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java deleted file mode 100644 index 643417b5..00000000 --- a/altosui/AltosSiteMap.java +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import javax.swing.*; -import java.io.*; -import java.lang.Math; -import java.awt.geom.Point2D; -import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; - -public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { - // preferred vertical step in a tile in naut. miles - // will actually choose a step size between x and 2x, where this - // is 1.5x - static final double tile_size_nmi = 0.75; - - static final int px_size = 512; - - static final int MAX_TILE_DELTA = 100; - - private static Point2D.Double translatePoint(Point2D.Double p, - Point2D.Double d) - { - return new Point2D.Double(p.x + d.x, p.y + d.y); - } - - static class LatLng { - public double lat, lng; - public LatLng(double lat, double lng) { - this.lat = lat; - this.lng = lng; - } - } - - // based on google js - // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js - // search for fromLatLngToPoint and fromPointToLatLng - /* - private static Point2D.Double pt(LatLng latlng, int zoom) { - double scale_x = 256/360.0 * Math.pow(2, zoom); - double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - return pt(latlng, scale_x, scale_y); - } - */ - - private static Point2D.Double pt(LatLng latlng, - double scale_x, double scale_y) - { - Point2D.Double res = new Point2D.Double(); - double e; - - res.x = latlng.lng * scale_x; - - e = Math.sin(Math.toRadians(latlng.lat)); - e = Math.max(e,-(1-1.0E-15)); - e = Math.min(e, 1-1.0E-15 ); - - res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y; - return res; - } - - static private LatLng latlng(Point2D.Double pt, - double scale_x, double scale_y) - { - double lat, lng; - double rads; - - lng = pt.x/scale_x; - rads = 2 * Math.atan(Math.exp(-pt.y/scale_y)); - lat = Math.toDegrees(rads - Math.PI/2); - - return new LatLng(lat,lng); - } - - int zoom; - double scale_x, scale_y; - - int radius; /* half width/height of tiles to load */ - - private Point2D.Double pt(double lat, double lng) { - return pt(new LatLng(lat, lng), scale_x, scale_y); - } - - private LatLng latlng(double x, double y) { - return latlng(new Point2D.Double(x,y), scale_x, scale_y); - } - /* - private LatLng latlng(Point2D.Double pt) { - return latlng(pt, scale_x, scale_y); - } - */ - - ConcurrentHashMap mapTiles = new ConcurrentHashMap(); - Point2D.Double centre; - - private Point2D.Double tileCoordOffset(Point p) { - return new Point2D.Double(centre.x - p.x*px_size, - centre.y - p.y * px_size); - } - - private Point tileOffset(Point2D.Double p) { - return new Point((int)Math.floor((centre.x+p.x)/px_size), - (int)Math.floor((centre.y+p.y)/px_size)); - } - - private Point2D.Double getBaseLocation(double lat, double lng) { - Point2D.Double locn, north_step; - - zoom = 2; - // stupid loop structure to please Java's control flow analysis - do { - zoom++; - scale_x = 256/360.0 * Math.pow(2, zoom); - scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - locn = pt(lat, lng); - north_step = pt(lat+tile_size_nmi*4/3/60.0, lng); - if (locn.y - north_step.y > px_size) - break; - } while (zoom < 22); - locn.x = -px_size * Math.floor(locn.x/px_size); - locn.y = -px_size * Math.floor(locn.y/px_size); - return locn; - } - - public void reset() { - // nothing - } - - public void set_font() { - // nothing - } - - private void loadMap(final AltosSiteMapTile tile, - File pngfile, String pngurl) - { - final ImageIcon res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); - if (res != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - tile.loadMap(res); - } - }); - } else { - System.out.printf("# Failed to fetch file %s\n", pngfile); - System.out.printf(" wget -O '%s' '%s'\n", pngfile, pngurl); - } - } - - File pngfile; - String pngurl; - - public int prefetchMap(int x, int y) { - LatLng map_latlng = latlng( - -centre.x + x*px_size + px_size/2, - -centre.y + y*px_size + px_size/2); - pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); - pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); - if (pngfile.exists()) { - return 1; - } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { - return 0; - } else { - return -1; - } - } - - public static void prefetchMaps(double lat, double lng) { - int w = AltosSiteMapPreload.width; - int h = AltosSiteMapPreload.height; - AltosSiteMap asm = new AltosSiteMap(true); - asm.centre = asm.getBaseLocation(lat, lng); - - //Point2D.Double p = new Point2D.Double(); - //Point2D.Double p2; - int dx = -w/2, dy = -h/2; - for (int y = dy; y < h+dy; y++) { - for (int x = dx; x < w+dx; x++) { - int r = asm.prefetchMap(x, y); - switch (r) { - case 1: - System.out.printf("Already have %s\n", asm.pngfile); - break; - case 0: - System.out.printf("Fetched map %s\n", asm.pngfile); - break; - case -1: - System.out.printf("# Failed to fetch file %s\n", asm.pngfile); - System.out.printf(" wget -O '%s' ''\n", asm.pngfile, asm.pngurl); - break; - } - } - } - } - - public String initMap(Point offset) { - AltosSiteMapTile tile = mapTiles.get(offset); - Point2D.Double coord = tileCoordOffset(offset); - - LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y); - - File pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); - String pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); - loadMap(tile, pngfile, pngurl); - return pngfile.toString(); - } - - public void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) { - Thread thread = new Thread() { - public void run() { - initMap(offset); - finishTileLater(tile, offset); - } - }; - thread.start(); - } - - public void setBaseLocation(double lat, double lng) { - for (Point k : mapTiles.keySet()) { - AltosSiteMapTile tile = mapTiles.get(k); - tile.clearMap(); - } - - centre = getBaseLocation(lat, lng); - scrollRocketToVisible(pt(lat,lng)); - } - - private void initMaps(double lat, double lng) { - setBaseLocation(lat, lng); - - Thread thread = new Thread() { - public void run() { - for (Point k : mapTiles.keySet()) - initMap(k); - } - }; - thread.start(); - } - - private static File MapFile(double lat, double lng, int zoom) { - char chlat = lat < 0 ? 'S' : 'N'; - char chlng = lng < 0 ? 'W' : 'E'; - if (lat < 0) lat = -lat; - if (lng < 0) lng = -lng; - return new File(AltosUIPreferences.mapdir(), - String.format("map-%c%.6f,%c%.6f-%d.png", - chlat, lat, chlng, lng, zoom)); - } - - private static String MapURL(double lat, double lng, int zoom) { - return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); - } - - boolean initialised = false; - Point2D.Double last_pt = null; - int last_state = -1; - - public void show(double lat, double lon) { - System.out.printf ("show %g %g\n", lat, lon); - return; -// initMaps(lat, lon); -// scrollRocketToVisible(pt(lat, lon)); - } - public void show(final AltosState state, final AltosListenerState listener_state) { - // if insufficient gps data, nothing to update - AltosGPS gps = state.gps; - - if (gps == null) - return; - - if (!gps.locked && gps.nsat < 4) - return; - - if (!initialised) { - if (state.pad_lat != AltosLib.MISSING && state.pad_lon != AltosLib.MISSING) { - initMaps(state.pad_lat, state.pad_lon); - initialised = true; - } else if (gps.lat != AltosLib.MISSING && gps.lon != AltosLib.MISSING) { - initMaps(gps.lat, gps.lon); - initialised = true; - } else { - return; - } - } - - final Point2D.Double pt = pt(gps.lat, gps.lon); - if (last_pt == pt && last_state == state.state) - return; - - if (last_pt == null) { - last_pt = pt; - } - boolean in_any = false; - for (Point offset : mapTiles.keySet()) { - AltosSiteMapTile tile = mapTiles.get(offset); - Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(offset)); - lref = translatePoint(last_pt, tileCoordOffset(offset)); - tile.show(state, listener_state, lref, ref); - if (0 <= ref.x && ref.x < px_size) - if (0 <= ref.y && ref.y < px_size) - in_any = true; - } - - Point offset = tileOffset(pt); - if (!in_any) { - Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(offset)); - lref = translatePoint(last_pt, tileCoordOffset(offset)); - - AltosSiteMapTile tile = createTile(offset); - tile.show(state, listener_state, lref, ref); - initAndFinishMapAsync(tile, offset); - } - - scrollRocketToVisible(pt); - - if (offset != tileOffset(last_pt)) { - ensureTilesAround(offset); - } - - last_pt = pt; - last_state = state.state; - } - - public void centre(Point2D.Double pt) { - Rectangle r = comp.getVisibleRect(); - Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); - int dx = (int)copt.x - r.width/2 - r.x; - int dy = (int)copt.y - r.height/2 - r.y; - r.x += dx; - r.y += dy; - comp.scrollRectToVisible(r); - } - - public void centre(AltosState state) { - if (!state.gps.locked && state.gps.nsat < 4) - return; - centre(pt(state.gps.lat, state.gps.lon)); - } - - public void draw_circle(double lat, double lon) { - final Point2D.Double pt = pt(lat, lon); - - for (Point offset : mapTiles.keySet()) { - AltosSiteMapTile tile = mapTiles.get(offset); - Point2D.Double ref = translatePoint(pt, tileCoordOffset(offset)); - tile.draw_circle(ref); - } - } - - private AltosSiteMapTile createTile(Point offset) { - AltosSiteMapTile tile = new AltosSiteMapTile(px_size); - mapTiles.put(offset, tile); - return tile; - } - private void finishTileLater(final AltosSiteMapTile tile, - final Point offset) - { - SwingUtilities.invokeLater( new Runnable() { - public void run() { - addTileAt(tile, offset); - } - } ); - } - - private void ensureTilesAround(Point base_offset) { - for (int x = -radius; x <= radius; x++) { - for (int y = -radius; y <= radius; y++) { - Point offset = new Point(base_offset.x + x, base_offset.y + y); - if (mapTiles.containsKey(offset)) - continue; - AltosSiteMapTile tile = createTile(offset); - initAndFinishMapAsync(tile, offset); - } - } - } - - private Point topleft = new Point(0,0); - private void scrollRocketToVisible(Point2D.Double pt) { - Rectangle r = comp.getVisibleRect(); - Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); - int dx = (int)copt.x - r.width/2 - r.x; - int dy = (int)copt.y - r.height/2 - r.y; - if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) { - r.x += dx; - r.y += dy; - comp.scrollRectToVisible(r); - } - } - - private void addTileAt(AltosSiteMapTile tile, Point offset) { - if (Math.abs(offset.x) >= MAX_TILE_DELTA || - Math.abs(offset.y) >= MAX_TILE_DELTA) - { - System.out.printf("Rocket too far away from pad (tile %d,%d)\n", - offset.x, offset.y); - return; - } - - boolean review = false; - Rectangle r = comp.getVisibleRect(); - if (offset.x < topleft.x) { - r.x += (topleft.x - offset.x) * px_size; - topleft.x = offset.x; - review = true; - } - if (offset.y < topleft.y) { - r.y += (topleft.y - offset.y) * px_size; - topleft.y = offset.y; - review = true; - } - GridBagConstraints c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.BOTH; - // put some space between the map tiles, debugging only - // c.insets = new Insets(5, 5, 5, 5); - - c.gridx = offset.x + MAX_TILE_DELTA; - c.gridy = offset.y + MAX_TILE_DELTA; - layout.setConstraints(tile, c); - - comp.add(tile); - if (review) { - comp.scrollRectToVisible(r); - } - } - - private AltosSiteMap(boolean knowWhatYouAreDoing) { - if (!knowWhatYouAreDoing) { - throw new RuntimeException("Arggh."); - } - } - - JComponent comp = new JComponent() { }; - private GridBagLayout layout = new GridBagLayout(); - - public AltosSiteMap(int in_radius) { - radius = in_radius; - - GrabNDrag scroller = new GrabNDrag(comp); - - comp.setLayout(layout); - - for (int x = -radius; x <= radius; x++) { - for (int y = -radius; y <= radius; y++) { - Point offset = new Point(x, y); - AltosSiteMapTile t = createTile(offset); - addTileAt(t, offset); - } - } - setViewportView(comp); - setPreferredSize(new Dimension(500,500)); - } - - public AltosSiteMap() { - this(1); - } -} diff --git a/altosui/AltosSiteMapCache.java b/altosui/AltosSiteMapCache.java deleted file mode 100644 index 03dc3cf5..00000000 --- a/altosui/AltosSiteMapCache.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * 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 javax.swing.*; -import javax.imageio.ImageIO; -import java.awt.image.*; -import java.io.*; -import java.net.URL; -import java.net.URLConnection; - -public class AltosSiteMapCache extends JLabel { - static final long google_maps_ratelimit_ms = 1200; - // Google limits static map queries to 50 per minute per IP, so - // each query should take at least 1.2 seconds. - - public static boolean fetchMap(File file, String url) { - URL u; - long startTime = System.nanoTime(); - - try { - u = new URL(url); - } catch (java.net.MalformedURLException e) { - return false; - } - - byte[] data; - try { - URLConnection uc = u.openConnection(); - int contentLength = uc.getContentLength(); - InputStream in = new BufferedInputStream(uc.getInputStream()); - int bytesRead = 0; - int offset = 0; - data = new byte[contentLength]; - while (offset < contentLength) { - bytesRead = in.read(data, offset, data.length - offset); - if (bytesRead == -1) - break; - offset += bytesRead; - } - in.close(); - - if (offset != contentLength) { - return false; - } - } catch (IOException e) { - return false; - } - - try { - FileOutputStream out = new FileOutputStream(file); - out.write(data); - out.flush(); - out.close(); - } catch (FileNotFoundException e) { - return false; - } catch (IOException e) { - if (file.exists()) { - file.delete(); - } - return false; - } - - long duration_ms = (System.nanoTime() - startTime) / 1000000; - if (duration_ms < google_maps_ratelimit_ms) { - try { - Thread.sleep(google_maps_ratelimit_ms - duration_ms); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - return true; - } - - public static ImageIcon fetchAndLoadMap(File pngfile, String url) { - if (!pngfile.exists()) { - if (!fetchMap(pngfile, url)) { - return null; - } - } - return loadMap(pngfile, url); - } - - public static ImageIcon loadMap(File pngfile, String url) { - if (!pngfile.exists()) { - return null; - } - - try { - BufferedImage img; - - img = ImageIO.read(pngfile); - if (img == null) { - System.out.printf("# Can't read pngfile %s\n", pngfile); - return null; - } - return new ImageIcon(img); - } catch (IOException e) { - System.out.printf("# IO error trying to load %s\n", pngfile); - return null; - } - } -} diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java deleted file mode 100644 index 8380b967..00000000 --- a/altosui/AltosSiteMapPreload.java +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import java.io.*; -import java.util.*; -import java.text.*; -import java.lang.Math; -import java.net.URL; -import java.net.URLConnection; -import org.altusmetrum.altosuilib_1.*; - -class AltosMapPos extends Box { - AltosUI owner; - JLabel label; - JComboBox hemi; - JTextField deg; - JLabel deg_label; - JTextField min; - JLabel min_label; - - public void set_value(double new_value) { - double d, m; - int h; - - h = 0; - if (new_value < 0) { - h = 1; - new_value = -new_value; - } - d = Math.floor(new_value); - deg.setText(String.format("%3.0f", d)); - m = (new_value - d) * 60.0; - min.setText(String.format("%7.4f", m)); - hemi.setSelectedIndex(h); - } - - public double get_value() throws NumberFormatException { - int h = hemi.getSelectedIndex(); - String d_t = deg.getText(); - String m_t = min.getText(); - double d, m, v; - try { - d = Double.parseDouble(d_t); - } catch (NumberFormatException ne) { - JOptionPane.showMessageDialog(owner, - String.format("Invalid degrees \"%s\"", - d_t), - "Invalid number", - JOptionPane.ERROR_MESSAGE); - throw ne; - } - try { - if (m_t.equals("")) - m = 0; - else - m = Double.parseDouble(m_t); - } catch (NumberFormatException ne) { - JOptionPane.showMessageDialog(owner, - String.format("Invalid minutes \"%s\"", - m_t), - "Invalid number", - JOptionPane.ERROR_MESSAGE); - throw ne; - } - v = d + m/60.0; - if (h == 1) - v = -v; - return v; - } - - public AltosMapPos(AltosUI in_owner, - String label_value, - String[] hemi_names, - double default_value) { - super(BoxLayout.X_AXIS); - owner = in_owner; - label = new JLabel(label_value); - hemi = new JComboBox(hemi_names); - hemi.setEditable(false); - deg = new JTextField(5); - deg.setMinimumSize(deg.getPreferredSize()); - deg.setHorizontalAlignment(JTextField.RIGHT); - deg_label = new JLabel("°"); - min = new JTextField(9); - min.setMinimumSize(min.getPreferredSize()); - min_label = new JLabel("'"); - set_value(default_value); - add(label); - add(Box.createRigidArea(new Dimension(5, 0))); - add(hemi); - add(Box.createRigidArea(new Dimension(5, 0))); - add(deg); - add(Box.createRigidArea(new Dimension(5, 0))); - add(deg_label); - add(Box.createRigidArea(new Dimension(5, 0))); - add(min); - add(Box.createRigidArea(new Dimension(5, 0))); - add(min_label); - } -} - -class AltosSite { - String name; - double latitude; - double longitude; - - public String toString() { - return name; - } - - public AltosSite(String in_name, double in_latitude, double in_longitude) { - name = in_name; - latitude = in_latitude; - longitude = in_longitude; - } - - public AltosSite(String line) throws ParseException { - String[] elements = line.split(":"); - - if (elements.length < 3) - throw new ParseException(String.format("Invalid site line %s", line), 0); - - name = elements[0]; - - try { - latitude = Double.parseDouble(elements[1]); - longitude = Double.parseDouble(elements[2]); - } catch (NumberFormatException ne) { - throw new ParseException(String.format("Invalid site line %s", line), 0); - } - } -} - -class AltosSites extends Thread { - AltosSiteMapPreload preload; - URL url; - LinkedList sites; - - void notify_complete() { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - preload.set_sites(); - } - }); - } - - void add(AltosSite site) { - sites.add(site); - } - - void add(String line) { - try { - add(new AltosSite(line)); - } catch (ParseException pe) { - } - } - - public void run() { - try { - URLConnection uc = url.openConnection(); - //int length = uc.getContentLength(); - - InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), Altos.unicode_set); - BufferedReader in = new BufferedReader(in_stream); - - for (;;) { - String line = in.readLine(); - if (line == null) - break; - add(line); - } - } catch (IOException e) { - } finally { - notify_complete(); - } - } - - public AltosSites(AltosSiteMapPreload in_preload) { - sites = new LinkedList(); - preload = in_preload; - try { - url = new URL(Altos.launch_sites_url); - } catch (java.net.MalformedURLException e) { - notify_complete(); - } - start(); - } -} - -public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener, ItemListener { - AltosUI owner; - AltosSiteMap map; - - AltosMapPos lat; - AltosMapPos lon; - - final static int radius = 5; - final static int width = (radius * 2 + 1); - final static int height = (radius * 2 + 1); - - JProgressBar pbar; - - AltosSites sites; - JLabel site_list_label; - JComboBox site_list; - - JToggleButton load_button; - boolean loading; - JButton close_button; - - static final String[] lat_hemi_names = { "N", "S" }; - static final String[] lon_hemi_names = { "E", "W" }; - - class updatePbar implements Runnable { - int n; - String s; - - public updatePbar(int x, int y, String in_s) { - n = (x + radius) + (y + radius) * width + 1; - s = in_s; - } - - public void run() { - pbar.setValue(n); - pbar.setString(s); - if (n < width * height) { - pbar.setValue(n); - pbar.setString(s); - } else { - pbar.setValue(0); - pbar.setString(""); - load_button.setSelected(false); - loading = false; - } - } - } - - class bgLoad extends Thread { - - AltosSiteMap map; - - public bgLoad(AltosSiteMap in_map) { - map = in_map; - } - - public void run() { - for (int y = -map.radius; y <= map.radius; y++) { - for (int x = -map.radius; x <= map.radius; x++) { - String pngfile; - pngfile = map.initMap(new Point(x,y)); - SwingUtilities.invokeLater(new updatePbar(x, y, pngfile)); - } - } - } - } - - public void set_sites() { - int i = 1; - for (AltosSite site : sites.sites) { - site_list.insertItemAt(site, i); - i++; - } - } - - public void itemStateChanged(ItemEvent e) { - int state = e.getStateChange(); - - if (state == ItemEvent.SELECTED) { - Object o = e.getItem(); - if (o instanceof AltosSite) { - AltosSite site = (AltosSite) o; - lat.set_value(site.latitude); - lon.set_value(site.longitude); - } - } - } - - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - - if (cmd.equals("close")) - setVisible(false); - - if (cmd.equals("load")) { - if (!loading) { - try { - final double latitude = lat.get_value(); - final double longitude = lon.get_value(); - map.setBaseLocation(latitude,longitude); - map.draw_circle(latitude,longitude); - loading = true; - bgLoad thread = new bgLoad(map); - thread.start(); - } catch (NumberFormatException ne) { - load_button.setSelected(false); - } - } - } - } - - public AltosSiteMapPreload(AltosUI in_owner) { - owner = in_owner; - - Container pane = getContentPane(); - GridBagConstraints c = new GridBagConstraints(); - Insets i = new Insets(4,4,4,4); - - pane.setLayout(new GridBagLayout()); - - map = new AltosSiteMap(radius); - - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 2; - c.anchor = GridBagConstraints.CENTER; - - pane.add(map, c); - - pbar = new JProgressBar(); - pbar.setMinimum(0); - pbar.setMaximum(width * height); - pbar.setValue(0); - pbar.setString(""); - pbar.setStringPainted(true); - - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 2; - - pane.add(pbar, c); - - site_list_label = new JLabel ("Known Launch Sites:"); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 0; - c.gridy = 2; - c.gridwidth = 1; - - pane.add(site_list_label, c); - - site_list = new JComboBox(new String[] { "Site List" }); - site_list.addItemListener(this); - - sites = new AltosSites(this); - - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 1; - c.gridy = 2; - c.gridwidth = 1; - - pane.add(site_list, c); - - lat = new AltosMapPos(owner, - "Latitude:", - lat_hemi_names, - 37.167833333); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 0; - c.weighty = 0; - - c.gridx = 0; - c.gridy = 3; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(lat, c); - - lon = new AltosMapPos(owner, - "Longitude:", - lon_hemi_names, - -97.73975); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 0; - c.weighty = 0; - - c.gridx = 1; - c.gridy = 3; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(lon, c); - - load_button = new JToggleButton("Load Map"); - load_button.addActionListener(this); - load_button.setActionCommand("load"); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 0; - c.gridy = 4; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(load_button, c); - - close_button = new JButton("Close"); - close_button.addActionListener(this); - close_button.setActionCommand("close"); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 1; - c.gridy = 4; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(close_button, c); - - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } -} diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java deleted file mode 100644 index 7d5b65e1..00000000 --- a/altosui/AltosSiteMapTile.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.image.*; -import javax.swing.*; -import java.awt.geom.Point2D; -import java.awt.geom.Line2D; -import org.altusmetrum.altoslib_3.*; - -public class AltosSiteMapTile extends JLayeredPane { - JLabel mapLabel; - JLabel draw; - Graphics2D g2d; - int px_size; - - public void loadMap(ImageIcon icn) { - mapLabel.setIcon(icn); - } - - public void clearMap() { - fillLabel(mapLabel, Color.GRAY, px_size); - g2d = fillLabel(draw, new Color(127,127,127,0), px_size); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - } - - static Color stateColors[] = { - Color.WHITE, // startup - Color.WHITE, // idle - Color.WHITE, // pad - Color.RED, // boost - Color.PINK, // fast - Color.YELLOW, // coast - Color.CYAN, // drogue - Color.BLUE, // main - Color.BLACK // landed - }; - - private boolean drawn_landed_circle = false; - private boolean drawn_boost_circle = false; - public synchronized void show(AltosState state, AltosListenerState listener_state, - Point2D.Double last_pt, Point2D.Double pt) - { - if (0 <= state.state && state.state < stateColors.length) { - g2d.setColor(stateColors[state.state]); - } - g2d.draw(new Line2D.Double(last_pt, pt)); - - if (state.state == 3 && !drawn_boost_circle) { - drawn_boost_circle = true; - g2d.setColor(Color.RED); - g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10); - g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40); - g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70); - } - if (state.state == 8 && !drawn_landed_circle) { - drawn_landed_circle = true; - g2d.setColor(Color.BLACK); - g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); - g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); - g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); - } - - repaint(); - } - - public void draw_circle(Point2D.Double pt) { - g2d.setColor(Color.RED); - g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); - g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); - g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); - } - - public static Graphics2D fillLabel(JLabel l, Color c, int px_size) { - BufferedImage img = new BufferedImage(px_size, px_size, - BufferedImage.TYPE_INT_ARGB); - Graphics2D g = img.createGraphics(); - g.setColor(c); - g.fillRect(0, 0, px_size, px_size); - l.setIcon(new ImageIcon(img)); - return g; - } - - public AltosSiteMapTile(int in_px_size) { - px_size = in_px_size; - setPreferredSize(new Dimension(px_size, px_size)); - - mapLabel = new JLabel(); - fillLabel(mapLabel, Color.GRAY, px_size); - mapLabel.setOpaque(true); - mapLabel.setBounds(0, 0, px_size, px_size); - add(mapLabel, new Integer(0)); - - draw = new JLabel(); - g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - draw.setBounds(0, 0, px_size, px_size); - draw.setOpaque(false); - - add(draw, new Integer(1)); - } -} diff --git a/altosui/AltosVoice.java b/altosui/AltosVoice.java deleted file mode 100644 index 2ed6a8c2..00000000 --- a/altosui/AltosVoice.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 com.sun.speech.freetts.Voice; -import com.sun.speech.freetts.VoiceManager; -import java.util.concurrent.LinkedBlockingQueue; -import org.altusmetrum.altosuilib_1.*; - -public class AltosVoice implements Runnable { - VoiceManager voice_manager; - Voice voice; - LinkedBlockingQueue phrases; - Thread thread; - boolean busy; - - final static String voice_name = "kevin16"; - - public void run() { - try { - for (;;) { - String s = phrases.take(); - voice.speak(s); - synchronized(this) { - if (phrases.isEmpty()) { - busy = false; - notifyAll(); - } - } - } - } catch (InterruptedException e) { - } - } - - public synchronized void drain() throws InterruptedException { - while (busy) - wait(); - } - - public void speak_always(String s) { - try { - if (voice != null) { - synchronized(this) { - busy = true; - phrases.put(s); - } - } - } catch (InterruptedException e) { - } - } - - public void speak(String s) { - if (AltosUIPreferences.voice()) - speak_always(s); - } - - public void speak(String format, Object... parameters) { - speak(String.format(format, parameters)); - } - - public AltosVoice () { - busy = false; - voice_manager = VoiceManager.getInstance(); - voice = voice_manager.getVoice(voice_name); - if (voice != null) { - voice.allocate(); - phrases = new LinkedBlockingQueue (); - thread = new Thread(this); - thread.start(); - } else { - System.out.printf("Voice manager failed to open %s\n", voice_name); - Voice[] voices = voice_manager.getVoices(); - System.out.printf("Available voices:\n"); - for (int i = 0; i < voices.length; i++) { - System.out.println(" " + voices[i].getName() - + " (" + voices[i].getDomain() + " domain)"); - } - } - } -} diff --git a/altosui/GrabNDrag.java b/altosui/GrabNDrag.java deleted file mode 100644 index 2fd6c4da..00000000 --- a/altosui/GrabNDrag.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.event.MouseInputAdapter; - -class GrabNDrag extends MouseInputAdapter { - private JComponent scroll; - private Point startPt = new Point(); - - public GrabNDrag(JComponent scroll) { - this.scroll = scroll; - scroll.addMouseMotionListener(this); - scroll.addMouseListener(this); - scroll.setAutoscrolls(true); - } - - public void mousePressed(MouseEvent e) { - startPt.setLocation(e.getPoint()); - } - public void mouseDragged(MouseEvent e) { - int xd = e.getX() - startPt.x; - int yd = e.getY() - startPt.y; - - Rectangle r = scroll.getVisibleRect(); - r.x -= xd; - r.y -= yd; - scroll.scrollRectToVisible(r); - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 76fe9961..0440b4af 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -1,6 +1,6 @@ JAVAROOT=classes -AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6 +AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6 man_MANS=altosui.1 @@ -17,7 +17,6 @@ altosui_BT = \ AltosBTKnown.java altosui_JAVA = \ - GrabNDrag.java \ AltosAscent.java \ AltosChannelMenu.java \ AltosCompanionInfo.java \ @@ -31,20 +30,16 @@ altosui_JAVA = \ AltosCSVUI.java \ AltosDescent.java \ AltosDeviceUIDialog.java \ - AltosDisplayThread.java \ AltosEepromDelete.java \ AltosEepromManage.java \ AltosEepromMonitorUI.java \ AltosEepromSelect.java \ AltosFlashUI.java \ - AltosFlightDisplay.java \ AltosFlightInfoTableModel.java \ - AltosFlightStats.java \ AltosFlightStatsTable.java \ AltosFlightStatus.java \ AltosFlightStatusUpdate.java \ AltosFlightUI.java \ - AltosFreqList.java \ Altos.java \ AltosIdleMonitorUI.java \ AltosIgniteUI.java \ @@ -61,17 +56,12 @@ altosui_JAVA = \ AltosScanUI.java \ AltosSerial.java \ AltosSerialInUseException.java \ - AltosSiteMap.java \ - AltosSiteMapPreload.java \ - AltosSiteMapCache.java \ - AltosSiteMapTile.java \ AltosUI.java \ AltosGraph.java \ AltosGraphDataPoint.java \ AltosGraphDataSet.java \ AltosGraphUI.java \ AltosDataChooser.java \ - AltosVoice.java \ $(altosui_BT) JFREECHART_CLASS= \ diff --git a/altosuilib/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java new file mode 100644 index 00000000..e88a891e --- /dev/null +++ b/altosuilib/AltosDisplayThread.java @@ -0,0 +1,259 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import javax.swing.*; +import java.io.*; +import java.text.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosDisplayThread extends Thread { + + Frame parent; + IdleThread idle_thread; + AltosVoice voice; + AltosFlightReader reader; + AltosState old_state, state; + AltosListenerState listener_state; + AltosFlightDisplay display; + + synchronized void show_safely() { + final AltosState my_state = state; + final AltosListenerState my_listener_state = listener_state; + Runnable r = new Runnable() { + public void run() { + try { + display.show(my_state, my_listener_state); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + void reading_error_internal() { + JOptionPane.showMessageDialog(parent, + String.format("Error reading from \"%s\"", reader.name), + "Telemetry Read Error", + JOptionPane.ERROR_MESSAGE); + } + + void reading_error_safely() { + Runnable r = new Runnable() { + public void run() { + try { + reading_error_internal(); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + class IdleThread extends Thread { + + boolean started; + int reported_landing; + int report_interval; + long report_time; + + public synchronized void report(boolean last) { + if (state == null) + return; + + /* reset the landing count once we hear about a new flight */ + if (state.state < AltosLib.ao_flight_drogue) + reported_landing = 0; + + /* Shut up once the rocket is on the ground */ + if (reported_landing > 2) { + return; + } + + /* If the rocket isn't on the pad, then report height */ + if (AltosLib.ao_flight_drogue <= state.state && + state.state < AltosLib.ao_flight_landed && + state.from_pad != null && + state.range >= 0) + { + voice.speak("Height %s, bearing %s %d, elevation %d, range %s.\n", + AltosConvert.height.say(state.height()), + state.from_pad.bearing_words( + AltosGreatCircle.BEARING_VOICE), + (int) (state.from_pad.bearing + 0.5), + (int) (state.elevation + 0.5), + AltosConvert.distance.say(state.range)); + } else if (state.state > AltosLib.ao_flight_pad) { + voice.speak(AltosConvert.height.say_units(state.height())); + } else { + reported_landing = 0; + } + + /* If the rocket is coming down, check to see if it has landed; + * either we've got a landed report or we haven't heard from it in + * a long time + */ + if (state.state >= AltosLib.ao_flight_drogue && + (last || + System.currentTimeMillis() - state.received_time >= 15000 || + state.state == AltosLib.ao_flight_landed)) + { + if (Math.abs(state.speed()) < 20 && state.height() < 100) + voice.speak("rocket landed safely"); + else + voice.speak("rocket may have crashed"); + if (state.from_pad != null) + voice.speak("Bearing %d degrees, range %s.", + (int) (state.from_pad.bearing + 0.5), + AltosConvert.distance.say_units(state.from_pad.distance)); + ++reported_landing; + if (state.state != AltosLib.ao_flight_landed) { + state.state = AltosLib.ao_flight_landed; + show_safely(); + } + } + } + + long now () { + return System.currentTimeMillis(); + } + + void set_report_time() { + report_time = now() + report_interval; + } + + public void run () { + try { + for (;;) { + if (reader.has_monitor_battery()) { + listener_state.battery = reader.monitor_battery(); + show_safely(); + } + set_report_time(); + for (;;) { + voice.drain(); + synchronized (this) { + long sleep_time = report_time - now(); + if (sleep_time <= 0) + break; + wait(sleep_time); + } + } + + report(false); + } + } catch (InterruptedException ie) { + try { + voice.drain(); + } catch (InterruptedException iie) { } + } + } + + public synchronized void notice(boolean spoken) { + if (old_state != null && old_state.state != state.state) { + report_time = now(); + this.notify(); + } else if (spoken) + set_report_time(); + } + + public IdleThread() { + reported_landing = 0; + report_interval = 10000; + } + } + + synchronized boolean tell() { + boolean ret = false; + if (old_state == null || old_state.state != state.state) { + voice.speak(state.state_name()); + if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) && + state.state > AltosLib.ao_flight_boost) { + voice.speak("max speed: %s.", + AltosConvert.speed.say_units(state.max_speed() + 0.5)); + ret = true; + } else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) && + state.state >= AltosLib.ao_flight_drogue) { + voice.speak("max height: %s.", + AltosConvert.height.say_units(state.max_height() + 0.5)); + ret = true; + } + } + if (old_state == null || old_state.gps_ready != state.gps_ready) { + if (state.gps_ready) { + voice.speak("GPS ready"); + ret = true; + } + else if (old_state != null) { + voice.speak("GPS lost"); + ret = true; + } + } + old_state = state; + return ret; + } + + public void run() { + boolean interrupted = false; + boolean told; + + idle_thread = new IdleThread(); + idle_thread.start(); + + try { + for (;;) { + try { + state = reader.read(); + if (state == null) + break; + reader.update(state); + show_safely(); + told = tell(); + idle_thread.notice(told); + } catch (ParseException pp) { + System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); + } catch (AltosCRCException ce) { + ++listener_state.crc_errors; + show_safely(); + } + } + } catch (InterruptedException ee) { + interrupted = true; + } catch (IOException ie) { + reading_error_safely(); + } finally { + if (!interrupted) + idle_thread.report(true); + reader.close(interrupted); + idle_thread.interrupt(); + try { + idle_thread.join(); + } catch (InterruptedException ie) {} + } + } + + public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) { + listener_state = new AltosListenerState(); + parent = in_parent; + voice = in_voice; + display = in_display; + reader = in_reader; + display.reset(); + } +} diff --git a/altosuilib/AltosFlightDisplay.java b/altosuilib/AltosFlightDisplay.java new file mode 100644 index 00000000..5695a015 --- /dev/null +++ b/altosuilib/AltosFlightDisplay.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import org.altusmetrum.altoslib_4.*; + +public interface AltosFlightDisplay { + void reset(); + + void show(AltosState state, AltosListenerState listener_state); + + void set_font(); +} diff --git a/altosuilib/AltosFreqList.java b/altosuilib/AltosFreqList.java new file mode 100644 index 00000000..e1299aae --- /dev/null +++ b/altosuilib/AltosFreqList.java @@ -0,0 +1,85 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosFreqList extends JComboBox { + + String product; + int serial; + int calibrate; + + public void set_frequency(double new_frequency) { + int i; + + if (new_frequency < 0) { + setVisible(false); + return; + } + + for (i = 0; i < getItemCount(); i++) { + AltosFrequency f = (AltosFrequency) getItemAt(i); + + if (f.close(new_frequency)) { + setSelectedIndex(i); + return; + } + } + for (i = 0; i < getItemCount(); i++) { + AltosFrequency f = (AltosFrequency) getItemAt(i); + + if (new_frequency < f.frequency) + break; + } + String description = String.format("%s serial %d", product, serial); + AltosFrequency frequency = new AltosFrequency(new_frequency, description); + AltosUIPreferences.add_common_frequency(frequency); + insertItemAt(frequency, i); + setMaximumRowCount(getItemCount()); + } + + public void set_product(String new_product) { + product = new_product; + } + + public void set_serial(int new_serial) { + serial = new_serial; + } + + public double frequency() { + AltosFrequency f = (AltosFrequency) getSelectedItem(); + if (f != null) + return f.frequency; + return 434.550; + } + + public AltosFreqList () { + super(AltosUIPreferences.common_frequencies()); + setMaximumRowCount(getItemCount()); + setEditable(false); + product = "Unknown"; + serial = 0; + } + + public AltosFreqList(double in_frequency) { + this(); + set_frequency(in_frequency); + } +} diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java new file mode 100644 index 00000000..1cfbc8b5 --- /dev/null +++ b/altosuilib/AltosSiteMap.java @@ -0,0 +1,484 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import javax.swing.*; +import java.io.*; +import java.lang.Math; +import java.awt.geom.Point2D; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { + // preferred vertical step in a tile in naut. miles + // will actually choose a step size between x and 2x, where this + // is 1.5x + static final double tile_size_nmi = 0.75; + + static final int px_size = 512; + + static final int MAX_TILE_DELTA = 100; + + private static Point2D.Double translatePoint(Point2D.Double p, + Point2D.Double d) + { + return new Point2D.Double(p.x + d.x, p.y + d.y); + } + + static class LatLng { + public double lat, lng; + public LatLng(double lat, double lng) { + this.lat = lat; + this.lng = lng; + } + } + + // based on google js + // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js + // search for fromLatLngToPoint and fromPointToLatLng + /* + private static Point2D.Double pt(LatLng latlng, int zoom) { + double scale_x = 256/360.0 * Math.pow(2, zoom); + double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + return pt(latlng, scale_x, scale_y); + } + */ + + private static Point2D.Double pt(LatLng latlng, + double scale_x, double scale_y) + { + Point2D.Double res = new Point2D.Double(); + double e; + + res.x = latlng.lng * scale_x; + + e = Math.sin(Math.toRadians(latlng.lat)); + e = Math.max(e,-(1-1.0E-15)); + e = Math.min(e, 1-1.0E-15 ); + + res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y; + return res; + } + + static private LatLng latlng(Point2D.Double pt, + double scale_x, double scale_y) + { + double lat, lng; + double rads; + + lng = pt.x/scale_x; + rads = 2 * Math.atan(Math.exp(-pt.y/scale_y)); + lat = Math.toDegrees(rads - Math.PI/2); + + return new LatLng(lat,lng); + } + + int zoom; + double scale_x, scale_y; + + int radius; /* half width/height of tiles to load */ + + private Point2D.Double pt(double lat, double lng) { + return pt(new LatLng(lat, lng), scale_x, scale_y); + } + + private LatLng latlng(double x, double y) { + return latlng(new Point2D.Double(x,y), scale_x, scale_y); + } + /* + private LatLng latlng(Point2D.Double pt) { + return latlng(pt, scale_x, scale_y); + } + */ + + ConcurrentHashMap mapTiles = new ConcurrentHashMap(); + Point2D.Double centre; + + private Point2D.Double tileCoordOffset(Point p) { + return new Point2D.Double(centre.x - p.x*px_size, + centre.y - p.y * px_size); + } + + private Point tileOffset(Point2D.Double p) { + return new Point((int)Math.floor((centre.x+p.x)/px_size), + (int)Math.floor((centre.y+p.y)/px_size)); + } + + private Point2D.Double getBaseLocation(double lat, double lng) { + Point2D.Double locn, north_step; + + zoom = 2; + // stupid loop structure to please Java's control flow analysis + do { + zoom++; + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + locn = pt(lat, lng); + north_step = pt(lat+tile_size_nmi*4/3/60.0, lng); + if (locn.y - north_step.y > px_size) + break; + } while (zoom < 22); + locn.x = -px_size * Math.floor(locn.x/px_size); + locn.y = -px_size * Math.floor(locn.y/px_size); + return locn; + } + + public void reset() { + // nothing + } + + public void set_font() { + // nothing + } + + private void loadMap(final AltosSiteMapTile tile, + final File pngfile, String pngurl) + { + boolean loaded = AltosSiteMapCache.fetchMap(pngfile, pngurl); + if (loaded) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + tile.loadMap(pngfile); + } + }); + } else { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' '%s'\n", pngfile, pngurl); + } + } + + + class AltosSiteMapPrefetch { + int x; + int y; + int result; + File pngfile; + String pngurl; + } + + public AltosSiteMapPrefetch prefetchMap(int x, int y) { + AltosSiteMapPrefetch prefetch = new AltosSiteMapPrefetch(); + LatLng map_latlng = latlng( + -centre.x + x*px_size + px_size/2, + -centre.y + y*px_size + px_size/2); + prefetch.pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); + prefetch.pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); + if (prefetch.pngfile.exists()) { + prefetch.result = 1; + } else if (AltosSiteMapCache.fetchMap(prefetch.pngfile, prefetch.pngurl)) { + prefetch.result = 0; + } else { + prefetch.result = -1; + } + return prefetch; + } + + public static void prefetchMaps(double lat, double lng) { + int w = AltosSiteMapPreload.width; + int h = AltosSiteMapPreload.height; + AltosSiteMap asm = new AltosSiteMap(true); + asm.centre = asm.getBaseLocation(lat, lng); + + //Point2D.Double p = new Point2D.Double(); + //Point2D.Double p2; + int dx = -w/2, dy = -h/2; + for (int y = dy; y < h+dy; y++) { + for (int x = dx; x < w+dx; x++) { + AltosSiteMapPrefetch prefetch = asm.prefetchMap(x, y); + switch (prefetch.result) { + case 1: + System.out.printf("Already have %s\n", prefetch.pngfile); + break; + case 0: + System.out.printf("Fetched map %s\n", prefetch.pngfile); + break; + case -1: + System.out.printf("# Failed to fetch file %s\n", prefetch.pngfile); + System.out.printf(" wget -O '%s' ''\n", + prefetch.pngfile, prefetch.pngurl); + break; + } + } + } + } + + public String initMap(Point offset) { + AltosSiteMapTile tile = mapTiles.get(offset); + Point2D.Double coord = tileCoordOffset(offset); + + LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y); + + File pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); + String pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); + loadMap(tile, pngfile, pngurl); + return pngfile.toString(); + } + + public void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) { + Thread thread = new Thread() { + public void run() { + initMap(offset); + finishTileLater(tile, offset); + } + }; + thread.start(); + } + + public void setBaseLocation(double lat, double lng) { + for (Point k : mapTiles.keySet()) { + AltosSiteMapTile tile = mapTiles.get(k); + tile.clearMap(); + } + + centre = getBaseLocation(lat, lng); + scrollRocketToVisible(pt(lat,lng)); + } + + private void initMaps(double lat, double lng) { + setBaseLocation(lat, lng); + + Thread thread = new Thread() { + public void run() { + for (Point k : mapTiles.keySet()) + initMap(k); + } + }; + thread.start(); + } + + private static File MapFile(double lat, double lng, int zoom) { + char chlat = lat < 0 ? 'S' : 'N'; + char chlng = lng < 0 ? 'W' : 'E'; + if (lat < 0) lat = -lat; + if (lng < 0) lng = -lng; + return new File(AltosUIPreferences.mapdir(), + String.format("map-%c%.6f,%c%.6f-%d.png", + chlat, lat, chlng, lng, zoom)); + } + + private static String MapURL(double lat, double lng, int zoom) { + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); + } + + boolean initialised = false; + Point2D.Double last_pt = null; + int last_state = -1; + + public void show(double lat, double lon) { + System.out.printf ("show %g %g\n", lat, lon); + return; +// initMaps(lat, lon); +// scrollRocketToVisible(pt(lat, lon)); + } + public void show(final AltosState state, final AltosListenerState listener_state) { + // if insufficient gps data, nothing to update + AltosGPS gps = state.gps; + + if (gps == null) + return; + + if (!gps.locked && gps.nsat < 4) + return; + + if (!initialised) { + if (state.pad_lat != AltosLib.MISSING && state.pad_lon != AltosLib.MISSING) { + initMaps(state.pad_lat, state.pad_lon); + initialised = true; + } else if (gps.lat != AltosLib.MISSING && gps.lon != AltosLib.MISSING) { + initMaps(gps.lat, gps.lon); + initialised = true; + } else { + return; + } + } + + final Point2D.Double pt = pt(gps.lat, gps.lon); + if (last_pt == pt && last_state == state.state) + return; + + if (last_pt == null) { + last_pt = pt; + } + boolean in_any = false; + for (Point offset : mapTiles.keySet()) { + AltosSiteMapTile tile = mapTiles.get(offset); + Point2D.Double ref, lref; + ref = translatePoint(pt, tileCoordOffset(offset)); + lref = translatePoint(last_pt, tileCoordOffset(offset)); + tile.show(state, listener_state, lref, ref); + if (0 <= ref.x && ref.x < px_size) + if (0 <= ref.y && ref.y < px_size) + in_any = true; + } + + Point offset = tileOffset(pt); + if (!in_any) { + Point2D.Double ref, lref; + ref = translatePoint(pt, tileCoordOffset(offset)); + lref = translatePoint(last_pt, tileCoordOffset(offset)); + + AltosSiteMapTile tile = createTile(offset); + tile.show(state, listener_state, lref, ref); + initAndFinishMapAsync(tile, offset); + } + + scrollRocketToVisible(pt); + + if (offset != tileOffset(last_pt)) { + ensureTilesAround(offset); + } + + last_pt = pt; + last_state = state.state; + } + + public void centre(Point2D.Double pt) { + Rectangle r = comp.getVisibleRect(); + Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); + int dx = (int)copt.x - r.width/2 - r.x; + int dy = (int)copt.y - r.height/2 - r.y; + r.x += dx; + r.y += dy; + comp.scrollRectToVisible(r); + } + + public void centre(AltosState state) { + if (!state.gps.locked && state.gps.nsat < 4) + return; + centre(pt(state.gps.lat, state.gps.lon)); + } + + public void draw_circle(double lat, double lon) { + final Point2D.Double pt = pt(lat, lon); + + for (Point offset : mapTiles.keySet()) { + AltosSiteMapTile tile = mapTiles.get(offset); + Point2D.Double ref = translatePoint(pt, tileCoordOffset(offset)); + tile.set_boost(ref); + } + } + + private AltosSiteMapTile createTile(Point offset) { + AltosSiteMapTile tile = new AltosSiteMapTile(px_size); + mapTiles.put(offset, tile); + return tile; + } + private void finishTileLater(final AltosSiteMapTile tile, + final Point offset) + { + SwingUtilities.invokeLater( new Runnable() { + public void run() { + addTileAt(tile, offset); + } + } ); + } + + private void ensureTilesAround(Point base_offset) { + for (int x = -radius; x <= radius; x++) { + for (int y = -radius; y <= radius; y++) { + Point offset = new Point(base_offset.x + x, base_offset.y + y); + if (mapTiles.containsKey(offset)) + continue; + AltosSiteMapTile tile = createTile(offset); + initAndFinishMapAsync(tile, offset); + } + } + } + + private Point topleft = new Point(0,0); + private void scrollRocketToVisible(Point2D.Double pt) { + Rectangle r = comp.getVisibleRect(); + Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); + int dx = (int)copt.x - r.width/2 - r.x; + int dy = (int)copt.y - r.height/2 - r.y; + if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) { + r.x += dx; + r.y += dy; + comp.scrollRectToVisible(r); + } + } + + private void addTileAt(AltosSiteMapTile tile, Point offset) { + if (Math.abs(offset.x) >= MAX_TILE_DELTA || + Math.abs(offset.y) >= MAX_TILE_DELTA) + { + System.out.printf("Rocket too far away from pad (tile %d,%d)\n", + offset.x, offset.y); + return; + } + + boolean review = false; + Rectangle r = comp.getVisibleRect(); + if (offset.x < topleft.x) { + r.x += (topleft.x - offset.x) * px_size; + topleft.x = offset.x; + review = true; + } + if (offset.y < topleft.y) { + r.y += (topleft.y - offset.y) * px_size; + topleft.y = offset.y; + review = true; + } + GridBagConstraints c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + // put some space between the map tiles, debugging only + // c.insets = new Insets(5, 5, 5, 5); + + c.gridx = offset.x + MAX_TILE_DELTA; + c.gridy = offset.y + MAX_TILE_DELTA; + layout.setConstraints(tile, c); + + comp.add(tile); + if (review) { + comp.scrollRectToVisible(r); + } + } + + private AltosSiteMap(boolean knowWhatYouAreDoing) { + if (!knowWhatYouAreDoing) { + throw new RuntimeException("Arggh."); + } + } + + JComponent comp = new JComponent() { }; + private GridBagLayout layout = new GridBagLayout(); + + public AltosSiteMap(int in_radius) { + radius = in_radius; + + GrabNDrag scroller = new GrabNDrag(comp); + + comp.setLayout(layout); + + for (int x = -radius; x <= radius; x++) { + for (int y = -radius; y <= radius; y++) { + Point offset = new Point(x, y); + AltosSiteMapTile t = createTile(offset); + addTileAt(t, offset); + } + } + setViewportView(comp); + setPreferredSize(new Dimension(500,500)); + } + + public AltosSiteMap() { + this(1); + } +} diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java new file mode 100644 index 00000000..cf93016a --- /dev/null +++ b/altosuilib/AltosSiteMapCache.java @@ -0,0 +1,194 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.*; +import javax.imageio.ImageIO; +import java.awt.image.*; +import java.awt.*; +import java.io.*; +import java.net.URL; +import java.net.URLConnection; + + +class AltosCacheImage { + Component component; + File file; + VolatileImage image; + int width; + int height; + long used; + + public void load_image() throws IOException { + BufferedImage bimg = ImageIO.read(file); + Graphics2D g = image.createGraphics(); + g.drawImage(bimg, 0, 0, null); + bimg.flush(); + } + + public Image validate() { + int returnCode; + + if (image != null) + returnCode = image.validate(component.getGraphicsConfiguration()); + else + returnCode = VolatileImage.IMAGE_INCOMPATIBLE; + if (returnCode == VolatileImage.IMAGE_RESTORED) { + try { + load_image(); + } catch (IOException e) { + return null; + } + } else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) { + image = component.createVolatileImage(width, height); + try { + load_image(); + } catch (IOException e) { + return null; + } + } + return image; + } + + public void flush() { + image.flush(); + } + + public AltosCacheImage(Component component, File file, int w, int h) throws IOException { + this.component = component; + this.file = file; + width = w; + height = h; + image = component.createVolatileImage(w, h); + used = 0; + } +} + +public class AltosSiteMapCache extends JLabel { + static final long google_maps_ratelimit_ms = 1200; + // Google limits static map queries to 50 per minute per IP, so + // each query should take at least 1.2 seconds. + + public static boolean fetchMap(File file, String url) { + if (file.exists()) + return true; + + URL u; + long startTime = System.nanoTime(); + + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return false; + } + + byte[] data; + try { + URLConnection uc = u.openConnection(); + int contentLength = uc.getContentLength(); + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); + + if (offset != contentLength) { + return false; + } + } catch (IOException e) { + return false; + } + + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + if (file.exists()) { + file.delete(); + } + return false; + } + + long duration_ms = (System.nanoTime() - startTime) / 1000000; + if (duration_ms < google_maps_ratelimit_ms) { + try { + Thread.sleep(google_maps_ratelimit_ms - duration_ms); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + return true; + } + + static int cache_size = 9; + + static AltosCacheImage[] images; + + static long used; + + public static void set_cache_size(int cache_size) { + AltosSiteMapCache.cache_size = cache_size; + images = null; + } + + public static Image get_image(Component component, File file, int width, int height) { + int oldest = -1; + long age = used; + AltosCacheImage image; + if (images == null) + images = new AltosCacheImage[cache_size]; + for (int i = 0; i < cache_size; i++) { + image = images[i]; + + if (image == null) { + oldest = i; + break; + } + if (image.component == component && file.equals(image.file)) { + image.used = used++; + return image.validate(); + } + if (image.used < age) { + oldest = i; + age = image.used; + } + } + + try { + image = new AltosCacheImage(component, file, width, height); + image.used = used++; + if (images[oldest] != null) + images[oldest].flush(); + images[oldest] = image; + return image.validate(); + } catch (IOException e) { + return null; + } + } +} diff --git a/altosuilib/AltosSiteMapPreload.java b/altosuilib/AltosSiteMapPreload.java new file mode 100644 index 00000000..baa7fc37 --- /dev/null +++ b/altosuilib/AltosSiteMapPreload.java @@ -0,0 +1,467 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.lang.Math; +import java.net.URL; +import java.net.URLConnection; +import org.altusmetrum.altoslib_4.*; + +class AltosMapPos extends Box { + AltosUIFrame owner; + JLabel label; + JComboBox hemi; + JTextField deg; + JLabel deg_label; + JTextField min; + JLabel min_label; + + public void set_value(double new_value) { + double d, m; + int h; + + h = 0; + if (new_value < 0) { + h = 1; + new_value = -new_value; + } + d = Math.floor(new_value); + deg.setText(String.format("%3.0f", d)); + m = (new_value - d) * 60.0; + min.setText(String.format("%7.4f", m)); + hemi.setSelectedIndex(h); + } + + public double get_value() throws NumberFormatException { + int h = hemi.getSelectedIndex(); + String d_t = deg.getText(); + String m_t = min.getText(); + double d, m, v; + try { + d = Double.parseDouble(d_t); + } catch (NumberFormatException ne) { + JOptionPane.showMessageDialog(owner, + String.format("Invalid degrees \"%s\"", + d_t), + "Invalid number", + JOptionPane.ERROR_MESSAGE); + throw ne; + } + try { + if (m_t.equals("")) + m = 0; + else + m = Double.parseDouble(m_t); + } catch (NumberFormatException ne) { + JOptionPane.showMessageDialog(owner, + String.format("Invalid minutes \"%s\"", + m_t), + "Invalid number", + JOptionPane.ERROR_MESSAGE); + throw ne; + } + v = d + m/60.0; + if (h == 1) + v = -v; + return v; + } + + public AltosMapPos(AltosUIFrame in_owner, + String label_value, + String[] hemi_names, + double default_value) { + super(BoxLayout.X_AXIS); + owner = in_owner; + label = new JLabel(label_value); + hemi = new JComboBox(hemi_names); + hemi.setEditable(false); + deg = new JTextField(5); + deg.setMinimumSize(deg.getPreferredSize()); + deg.setHorizontalAlignment(JTextField.RIGHT); + deg_label = new JLabel("°"); + min = new JTextField(9); + min.setMinimumSize(min.getPreferredSize()); + min_label = new JLabel("'"); + set_value(default_value); + add(label); + add(Box.createRigidArea(new Dimension(5, 0))); + add(hemi); + add(Box.createRigidArea(new Dimension(5, 0))); + add(deg); + add(Box.createRigidArea(new Dimension(5, 0))); + add(deg_label); + add(Box.createRigidArea(new Dimension(5, 0))); + add(min); + add(Box.createRigidArea(new Dimension(5, 0))); + add(min_label); + } +} + +class AltosSite { + String name; + double latitude; + double longitude; + + public String toString() { + return name; + } + + public AltosSite(String in_name, double in_latitude, double in_longitude) { + name = in_name; + latitude = in_latitude; + longitude = in_longitude; + } + + public AltosSite(String line) throws ParseException { + String[] elements = line.split(":"); + + if (elements.length < 3) + throw new ParseException(String.format("Invalid site line %s", line), 0); + + name = elements[0]; + + try { + latitude = Double.parseDouble(elements[1]); + longitude = Double.parseDouble(elements[2]); + } catch (NumberFormatException ne) { + throw new ParseException(String.format("Invalid site line %s", line), 0); + } + } +} + +class AltosSites extends Thread { + AltosSiteMapPreload preload; + URL url; + LinkedList sites; + + void notify_complete() { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + preload.set_sites(); + } + }); + } + + void add(AltosSite site) { + sites.add(site); + } + + void add(String line) { + try { + add(new AltosSite(line)); + } catch (ParseException pe) { + } + } + + public void run() { + try { + URLConnection uc = url.openConnection(); + //int length = uc.getContentLength(); + + InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set); + BufferedReader in = new BufferedReader(in_stream); + + for (;;) { + String line = in.readLine(); + if (line == null) + break; + add(line); + } + } catch (IOException e) { + } finally { + notify_complete(); + } + } + + public AltosSites(AltosSiteMapPreload in_preload) { + sites = new LinkedList(); + preload = in_preload; + try { + url = new URL(AltosLib.launch_sites_url); + } catch (java.net.MalformedURLException e) { + notify_complete(); + } + start(); + } +} + +public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener, ItemListener { + AltosUIFrame owner; + AltosSiteMap map; + + AltosMapPos lat; + AltosMapPos lon; + + final static int radius = 5; + final static int width = (radius * 2 + 1); + final static int height = (radius * 2 + 1); + + JProgressBar pbar; + + AltosSites sites; + JLabel site_list_label; + JComboBox site_list; + + JToggleButton load_button; + boolean loading; + JButton close_button; + + static final String[] lat_hemi_names = { "N", "S" }; + static final String[] lon_hemi_names = { "E", "W" }; + + class updatePbar implements Runnable { + int n; + String s; + + public updatePbar(int x, int y, String in_s) { + n = (x + radius) + (y + radius) * width + 1; + s = in_s; + } + + public void run() { + pbar.setValue(n); + pbar.setString(s); + if (n < width * height) { + pbar.setValue(n); + pbar.setString(s); + } else { + pbar.setValue(0); + pbar.setString(""); + load_button.setSelected(false); + loading = false; + } + } + } + + class bgLoad extends Thread { + + AltosSiteMap map; + + public bgLoad(AltosSiteMap in_map) { + map = in_map; + } + + public void run() { + for (int y = -map.radius; y <= map.radius; y++) { + for (int x = -map.radius; x <= map.radius; x++) { + String pngfile; + pngfile = map.initMap(new Point(x,y)); + SwingUtilities.invokeLater(new updatePbar(x, y, pngfile)); + } + } + } + } + + public void set_sites() { + int i = 1; + for (AltosSite site : sites.sites) { + site_list.insertItemAt(site, i); + i++; + } + } + + public void itemStateChanged(ItemEvent e) { + int state = e.getStateChange(); + + if (state == ItemEvent.SELECTED) { + Object o = e.getItem(); + if (o instanceof AltosSite) { + AltosSite site = (AltosSite) o; + lat.set_value(site.latitude); + lon.set_value(site.longitude); + } + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("close")) + setVisible(false); + + if (cmd.equals("load")) { + if (!loading) { + try { + final double latitude = lat.get_value(); + final double longitude = lon.get_value(); + map.setBaseLocation(latitude,longitude); + map.draw_circle(latitude,longitude); + loading = true; + bgLoad thread = new bgLoad(map); + thread.start(); + } catch (NumberFormatException ne) { + load_button.setSelected(false); + } + } + } + } + + public AltosSiteMapPreload(AltosUIFrame in_owner) { + owner = in_owner; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + pane.setLayout(new GridBagLayout()); + + map = new AltosSiteMap(radius); + + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + + pane.add(map, c); + + pbar = new JProgressBar(); + pbar.setMinimum(0); + pbar.setMaximum(width * height); + pbar.setValue(0); + pbar.setString(""); + pbar.setStringPainted(true); + + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 2; + + pane.add(pbar, c); + + site_list_label = new JLabel ("Known Launch Sites:"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + + pane.add(site_list_label, c); + + site_list = new JComboBox(new AltosSite[] { new AltosSite("Site List", 0, 0) }); + site_list.addItemListener(this); + + sites = new AltosSites(this); + + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + + pane.add(site_list, c); + + lat = new AltosMapPos(owner, + "Latitude:", + lat_hemi_names, + 37.167833333); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 0; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(lat, c); + + lon = new AltosMapPos(owner, + "Longitude:", + lon_hemi_names, + -97.73975); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 0; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(lon, c); + + load_button = new JToggleButton("Load Map"); + load_button.addActionListener(this); + load_button.setActionCommand("load"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(load_button, c); + + close_button = new JButton("Close"); + close_button.addActionListener(this); + close_button.setActionCommand("close"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(close_button, c); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } +} diff --git a/altosuilib/AltosSiteMapTile.java b/altosuilib/AltosSiteMapTile.java new file mode 100644 index 00000000..1046d6bd --- /dev/null +++ b/altosuilib/AltosSiteMapTile.java @@ -0,0 +1,142 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.image.*; +import javax.swing.*; +import javax.imageio.*; +import java.awt.geom.Point2D; +import java.awt.geom.Line2D; +import java.io.*; +import java.util.*; +import org.altusmetrum.altoslib_4.*; + +class AltosPoint { + Point2D.Double pt; + int state; + + AltosPoint(Point2D.Double pt, int state) { + this.pt = pt; + this.state = state; + } +} + +public class AltosSiteMapTile extends JComponent { + int px_size; + File file; + + Point2D.Double boost; + Point2D.Double landed; + + LinkedList points; + + public void loadMap(File pngFile) { + file = pngFile; + repaint(); + } + + public void clearMap() { + boost = null; + landed = null; + points = null; + file = null; + } + + static Color stateColors[] = { + Color.WHITE, // startup + Color.WHITE, // idle + Color.WHITE, // pad + Color.RED, // boost + Color.PINK, // fast + Color.YELLOW, // coast + Color.CYAN, // drogue + Color.BLUE, // main + Color.BLACK // landed + }; + + private void draw_circle(Graphics g, Point2D.Double pt) { + g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); + g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); + g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); + } + + public void set_boost(Point2D.Double boost) { + this.boost = boost; + repaint(); + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + AltosPoint prev = null; + Image img = null; + + if (file != null) + img = AltosSiteMapCache.get_image(this, file, px_size, px_size); + + if (img != null) { + g2d.drawImage(img, 0, 0, null); + } else { + g2d.setColor(Color.GRAY); + g2d.fillRect(0, 0, getWidth(), getHeight()); + } + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + + if (points != null) { + for (AltosPoint point : points) { + if (prev != null) { + if (0 <= point.state && point.state < stateColors.length) + g2d.setColor(stateColors[point.state]); + g2d.draw(new Line2D.Double(prev.pt, point.pt)); + } + prev = point; + } + } + if (boost != null) { + g2d.setColor(Color.RED); + draw_circle(g2d, boost); + } + if (landed != null) { + g2d.setColor(Color.BLACK); + draw_circle(g2d, landed); + } + } + + public synchronized void show(AltosState state, AltosListenerState listener_state, + Point2D.Double last_pt, Point2D.Double pt) + { + if (points == null) + points = new LinkedList(); + + points.add(new AltosPoint(pt, state.state)); + + if (state.state == AltosLib.ao_flight_boost && boost == null) + boost = pt; + if (state.state == AltosLib.ao_flight_landed && landed == null) + landed = pt; + repaint(); + } + + public AltosSiteMapTile(int in_px_size) { + px_size = in_px_size; + setPreferredSize(new Dimension(px_size, px_size)); + } +} diff --git a/altosuilib/AltosVoice.java b/altosuilib/AltosVoice.java new file mode 100644 index 00000000..a3995f68 --- /dev/null +++ b/altosuilib/AltosVoice.java @@ -0,0 +1,94 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import com.sun.speech.freetts.Voice; +import com.sun.speech.freetts.VoiceManager; +import java.util.concurrent.LinkedBlockingQueue; + +public class AltosVoice implements Runnable { + VoiceManager voice_manager; + Voice voice; + LinkedBlockingQueue phrases; + Thread thread; + boolean busy; + + final static String voice_name = "kevin16"; + + public void run() { + try { + for (;;) { + String s = phrases.take(); + voice.speak(s); + synchronized(this) { + if (phrases.isEmpty()) { + busy = false; + notifyAll(); + } + } + } + } catch (InterruptedException e) { + } + } + + public synchronized void drain() throws InterruptedException { + while (busy) + wait(); + } + + public void speak_always(String s) { + try { + if (voice != null) { + synchronized(this) { + busy = true; + phrases.put(s); + } + } + } catch (InterruptedException e) { + } + } + + public void speak(String s) { + if (AltosUIPreferences.voice()) + speak_always(s); + } + + public void speak(String format, Object... parameters) { + speak(String.format(format, parameters)); + } + + public AltosVoice () { + busy = false; + voice_manager = VoiceManager.getInstance(); + voice = voice_manager.getVoice(voice_name); + if (voice != null) { + voice.allocate(); + phrases = new LinkedBlockingQueue (); + thread = new Thread(this); + thread.start(); + } else { + System.out.printf("Voice manager failed to open %s\n", voice_name); + Voice[] voices = voice_manager.getVoices(); + System.out.printf("Available voices:\n"); + for (int i = 0; i < voices.length; i++) { + System.out.println(" " + voices[i].getName() + + " (" + voices[i].getDomain() + " domain)"); + } + } + } +} diff --git a/altosuilib/GrabNDrag.java b/altosuilib/GrabNDrag.java new file mode 100644 index 00000000..5e5fdd52 --- /dev/null +++ b/altosuilib/GrabNDrag.java @@ -0,0 +1,48 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.MouseInputAdapter; + +class GrabNDrag extends MouseInputAdapter { + private JComponent scroll; + private Point startPt = new Point(); + + public GrabNDrag(JComponent scroll) { + this.scroll = scroll; + scroll.addMouseMotionListener(this); + scroll.addMouseListener(this); + scroll.setAutoscrolls(true); + } + + public void mousePressed(MouseEvent e) { + startPt.setLocation(e.getPoint()); + } + public void mouseDragged(MouseEvent e) { + int xd = e.getX() - startPt.x; + int yd = e.getY() - startPt.y; + + Rectangle r = scroll.getVisibleRect(); + r.x -= xd; + r.y -= yd; + scroll.scrollRectToVisible(r); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 4b22af1f..b7d624e2 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -1,4 +1,4 @@ -AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6 +AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6 JAVAROOT=bin @@ -9,8 +9,10 @@ SRC=. altosuilibdir = $(datadir)/java altosuilib_JAVA = \ + GrabNDrag.java \ AltosDevice.java \ AltosDeviceDialog.java \ + AltosFlightDisplay.java \ AltosFontListener.java \ AltosPositionListener.java \ AltosUIConfigure.java \ @@ -30,7 +32,14 @@ altosuilib_JAVA = \ AltosUIPreferences.java \ AltosUISeries.java \ AltosUIVersion.java \ - AltosUSBDevice.java + AltosUSBDevice.java \ + AltosSiteMap.java \ + AltosSiteMapCache.java \ + AltosSiteMapPreload.java \ + AltosSiteMapTile.java \ + AltosVoice.java \ + AltosDisplayThread.java \ + AltosFreqList.java JAR=altosuilib_$(ALTOSUILIB_VERSION).jar -- cgit v1.2.3 From f0216d721ed13f4d3dc608bb6ad8f83732b27c0a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 May 2014 21:01:38 -0700 Subject: altoslib/altosuilib: Change versions to altoslib:4, altosuilib:2 API has changed for these libraries, time to bump the file versions Signed-off-by: Keith Packard --- altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java | 2 +- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java | 2 +- altoslib/AltosAccel.java | 2 +- altoslib/AltosCRCException.java | 2 +- altoslib/AltosCSV.java | 2 +- altoslib/AltosCompanion.java | 2 +- altoslib/AltosConfigData.java | 2 +- altoslib/AltosConfigValues.java | 2 +- altoslib/AltosConvert.java | 2 +- altoslib/AltosDebug.java | 2 +- altoslib/AltosDistance.java | 2 +- altoslib/AltosEeprom.java | 2 +- altoslib/AltosEepromChunk.java | 2 +- altoslib/AltosEepromDownload.java | 2 +- altoslib/AltosEepromFile.java | 2 +- altoslib/AltosEepromHeader.java | 2 +- altoslib/AltosEepromIterable.java | 2 +- altoslib/AltosEepromList.java | 2 +- altoslib/AltosEepromLog.java | 2 +- altoslib/AltosEepromMega.java | 2 +- altoslib/AltosEepromMetrum2.java | 2 +- altoslib/AltosEepromMini.java | 2 +- altoslib/AltosEepromMonitor.java | 2 +- altoslib/AltosEepromTM.java | 2 +- altoslib/AltosEepromTm.java | 2 +- altoslib/AltosFile.java | 2 +- altoslib/AltosFlash.java | 2 +- altoslib/AltosFlashListener.java | 2 +- altoslib/AltosFlightReader.java | 2 +- altoslib/AltosFrequency.java | 2 +- altoslib/AltosGPS.java | 2 +- altoslib/AltosGPSSat.java | 2 +- altoslib/AltosGreatCircle.java | 2 +- altoslib/AltosHeight.java | 2 +- altoslib/AltosHexfile.java | 2 +- altoslib/AltosHexsym.java | 2 +- altoslib/AltosIMU.java | 2 +- altoslib/AltosIdle.java | 2 +- altoslib/AltosIdleFetch.java | 2 +- altoslib/AltosIdleMonitor.java | 2 +- altoslib/AltosIdleMonitorListener.java | 2 +- altoslib/AltosIgnite.java | 2 +- altoslib/AltosKML.java | 2 +- altoslib/AltosLib.java | 2 +- altoslib/AltosLine.java | 2 +- altoslib/AltosLink.java | 2 +- altoslib/AltosListenerState.java | 2 +- altoslib/AltosLog.java | 2 +- altoslib/AltosMag.java | 2 +- altoslib/AltosMma655x.java | 2 +- altoslib/AltosMs5607.java | 2 +- altoslib/AltosNoSymbol.java | 2 +- altoslib/AltosOrient.java | 2 +- altoslib/AltosParse.java | 2 +- altoslib/AltosPreferences.java | 2 +- altoslib/AltosPreferencesBackend.java | 2 +- altoslib/AltosProgrammer.java | 2 +- altoslib/AltosPyro.java | 2 +- altoslib/AltosReplayReader.java | 2 +- altoslib/AltosRomconfig.java | 2 +- altoslib/AltosSelfFlash.java | 2 +- altoslib/AltosSensorEMini.java | 2 +- altoslib/AltosSensorMM.java | 2 +- altoslib/AltosSensorMega.java | 2 +- altoslib/AltosSensorMetrum.java | 2 +- altoslib/AltosSensorTM.java | 2 +- altoslib/AltosSensorTMini.java | 2 +- altoslib/AltosSpeed.java | 2 +- altoslib/AltosState.java | 2 +- altoslib/AltosStateIterable.java | 2 +- altoslib/AltosStateUpdate.java | 2 +- altoslib/AltosTelemetry.java | 2 +- altoslib/AltosTelemetryConfiguration.java | 2 +- altoslib/AltosTelemetryFile.java | 2 +- altoslib/AltosTelemetryIterable.java | 2 +- altoslib/AltosTelemetryLegacy.java | 2 +- altoslib/AltosTelemetryLocation.java | 2 +- altoslib/AltosTelemetryMap.java | 2 +- altoslib/AltosTelemetryMegaData.java | 2 +- altoslib/AltosTelemetryMegaSensor.java | 2 +- altoslib/AltosTelemetryMetrumData.java | 2 +- altoslib/AltosTelemetryMetrumSensor.java | 2 +- altoslib/AltosTelemetryMini.java | 2 +- altoslib/AltosTelemetryRaw.java | 2 +- altoslib/AltosTelemetryReader.java | 2 +- altoslib/AltosTelemetrySatellite.java | 2 +- altoslib/AltosTelemetrySensor.java | 2 +- altoslib/AltosTelemetryStandard.java | 2 +- altoslib/AltosTemperature.java | 2 +- altoslib/AltosUnits.java | 2 +- altoslib/AltosUnitsListener.java | 2 +- altoslib/AltosWriter.java | 2 +- altosui/Altos.java | 4 ++-- altosui/AltosAscent.java | 3 ++- altosui/AltosBTDevice.java | 2 +- altosui/AltosBTKnown.java | 4 ++-- altosui/AltosBTManage.java | 2 +- altosui/AltosCSVUI.java | 4 ++-- altosui/AltosCompanionInfo.java | 2 +- altosui/AltosConfig.java | 4 ++-- altosui/AltosConfigFreqUI.java | 4 ++-- altosui/AltosConfigPyroUI.java | 4 ++-- altosui/AltosConfigTD.java | 4 ++-- altosui/AltosConfigTDUI.java | 4 ++-- altosui/AltosConfigUI.java | 4 ++-- altosui/AltosConfigureUI.java | 2 +- altosui/AltosDataChooser.java | 4 ++-- altosui/AltosDescent.java | 3 ++- altosui/AltosDeviceUIDialog.java | 2 +- altosui/AltosEepromDelete.java | 2 +- altosui/AltosEepromManage.java | 4 ++-- altosui/AltosEepromMonitor.java | 2 +- altosui/AltosEepromMonitorUI.java | 4 ++-- altosui/AltosEepromSelect.java | 4 ++-- altosui/AltosFlashUI.java | 4 ++-- altosui/AltosFlightStatsTable.java | 2 +- altosui/AltosFlightStatus.java | 3 ++- altosui/AltosFlightStatusTableModel.java | 2 +- altosui/AltosFlightStatusUpdate.java | 2 +- altosui/AltosFlightUI.java | 4 ++-- altosui/AltosGraph.java | 4 ++-- altosui/AltosGraphDataPoint.java | 4 ++-- altosui/AltosGraphDataSet.java | 4 ++-- altosui/AltosGraphUI.java | 4 ++-- altosui/AltosIdleMonitorUI.java | 4 ++-- altosui/AltosIgniteUI.java | 4 ++-- altosui/AltosIgnitor.java | 3 ++- altosui/AltosInfoTable.java | 2 +- altosui/AltosLanded.java | 3 ++- altosui/AltosLaunch.java | 2 +- altosui/AltosLaunchUI.java | 2 +- altosui/AltosPad.java | 3 ++- altosui/AltosRomconfigUI.java | 4 ++-- altosui/AltosScanUI.java | 4 ++-- altosui/AltosSerial.java | 4 ++-- altosui/AltosSerialInUseException.java | 2 +- altosui/AltosUI.java | 4 ++-- altosui/AltosUIPreferencesBackend.java | 2 +- altosuilib/AltosDevice.java | 2 +- altosuilib/AltosDeviceDialog.java | 2 +- altosuilib/AltosFontListener.java | 2 +- altosuilib/AltosPositionListener.java | 2 +- altosuilib/AltosUIAxis.java | 4 ++-- altosuilib/AltosUIConfigure.java | 2 +- altosuilib/AltosUIDataMissing.java | 2 +- altosuilib/AltosUIDataPoint.java | 2 +- altosuilib/AltosUIDataSet.java | 2 +- altosuilib/AltosUIDialog.java | 2 +- altosuilib/AltosUIEnable.java | 4 ++-- altosuilib/AltosUIFrame.java | 2 +- altosuilib/AltosUIGraph.java | 4 ++-- altosuilib/AltosUIGrapher.java | 4 ++-- altosuilib/AltosUILib.java | 4 ++-- altosuilib/AltosUIListener.java | 2 +- altosuilib/AltosUIMarker.java | 4 ++-- altosuilib/AltosUIPreferences.java | 4 ++-- altosuilib/AltosUIPreferencesBackend.java | 4 ++-- altosuilib/AltosUISeries.java | 4 ++-- altosuilib/AltosUIVersion.java.in | 2 +- altosuilib/AltosUSBDevice.java | 2 +- configure.ac | 4 ++-- micropeak/MicroData.java | 4 ++-- micropeak/MicroDataPoint.java | 2 +- micropeak/MicroDeviceDialog.java | 2 +- micropeak/MicroDownload.java | 4 ++-- micropeak/MicroExport.java | 4 ++-- micropeak/MicroFile.java | 4 ++-- micropeak/MicroFileChooser.java | 4 ++-- micropeak/MicroFrame.java | 2 +- micropeak/MicroGraph.java | 4 ++-- micropeak/MicroPeak.java | 4 ++-- micropeak/MicroRaw.java | 4 ++-- micropeak/MicroSave.java | 4 ++-- micropeak/MicroSerial.java | 2 +- micropeak/MicroSerialLog.java | 2 +- micropeak/MicroStats.java | 4 ++-- micropeak/MicroStatsTable.java | 4 ++-- micropeak/MicroUSB.java | 2 +- 189 files changed, 241 insertions(+), 235 deletions(-) (limited to 'altosuilib') diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 634769cc..1b4d45ed 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -31,7 +31,7 @@ import android.os.Handler; //import android.os.Message; import android.util.Log; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosBluetooth extends AltosLink { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 9125d56b..f61baf1e 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -49,7 +49,7 @@ import android.widget.Toast; import android.app.AlertDialog; import android.location.Location; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosDroid extends FragmentActivity { // Debugging diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java index 067cb620..f6e6881d 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java @@ -23,7 +23,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosDroidPreferences implements AltosPreferencesBackend { public final static String NAME = "org.altusmetrum.AltosDroid"; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java index 9d155385..fac4b8d4 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import android.location.Location; public interface AltosDroidTab { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java index b50cab22..77d4ba38 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java @@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid; import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech.OnInitListener; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosVoice { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java index edfd8245..e4a815eb 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import android.app.Activity; import android.os.Bundle; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java index cc070b0d..cbbe4d44 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import android.app.Activity; import android.os.Bundle; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java index 5a703978..b2e6fd20 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import android.app.Activity; import android.os.Bundle; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java index 5fe88f51..38922771 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java @@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid; import java.util.Arrays; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java index 3f0a1887..10bb3bd9 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import android.app.Activity; import android.os.Bundle; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java index c8c61838..4215a330 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java @@ -1,6 +1,6 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java index 2a2cc404..5bc4b90d 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java @@ -25,7 +25,7 @@ import java.util.concurrent.*; import android.util.Log; import android.os.Handler; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class TelemetryReader extends Thread { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 96cedad8..da5e044f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -44,7 +44,7 @@ import android.location.LocationManager; import android.location.LocationListener; import android.location.Criteria; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class TelemetryService extends Service implements LocationListener { diff --git a/altoslib/AltosAccel.java b/altoslib/AltosAccel.java index 43dc20bd..3d340e5d 100644 --- a/altoslib/AltosAccel.java +++ b/altoslib/AltosAccel.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosAccel extends AltosUnits { diff --git a/altoslib/AltosCRCException.java b/altoslib/AltosCRCException.java index 94962731..253ca435 100644 --- a/altoslib/AltosCRCException.java +++ b/altoslib/AltosCRCException.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosCRCException extends Exception { public int rssi; diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java index 8176d21b..27e1fade 100644 --- a/altoslib/AltosCSV.java +++ b/altoslib/AltosCSV.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosCompanion.java b/altoslib/AltosCompanion.java index 47ca328e..09bfe9f3 100644 --- a/altoslib/AltosCompanion.java +++ b/altoslib/AltosCompanion.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosCompanion { public final static int board_id_telescience = 0x0a; diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 213d8f13..e5c546ff 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.*; import java.text.*; diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java index 1a9fddbf..b7c0c6ed 100644 --- a/altoslib/AltosConfigValues.java +++ b/altoslib/AltosConfigValues.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public interface AltosConfigValues { /* set and get all of the dialog values */ diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 4ed45c68..484f6213 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -18,7 +18,7 @@ /* * Sensor data conversion functions */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosConvert { /* diff --git a/altoslib/AltosDebug.java b/altoslib/AltosDebug.java index 4dfb31e5..b0e52fc1 100644 --- a/altoslib/AltosDebug.java +++ b/altoslib/AltosDebug.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java index 71ee81d7..76ca20c0 100644 --- a/altoslib/AltosDistance.java +++ b/altoslib/AltosDistance.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosDistance extends AltosUnits { diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java index 57ee73ad..be18ba24 100644 --- a/altoslib/AltosEeprom.java +++ b/altoslib/AltosEeprom.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java index c884b659..32de96bc 100644 --- a/altoslib/AltosEepromChunk.java +++ b/altoslib/AltosEepromChunk.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java index 163ffad9..a2dfc438 100644 --- a/altoslib/AltosEepromDownload.java +++ b/altoslib/AltosEepromDownload.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 91ffc223..2a26c484 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromHeader.java b/altoslib/AltosEepromHeader.java index fe5bf6c3..0d022f46 100644 --- a/altoslib/AltosEepromHeader.java +++ b/altoslib/AltosEepromHeader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java index 081721b3..415c5b62 100644 --- a/altoslib/AltosEepromIterable.java +++ b/altoslib/AltosEepromIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java index a9dac13a..ab853a88 100644 --- a/altoslib/AltosEepromList.java +++ b/altoslib/AltosEepromList.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java index cc298207..1a430c03 100644 --- a/altoslib/AltosEepromLog.java +++ b/altoslib/AltosEepromLog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java index f0d7097e..71719a26 100644 --- a/altoslib/AltosEepromMega.java +++ b/altoslib/AltosEepromMega.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromMetrum2.java b/altoslib/AltosEepromMetrum2.java index d13aac42..d137614a 100644 --- a/altoslib/AltosEepromMetrum2.java +++ b/altoslib/AltosEepromMetrum2.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java index b308fbf4..32985639 100644 --- a/altoslib/AltosEepromMini.java +++ b/altoslib/AltosEepromMini.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromMonitor.java b/altoslib/AltosEepromMonitor.java index 9ab1a5ab..b97287c3 100644 --- a/altoslib/AltosEepromMonitor.java +++ b/altoslib/AltosEepromMonitor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public interface AltosEepromMonitor { diff --git a/altoslib/AltosEepromTM.java b/altoslib/AltosEepromTM.java index c8b1e60c..77fe20c5 100644 --- a/altoslib/AltosEepromTM.java +++ b/altoslib/AltosEepromTM.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromTm.java b/altoslib/AltosEepromTm.java index 049dd340..6cbb7253 100644 --- a/altoslib/AltosEepromTm.java +++ b/altoslib/AltosEepromTm.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java index 79f6f1c6..2a738996 100644 --- a/altoslib/AltosFile.java +++ b/altoslib/AltosFile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.File; import java.util.*; diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java index 25c76863..8e8722c2 100644 --- a/altoslib/AltosFlash.java +++ b/altoslib/AltosFlash.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; diff --git a/altoslib/AltosFlashListener.java b/altoslib/AltosFlashListener.java index b7fcd73b..8bb86bba 100644 --- a/altoslib/AltosFlashListener.java +++ b/altoslib/AltosFlashListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public interface AltosFlashListener { public void position(String label, int percent); diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java index 86757e82..2fcd556e 100644 --- a/altoslib/AltosFlightReader.java +++ b/altoslib/AltosFlightReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; import java.io.*; diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java index 5770b646..7c291ea9 100644 --- a/altoslib/AltosFrequency.java +++ b/altoslib/AltosFrequency.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosFrequency { public double frequency; diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index 01e6fdbc..2708d026 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosGPSSat.java b/altoslib/AltosGPSSat.java index 76fa3a56..ef24d497 100644 --- a/altoslib/AltosGPSSat.java +++ b/altoslib/AltosGPSSat.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosGPSSat { public int svid; diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java index b884a3bc..39df4fc8 100644 --- a/altoslib/AltosGreatCircle.java +++ b/altoslib/AltosGreatCircle.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.lang.Math; diff --git a/altoslib/AltosHeight.java b/altoslib/AltosHeight.java index a81897e7..84981032 100644 --- a/altoslib/AltosHeight.java +++ b/altoslib/AltosHeight.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosHeight extends AltosUnits { diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java index 60f4ecdc..d5fa8f5f 100644 --- a/altoslib/AltosHexfile.java +++ b/altoslib/AltosHexfile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.LinkedList; diff --git a/altoslib/AltosHexsym.java b/altoslib/AltosHexsym.java index a98ef0fc..403b5644 100644 --- a/altoslib/AltosHexsym.java +++ b/altoslib/AltosHexsym.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosHexsym { String name; diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index 99efb76f..a22b3fed 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.*; diff --git a/altoslib/AltosIdle.java b/altoslib/AltosIdle.java index c7b546b6..55f6f5c9 100644 --- a/altoslib/AltosIdle.java +++ b/altoslib/AltosIdle.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index b0e45797..5cd8bf36 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index 8342f8a5..f81abdff 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.concurrent.*; diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java index dcaa77a6..6a9abea2 100644 --- a/altoslib/AltosIdleMonitorListener.java +++ b/altoslib/AltosIdleMonitorListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public interface AltosIdleMonitorListener { public void update(AltosState state, AltosListenerState listener_state); diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java index 8ab47d1d..c21f17ac 100644 --- a/altoslib/AltosIgnite.java +++ b/altoslib/AltosIgnite.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.*; import java.io.*; diff --git a/altoslib/AltosKML.java b/altoslib/AltosKML.java index cc9a9f51..d55da9ef 100644 --- a/altoslib/AltosKML.java +++ b/altoslib/AltosKML.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 3f25bc31..5e18202f 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.*; import java.io.*; diff --git a/altoslib/AltosLine.java b/altoslib/AltosLine.java index 9d796a89..f9c712a3 100644 --- a/altoslib/AltosLine.java +++ b/altoslib/AltosLine.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosLine { public String line; diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 469b03c0..7f434a06 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.concurrent.*; diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java index 53ed33f9..5bf761b0 100644 --- a/altoslib/AltosListenerState.java +++ b/altoslib/AltosListenerState.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosListenerState { public int crc_errors; diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java index 70c017b7..8ecb1e96 100644 --- a/altoslib/AltosLog.java +++ b/altoslib/AltosLog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.text.*; diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index a3a0a74b..9262de2d 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.*; diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java index 0d90c351..cb2e63d4 100644 --- a/altoslib/AltosMma655x.java +++ b/altoslib/AltosMma655x.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.*; diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index 4a851524..5aa3a7ec 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.*; diff --git a/altoslib/AltosNoSymbol.java b/altoslib/AltosNoSymbol.java index 791899c0..f5e53b8c 100644 --- a/altoslib/AltosNoSymbol.java +++ b/altoslib/AltosNoSymbol.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosNoSymbol extends Exception { public AltosNoSymbol(String name) { diff --git a/altoslib/AltosOrient.java b/altoslib/AltosOrient.java index d916a0fb..5fcbe28d 100644 --- a/altoslib/AltosOrient.java +++ b/altoslib/AltosOrient.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosOrient extends AltosUnits { diff --git a/altoslib/AltosParse.java b/altoslib/AltosParse.java index 5137fef8..1bff7682 100644 --- a/altoslib/AltosParse.java +++ b/altoslib/AltosParse.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 484cb644..d299f27b 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java index 2eb29702..461b5c80 100644 --- a/altoslib/AltosPreferencesBackend.java +++ b/altoslib/AltosPreferencesBackend.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.File; diff --git a/altoslib/AltosProgrammer.java b/altoslib/AltosProgrammer.java index 750e1f02..c96f04ca 100644 --- a/altoslib/AltosProgrammer.java +++ b/altoslib/AltosProgrammer.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java index a1414123..9e47bc80 100644 --- a/altoslib/AltosPyro.java +++ b/altoslib/AltosPyro.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.*; import java.text.*; diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java index 4cf642ca..ac7df414 100644 --- a/altoslib/AltosReplayReader.java +++ b/altoslib/AltosReplayReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java index 506c3961..10df11af 100644 --- a/altoslib/AltosRomconfig.java +++ b/altoslib/AltosRomconfig.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java index 051aa766..502c6d65 100644 --- a/altoslib/AltosSelfFlash.java +++ b/altoslib/AltosSelfFlash.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; diff --git a/altoslib/AltosSensorEMini.java b/altoslib/AltosSensorEMini.java index 5f43b3a9..ee0238f9 100644 --- a/altoslib/AltosSensorEMini.java +++ b/altoslib/AltosSensorEMini.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java index 0c23d671..e34e71b7 100644 --- a/altoslib/AltosSensorMM.java +++ b/altoslib/AltosSensorMM.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorMega.java b/altoslib/AltosSensorMega.java index c52f688d..02f3a256 100644 --- a/altoslib/AltosSensorMega.java +++ b/altoslib/AltosSensorMega.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorMetrum.java b/altoslib/AltosSensorMetrum.java index bb794a1e..e5421ef5 100644 --- a/altoslib/AltosSensorMetrum.java +++ b/altoslib/AltosSensorMetrum.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index a5129783..2d60d8cf 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorTMini.java b/altoslib/AltosSensorTMini.java index bb60a794..b9eeca0c 100644 --- a/altoslib/AltosSensorTMini.java +++ b/altoslib/AltosSensorTMini.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java index d93229dd..9134f5f4 100644 --- a/altoslib/AltosSpeed.java +++ b/altoslib/AltosSpeed.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosSpeed extends AltosUnits { diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 4dbd751b..71263151 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -19,7 +19,7 @@ * Track flight state from telemetry or eeprom data stream */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosState implements Cloneable { diff --git a/altoslib/AltosStateIterable.java b/altoslib/AltosStateIterable.java index 7ea3041b..be812095 100644 --- a/altoslib/AltosStateIterable.java +++ b/altoslib/AltosStateIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosStateUpdate.java index 4614c67a..ac4e963e 100644 --- a/altoslib/AltosStateUpdate.java +++ b/altoslib/AltosStateUpdate.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public interface AltosStateUpdate { public void update_state(AltosState state) throws InterruptedException; diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index 1c4ce7bc..62948378 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java index 67a43748..d1341b9e 100644 --- a/altoslib/AltosTelemetryConfiguration.java +++ b/altoslib/AltosTelemetryConfiguration.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetryConfiguration extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index f6643134..3d3fa407 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java index 002f53b4..cba97ddc 100644 --- a/altoslib/AltosTelemetryIterable.java +++ b/altoslib/AltosTelemetryIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.io.*; import java.util.*; diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java index da9296e4..3367ece7 100644 --- a/altoslib/AltosTelemetryLegacy.java +++ b/altoslib/AltosTelemetryLegacy.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java index 8dcda9e1..8368188f 100644 --- a/altoslib/AltosTelemetryLocation.java +++ b/altoslib/AltosTelemetryLocation.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetryLocation extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryMap.java b/altoslib/AltosTelemetryMap.java index 37b2527b..8d0de355 100644 --- a/altoslib/AltosTelemetryMap.java +++ b/altoslib/AltosTelemetryMap.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; import java.util.HashMap; diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java index ffd82546..fac5695f 100644 --- a/altoslib/AltosTelemetryMegaData.java +++ b/altoslib/AltosTelemetryMegaData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetryMegaData extends AltosTelemetryStandard { int state; diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java index d9fd7fde..9e73bc4e 100644 --- a/altoslib/AltosTelemetryMegaSensor.java +++ b/altoslib/AltosTelemetryMegaSensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetryMegaSensor extends AltosTelemetryStandard { int accel; diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java index b8f7e9ea..96617306 100644 --- a/altoslib/AltosTelemetryMetrumData.java +++ b/altoslib/AltosTelemetryMetrumData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetryMetrumData extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java index 232468bb..e7055404 100644 --- a/altoslib/AltosTelemetryMetrumSensor.java +++ b/altoslib/AltosTelemetryMetrumSensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryMini.java b/altoslib/AltosTelemetryMini.java index e0a493dc..fbfaff8e 100644 --- a/altoslib/AltosTelemetryMini.java +++ b/altoslib/AltosTelemetryMini.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetryMini extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java index 91cfbb18..0dca62aa 100644 --- a/altoslib/AltosTelemetryRaw.java +++ b/altoslib/AltosTelemetryRaw.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetryRaw extends AltosTelemetryStandard { public AltosTelemetryRaw(int[] bytes) { diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 5e283587..3dff661a 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; import java.text.*; import java.io.*; diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java index 24777b28..d611e88c 100644 --- a/altoslib/AltosTelemetrySatellite.java +++ b/altoslib/AltosTelemetrySatellite.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetrySatellite extends AltosTelemetryStandard { int channels; diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java index d6389865..ad4d9283 100644 --- a/altoslib/AltosTelemetrySensor.java +++ b/altoslib/AltosTelemetrySensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTelemetrySensor extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java index c9531fcb..23ae9d21 100644 --- a/altoslib/AltosTelemetryStandard.java +++ b/altoslib/AltosTelemetryStandard.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public abstract class AltosTelemetryStandard extends AltosTelemetry { int[] bytes; diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java index 36e26564..5fa71b86 100644 --- a/altoslib/AltosTemperature.java +++ b/altoslib/AltosTemperature.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public class AltosTemperature extends AltosUnits { diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java index 82f102e4..d29cfae7 100644 --- a/altoslib/AltosUnits.java +++ b/altoslib/AltosUnits.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public abstract class AltosUnits { diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java index e9b29f9a..ca6faafd 100644 --- a/altoslib/AltosUnitsListener.java +++ b/altoslib/AltosUnitsListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public interface AltosUnitsListener { public void units_changed(boolean imperial_units); diff --git a/altoslib/AltosWriter.java b/altoslib/AltosWriter.java index 0b0daebd..c3479a93 100644 --- a/altoslib/AltosWriter.java +++ b/altoslib/AltosWriter.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_3; +package org.altusmetrum.altoslib_4; public interface AltosWriter { diff --git a/altosui/Altos.java b/altosui/Altos.java index 4b171fa7..28038ad6 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -20,8 +20,8 @@ package altosui; import java.awt.*; import libaltosJNI.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class Altos extends AltosUILib { diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index 81b08d2c..f6ccbf0c 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -19,7 +19,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosAscent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 727a9f66..e920803a 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -17,7 +17,7 @@ package altosui; import libaltosJNI.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class AltosBTDevice extends altos_bt_device implements AltosDevice { diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java index 968d72d5..3abbbe08 100644 --- a/altosui/AltosBTKnown.java +++ b/altosui/AltosBTKnown.java @@ -17,8 +17,8 @@ package altosui; import java.util.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosBTKnown implements Iterable { LinkedList devices = new LinkedList(); diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index ad1c28b6..e6e7efd4 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -23,7 +23,7 @@ import javax.swing.*; import javax.swing.plaf.basic.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable { LinkedBlockingQueue found_devices; diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index 95a8aeea..a0fceee5 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -21,8 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosCSVUI extends AltosUIDialog diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index b90240fb..42413a57 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -19,7 +19,7 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosCompanionInfo extends JTable { private AltosFlightInfoTableModel model; diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index e1805fc1..3128114f 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -22,8 +22,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.text.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosConfig implements ActionListener { diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java index 663782f0..c7181e14 100644 --- a/altosui/AltosConfigFreqUI.java +++ b/altosui/AltosConfigFreqUI.java @@ -21,8 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; class AltosEditFreqUI extends AltosUIDialog implements ActionListener { Frame frame; diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java index cd42a3b0..9df2d87d 100644 --- a/altosui/AltosConfigPyroUI.java +++ b/altosui/AltosConfigPyroUI.java @@ -21,8 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosConfigPyroUI extends AltosUIDialog diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java index ad9ebbfa..bfbd2c77 100644 --- a/altosui/AltosConfigTD.java +++ b/altosui/AltosConfigTD.java @@ -21,8 +21,8 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosConfigTD implements ActionListener { diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java index 55d6aed9..22b3384d 100644 --- a/altosui/AltosConfigTDUI.java +++ b/altosui/AltosConfigTDUI.java @@ -21,8 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosConfigTDUI extends AltosUIDialog diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 7f4e1eb0..3ec3cdb0 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -21,8 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosConfigUI extends AltosUIDialog diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 80876959..e61a4a5b 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -22,7 +22,7 @@ import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class AltosConfigureUI extends AltosUIConfigure diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index a9344a01..43726a44 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -20,8 +20,8 @@ package altosui; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosDataChooser extends JFileChooser { JFrame frame; diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index cd993a75..5cb693fe 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -19,7 +19,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosDescent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosDeviceUIDialog.java b/altosui/AltosDeviceUIDialog.java index ca34357e..307c77f8 100644 --- a/altosui/AltosDeviceUIDialog.java +++ b/altosui/AltosDeviceUIDialog.java @@ -20,7 +20,7 @@ package altosui; import javax.swing.*; import java.awt.*; import java.awt.event.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class AltosDeviceUIDialog extends AltosDeviceDialog { diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index b2d2e291..b6ac7edb 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -21,7 +21,7 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosEepromDelete implements Runnable { AltosEepromList flights; diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index e3635571..aa43ab9e 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -21,8 +21,8 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosEepromManage implements ActionListener { diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java index 50921da1..ce1c1625 100644 --- a/altosui/AltosEepromMonitor.java +++ b/altosui/AltosEepromMonitor.java @@ -20,7 +20,7 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class AltosEepromMonitor extends AltosUIDialog { diff --git a/altosui/AltosEepromMonitorUI.java b/altosui/AltosEepromMonitorUI.java index c2e925a2..c1c1eb25 100644 --- a/altosui/AltosEepromMonitorUI.java +++ b/altosui/AltosEepromMonitorUI.java @@ -20,8 +20,8 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altosuilib_1.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_4.*; public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor { JFrame owner; diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index b7cdbb72..66a197c9 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -21,8 +21,8 @@ import javax.swing.*; import javax.swing.border.*; import java.awt.*; import java.awt.event.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; class AltosEepromItem implements ActionListener { AltosEepromLog log; diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index ff9cb95d..d8c70a06 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -23,8 +23,8 @@ import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosFlashUI extends AltosUIDialog diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java index da71154e..e7a8e728 100644 --- a/altosui/AltosFlightStatsTable.java +++ b/altosui/AltosFlightStatsTable.java @@ -19,7 +19,7 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosFlightStatsTable extends JComponent { GridBagLayout layout; diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index b467bbde..73b84f8d 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -19,7 +19,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosFlightStatus extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java index e372d401..b33f40a4 100644 --- a/altosui/AltosFlightStatusTableModel.java +++ b/altosui/AltosFlightStatusTableModel.java @@ -27,7 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosFlightStatusTableModel extends AbstractTableModel { private String[] columnNames = { diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java index 93399a13..0daec04e 100644 --- a/altosui/AltosFlightStatusUpdate.java +++ b/altosui/AltosFlightStatusUpdate.java @@ -18,7 +18,7 @@ package altosui; import java.awt.event.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosFlightStatusUpdate implements ActionListener { diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index b31de12c..2bd60d6c 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -21,8 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener { AltosVoice voice; diff --git a/altosui/AltosGraph.java b/altosui/AltosGraph.java index d5c00247..ba3875c6 100644 --- a/altosui/AltosGraph.java +++ b/altosui/AltosGraph.java @@ -22,8 +22,8 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosui/AltosGraphDataPoint.java b/altosui/AltosGraphDataPoint.java index a0b0925c..06a9b62d 100644 --- a/altosui/AltosGraphDataPoint.java +++ b/altosui/AltosGraphDataPoint.java @@ -17,8 +17,8 @@ package altosui; -import org.altusmetrum.altosuilib_1.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_4.*; public class AltosGraphDataPoint implements AltosUIDataPoint { diff --git a/altosui/AltosGraphDataSet.java b/altosui/AltosGraphDataSet.java index d2773a3f..a90c2563 100644 --- a/altosui/AltosGraphDataSet.java +++ b/altosui/AltosGraphDataSet.java @@ -20,8 +20,8 @@ package altosui; import java.lang.*; import java.io.*; import java.util.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; class AltosGraphIterator implements Iterator { AltosGraphDataSet dataSet; diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 92b9b94a..33e12130 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 7ca935b6..62b50568 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -24,8 +24,8 @@ import javax.swing.event.*; import java.io.*; import java.util.concurrent.*; import java.util.Arrays; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener, AltosIdleMonitorListener, DocumentListener { AltosDevice device; diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 3028bb9c..c251bbe2 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -24,8 +24,8 @@ import java.io.*; import java.text.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosIgniteUI extends AltosUIDialog diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java index fcab7427..7f79f42b 100644 --- a/altosui/AltosIgnitor.java +++ b/altosui/AltosIgnitor.java @@ -19,7 +19,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosIgnitor extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index 3242d652..125fa94c 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -20,7 +20,7 @@ package altosui; import java.awt.*; import javax.swing.*; import javax.swing.table.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosInfoTable extends JTable { private AltosFlightInfoTableModel model; diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 25d768ad..707d8fcc 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -21,7 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosLanded extends JComponent implements AltosFlightDisplay, ActionListener { GridBagLayout layout; diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java index 04948ee6..9ac1e44c 100644 --- a/altosui/AltosLaunch.java +++ b/altosui/AltosLaunch.java @@ -20,7 +20,7 @@ package altosui; import java.io.*; import java.util.concurrent.*; import java.awt.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class AltosLaunch { AltosDevice device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 4d9fbda5..cc082542 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -23,7 +23,7 @@ import javax.swing.*; import java.io.*; import java.text.*; import java.util.concurrent.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; class FireButton extends JButton { protected void processMouseEvent(MouseEvent e) { diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 2844b32c..a6ac70db 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -19,7 +19,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosPad extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java index 89994679..d2fe54d9 100644 --- a/altosui/AltosRomconfigUI.java +++ b/altosui/AltosRomconfigUI.java @@ -20,8 +20,8 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosRomconfigUI extends AltosUIDialog diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 5cc74a77..1f1f59ad 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -25,8 +25,8 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; class AltosScanResult { String callsign; diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 2c5d2dfd..9b2180ba 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -25,8 +25,8 @@ import java.io.*; import java.util.*; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; import libaltosJNI.*; diff --git a/altosui/AltosSerialInUseException.java b/altosui/AltosSerialInUseException.java index b45d9157..318155c8 100644 --- a/altosui/AltosSerialInUseException.java +++ b/altosui/AltosSerialInUseException.java @@ -16,7 +16,7 @@ */ package altosui; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class AltosSerialInUseException extends Exception { public AltosDevice device; diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index a1bc83bf..9df02ec9 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -22,8 +22,8 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class AltosUI extends AltosUIFrame { public AltosVoice voice = new AltosVoice(); diff --git a/altosui/AltosUIPreferencesBackend.java b/altosui/AltosUIPreferencesBackend.java index f85735e8..28047086 100644 --- a/altosui/AltosUIPreferencesBackend.java +++ b/altosui/AltosUIPreferencesBackend.java @@ -19,7 +19,7 @@ package altosui; import java.io.File; import java.util.prefs.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import javax.swing.filechooser.FileSystemView; public class AltosUIPreferencesBackend implements AltosPreferencesBackend { diff --git a/altosuilib/AltosDevice.java b/altosuilib/AltosDevice.java index 2461df1b..251ae994 100644 --- a/altosuilib/AltosDevice.java +++ b/altosuilib/AltosDevice.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import libaltosJNI.*; diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java index 7fb23e13..0bedea97 100644 --- a/altosuilib/AltosDeviceDialog.java +++ b/altosuilib/AltosDeviceDialog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import javax.swing.*; import java.awt.*; diff --git a/altosuilib/AltosFontListener.java b/altosuilib/AltosFontListener.java index da903352..a98cc131 100644 --- a/altosuilib/AltosFontListener.java +++ b/altosuilib/AltosFontListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; public interface AltosFontListener { void font_size_changed(int font_size); diff --git a/altosuilib/AltosPositionListener.java b/altosuilib/AltosPositionListener.java index e75d2de5..34cf1650 100644 --- a/altosuilib/AltosPositionListener.java +++ b/altosuilib/AltosPositionListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; public interface AltosPositionListener { public void position_changed(int position); diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java index 7bc2def9..74561673 100644 --- a/altosuilib/AltosUIAxis.java +++ b/altosuilib/AltosUIAxis.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java index 153eb8ee..ae7626de 100644 --- a/altosuilib/AltosUIConfigure.java +++ b/altosuilib/AltosUIConfigure.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/AltosUIDataMissing.java b/altosuilib/AltosUIDataMissing.java index c7b01859..353ff30f 100644 --- a/altosuilib/AltosUIDataMissing.java +++ b/altosuilib/AltosUIDataMissing.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; public class AltosUIDataMissing extends Exception { public int id; diff --git a/altosuilib/AltosUIDataPoint.java b/altosuilib/AltosUIDataPoint.java index d3020410..3f16500e 100644 --- a/altosuilib/AltosUIDataPoint.java +++ b/altosuilib/AltosUIDataPoint.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; public interface AltosUIDataPoint { public abstract double x() throws AltosUIDataMissing; diff --git a/altosuilib/AltosUIDataSet.java b/altosuilib/AltosUIDataSet.java index 6f23ef9a..ee70a3fd 100644 --- a/altosuilib/AltosUIDataSet.java +++ b/altosuilib/AltosUIDataSet.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; public interface AltosUIDataSet { public abstract String name(); diff --git a/altosuilib/AltosUIDialog.java b/altosuilib/AltosUIDialog.java index e1e699a7..dc737414 100644 --- a/altosuilib/AltosUIDialog.java +++ b/altosuilib/AltosUIDialog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java index 40b5f087..8d42c09b 100644 --- a/altosuilib/AltosUIEnable.java +++ b/altosuilib/AltosUIEnable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.awt.*; import java.awt.event.*; @@ -23,7 +23,7 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java index 3dc2a0ad..ce86ad83 100644 --- a/altosuilib/AltosUIFrame.java +++ b/altosuilib/AltosUIFrame.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java index 21e13cf6..909c471b 100644 --- a/altosuilib/AltosUIGraph.java +++ b/altosuilib/AltosUIGraph.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosuilib/AltosUIGrapher.java b/altosuilib/AltosUIGrapher.java index 54f8d5a9..724fac18 100644 --- a/altosuilib/AltosUIGrapher.java +++ b/altosuilib/AltosUIGrapher.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java index 76782e2e..b51c5963 100644 --- a/altosuilib/AltosUILib.java +++ b/altosuilib/AltosUILib.java @@ -15,12 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.awt.*; import libaltosJNI.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosUILib extends AltosLib { diff --git a/altosuilib/AltosUIListener.java b/altosuilib/AltosUIListener.java index 450dc0bf..75a0ad94 100644 --- a/altosuilib/AltosUIListener.java +++ b/altosuilib/AltosUIListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; public interface AltosUIListener { public void ui_changed(String look_and_feel); diff --git a/altosuilib/AltosUIMarker.java b/altosuilib/AltosUIMarker.java index efd27921..cd6fa589 100644 --- a/altosuilib/AltosUIMarker.java +++ b/altosuilib/AltosUIMarker.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosuilib/AltosUIPreferences.java b/altosuilib/AltosUIPreferences.java index 4c995f80..7a582a7d 100644 --- a/altosuilib/AltosUIPreferences.java +++ b/altosuilib/AltosUIPreferences.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.io.*; import java.util.*; import java.awt.Component; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; public class AltosUIPreferences extends AltosPreferences { diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java index d6575717..da29253d 100644 --- a/altosuilib/AltosUIPreferencesBackend.java +++ b/altosuilib/AltosUIPreferencesBackend.java @@ -15,11 +15,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.io.File; import java.util.prefs.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import javax.swing.filechooser.FileSystemView; public class AltosUIPreferencesBackend implements AltosPreferencesBackend { diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java index 10ea1614..b0632d18 100644 --- a/altosuilib/AltosUISeries.java +++ b/altosuilib/AltosUISeries.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; +import org.altusmetrum.altoslib_4.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosuilib/AltosUIVersion.java.in b/altosuilib/AltosUIVersion.java.in index 169cca1b..3f629560 100644 --- a/altosuilib/AltosUIVersion.java.in +++ b/altosuilib/AltosUIVersion.java.in @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; public class AltosUIVersion { public final static String version = "@VERSION@"; diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index 4f329840..b70b5e83 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_1; +package org.altusmetrum.altosuilib_2; import java.util.*; import libaltosJNI.*; diff --git a/configure.ac b/configure.ac index 01867e9f..d2d87754 100644 --- a/configure.ac +++ b/configure.ac @@ -29,8 +29,8 @@ AC_SUBST(VERSION_DASH) dnl ========================================================================== dnl Java library versions -ALTOSUILIB_VERSION=1 -ALTOSLIB_VERSION=3 +ALTOSUILIB_VERSION=2 +ALTOSLIB_VERSION=4 AC_SUBST(ALTOSLIB_VERSION) AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package]) diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index e786ff1e..ca211f16 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak; import java.lang.*; import java.io.*; import java.util.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; class MicroIterator implements Iterator { int i; diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java index 61faf794..5a5e8c37 100644 --- a/micropeak/MicroDataPoint.java +++ b/micropeak/MicroDataPoint.java @@ -17,7 +17,7 @@ package org.altusmetrum.micropeak; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class MicroDataPoint implements AltosUIDataPoint { public double time; diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java index 533605d6..305421a7 100644 --- a/micropeak/MicroDeviceDialog.java +++ b/micropeak/MicroDeviceDialog.java @@ -21,7 +21,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class MicroDeviceDialog extends AltosDeviceDialog { diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java index 7d2e9eb4..1c70e1d1 100644 --- a/micropeak/MicroDownload.java +++ b/micropeak/MicroDownload.java @@ -23,8 +23,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener { MicroPeak owner; diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java index c170f544..87d5499b 100644 --- a/micropeak/MicroExport.java +++ b/micropeak/MicroExport.java @@ -23,8 +23,8 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroExport extends JFileChooser { diff --git a/micropeak/MicroFile.java b/micropeak/MicroFile.java index b6a9d401..019346ae 100644 --- a/micropeak/MicroFile.java +++ b/micropeak/MicroFile.java @@ -19,8 +19,8 @@ package org.altusmetrum.micropeak; import java.io.*; import java.util.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroFile { diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java index 595d1ff7..00b6690a 100644 --- a/micropeak/MicroFileChooser.java +++ b/micropeak/MicroFileChooser.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroFileChooser extends JFileChooser { JFrame frame; diff --git a/micropeak/MicroFrame.java b/micropeak/MicroFrame.java index ef8b24cc..5bfe5bf7 100644 --- a/micropeak/MicroFrame.java +++ b/micropeak/MicroFrame.java @@ -21,7 +21,7 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class MicroFrame extends AltosUIFrame { static String[] micro_icon_names = { diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index 5960fe4d..f9968919 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -22,8 +22,8 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 78bc857e..19e91660 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -23,8 +23,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroPeak extends MicroFrame implements ActionListener, ItemListener { diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java index d64da387..26d62012 100644 --- a/micropeak/MicroRaw.java +++ b/micropeak/MicroRaw.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak; import java.awt.*; import java.io.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroRaw extends JTextArea { diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java index 0addfa88..7c5d6abe 100644 --- a/micropeak/MicroSave.java +++ b/micropeak/MicroSave.java @@ -24,8 +24,8 @@ import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroSave extends JFileChooser { diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java index 39f421ec..37b68636 100644 --- a/micropeak/MicroSerial.java +++ b/micropeak/MicroSerial.java @@ -20,7 +20,7 @@ package org.altusmetrum.micropeak; import java.util.*; import java.io.*; import libaltosJNI.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class MicroSerial extends InputStream { SWIGTYPE_p_altos_file file; diff --git a/micropeak/MicroSerialLog.java b/micropeak/MicroSerialLog.java index 0a5a0b91..7300f06d 100644 --- a/micropeak/MicroSerialLog.java +++ b/micropeak/MicroSerialLog.java @@ -20,7 +20,7 @@ package org.altusmetrum.micropeak; import java.util.*; import java.io.*; import libaltosJNI.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public interface MicroSerialLog { diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java index 765525b0..45c9f225 100644 --- a/micropeak/MicroStats.java +++ b/micropeak/MicroStats.java @@ -18,8 +18,8 @@ package org.altusmetrum.micropeak; import java.io.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroStats { double coast_height; diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java index ea1609ac..268a7ff0 100644 --- a/micropeak/MicroStatsTable.java +++ b/micropeak/MicroStatsTable.java @@ -19,8 +19,8 @@ package org.altusmetrum.micropeak; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_3.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; public class MicroStatsTable extends JComponent implements AltosFontListener { GridBagLayout layout; diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java index 3bd61470..437fa0bc 100644 --- a/micropeak/MicroUSB.java +++ b/micropeak/MicroUSB.java @@ -19,7 +19,7 @@ package org.altusmetrum.micropeak; import java.util.*; import libaltosJNI.*; -import org.altusmetrum.altosuilib_1.*; +import org.altusmetrum.altosuilib_2.*; public class MicroUSB extends altos_device implements AltosDevice { -- cgit v1.2.3 From db08e99361d82de63058d3388823f486e5fc9839 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 May 2014 10:58:53 -0700 Subject: altosuilib: Add multiple zoom levels and content types to map Also changes the file format for hybrid, satellite and terrain maps to jpg to save disk space. Signed-off-by: Keith Packard --- altosuilib/AltosSiteMap.java | 395 +++++++++++++++++++++++++++++------- altosuilib/AltosSiteMapCache.java | 73 ++++--- altosuilib/AltosSiteMapPreload.java | 8 +- altosuilib/AltosSiteMapTile.java | 74 ++++++- 4 files changed, 436 insertions(+), 114 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index 1cfbc8b5..f4143fe2 100644 --- a/altosuilib/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -18,14 +18,39 @@ package org.altusmetrum.altosuilib_2; import java.awt.*; +import java.awt.event.*; import javax.swing.*; import java.io.*; import java.lang.Math; import java.awt.geom.Point2D; +import java.util.*; import java.util.concurrent.*; import org.altusmetrum.altoslib_4.*; -public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { +class MapPoint { + double lat, lon; + int state; + + public MapPoint(double lat, double lon, int state) { + this.lat = lat; + this.lon = lon; + this.state = state; + } + + public boolean equals(MapPoint other) { + if (other == null) + return false; + if (other.lat != lat) + return false; + if (other.lon != lon) + return false; + if (other.state != state) + return false; + return true; + } +} + +public class AltosSiteMap extends JComponent implements AltosFlightDisplay { // preferred vertical step in a tile in naut. miles // will actually choose a step size between x and 2x, where this // is 1.5x @@ -35,6 +60,29 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { static final int MAX_TILE_DELTA = 100; + static final int maptype_hybrid = 0; + static final int maptype_roadmap = 1; + static final int maptype_satellite = 2; + static final int maptype_terrain = 3; + + int maptype = maptype_hybrid; + + static final String[] maptype_names = { + "hybrid", + "roadmap", + "satellite", + "terrain" + }; + + static final String[] maptype_labels = { + "Hybrid", + "Roadmap", + "Satellite", + "Terrain" + }; + + LinkedList points = new LinkedList(); + private static Point2D.Double translatePoint(Point2D.Double p, Point2D.Double d) { @@ -89,7 +137,12 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { return new LatLng(lat,lng); } - int zoom; + static final int default_zoom = 15; + static final int min_zoom = 3; + static final int max_zoom = 21; + + int zoom = default_zoom; + double scale_x, scale_y; int radius; /* half width/height of tiles to load */ @@ -112,7 +165,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { private Point2D.Double tileCoordOffset(Point p) { return new Point2D.Double(centre.x - p.x*px_size, - centre.y - p.y * px_size); + centre.y - p.y*px_size); } private Point tileOffset(Point2D.Double p) { @@ -121,19 +174,11 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } private Point2D.Double getBaseLocation(double lat, double lng) { - Point2D.Double locn, north_step; - - zoom = 2; - // stupid loop structure to please Java's control flow analysis - do { - zoom++; - scale_x = 256/360.0 * Math.pow(2, zoom); - scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - locn = pt(lat, lng); - north_step = pt(lat+tile_size_nmi*4/3/60.0, lng); - if (locn.y - north_step.y > px_size) - break; - } while (zoom < 22); + Point2D.Double locn = pt(0,0), north_step; + + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + locn = pt(lat, lng); locn.x = -px_size * Math.floor(locn.x/px_size); locn.y = -px_size * Math.floor(locn.y/px_size); return locn; @@ -144,23 +189,38 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } public void set_font() { - // nothing + for (AltosSiteMapTile tile : mapTiles.values()) + tile.set_font(AltosUILib.value_font); } - private void loadMap(final AltosSiteMapTile tile, - final File pngfile, String pngurl) + static final int load_mode_cached = 1; + static final int load_mode_uncached = 2; + + private boolean load_map(final AltosSiteMapTile tile, + final File pngfile, String pngurl, + int load_mode) { - boolean loaded = AltosSiteMapCache.fetchMap(pngfile, pngurl); - if (loaded) { + boolean has_map = AltosSiteMapCache.has_map(pngfile, pngurl); + if ((load_mode & load_mode_uncached) == 0 && !has_map) + return false; + if ((load_mode & load_mode_cached) == 0 && has_map) + return false; + + tile.set_status(AltosSiteMapCache.loading); + int status = AltosSiteMapCache.fetch_map(pngfile, pngurl); + if (status == AltosSiteMapCache.success) { SwingUtilities.invokeLater(new Runnable() { public void run() { - tile.loadMap(pngfile); + tile.load_map(pngfile); } }); } else { - System.out.printf("# Failed to fetch file %s\n", pngfile); + tile.set_status(status); + System.out.printf("# Failed to fetch file %s (status %d)\n", pngfile, status); System.out.printf(" wget -O '%s' '%s'\n", pngfile, pngurl); + System.out.printf(" sleep 1\n"); } + return true; } @@ -177,11 +237,11 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { LatLng map_latlng = latlng( -centre.x + x*px_size + px_size/2, -centre.y + y*px_size + px_size/2); - prefetch.pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); - prefetch.pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); - if (prefetch.pngfile.exists()) { + prefetch.pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom, maptype_hybrid); + prefetch.pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom, maptype_hybrid); + if (AltosSiteMapCache.has_map(prefetch.pngfile, prefetch.pngurl)) { prefetch.result = 1; - } else if (AltosSiteMapCache.fetchMap(prefetch.pngfile, prefetch.pngurl)) { + } else if (AltosSiteMapCache.fetch_map(prefetch.pngfile, prefetch.pngurl) == AltosSiteMapCache.success) { prefetch.result = 0; } else { prefetch.result = -1; @@ -218,33 +278,45 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } } - public String initMap(Point offset) { + public File init_map(Point offset, int load_mode) { AltosSiteMapTile tile = mapTiles.get(offset); Point2D.Double coord = tileCoordOffset(offset); LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y); - File pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); - String pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); - loadMap(tile, pngfile, pngurl); - return pngfile.toString(); + File pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom, maptype); + String pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom, maptype); + load_map(tile, pngfile, pngurl, load_mode); + return pngfile; } public void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) { Thread thread = new Thread() { public void run() { - initMap(offset); + init_map(offset, load_mode_cached|load_mode_uncached); finishTileLater(tile, offset); } }; thread.start(); } + double lat, lon; + boolean base_location_set = false; + + public void clear_base_location() { + base_location_set = false; + circle_set = false; + points = new LinkedList(); + for (AltosSiteMapTile tile : mapTiles.values()) + tile.clearMap(); + } + public void setBaseLocation(double lat, double lng) { - for (Point k : mapTiles.keySet()) { - AltosSiteMapTile tile = mapTiles.get(k); + this.lat = lat; + this.lon = lng; + base_location_set = true; + for (AltosSiteMapTile tile : mapTiles.values()) tile.clearMap(); - } centre = getBaseLocation(lat, lng); scrollRocketToVisible(pt(lat,lng)); @@ -256,28 +328,42 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { Thread thread = new Thread() { public void run() { for (Point k : mapTiles.keySet()) - initMap(k); + init_map(k, load_mode_cached); + for (Point k : mapTiles.keySet()) + init_map(k, load_mode_uncached); } }; thread.start(); } - private static File MapFile(double lat, double lng, int zoom) { + private static File MapFile(double lat, double lng, int zoom, int maptype) { char chlat = lat < 0 ? 'S' : 'N'; char chlng = lng < 0 ? 'W' : 'E'; if (lat < 0) lat = -lat; if (lng < 0) lng = -lng; + String maptype_string = String.format("%s-", maptype_names[maptype]); + String format_string; + if (maptype == maptype_hybrid || maptype == maptype_satellite || maptype == maptype_terrain) + format_string = "jpg"; + else + format_string = "png"; return new File(AltosUIPreferences.mapdir(), - String.format("map-%c%.6f,%c%.6f-%d.png", - chlat, lat, chlng, lng, zoom)); + String.format("map-%c%.6f,%c%.6f-%s%d.%s", + chlat, lat, chlng, lng, maptype_string, zoom, format_string)); } - private static String MapURL(double lat, double lng, int zoom) { - return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); + private static String MapURL(double lat, double lng, int zoom, int maptype) { + String format_string; + if (maptype == maptype_hybrid || maptype == maptype_satellite || maptype == maptype_terrain) + format_string = "jpg"; + else + format_string = "png32"; + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s", + lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string); } boolean initialised = false; - Point2D.Double last_pt = null; + MapPoint last_point = null; int last_state = -1; public void show(double lat, double lon) { @@ -286,42 +372,44 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // initMaps(lat, lon); // scrollRocketToVisible(pt(lat, lon)); } - public void show(final AltosState state, final AltosListenerState listener_state) { - // if insufficient gps data, nothing to update - AltosGPS gps = state.gps; - if (gps == null) - return; + JLabel zoom_label; - if (!gps.locked && gps.nsat < 4) - return; + public void set_zoom_label() { + zoom_label.setText(String.format("- %d -", zoom - default_zoom)); + } - if (!initialised) { - if (state.pad_lat != AltosLib.MISSING && state.pad_lon != AltosLib.MISSING) { - initMaps(state.pad_lat, state.pad_lon); - initialised = true; - } else if (gps.lat != AltosLib.MISSING && gps.lon != AltosLib.MISSING) { - initMaps(gps.lat, gps.lon); - initialised = true; - } else { - return; - } + public void set_zoom(int zoom) { + if (min_zoom <= zoom && zoom <= max_zoom) { + this.zoom = zoom; + if (base_location_set) + initMaps(lat, lon); + redraw(); + set_zoom_label(); } + } - final Point2D.Double pt = pt(gps.lat, gps.lon); - if (last_pt == pt && last_state == state.state) - return; + public int get_zoom() { + return zoom; + } - if (last_pt == null) { - last_pt = pt; + public void draw(MapPoint last_point, MapPoint point) { + boolean force_ensure = false; + if (last_point == null) { + force_ensure = true; + last_point = point; } + + Point2D.Double pt = pt(point.lat, point.lon); + Point2D.Double last_pt = pt(last_point.lat, last_point.lon); + boolean in_any = false; for (Point offset : mapTiles.keySet()) { AltosSiteMapTile tile = mapTiles.get(offset); Point2D.Double ref, lref; ref = translatePoint(pt, tileCoordOffset(offset)); lref = translatePoint(last_pt, tileCoordOffset(offset)); - tile.show(state, listener_state, lref, ref); + tile.show(point.state, lref, ref); if (0 <= ref.x && ref.x < px_size) if (0 <= ref.y && ref.y < px_size) in_any = true; @@ -334,18 +422,60 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { lref = translatePoint(last_pt, tileCoordOffset(offset)); AltosSiteMapTile tile = createTile(offset); - tile.show(state, listener_state, lref, ref); + tile.show(point.state, lref, ref); initAndFinishMapAsync(tile, offset); } scrollRocketToVisible(pt); - if (offset != tileOffset(last_pt)) { + if (force_ensure || offset != tileOffset(last_pt)) { ensureTilesAround(offset); } + } + + public void redraw() { + MapPoint last_point = null; + + for (MapPoint point : points) { + draw(last_point, point); + last_point = point; + } + if (circle_set) + draw_circle(circle_lat, circle_lon); + } + + public void show(final AltosState state, final AltosListenerState listener_state) { + // if insufficient gps data, nothing to update + AltosGPS gps = state.gps; + + if (gps == null) + return; + + if (!gps.locked && gps.nsat < 4) + return; + + if (!initialised) { + if (state.pad_lat != AltosLib.MISSING && state.pad_lon != AltosLib.MISSING) { + initMaps(state.pad_lat, state.pad_lon); + initialised = true; + } else if (gps.lat != AltosLib.MISSING && gps.lon != AltosLib.MISSING) { + initMaps(gps.lat, gps.lon); + initialised = true; + } else { + return; + } + } - last_pt = pt; - last_state = state.state; + MapPoint point = new MapPoint(gps.lat, gps.lon, state.state); + + if (point.equals(last_point)) + return; + + points.add(point); + + draw(last_point, point); + + last_point = point; } public void centre(Point2D.Double pt) { @@ -355,6 +485,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { int dy = (int)copt.y - r.height/2 - r.y; r.x += dx; r.y += dy; + r.width = 1; + r.height = 1; comp.scrollRectToVisible(r); } @@ -364,8 +496,15 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { centre(pt(state.gps.lat, state.gps.lon)); } + private double circle_lat, circle_lon; + private boolean circle_set = false; + public void draw_circle(double lat, double lon) { - final Point2D.Double pt = pt(lat, lon); + circle_lat = lat; + circle_lon = lon; + circle_set = true; + + Point2D.Double pt = pt(lat, lon); for (Point offset : mapTiles.keySet()) { AltosSiteMapTile tile = mapTiles.get(offset); @@ -376,6 +515,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { private AltosSiteMapTile createTile(Point offset) { AltosSiteMapTile tile = new AltosSiteMapTile(px_size); + tile.set_font(AltosUILib.value_font); mapTiles.put(offset, tile); return tile; } @@ -405,6 +545,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { private void scrollRocketToVisible(Point2D.Double pt) { Rectangle r = comp.getVisibleRect(); Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); + int dx = (int)copt.x - r.width/2 - r.x; int dy = (int)copt.y - r.height/2 - r.y; if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) { @@ -446,9 +587,9 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { layout.setConstraints(tile, c); comp.add(tile); - if (review) { - comp.scrollRectToVisible(r); - } +// if (review) { +// comp.scrollRectToVisible(r); +// } } private AltosSiteMap(boolean knowWhatYouAreDoing) { @@ -460,6 +601,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { JComponent comp = new JComponent() { }; private GridBagLayout layout = new GridBagLayout(); + JScrollPane pane = new JScrollPane(); + public AltosSiteMap(int in_radius) { radius = in_radius; @@ -474,8 +617,108 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { addTileAt(t, offset); } } - setViewportView(comp); - setPreferredSize(new Dimension(500,500)); + pane.setViewportView(comp); + pane.setPreferredSize(new Dimension(500,500)); + pane.setVisible(true); + pane.setEnabled(true); + + GridBagLayout my_layout = new GridBagLayout(); + + setLayout(my_layout); + + GridBagConstraints c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 10; + c.weightx = 1; + c.weighty = 1; + add(pane, c); + + int y = 0; + + zoom_label = new JLabel("", JLabel.CENTER); + set_zoom_label(); + + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(zoom_label, c); + + JButton zoom_reset = new JButton("0"); + zoom_reset.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + set_zoom(default_zoom); + } + }); + + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(zoom_reset, c); + + JButton zoom_in = new JButton("+"); + zoom_in.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + set_zoom(get_zoom() + 1); + } + }); + + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(zoom_in, c); + + JButton zoom_out = new JButton("-"); + zoom_out.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + set_zoom(get_zoom() - 1); + } + }); + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(zoom_out, c); + + final JComboBox maptype_combo = new JComboBox(maptype_labels); + + maptype_combo.setEditable(false); + maptype_combo.setMaximumRowCount(maptype_combo.getItemCount()); + maptype_combo.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + maptype = maptype_combo.getSelectedIndex(); + if (base_location_set) + initMaps(lat, lon); + redraw(); + } + }); + + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(maptype_combo, c); } public AltosSiteMap() { diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index cf93016a..acc84ab0 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -22,9 +22,7 @@ import javax.imageio.ImageIO; import java.awt.image.*; import java.awt.*; import java.io.*; -import java.net.URL; -import java.net.URLConnection; - +import java.net.*; class AltosCacheImage { Component component; @@ -36,9 +34,12 @@ class AltosCacheImage { public void load_image() throws IOException { BufferedImage bimg = ImageIO.read(file); + if (bimg == null) + throw new IOException("Can't load image file"); Graphics2D g = image.createGraphics(); g.drawImage(bimg, 0, 0, null); bimg.flush(); + bimg = null; } public Image validate() { @@ -79,14 +80,31 @@ class AltosCacheImage { } } -public class AltosSiteMapCache extends JLabel { +public class AltosSiteMapCache { static final long google_maps_ratelimit_ms = 1200; // Google limits static map queries to 50 per minute per IP, so // each query should take at least 1.2 seconds. - public static boolean fetchMap(File file, String url) { + static final int success = 0; + static final int loading = 1; + static final int failed = 2; + static final int bad_request = 3; + static final int forbidden = 4; + + public static synchronized boolean has_map(File file, String url) { + return file.exists(); + } + + static long forbidden_time; + static boolean forbidden_set = false; + static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; + + public static synchronized int fetch_map(File file, String url) { if (file.exists()) - return true; + return success; + + if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) + return forbidden; URL u; long startTime = System.nanoTime(); @@ -94,13 +112,26 @@ public class AltosSiteMapCache extends JLabel { try { u = new URL(url); } catch (java.net.MalformedURLException e) { - return false; + return bad_request; } byte[] data; + URLConnection uc = null; try { - URLConnection uc = u.openConnection(); + uc = u.openConnection(); + String type = uc.getContentType(); int contentLength = uc.getContentLength(); + if (uc instanceof HttpURLConnection) { + int response = ((HttpURLConnection) uc).getResponseCode(); + switch (response) { + case HttpURLConnection.HTTP_FORBIDDEN: + case HttpURLConnection.HTTP_PAYMENT_REQUIRED: + case HttpURLConnection.HTTP_UNAUTHORIZED: + forbidden_time = System.nanoTime(); + forbidden_set = true; + return forbidden; + } + } InputStream in = new BufferedInputStream(uc.getInputStream()); int bytesRead = 0; int offset = 0; @@ -113,11 +144,11 @@ public class AltosSiteMapCache extends JLabel { } in.close(); - if (offset != contentLength) { - return false; - } + if (offset != contentLength) + return failed; + } catch (IOException e) { - return false; + return failed; } try { @@ -126,12 +157,11 @@ public class AltosSiteMapCache extends JLabel { out.flush(); out.close(); } catch (FileNotFoundException e) { - return false; + return bad_request; } catch (IOException e) { - if (file.exists()) { + if (file.exists()) file.delete(); - } - return false; + return bad_request; } long duration_ms = (System.nanoTime() - startTime) / 1000000; @@ -143,21 +173,16 @@ public class AltosSiteMapCache extends JLabel { } } - return true; + return success; } - static int cache_size = 9; + static final int cache_size = 12; static AltosCacheImage[] images; static long used; - public static void set_cache_size(int cache_size) { - AltosSiteMapCache.cache_size = cache_size; - images = null; - } - - public static Image get_image(Component component, File file, int width, int height) { + public static synchronized Image get_image(Component component, File file, int width, int height) { int oldest = -1; long age = used; AltosCacheImage image; diff --git a/altosuilib/AltosSiteMapPreload.java b/altosuilib/AltosSiteMapPreload.java index baa7fc37..107b09f8 100644 --- a/altosuilib/AltosSiteMapPreload.java +++ b/altosuilib/AltosSiteMapPreload.java @@ -265,9 +265,10 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener public void run() { for (int y = -map.radius; y <= map.radius; y++) { for (int x = -map.radius; x <= map.radius; x++) { - String pngfile; - pngfile = map.initMap(new Point(x,y)); - SwingUtilities.invokeLater(new updatePbar(x, y, pngfile)); + File pngfile; + pngfile = map.init_map(new Point(x,y), + AltosSiteMap.load_mode_cached|AltosSiteMap.load_mode_uncached); + SwingUtilities.invokeLater(new updatePbar(x, y, pngfile.toString())); } } } @@ -305,6 +306,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener try { final double latitude = lat.get_value(); final double longitude = lon.get_value(); + map.clear_base_location(); map.setBaseLocation(latitude,longitude); map.draw_circle(latitude,longitude); loading = true; diff --git a/altosuilib/AltosSiteMapTile.java b/altosuilib/AltosSiteMapTile.java index 1046d6bd..9610b248 100644 --- a/altosuilib/AltosSiteMapTile.java +++ b/altosuilib/AltosSiteMapTile.java @@ -21,10 +21,10 @@ import java.awt.*; import java.awt.image.*; import javax.swing.*; import javax.imageio.*; -import java.awt.geom.Point2D; -import java.awt.geom.Line2D; +import java.awt.geom.*; import java.io.*; import java.util.*; +import java.awt.RenderingHints.*; import org.altusmetrum.altoslib_4.*; class AltosPoint { @@ -40,15 +40,38 @@ class AltosPoint { public class AltosSiteMapTile extends JComponent { int px_size; File file; + int status; Point2D.Double boost; Point2D.Double landed; LinkedList points; - public void loadMap(File pngFile) { + public synchronized void queue_repaint() { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + repaint(); + } + }); + } + + public void load_map(File pngFile) { file = pngFile; - repaint(); + queue_repaint(); + } + + private Font font = null; + + public void set_font(Font font) { + this.font = font; + this.status = AltosSiteMapCache.success; + queue_repaint(); + } + + public void set_status(int status) { + file = null; + this.status = status; + queue_repaint(); } public void clearMap() { @@ -56,6 +79,8 @@ public class AltosSiteMapTile extends JComponent { landed = null; points = null; file = null; + status = AltosSiteMapCache.success; + queue_repaint(); } static Color stateColors[] = { @@ -78,7 +103,7 @@ public class AltosSiteMapTile extends JComponent { public void set_boost(Point2D.Double boost) { this.boost = boost; - repaint(); + queue_repaint(); } public void paint(Graphics g) { @@ -94,6 +119,34 @@ public class AltosSiteMapTile extends JComponent { } else { g2d.setColor(Color.GRAY); g2d.fillRect(0, 0, getWidth(), getHeight()); + String message = null; + switch (status) { + case AltosSiteMapCache.loading: + message = "Loading..."; + break; + case AltosSiteMapCache.bad_request: + message = "Internal error"; + break; + case AltosSiteMapCache.failed: + message = "Network error, check connection"; + break; + case AltosSiteMapCache.forbidden: + message = "Too many requests, try later"; + break; + } + if (message != null && font != null) { + g2d.setFont(font); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + Rectangle2D bounds; + bounds = font.getStringBounds(message, g2d.getFontRenderContext()); + + float x = getWidth() / 2.0f; + float y = getHeight() / 2.0f; + x = x - (float) bounds.getWidth() / 2.0f; + y = y - (float) bounds.getHeight() / 2.0f; + g2d.setColor(Color.BLACK); + g2d.drawString(message, x, y); + } } g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, @@ -120,19 +173,18 @@ public class AltosSiteMapTile extends JComponent { } } - public synchronized void show(AltosState state, AltosListenerState listener_state, - Point2D.Double last_pt, Point2D.Double pt) + public synchronized void show(int state, Point2D.Double last_pt, Point2D.Double pt) { if (points == null) points = new LinkedList(); - points.add(new AltosPoint(pt, state.state)); + points.add(new AltosPoint(pt, state)); - if (state.state == AltosLib.ao_flight_boost && boost == null) + if (state == AltosLib.ao_flight_boost && boost == null) boost = pt; - if (state.state == AltosLib.ao_flight_landed && landed == null) + if (state == AltosLib.ao_flight_landed && landed == null) landed = pt; - repaint(); + queue_repaint(); } public AltosSiteMapTile(int in_px_size) { -- cgit v1.2.3 From 8e44580cbe978f1570d4d2ac13d3dd7cd470ecf7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 May 2014 15:39:13 -0700 Subject: altosuilib: Add distance measuring line to site map. Use any modifier or button other than the left one to draw a line on the map. The length of the line is shown at the start of the line. Signed-off-by: Keith Packard --- altosuilib/AltosSiteMap.java | 90 ++++++++++++++++++++++++++++++++++++--- altosuilib/AltosSiteMapCache.java | 4 +- altosuilib/AltosSiteMapTile.java | 68 ++++++++++++++++++++++++++++- altosuilib/GrabNDrag.java | 21 ++++++--- 4 files changed, 166 insertions(+), 17 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index f4143fe2..f22d9531 100644 --- a/altosuilib/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -22,7 +22,7 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.lang.Math; -import java.awt.geom.Point2D; +import java.awt.geom.*; import java.util.*; import java.util.concurrent.*; import org.altusmetrum.altoslib_4.*; @@ -50,7 +50,7 @@ class MapPoint { } } -public class AltosSiteMap extends JComponent implements AltosFlightDisplay { +public class AltosSiteMap extends JComponent implements AltosFlightDisplay, MouseMotionListener, MouseListener { // preferred vertical step in a tile in naut. miles // will actually choose a step size between x and 2x, where this // is 1.5x @@ -160,6 +160,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } */ + private LatLng latlng(Point pt) { + return latlng(new Point2D.Double(pt.x, pt.y), scale_x, scale_y); + } + ConcurrentHashMap mapTiles = new ConcurrentHashMap(); Point2D.Double centre; @@ -307,16 +311,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { base_location_set = false; circle_set = false; points = new LinkedList(); - for (AltosSiteMapTile tile : mapTiles.values()) - tile.clearMap(); + line_start = line_end = null; } public void setBaseLocation(double lat, double lng) { + for (AltosSiteMapTile tile : mapTiles.values()) + tile.clearMap(); this.lat = lat; this.lon = lng; base_location_set = true; - for (AltosSiteMapTile tile : mapTiles.values()) - tile.clearMap(); centre = getBaseLocation(lat, lng); scrollRocketToVisible(pt(lat,lng)); @@ -442,6 +445,8 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } if (circle_set) draw_circle(circle_lat, circle_lon); + if (line_start != null) + set_line(); } public void show(final AltosState state, final AltosListenerState listener_state) { @@ -598,14 +603,85 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } } - JComponent comp = new JComponent() { }; + JComponent comp; + private GridBagLayout layout = new GridBagLayout(); + LatLng line_start, line_end; + + private void set_line() { + if (line_start != null && line_end != null) { + Point2D.Double start = pt(line_start.lat, line_start.lng); + Point2D.Double end = pt(line_end.lat, line_end.lng); + AltosGreatCircle g = new AltosGreatCircle(line_start.lat, line_start.lng, + line_end.lat, line_end.lng); + + for (Point offset : mapTiles.keySet()) { + AltosSiteMapTile tile = mapTiles.get(offset); + Point2D.Double s, e; + s = translatePoint(start, tileCoordOffset(offset)); + e = translatePoint(end, tileCoordOffset(offset)); + tile.set_line(new Line2D.Double(s.x, s.y, e.x, e.y), g.distance); + } + } else { + for (AltosSiteMapTile tile : mapTiles.values()) + tile.set_line(null, 0); + } + } + + LatLng latlng(MouseEvent e) { + if (!base_location_set) + return null; + + Rectangle zerozero = mapTiles.get(new Point(0, 0)).getBounds(); + + return latlng(-centre.x + e.getPoint().x - zerozero.x, -centre.y + e.getPoint().y - zerozero.y); + } + + /* MouseMotionListener methods */ + public void mouseDragged(MouseEvent e) { + if (!GrabNDrag.grab_n_drag(e)) { + LatLng loc = latlng(e); + line_end = loc; + set_line(); + } + } + + public void mouseMoved(MouseEvent e) { + } + + /* MouseListener methods */ + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + if (!GrabNDrag.grab_n_drag(e)) { + LatLng loc = latlng(e); + line_start = loc; + line_end = null; + set_line(); + } + } + + public void mouseReleased(MouseEvent e) { + } + JScrollPane pane = new JScrollPane(); public AltosSiteMap(int in_radius) { radius = in_radius; + comp = new JComponent() { }; + + comp.addMouseMotionListener(this); + comp.addMouseListener(this); + GrabNDrag scroller = new GrabNDrag(comp); comp.setLayout(layout); diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index acc84ab0..42914deb 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -91,7 +91,7 @@ public class AltosSiteMapCache { static final int bad_request = 3; static final int forbidden = 4; - public static synchronized boolean has_map(File file, String url) { + public static boolean has_map(File file, String url) { return file.exists(); } @@ -182,7 +182,7 @@ public class AltosSiteMapCache { static long used; - public static synchronized Image get_image(Component component, File file, int width, int height) { + public static Image get_image(Component component, File file, int width, int height) { int oldest = -1; long age = used; AltosCacheImage image; diff --git a/altosuilib/AltosSiteMapTile.java b/altosuilib/AltosSiteMapTile.java index 9610b248..09f184a3 100644 --- a/altosuilib/AltosSiteMapTile.java +++ b/altosuilib/AltosSiteMapTile.java @@ -44,6 +44,9 @@ public class AltosSiteMapTile extends JComponent { Point2D.Double boost; Point2D.Double landed; + Line2D.Double line; + double line_course; + double line_dist; LinkedList points; @@ -81,6 +84,7 @@ public class AltosSiteMapTile extends JComponent { file = null; status = AltosSiteMapCache.success; queue_repaint(); + line = null; } static Color stateColors[] = { @@ -106,6 +110,47 @@ public class AltosSiteMapTile extends JComponent { queue_repaint(); } + public void set_line(Line2D.Double line, double distance) { + this.line = line; + line_dist = distance; + queue_repaint(); + } + + private String line_dist() { + String format; + double distance = line_dist; + + if (AltosConvert.imperial_units) { + distance = AltosConvert.meters_to_feet(distance); + if (distance < 10000) { + format = "%4.0fft"; + } else { + distance /= 5280; + if (distance < 10) + format = "%5.3fmi"; + else if (distance < 100) + format = "%5.2fmi"; + else if (distance < 1000) + format = "%5.1fmi"; + else + format = "%5.0fmi"; + } + } else { + if (distance < 10000) { + format = "%4.0fm"; + } else { + distance /= 1000; + if (distance < 100) + format = "%5.2fkm"; + else if (distance < 1000) + format = "%5.1fkm"; + else + format = "%5.0fkm"; + } + } + return String.format(format, distance); + } + public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; AltosPoint prev = null; @@ -143,7 +188,7 @@ public class AltosSiteMapTile extends JComponent { float x = getWidth() / 2.0f; float y = getHeight() / 2.0f; x = x - (float) bounds.getWidth() / 2.0f; - y = y - (float) bounds.getHeight() / 2.0f; + y = y + (float) bounds.getHeight() / 2.0f; g2d.setColor(Color.BLACK); g2d.drawString(message, x, y); } @@ -171,6 +216,27 @@ public class AltosSiteMapTile extends JComponent { g2d.setColor(Color.BLACK); draw_circle(g2d, landed); } + + if (line != null) { + g2d.setColor(Color.BLUE); + g2d.draw(line); + + String message = line_dist(); + g2d.setFont(font); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + Rectangle2D bounds; + bounds = font.getStringBounds(message, g2d.getFontRenderContext()); + + float x = (float) line.x1; + float y = (float) line.y1 + (float) bounds.getHeight() / 2.0f; + + if (line.x1 < line.x2) { + x -= (float) bounds.getWidth() + 2.0f; + } else { + x += 2.0f; + } + g2d.drawString(message, x, y); + } } public synchronized void show(int state, Point2D.Double last_pt, Point2D.Double pt) diff --git a/altosuilib/GrabNDrag.java b/altosuilib/GrabNDrag.java index 5e5fdd52..4426f7a3 100644 --- a/altosuilib/GrabNDrag.java +++ b/altosuilib/GrabNDrag.java @@ -33,16 +33,23 @@ class GrabNDrag extends MouseInputAdapter { scroll.setAutoscrolls(true); } + public static boolean grab_n_drag(MouseEvent e) { + return e.getModifiers() == InputEvent.BUTTON1_MASK; + } + public void mousePressed(MouseEvent e) { - startPt.setLocation(e.getPoint()); + if (grab_n_drag(e)) + startPt.setLocation(e.getPoint()); } public void mouseDragged(MouseEvent e) { - int xd = e.getX() - startPt.x; - int yd = e.getY() - startPt.y; + if (grab_n_drag(e)) { + int xd = e.getX() - startPt.x; + int yd = e.getY() - startPt.y; - Rectangle r = scroll.getVisibleRect(); - r.x -= xd; - r.y -= yd; - scroll.scrollRectToVisible(r); + Rectangle r = scroll.getVisibleRect(); + r.x -= xd; + r.y -= yd; + scroll.scrollRectToVisible(r); + } } } -- cgit v1.2.3 From e6cfa25702b3dc1d492c5f1a4d0b4ba4831d30bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 May 2014 20:34:29 -0700 Subject: altosuilib: Decompress map images asynchronously and in parallel This speeds up loading map images from disk quite a bit, and keeps the UI responsive while that happens as well. Signed-off-by: Keith Packard --- altosuilib/AltosSiteMap.java | 64 +++++--- altosuilib/AltosSiteMapCache.java | 304 ++++++++++++++++++++------------------ altosuilib/AltosSiteMapImage.java | 82 ++++++++++ altosuilib/AltosSiteMapTile.java | 70 ++++++--- altosuilib/Makefile.am | 1 + 5 files changed, 340 insertions(+), 181 deletions(-) create mode 100644 altosuilib/AltosSiteMapImage.java (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index f22d9531..ee9b8c05 100644 --- a/altosuilib/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -50,7 +50,7 @@ class MapPoint { } } -public class AltosSiteMap extends JComponent implements AltosFlightDisplay, MouseMotionListener, MouseListener { +public class AltosSiteMap extends JComponent implements AltosFlightDisplay, MouseMotionListener, MouseListener, HierarchyBoundsListener { // preferred vertical step in a tile in naut. miles // will actually choose a step size between x and 2x, where this // is 1.5x @@ -213,11 +213,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous tile.set_status(AltosSiteMapCache.loading); int status = AltosSiteMapCache.fetch_map(pngfile, pngurl); if (status == AltosSiteMapCache.success) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - tile.load_map(pngfile); - } - }); + if (SwingUtilities.isEventDispatchThread()) + tile.load_map(pngfile); + else { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + tile.load_map(pngfile); + } + }); + } } else { tile.set_status(status); System.out.printf("# Failed to fetch file %s (status %d)\n", pngfile, status); @@ -298,7 +302,11 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous Thread thread = new Thread() { public void run() { init_map(offset, load_mode_cached|load_mode_uncached); - finishTileLater(tile, offset); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + addTileAt(tile, offset); + } + } ); } }; thread.start(); @@ -315,8 +323,6 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous } public void setBaseLocation(double lat, double lng) { - for (AltosSiteMapTile tile : mapTiles.values()) - tile.clearMap(); this.lat = lat; this.lon = lng; base_location_set = true; @@ -328,6 +334,8 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous private void initMaps(double lat, double lng) { setBaseLocation(lat, lng); + for (AltosSiteMapTile tile : mapTiles.values()) + tile.clearMap(); Thread thread = new Thread() { public void run() { for (Point k : mapTiles.keySet()) @@ -379,7 +387,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous JLabel zoom_label; public void set_zoom_label() { - zoom_label.setText(String.format("- %d -", zoom - default_zoom)); + zoom_label.setText(String.format("Zoom %d", zoom - default_zoom)); } public void set_zoom(int zoom) { @@ -524,15 +532,6 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous mapTiles.put(offset, tile); return tile; } - private void finishTileLater(final AltosSiteMapTile tile, - final Point offset) - { - SwingUtilities.invokeLater( new Runnable() { - public void run() { - addTileAt(tile, offset); - } - } ); - } private void ensureTilesAround(Point base_offset) { for (int x = -radius; x <= radius; x++) { @@ -629,6 +628,14 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous } } + static void debug_component(Component who, String where) { +// Rectangle r = who.getBounds(); +// int x = r.x / px_size; +// int y = r.y / px_size; +// +// System.out.printf ("%3d, %3d: %s\n", x, y, where); + } + LatLng latlng(MouseEvent e) { if (!base_location_set) return null; @@ -672,6 +679,24 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous public void mouseReleased(MouseEvent e) { } + public void set_cache_size() { + Rectangle r = comp.getVisibleRect(); + + int width_tiles = (r.width + 2*px_size) / px_size; + int height_tiles = (r.height + 2*px_size) / px_size; + int tiles = width_tiles * height_tiles; + AltosSiteMapCache.set_cache_size(tiles); + } + + /* HierarchyBoundsListener methods */ + public void ancestorMoved(HierarchyEvent e) { + set_cache_size(); + } + + public void ancestorResized(HierarchyEvent e) { + set_cache_size(); + } + JScrollPane pane = new JScrollPane(); public AltosSiteMap(int in_radius) { @@ -681,6 +706,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous comp.addMouseMotionListener(this); comp.addMouseListener(this); + comp.addHierarchyBoundsListener(this); GrabNDrag scroller = new GrabNDrag(comp); diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index 42914deb..6e6046bc 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -24,62 +24,6 @@ import java.awt.*; import java.io.*; import java.net.*; -class AltosCacheImage { - Component component; - File file; - VolatileImage image; - int width; - int height; - long used; - - public void load_image() throws IOException { - BufferedImage bimg = ImageIO.read(file); - if (bimg == null) - throw new IOException("Can't load image file"); - Graphics2D g = image.createGraphics(); - g.drawImage(bimg, 0, 0, null); - bimg.flush(); - bimg = null; - } - - public Image validate() { - int returnCode; - - if (image != null) - returnCode = image.validate(component.getGraphicsConfiguration()); - else - returnCode = VolatileImage.IMAGE_INCOMPATIBLE; - if (returnCode == VolatileImage.IMAGE_RESTORED) { - try { - load_image(); - } catch (IOException e) { - return null; - } - } else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) { - image = component.createVolatileImage(width, height); - try { - load_image(); - } catch (IOException e) { - return null; - } - } - return image; - } - - public void flush() { - image.flush(); - } - - public AltosCacheImage(Component component, File file, int w, int h) throws IOException { - this.component = component; - this.file = file; - width = w; - height = h; - image = component.createVolatileImage(w, h); - used = 0; - } -} - public class AltosSiteMapCache { static final long google_maps_ratelimit_ms = 1200; // Google limits static map queries to 50 per minute per IP, so @@ -99,121 +43,197 @@ public class AltosSiteMapCache { static boolean forbidden_set = false; static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; - public static synchronized int fetch_map(File file, String url) { + static private Object fetch_lock = new Object(); + + public static int fetch_map(File file, String url) { if (file.exists()) return success; if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) return forbidden; - URL u; - long startTime = System.nanoTime(); + synchronized (fetch_lock) { + URL u; + long startTime = System.nanoTime(); - try { - u = new URL(url); - } catch (java.net.MalformedURLException e) { - return bad_request; - } + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return bad_request; + } - byte[] data; - URLConnection uc = null; - try { - uc = u.openConnection(); - String type = uc.getContentType(); - int contentLength = uc.getContentLength(); - if (uc instanceof HttpURLConnection) { - int response = ((HttpURLConnection) uc).getResponseCode(); - switch (response) { - case HttpURLConnection.HTTP_FORBIDDEN: - case HttpURLConnection.HTTP_PAYMENT_REQUIRED: - case HttpURLConnection.HTTP_UNAUTHORIZED: - forbidden_time = System.nanoTime(); - forbidden_set = true; - return forbidden; + byte[] data; + URLConnection uc = null; + try { + uc = u.openConnection(); + String type = uc.getContentType(); + int contentLength = uc.getContentLength(); + if (uc instanceof HttpURLConnection) { + int response = ((HttpURLConnection) uc).getResponseCode(); + switch (response) { + case HttpURLConnection.HTTP_FORBIDDEN: + case HttpURLConnection.HTTP_PAYMENT_REQUIRED: + case HttpURLConnection.HTTP_UNAUTHORIZED: + forbidden_time = System.nanoTime(); + forbidden_set = true; + return forbidden; + } } - } - InputStream in = new BufferedInputStream(uc.getInputStream()); - int bytesRead = 0; - int offset = 0; - data = new byte[contentLength]; - while (offset < contentLength) { - bytesRead = in.read(data, offset, data.length - offset); - if (bytesRead == -1) - break; - offset += bytesRead; - } - in.close(); + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); - if (offset != contentLength) + if (offset != contentLength) + return failed; + + } catch (IOException e) { return failed; + } - } catch (IOException e) { - return failed; - } + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return bad_request; + } catch (IOException e) { + if (file.exists()) + file.delete(); + return bad_request; + } - try { - FileOutputStream out = new FileOutputStream(file); - out.write(data); - out.flush(); - out.close(); - } catch (FileNotFoundException e) { - return bad_request; - } catch (IOException e) { - if (file.exists()) - file.delete(); - return bad_request; + long duration_ms = (System.nanoTime() - startTime) / 1000000; + if (duration_ms < google_maps_ratelimit_ms) { + try { + Thread.sleep(google_maps_ratelimit_ms - duration_ms); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + return success; } + } - long duration_ms = (System.nanoTime() - startTime) / 1000000; - if (duration_ms < google_maps_ratelimit_ms) { - try { - Thread.sleep(google_maps_ratelimit_ms - duration_ms); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + static final int min_cache_size = 9; + static final int max_cache_size = 24; + + static int cache_size = min_cache_size; + + static AltosSiteMapImage[] images = new AltosSiteMapImage[cache_size]; + + static Object cache_lock = new Object(); + + public static void set_cache_size(int new_size) { + if (new_size < min_cache_size) + new_size = min_cache_size; + if (new_size > max_cache_size) + new_size = max_cache_size; + if (new_size == cache_size) + return; + + synchronized(cache_lock) { + AltosSiteMapImage[] new_images = new AltosSiteMapImage[new_size]; + + for (int i = 0; i < cache_size; i++) { + if (i < new_size) + new_images[i] = images[i]; + else + images[i].flush(); } + images = new_images; + cache_size = new_size; } + } - return success; + static long used; + + private static Point tile_loc(AltosSiteMapTile tile) { + Rectangle r = tile.getBounds(); + int x = r.x / 512; + int y = r.y / 512; + + return new Point (x, y); } - static final int cache_size = 12; + private static void dump_cache() { + int min_x = 1000, max_x = -1000, min_y = 1000, max_y = -1000; - static AltosCacheImage[] images; + for (int i = 0; i < cache_size; i++) { + AltosSiteMapImage image = images[i]; + if (image != null) { + Point p = tile_loc(image.tile); + min_x = min_x < p.x ? min_x : p.x; + max_x = max_x > p.x ? max_x : p.x; + min_y = min_y < p.y ? min_y : p.y; + max_y = max_y > p.y ? max_y : p.y; + System.out.printf ("entry %d %d,%d used %d\n", i, p.x, p.y, image.used); + } else { + System.out.printf ("entry %d empty\n", i); + } + } - static long used; + int[][] map = new int[max_x - min_x + 1][max_y - min_y + 1]; + for (int i = 0; i < cache_size; i++) { + AltosSiteMapImage image = images[i]; + if (image != null) { + Point p = tile_loc(image.tile); + map[p.x - min_x][p.y - min_y]++; + } + } - public static Image get_image(Component component, File file, int width, int height) { + for (int y = min_y; y <= max_y; y++) { + for (int x = min_x; x <= max_x; x++) + System.out.printf (" %2d", map[x - min_x][y - min_y]); + System.out.printf("\n"); + } + } + + public static AltosSiteMapImage get_image(AltosSiteMapTile tile, File file, int width, int height) { int oldest = -1; long age = used; - AltosCacheImage image; - if (images == null) - images = new AltosCacheImage[cache_size]; - for (int i = 0; i < cache_size; i++) { - image = images[i]; - if (image == null) { - oldest = i; - break; + synchronized(cache_lock) { + AltosSiteMapImage image = null; + for (int i = 0; i < cache_size; i++) { + image = images[i]; + + if (image == null) { + oldest = i; + break; + } + if (image.tile == tile && file.equals(image.file)) { + image.used = used++; + return image; + } + if (image.used < age) { + oldest = i; + age = image.used; + } } - if (image.component == component && file.equals(image.file)) { + + try { + image = new AltosSiteMapImage(tile, file, width, height); image.used = used++; - return image.validate(); - } - if (image.used < age) { - oldest = i; - age = image.used; + if (images[oldest] != null) { +// dump_cache(); + AltosSiteMap.debug_component(images[oldest].tile, "replacing cache"); + AltosSiteMap.debug_component(tile, "replaced cache"); + images[oldest].flush(); + } + images[oldest] = image; + return image; + } catch (IOException e) { + return null; } } - - try { - image = new AltosCacheImage(component, file, width, height); - image.used = used++; - if (images[oldest] != null) - images[oldest].flush(); - images[oldest] = image; - return image.validate(); - } catch (IOException e) { - return null; - } } } diff --git a/altosuilib/AltosSiteMapImage.java b/altosuilib/AltosSiteMapImage.java new file mode 100644 index 00000000..f08c0b26 --- /dev/null +++ b/altosuilib/AltosSiteMapImage.java @@ -0,0 +1,82 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.image.*; +import javax.imageio.ImageIO; +import javax.swing.*; +import java.io.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosSiteMapImage { + AltosSiteMapTile tile; + File file; + BufferedImage image; + int width; + int height; + long used; + + Thread load_thread; + + public boolean validate() { + if (image != null) { + AltosSiteMap.debug_component(tile, "valid"); + return true; + } else { + AltosSiteMap.debug_component(tile, "loading"); + load_thread = new Thread() { + public void run() { + image = null; + try { + image = ImageIO.read(file); + } catch (Exception e) { + } + SwingUtilities.invokeLater( new Runnable() { + public void run() { + AltosSiteMap.debug_component(tile, "later"); + Graphics2D g2d = (Graphics2D) tile.getGraphics(); + tile.paint_graphics(g2d, image); + load_thread = null; + } + }); + } + }; + load_thread.start(); + return false; + } + } + + public void flush() { + if (load_thread == null) { + AltosSiteMap.debug_component(tile, "flush"); + image.flush(); + image = null; + } + } + + public AltosSiteMapImage (AltosSiteMapTile tile, File file, int w, int h) throws IOException { + this.tile = tile; + this.file = file; + width = w; + height = h; + image = null; + used = 0; + } +} + diff --git a/altosuilib/AltosSiteMapTile.java b/altosuilib/AltosSiteMapTile.java index 09f184a3..136fbd7a 100644 --- a/altosuilib/AltosSiteMapTile.java +++ b/altosuilib/AltosSiteMapTile.java @@ -51,11 +51,15 @@ public class AltosSiteMapTile extends JComponent { LinkedList points; public synchronized void queue_repaint() { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - repaint(); - } - }); + if (SwingUtilities.isEventDispatchThread()) + repaint(); + else { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + repaint(); + } + }); + } } public void load_map(File pngFile) { @@ -68,13 +72,14 @@ public class AltosSiteMapTile extends JComponent { public void set_font(Font font) { this.font = font; this.status = AltosSiteMapCache.success; - queue_repaint(); } public void set_status(int status) { - file = null; - this.status = status; - queue_repaint(); + if (status != this.status || file != null) { + file = null; + this.status = status; + queue_repaint(); + } } public void clearMap() { @@ -83,7 +88,6 @@ public class AltosSiteMapTile extends JComponent { points = null; file = null; status = AltosSiteMapCache.success; - queue_repaint(); line = null; } @@ -151,17 +155,14 @@ public class AltosSiteMapTile extends JComponent { return String.format(format, distance); } - public void paint(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - AltosPoint prev = null; - Image img = null; + boolean painting; - if (file != null) - img = AltosSiteMapCache.get_image(this, file, px_size, px_size); - - if (img != null) { - g2d.drawImage(img, 0, 0, null); + public void paint_graphics(Graphics2D g2d, Image image) { + if (image != null) { + AltosSiteMap.debug_component(this, "paint_graphics"); + g2d.drawImage(image, 0, 0, null); } else { + AltosSiteMap.debug_component(this, "erase_graphics"); g2d.setColor(Color.GRAY); g2d.fillRect(0, 0, getWidth(), getHeight()); String message = null; @@ -199,6 +200,7 @@ public class AltosSiteMapTile extends JComponent { g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); if (points != null) { + AltosPoint prev = null; for (AltosPoint point : points) { if (prev != null) { if (0 <= point.state && point.state < stateColors.length) @@ -237,9 +239,37 @@ public class AltosSiteMapTile extends JComponent { } g2d.drawString(message, x, y); } + painting = false; + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Image image = null; + boolean queued = false; + + if (painting) { + AltosSiteMap.debug_component(this, "already painting"); + return; + } + AltosSiteMap.debug_component(this, "paint"); + + if (file != null) { + AltosSiteMapImage aimage; + + aimage = AltosSiteMapCache.get_image(this, file, px_size, px_size); + if (aimage != null) { + if (aimage.validate()) + image = aimage.image; + else + queued = true; + } + } + if (!queued) + paint_graphics(g2d, image); + painting = queued; } - public synchronized void show(int state, Point2D.Double last_pt, Point2D.Double pt) + public void show(int state, Point2D.Double last_pt, Point2D.Double pt) { if (points == null) points = new LinkedList(); diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index b7d624e2..10b756b8 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -37,6 +37,7 @@ altosuilib_JAVA = \ AltosSiteMapCache.java \ AltosSiteMapPreload.java \ AltosSiteMapTile.java \ + AltosSiteMapImage.java \ AltosVoice.java \ AltosDisplayThread.java \ AltosFreqList.java -- cgit v1.2.3 From 3773e89c47d356c4df58edc5725c33bca89b9605 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 00:42:24 -0700 Subject: altosuilib: Add google maps API key, configured with -with-google-key This places the actual key outside of the repository, allowing the user to configure the name of the file containing the key. By default, this pulls the key from $HOME/altusmetrumllc/google-maps-api-key. With the key present, there are no longer any rate limits to loading map data. Signed-off-by: Keith Packard --- altosuilib/AltosSiteMap.java | 15 ++-- altosuilib/AltosSiteMapCache.java | 143 +++++++++++++++++++++----------------- altosuilib/AltosUIVersion.java.in | 6 ++ configure.ac | 17 ++++- 4 files changed, 110 insertions(+), 71 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index ee9b8c05..d9ea564c 100644 --- a/altosuilib/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -263,8 +263,6 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous AltosSiteMap asm = new AltosSiteMap(true); asm.centre = asm.getBaseLocation(lat, lng); - //Point2D.Double p = new Point2D.Double(); - //Point2D.Double p2; int dx = -w/2, dy = -h/2; for (int y = dy; y < h+dy; y++) { for (int x = dx; x < w+dx; x++) { @@ -334,8 +332,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous private void initMaps(double lat, double lng) { setBaseLocation(lat, lng); - for (AltosSiteMapTile tile : mapTiles.values()) + for (AltosSiteMapTile tile : mapTiles.values()) { tile.clearMap(); + tile.set_status(AltosSiteMapCache.loading); + } Thread thread = new Thread() { public void run() { for (Point k : mapTiles.keySet()) @@ -369,8 +369,13 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous format_string = "jpg"; else format_string = "png32"; - return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s", - lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string); + + if (AltosUIVersion.has_google_maps_api_key()) + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s&key=%s", + lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string, AltosUIVersion.google_maps_api_key); + else + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s", + lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string); } boolean initialised = false; diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index 6e6046bc..c4316dab 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -45,6 +45,67 @@ public class AltosSiteMapCache { static private Object fetch_lock = new Object(); + private static int fetch_one(File file, String url) { + URL u; + + System.out.printf("Loading URL %s\n", url); + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return bad_request; + } + + byte[] data; + URLConnection uc = null; + try { + uc = u.openConnection(); + String type = uc.getContentType(); + int contentLength = uc.getContentLength(); + if (uc instanceof HttpURLConnection) { + int response = ((HttpURLConnection) uc).getResponseCode(); + switch (response) { + case HttpURLConnection.HTTP_FORBIDDEN: + case HttpURLConnection.HTTP_PAYMENT_REQUIRED: + case HttpURLConnection.HTTP_UNAUTHORIZED: + forbidden_time = System.nanoTime(); + forbidden_set = true; + return forbidden; + } + } + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); + + if (offset != contentLength) + return failed; + + } catch (IOException e) { + return failed; + } + + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return bad_request; + } catch (IOException e) { + if (file.exists()) + file.delete(); + return bad_request; + } + return success; + } + public static int fetch_map(File file, String url) { if (file.exists()) return success; @@ -52,75 +113,27 @@ public class AltosSiteMapCache { if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) return forbidden; - synchronized (fetch_lock) { - URL u; - long startTime = System.nanoTime(); - - try { - u = new URL(url); - } catch (java.net.MalformedURLException e) { - return bad_request; - } - - byte[] data; - URLConnection uc = null; - try { - uc = u.openConnection(); - String type = uc.getContentType(); - int contentLength = uc.getContentLength(); - if (uc instanceof HttpURLConnection) { - int response = ((HttpURLConnection) uc).getResponseCode(); - switch (response) { - case HttpURLConnection.HTTP_FORBIDDEN: - case HttpURLConnection.HTTP_PAYMENT_REQUIRED: - case HttpURLConnection.HTTP_UNAUTHORIZED: - forbidden_time = System.nanoTime(); - forbidden_set = true; - return forbidden; + int status = bad_request; + + if (!AltosUIVersion.has_google_maps_api_key()) { + synchronized (fetch_lock) { + long startTime = System.nanoTime(); + status = fetch_one(file, url); + if (status == success) { + long duration_ms = (System.nanoTime() - startTime) / 1000000; + if (duration_ms < google_maps_ratelimit_ms) { + try { + Thread.sleep(google_maps_ratelimit_ms - duration_ms); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } } - InputStream in = new BufferedInputStream(uc.getInputStream()); - int bytesRead = 0; - int offset = 0; - data = new byte[contentLength]; - while (offset < contentLength) { - bytesRead = in.read(data, offset, data.length - offset); - if (bytesRead == -1) - break; - offset += bytesRead; - } - in.close(); - - if (offset != contentLength) - return failed; - - } catch (IOException e) { - return failed; - } - - try { - FileOutputStream out = new FileOutputStream(file); - out.write(data); - out.flush(); - out.close(); - } catch (FileNotFoundException e) { - return bad_request; - } catch (IOException e) { - if (file.exists()) - file.delete(); - return bad_request; - } - - long duration_ms = (System.nanoTime() - startTime) / 1000000; - if (duration_ms < google_maps_ratelimit_ms) { - try { - Thread.sleep(google_maps_ratelimit_ms - duration_ms); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } } - return success; + } else { + status = fetch_one(file, url); } + return status; } static final int min_cache_size = 9; diff --git a/altosuilib/AltosUIVersion.java.in b/altosuilib/AltosUIVersion.java.in index 3f629560..0edb5c04 100644 --- a/altosuilib/AltosUIVersion.java.in +++ b/altosuilib/AltosUIVersion.java.in @@ -19,4 +19,10 @@ package org.altusmetrum.altosuilib_2; public class AltosUIVersion { public final static String version = "@VERSION@"; + + public final static String google_maps_api_key = @GOOGLEKEY@; + + static boolean has_google_maps_api_key() { + return google_maps_api_key != null && google_maps_api_key.length() > 1; + } } diff --git a/configure.ac b/configure.ac index d2d87754..dfbe59bc 100644 --- a/configure.ac +++ b/configure.ac @@ -162,6 +162,20 @@ AM_CONDITIONAL(FATINSTALL, [test "x$FATDIR" != "xnone"]) AC_SUBST(FATDIR) +AC_ARG_WITH(google-key, AS_HELP_STRING([--with-google-key=PATH], + [Set the file to read the google maps API key from (defaults to ~/altusmetrumllc/google-maps-api-key)]), + [GOOGLEKEYFILE=$withval], [GOOGLEKEYFILE=$HOME/altusmetrumllc/google-maps-api-key]) + +if test -r "$GOOGLEKEYFILE" -a -s "$GOOGLEKEYFILE"; then + GOOGLEKEY='"'`cat "$GOOGLEKEYFILE"`'"' + HAVE_GOOGLE_KEY="yes" +else + GOOGLEKEY='null' + HAVE_GOOGLE_KEY="no" +fi + +AC_SUBST(GOOGLEKEY) + AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S @@ -537,11 +551,12 @@ echo " STlink support..............: ${HAVE_STLINK}" echo " Local pdclib................: ${HAVE_PDCLIB}" echo " i386 and amd64 libaltos.....: ${MULTI_ARCH}" echo "" -echo " Java paths" +echo " Java" echo " freetts.....................: ${FREETTS}" echo " jfreechart..................: ${JFREECHART}" echo " jcommon.....................: ${JCOMMON}" echo " JVM include.................: ${JVM_INCLUDE}" +echo " Google maps API key.........: ${HAVE_GOOGLE_KEY}" if test x${ANDROID_SDK} != "xno"; then echo "" echo " Android path" -- cgit v1.2.3 From 5c3991768d3cb17fc99ad32b2d6d8d11f0e37dfa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 02:18:41 -0700 Subject: altosuilib: Remove debug printf in AltosSiteMapCache Signed-off-by: Keith Packard --- altosuilib/AltosSiteMapCache.java | 1 - 1 file changed, 1 deletion(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index c4316dab..7f436ef0 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -48,7 +48,6 @@ public class AltosSiteMapCache { private static int fetch_one(File file, String url) { URL u; - System.out.printf("Loading URL %s\n", url); try { u = new URL(url); } catch (java.net.MalformedURLException e) { -- cgit v1.2.3 From 52ce41952c5a3c31532fa4f0d1b3155a162b76f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 10:16:38 -0700 Subject: altosuilib: Update map preloading UI to include zoom and maptypes This lets you specify precisely which maps to load. Signed-off-by: Keith Packard --- altosuilib/AltosSiteMap.java | 166 +++++++++++++++++++++++------------- altosuilib/AltosSiteMapCache.java | 2 + altosuilib/AltosSiteMapImage.java | 7 +- altosuilib/AltosSiteMapPreload.java | 139 +++++++++++++++++++++++++----- altosuilib/AltosSiteMapTile.java | 23 ++--- 5 files changed, 245 insertions(+), 92 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index d9ea564c..461886c7 100644 --- a/altosuilib/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -74,7 +74,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous "terrain" }; - static final String[] maptype_labels = { + public static final String[] maptype_labels = { "Hybrid", "Roadmap", "Satellite", @@ -240,7 +240,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous String pngurl; } - public AltosSiteMapPrefetch prefetchMap(int x, int y) { + private AltosSiteMapPrefetch prefetchMap(int x, int y) { AltosSiteMapPrefetch prefetch = new AltosSiteMapPrefetch(); LatLng map_latlng = latlng( -centre.x + x*px_size + px_size/2, @@ -257,28 +257,34 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous return prefetch; } - public static void prefetchMaps(double lat, double lng) { - int w = AltosSiteMapPreload.width; - int h = AltosSiteMapPreload.height; + public static void prefetchMaps(double lat, double lng, int radius, int maptypes, int min_zoom, int max_zoom) { AltosSiteMap asm = new AltosSiteMap(true); - asm.centre = asm.getBaseLocation(lat, lng); - - int dx = -w/2, dy = -h/2; - for (int y = dy; y < h+dy; y++) { - for (int x = dx; x < w+dx; x++) { - AltosSiteMapPrefetch prefetch = asm.prefetchMap(x, y); - switch (prefetch.result) { - case 1: - System.out.printf("Already have %s\n", prefetch.pngfile); - break; - case 0: - System.out.printf("Fetched map %s\n", prefetch.pngfile); - break; - case -1: - System.out.printf("# Failed to fetch file %s\n", prefetch.pngfile); - System.out.printf(" wget -O '%s' ''\n", - prefetch.pngfile, prefetch.pngurl); - break; + + for (int z = min_zoom; z <= max_zoom; z++) { + asm.zoom = z; + asm.set_radius(radius); + asm.centre = asm.getBaseLocation(lat, lng); + for (int t = maptype_hybrid; t <= maptype_terrain; t++) { + if ((maptypes & (1 << t)) !=0) { + asm.maptype = t; + for (int y = -radius; y <= radius; y++) { + for (int x = -radius; x <= radius; x++) { + AltosSiteMapPrefetch prefetch = asm.prefetchMap(x, y); + switch (prefetch.result) { + case 1: + System.out.printf("Already have %s\n", prefetch.pngfile); + break; + case 0: + System.out.printf("Fetched map %s\n", prefetch.pngfile); + break; + case -1: + System.out.printf("# Failed to fetch file %s\n", prefetch.pngfile); + System.out.printf(" wget -O '%s' ''\n", + prefetch.pngfile, prefetch.pngurl); + break; + } + } + } } } } @@ -296,7 +302,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous return pngfile; } - public void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) { + private void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) { Thread thread = new Thread() { public void run() { init_map(offset, load_mode_cached|load_mode_uncached); @@ -318,6 +324,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous circle_set = false; points = new LinkedList(); line_start = line_end = null; + for (AltosSiteMapTile tile : mapTiles.values()) { + tile.clearMap(); + tile.set_status(AltosSiteMapCache.loading); + } } public void setBaseLocation(double lat, double lng) { @@ -382,7 +392,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous MapPoint last_point = null; int last_state = -1; - public void show(double lat, double lon) { + private void show(double lat, double lon) { System.out.printf ("show %g %g\n", lat, lon); return; // initMaps(lat, lon); @@ -391,15 +401,17 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous JLabel zoom_label; - public void set_zoom_label() { + private void set_zoom_label() { zoom_label.setText(String.format("Zoom %d", zoom - default_zoom)); } public void set_zoom(int zoom) { if (min_zoom <= zoom && zoom <= max_zoom) { this.zoom = zoom; - if (base_location_set) + if (base_location_set) { + set_tiles(); initMaps(lat, lon); + } redraw(); set_zoom_label(); } @@ -409,7 +421,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous return zoom; } - public void draw(MapPoint last_point, MapPoint point) { + public void set_maptype(int type) { + maptype = type; + maptype_combo.setSelectedIndex(type); + if (base_location_set) + initMaps(lat, lon); + redraw(); + } + + private void draw(MapPoint last_point, MapPoint point) { boolean force_ensure = false; if (last_point == null) { force_ensure = true; @@ -449,7 +469,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous } } - public void redraw() { + private void redraw() { MapPoint last_point = null; for (MapPoint point : points) { @@ -496,7 +516,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous last_point = point; } - public void centre(Point2D.Double pt) { + private void centre(Point2D.Double pt) { Rectangle r = comp.getVisibleRect(); Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); int dx = (int)copt.x - r.width/2 - r.x; @@ -508,7 +528,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous comp.scrollRectToVisible(r); } - public void centre(AltosState state) { + private void centre(AltosState state) { if (!state.gps.locked && state.gps.nsat < 4) return; centre(pt(state.gps.lat, state.gps.lon)); @@ -550,6 +570,32 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous } } + private void set_tiles() { + for (int x = -radius; x <= radius; x++) { + for (int y = -radius; y <= radius; y++) { + Point offset = new Point(x, y); + if (mapTiles.containsKey(offset)) + continue; + AltosSiteMapTile t = createTile(offset); + addTileAt(t, offset); + } + } + for (Point offset : mapTiles.keySet()) { + if (offset.x < -radius || offset.x > radius || + offset.y < -radius || offset.y > radius) + { + removeTileAt(offset); + } + } + } + + public void set_radius(int radius) { + if (radius != this.radius) { + this.radius = radius; + set_tiles(); + } + } + private Point topleft = new Point(0,0); private void scrollRocketToVisible(Point2D.Double pt) { Rectangle r = comp.getVisibleRect(); @@ -573,18 +619,11 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous return; } - boolean review = false; - Rectangle r = comp.getVisibleRect(); - if (offset.x < topleft.x) { - r.x += (topleft.x - offset.x) * px_size; + if (offset.x < topleft.x) topleft.x = offset.x; - review = true; - } - if (offset.y < topleft.y) { - r.y += (topleft.y - offset.y) * px_size; + if (offset.y < topleft.y) topleft.y = offset.y; - review = true; - } + GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; @@ -596,9 +635,6 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous layout.setConstraints(tile, c); comp.add(tile); -// if (review) { -// comp.scrollRectToVisible(r); -// } } private AltosSiteMap(boolean knowWhatYouAreDoing) { @@ -607,6 +643,21 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous } } + private void removeTileAt(Point offset) { + AltosSiteMapTile tile = mapTiles.get(offset); + + mapTiles.remove(offset); + comp.remove(tile); + + topleft = new Point(MAX_TILE_DELTA, MAX_TILE_DELTA); + for (Point o : mapTiles.keySet()) { + if (o.x < topleft.x) + topleft.x = o.x; + if (o.y < topleft.y) + topleft.y = o.y; + } + } + JComponent comp; private GridBagLayout layout = new GridBagLayout(); @@ -634,11 +685,13 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous } static void debug_component(Component who, String where) { -// Rectangle r = who.getBounds(); -// int x = r.x / px_size; -// int y = r.y / px_size; -// -// System.out.printf ("%3d, %3d: %s\n", x, y, where); +/* + Rectangle r = who.getBounds(); + int x = r.x / px_size; + int y = r.y / px_size; + + System.out.printf ("%3d, %3d: %s\n", x, y, where); +*/ } LatLng latlng(MouseEvent e) { @@ -684,7 +737,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous public void mouseReleased(MouseEvent e) { } - public void set_cache_size() { + private void set_cache_size() { Rectangle r = comp.getVisibleRect(); int width_tiles = (r.width + 2*px_size) / px_size; @@ -704,6 +757,8 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous JScrollPane pane = new JScrollPane(); + JComboBox maptype_combo; + public AltosSiteMap(int in_radius) { radius = in_radius; @@ -717,13 +772,8 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous comp.setLayout(layout); - for (int x = -radius; x <= radius; x++) { - for (int y = -radius; y <= radius; y++) { - Point offset = new Point(x, y); - AltosSiteMapTile t = createTile(offset); - addTileAt(t, offset); - } - } + set_tiles(); + pane.setViewportView(comp); pane.setPreferredSize(new Dimension(500,500)); pane.setVisible(true); @@ -805,7 +855,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous c.weighty = 0; add(zoom_out, c); - final JComboBox maptype_combo = new JComboBox(maptype_labels); + maptype_combo = new JComboBox(maptype_labels); maptype_combo.setEditable(false); maptype_combo.setMaximumRowCount(maptype_combo.getItemCount()); diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index 7f436ef0..3e08e1b3 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -176,6 +176,7 @@ public class AltosSiteMapCache { return new Point (x, y); } +/* private static void dump_cache() { int min_x = 1000, max_x = -1000, min_y = 1000, max_y = -1000; @@ -208,6 +209,7 @@ public class AltosSiteMapCache { System.out.printf("\n"); } } +*/ public static AltosSiteMapImage get_image(AltosSiteMapTile tile, File file, int width, int height) { int oldest = -1; diff --git a/altosuilib/AltosSiteMapImage.java b/altosuilib/AltosSiteMapImage.java index f08c0b26..ae32418f 100644 --- a/altosuilib/AltosSiteMapImage.java +++ b/altosuilib/AltosSiteMapImage.java @@ -34,7 +34,7 @@ public class AltosSiteMapImage { Thread load_thread; - public boolean validate() { + public boolean validate(final int serial) { if (image != null) { AltosSiteMap.debug_component(tile, "valid"); return true; @@ -42,16 +42,15 @@ public class AltosSiteMapImage { AltosSiteMap.debug_component(tile, "loading"); load_thread = new Thread() { public void run() { - image = null; try { image = ImageIO.read(file); } catch (Exception e) { } SwingUtilities.invokeLater( new Runnable() { public void run() { - AltosSiteMap.debug_component(tile, "later"); + AltosSiteMap.debug_component(tile, file.toString()); Graphics2D g2d = (Graphics2D) tile.getGraphics(); - tile.paint_graphics(g2d, image); + tile.paint_graphics(g2d, image, serial); load_thread = null; } }); diff --git a/altosuilib/AltosSiteMapPreload.java b/altosuilib/AltosSiteMapPreload.java index 107b09f8..6b8066b3 100644 --- a/altosuilib/AltosSiteMapPreload.java +++ b/altosuilib/AltosSiteMapPreload.java @@ -206,18 +206,15 @@ class AltosSites extends Thread { } } -public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener, ItemListener { +public class AltosSiteMapPreload extends AltosUIFrame implements ActionListener, ItemListener { AltosUIFrame owner; AltosSiteMap map; AltosMapPos lat; AltosMapPos lon; - final static int radius = 5; - final static int width = (radius * 2 + 1); - final static int height = (radius * 2 + 1); - JProgressBar pbar; + int pbar_max; AltosSites sites; JLabel site_list_label; @@ -227,6 +224,15 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener boolean loading; JButton close_button; + JCheckBox[] maptypes = new JCheckBox[AltosSiteMap.maptype_terrain - AltosSiteMap.maptype_hybrid + 1]; + + JComboBox min_zoom; + JComboBox max_zoom; + JComboBox radius; + + Integer[] zooms = { -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 }; + Integer[] radii = { 1, 2, 3, 4, 5 }; + static final String[] lat_hemi_names = { "N", "S" }; static final String[] lon_hemi_names = { "E", "W" }; @@ -234,15 +240,16 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener int n; String s; - public updatePbar(int x, int y, String in_s) { - n = (x + radius) + (y + radius) * width + 1; + public updatePbar(int n, String in_s) { + this.n = n; s = in_s; } public void run() { pbar.setValue(n); pbar.setString(s); - if (n < width * height) { + if (n < pbar_max) { + pbar.setMaximum(pbar_max); pbar.setValue(n); pbar.setString(s); } else { @@ -258,17 +265,54 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener AltosSiteMap map; - public bgLoad(AltosSiteMap in_map) { + double lat, lon; + + int types = 0; + int r; + + int min_z = (Integer) min_zoom.getSelectedItem(); + int max_z = (Integer) max_zoom.getSelectedItem(); + + public bgLoad(AltosSiteMap in_map, double lat, double lon) { map = in_map; + this.lat = lat; + this.lon = lon; + if (max_z < min_z) + max_z = min_z; + int ntype = 0; + for (int t = AltosSiteMap.maptype_hybrid; t <= AltosSiteMap.maptype_terrain; t++) + if (maptypes[t].isSelected()) { + types |= (1 << t); + ntype++; + } + if (ntype == 0) { + types |= (1 << AltosSiteMap.maptype_hybrid); + ntype = 1; + } + r = (Integer) radius.getSelectedItem(); + pbar_max = (max_z - min_z + 1) * ntype * (r * 2 + 1) * (r * 2 + 1); } public void run() { - for (int y = -map.radius; y <= map.radius; y++) { - for (int x = -map.radius; x <= map.radius; x++) { - File pngfile; - pngfile = map.init_map(new Point(x,y), - AltosSiteMap.load_mode_cached|AltosSiteMap.load_mode_uncached); - SwingUtilities.invokeLater(new updatePbar(x, y, pngfile.toString())); + int i = 0; + for (int z = min_z; z <= max_z; z++) { + for (int t = AltosSiteMap.maptype_hybrid; t <= AltosSiteMap.maptype_terrain; t++) { + if ((types & (1 << t)) == 0) + continue; + map.clear_base_location(); + map.set_zoom(z + AltosSiteMap.default_zoom); + map.set_maptype(t); + map.set_radius(r); + map.setBaseLocation(lat, lon); + map.draw_circle(lat, lon); + for (int y = -r; y <= r; y++) { + for (int x = -r; x <= r; x++) { + File pngfile; + pngfile = map.init_map(new Point(x,y), + AltosSiteMap.load_mode_cached|AltosSiteMap.load_mode_uncached); + SwingUtilities.invokeLater(new updatePbar(++i, pngfile.toString())); + } + } } } } @@ -310,7 +354,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener map.setBaseLocation(latitude,longitude); map.draw_circle(latitude,longitude); loading = true; - bgLoad thread = new bgLoad(map); + bgLoad thread = new bgLoad(map, latitude, longitude); thread.start(); } catch (NumberFormatException ne) { load_button.setSelected(false); @@ -326,9 +370,11 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); + setTitle("AltOS Load Maps"); + pane.setLayout(new GridBagLayout()); - map = new AltosSiteMap(radius); + map = new AltosSiteMap(2); c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; @@ -338,14 +384,14 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener c.gridx = 0; c.gridy = 0; - c.gridwidth = 2; + c.gridwidth = 10; c.anchor = GridBagConstraints.CENTER; pane.add(map, c); pbar = new JProgressBar(); pbar.setMinimum(0); - pbar.setMaximum(width * height); + pbar.setMaximum(1); pbar.setValue(0); pbar.setString(""); pbar.setStringPainted(true); @@ -358,7 +404,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener c.gridx = 0; c.gridy = 1; - c.gridwidth = 2; + c.gridwidth = 10; pane.add(pbar, c); @@ -462,6 +508,59 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener pane.add(close_button, c); + JLabel types_label = new JLabel("Map Types"); + c.gridx = 2; + c.gridwidth = 2; + c.gridy = 2; + pane.add(types_label, c); + + c.gridwidth = 1; + + for (int type = AltosSiteMap.maptype_hybrid; type <= AltosSiteMap.maptype_terrain; type++) { + maptypes[type] = new JCheckBox(AltosSiteMap.maptype_labels[type], + type == AltosSiteMap.maptype_hybrid); + c.gridx = 2 + (type >> 1); + c.fill = GridBagConstraints.HORIZONTAL; + c.gridy = (type & 1) + 3; + pane.add(maptypes[type], c); + } + + JLabel min_zoom_label = new JLabel("Minimum Zoom"); + c.gridx = 4; + c.gridy = 2; + pane.add(min_zoom_label, c); + + min_zoom = new JComboBox(zooms); + min_zoom.setSelectedItem(zooms[10]); + min_zoom.setEditable(false); + c.gridx = 5; + c.gridy = 2; + pane.add(min_zoom, c); + + JLabel max_zoom_label = new JLabel("Maximum Zoom"); + c.gridx = 4; + c.gridy = 3; + pane.add(max_zoom_label, c); + + max_zoom = new JComboBox(zooms); + max_zoom.setSelectedItem(zooms[14]); + max_zoom.setEditable(false); + c.gridx = 5; + c.gridy = 3; + pane.add(max_zoom, c); + + JLabel radius_label = new JLabel("Tile Radius"); + c.gridx = 4; + c.gridy = 4; + pane.add(radius_label, c); + + radius = new JComboBox(radii); + radius.setSelectedItem(radii[4]); + radius.setEditable(false); + c.gridx = 5; + c.gridy = 4; + pane.add(radius, c); + pack(); setLocationRelativeTo(owner); setVisible(true); diff --git a/altosuilib/AltosSiteMapTile.java b/altosuilib/AltosSiteMapTile.java index 136fbd7a..f8b924a8 100644 --- a/altosuilib/AltosSiteMapTile.java +++ b/altosuilib/AltosSiteMapTile.java @@ -155,9 +155,16 @@ public class AltosSiteMapTile extends JComponent { return String.format(format, distance); } - boolean painting; + int painting_serial; + int painted_serial; + + public void paint_graphics(Graphics2D g2d, Image image, int serial) { + + if (serial < painted_serial) + return; + + painted_serial = serial; - public void paint_graphics(Graphics2D g2d, Image image) { if (image != null) { AltosSiteMap.debug_component(this, "paint_graphics"); g2d.drawImage(image, 0, 0, null); @@ -239,7 +246,6 @@ public class AltosSiteMapTile extends JComponent { } g2d.drawString(message, x, y); } - painting = false; } public void paint(Graphics g) { @@ -247,26 +253,23 @@ public class AltosSiteMapTile extends JComponent { Image image = null; boolean queued = false; - if (painting) { - AltosSiteMap.debug_component(this, "already painting"); - return; - } AltosSiteMap.debug_component(this, "paint"); + ++painting_serial; + if (file != null) { AltosSiteMapImage aimage; aimage = AltosSiteMapCache.get_image(this, file, px_size, px_size); if (aimage != null) { - if (aimage.validate()) + if (aimage.validate(painting_serial)) image = aimage.image; else queued = true; } } if (!queued) - paint_graphics(g2d, image); - painting = queued; + paint_graphics(g2d, image, painting_serial); } public void show(int state, Point2D.Double last_pt, Point2D.Double pt) -- cgit v1.2.3 From 1e5807ef428c9a0eb88ed8a3aef40098ab347d80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 10:27:52 -0700 Subject: altosuilib: Publish AltosSiteMap.centre. Add prefetchMaps with old API This gets altosui working again. Signed-off-by: Keith Packard --- altosuilib/AltosSiteMap.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index 461886c7..7f0e1844 100644 --- a/altosuilib/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -290,6 +290,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous } } + public static void prefetchMaps(double lat, double lon) { + prefetchMaps(lat, lon, 2, 1 << maptype_hybrid, 0, 0); + } + public File init_map(Point offset, int load_mode) { AltosSiteMapTile tile = mapTiles.get(offset); Point2D.Double coord = tileCoordOffset(offset); @@ -516,7 +520,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous last_point = point; } - private void centre(Point2D.Double pt) { + public void centre(Point2D.Double pt) { Rectangle r = comp.getVisibleRect(); Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); int dx = (int)copt.x - r.width/2 - r.x; @@ -528,7 +532,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous comp.scrollRectToVisible(r); } - private void centre(AltosState state) { + public void centre(AltosState state) { if (!state.gps.locked && state.gps.nsat < 4) return; centre(pt(state.gps.lat, state.gps.lon)); -- cgit v1.2.3 From 324380dcf86be338c6d556b901d6889ddde97f7e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 10:31:47 -0700 Subject: altosuilib: Don't try to draw to destroyed map windows Signed-off-by: Keith Packard --- altosuilib/AltosSiteMapImage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMapImage.java b/altosuilib/AltosSiteMapImage.java index ae32418f..f1cfa7c0 100644 --- a/altosuilib/AltosSiteMapImage.java +++ b/altosuilib/AltosSiteMapImage.java @@ -50,7 +50,8 @@ public class AltosSiteMapImage { public void run() { AltosSiteMap.debug_component(tile, file.toString()); Graphics2D g2d = (Graphics2D) tile.getGraphics(); - tile.paint_graphics(g2d, image, serial); + if (g2d != null) + tile.paint_graphics(g2d, image, serial); load_thread = null; } }); -- cgit v1.2.3 From 9b3516419981967a1c6ab956269139977ac368ca Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 16:06:14 -0700 Subject: altosui/altosuilib: Shuffle lots more code from altosui into altosuilib All of the bluetooth management stuff, and AltosSerial. Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 124 ----------- altosui/AltosBTDeviceIterator.java | 62 ------ altosui/AltosBTKnown.java | 101 --------- altosui/AltosBTManage.java | 353 ------------------------------ altosui/AltosDeviceUIDialog.java | 70 ------ altosui/AltosEepromDelete.java | 3 +- altosui/AltosSerial.java | 210 ------------------ altosui/AltosSerialInUseException.java | 27 --- altosui/Makefile.am | 12 +- altosuilib/AltosBTDevice.java | 125 +++++++++++ altosuilib/AltosBTDeviceIterator.java | 64 ++++++ altosuilib/AltosBTKnown.java | 101 +++++++++ altosuilib/AltosBTManage.java | 353 ++++++++++++++++++++++++++++++ altosuilib/AltosDeviceUIDialog.java | 69 ++++++ altosuilib/AltosSerial.java | 208 ++++++++++++++++++ altosuilib/AltosSerialInUseException.java | 26 +++ altosuilib/Makefile.am | 10 +- 17 files changed, 958 insertions(+), 960 deletions(-) delete mode 100644 altosui/AltosBTDevice.java delete mode 100644 altosui/AltosBTDeviceIterator.java delete mode 100644 altosui/AltosBTKnown.java delete mode 100644 altosui/AltosBTManage.java delete mode 100644 altosui/AltosDeviceUIDialog.java delete mode 100644 altosui/AltosSerial.java delete mode 100644 altosui/AltosSerialInUseException.java create mode 100644 altosuilib/AltosBTDevice.java create mode 100644 altosuilib/AltosBTDeviceIterator.java create mode 100644 altosuilib/AltosBTKnown.java create mode 100644 altosuilib/AltosBTManage.java create mode 100644 altosuilib/AltosDeviceUIDialog.java create mode 100644 altosuilib/AltosSerial.java create mode 100644 altosuilib/AltosSerialInUseException.java (limited to 'altosuilib') diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java deleted file mode 100644 index e920803a..00000000 --- a/altosui/AltosBTDevice.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 libaltosJNI.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosBTDevice extends altos_bt_device implements AltosDevice { - - public String getProductName() { - String name = getName(); - if (name == null) - return "Altus Metrum"; - int dash = name.lastIndexOf("-"); - if (dash < 0) - return name; - return name.substring(0,dash); - } - - public int getProduct() { - if (Altos.bt_product_telebt.equals(getProductName())) - return Altos.product_telebt; - return 0; - } - - public String getPath() { - return getAddr(); - } - - public String getErrorString() { - altos_error error = new altos_error(); - - libaltos.altos_get_last_error(error); - return String.format("%s (%d)", error.getString(), error.getCode()); - } - - public int getSerial() { - String name = getName(); - if (name == null) - return 0; - int dash = name.lastIndexOf("-"); - if (dash < 0 || dash >= name.length()) - return 0; - String sn = name.substring(dash + 1, name.length()); - try { - return Integer.parseInt(sn); - } catch (NumberFormatException ne) { - return 0; - } - } - - public String toString() { - return String.format("%-20.20s %4d %s", - getProductName(), getSerial(), getAddr()); - } - - public String toShortString() { - return String.format("%s %d %s", - getProductName(), getSerial(), getAddr()); - - } - - public SWIGTYPE_p_altos_file open() { - return libaltos.altos_bt_open(this); - } - - /* - private boolean isAltusMetrum() { - if (getName().startsWith(Altos.bt_product_telebt)) - return true; - return false; - } - */ - - public boolean matchProduct(int want_product) { - -// if (!isAltusMetrum()) -// return false; - - if (want_product == Altos.product_any) - return true; - - if (want_product == Altos.product_basestation) - return matchProduct(Altos.product_telebt); - - if (want_product == getProduct()) - return true; - - return false; - } - - public boolean equals(Object o) { - if (!(o instanceof AltosBTDevice)) - return false; - AltosBTDevice other = (AltosBTDevice) o; - return getName().equals(other.getName()) && getAddr().equals(other.getAddr()); - } - - public int hashCode() { - return getName().hashCode() ^ getAddr().hashCode(); - } - - public AltosBTDevice(String name, String addr) { - Altos.load_library(); - libaltos.altos_bt_fill_in(name, addr,this); - } - - public AltosBTDevice() { - } -} \ No newline at end of file diff --git a/altosui/AltosBTDeviceIterator.java b/altosui/AltosBTDeviceIterator.java deleted file mode 100644 index 4be5edf5..00000000 --- a/altosui/AltosBTDeviceIterator.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.util.*; -import libaltosJNI.*; - -public class AltosBTDeviceIterator implements Iterator { - AltosBTDevice current; - boolean done; - SWIGTYPE_p_altos_bt_list list; - - public boolean hasNext() { - if (list == null) - return false; - if (current != null) - return true; - if (done) - return false; - current = new AltosBTDevice(); - while (libaltos.altos_bt_list_next(list, current) != 0) { -// if (current.matchProduct(product)) - return true; - } - current = null; - done = true; - return false; - } - - public AltosBTDevice next() { - if (hasNext()) { - AltosBTDevice next = current; - current = null; - return next; - } - return null; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - public AltosBTDeviceIterator(int inquiry_time) { - done = false; - current = null; - list = libaltos.altos_bt_list_start(inquiry_time); - } -} diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java deleted file mode 100644 index 3abbbe08..00000000 --- a/altosui/AltosBTKnown.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.util.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosBTKnown implements Iterable { - LinkedList devices = new LinkedList(); - AltosPreferencesBackend bt_pref = AltosUIPreferences.bt_devices(); - - private String get_address(String name) { - return bt_pref.getString(name, ""); - } - - private void set_address(String name, String addr) { - bt_pref.putString(name, addr); - } - - private void remove(String name) { - bt_pref.remove(name); - } - - private void load() { - try { - String[] names = bt_pref.keys(); - for (int i = 0; i < names.length; i++) { - String name = names[i]; - String addr = get_address(name); - devices.add(new AltosBTDevice(name, addr)); - } - } catch (IllegalStateException ie) { - } - } - - public Iterator iterator() { - return devices.iterator(); - } - - private void flush() { - AltosUIPreferences.flush_preferences(); - } - - public void set(Iterable new_devices) { - for (AltosBTDevice old : devices) { - boolean found = false; - for (AltosBTDevice new_device : new_devices) { - if (new_device.equals(old)) { - found = true; - break; - } - } - if (!found) - remove(old.getName()); - } - devices = new LinkedList(); - for (AltosBTDevice new_device : new_devices) { - devices.add(new_device); - set_address(new_device.getName(), new_device.getAddr()); - } - flush(); - } - - public List list(int product) { - LinkedList list = new LinkedList(); - for (AltosBTDevice device : devices) { - if (device.matchProduct(product)) - list.add(device); - } - return list; - } - - public AltosBTKnown() { - devices = new LinkedList(); - bt_pref = AltosUIPreferences.bt_devices(); - load(); - } - - static AltosBTKnown known; - - static public AltosBTKnown bt_known() { - if (known == null) - known = new AltosBTKnown(); - return known; - } -} diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java deleted file mode 100644 index e6e7efd4..00000000 --- a/altosui/AltosBTManage.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.plaf.basic.*; -import java.util.*; -import java.util.concurrent.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable { - LinkedBlockingQueue found_devices; - Frame frame; - LinkedList listeners; - AltosBTKnown bt_known; - - class DeviceList extends JList implements Iterable { - LinkedList devices; - DefaultListModel list_model; - - public void add (AltosBTDevice device) { - if (!devices.contains(device)) { - devices.add(device); - list_model.addElement(device); - } - } - - public void remove (AltosBTDevice device) { - if (devices.contains(device)) { - devices.remove(device); - list_model.removeElement(device); - } - } - - public boolean contains(AltosBTDevice device) { - return devices.contains(device); - } - - //Subclass JList to workaround bug 4832765, which can cause the - //scroll pane to not let the user easily scroll up to the beginning - //of the list. An alternative would be to set the unitIncrement - //of the JScrollBar to a fixed value. You wouldn't get the nice - //aligned scrolling, but it should work. - public int getScrollableUnitIncrement(Rectangle visibleRect, - int orientation, - int direction) { - int row; - if (orientation == SwingConstants.VERTICAL && - direction < 0 && (row = getFirstVisibleIndex()) != -1) { - Rectangle r = getCellBounds(row, row); - if ((r.y == visibleRect.y) && (row != 0)) { - Point loc = r.getLocation(); - loc.y--; - int prevIndex = locationToIndex(loc); - Rectangle prevR = getCellBounds(prevIndex, prevIndex); - - if (prevR == null || prevR.y >= r.y) { - return 0; - } - return prevR.height; - } - } - return super.getScrollableUnitIncrement( - visibleRect, orientation, direction); - } - - public Iterator iterator() { - return devices.iterator(); - } - - public java.util.List selected_list() throws InterruptedException { - return getSelectedValuesList(); - } - - public DeviceList() { - devices = new LinkedList(); - list_model = new DefaultListModel(); - setModel(list_model); - setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - setLayoutOrientation(JList.HORIZONTAL_WRAP); - setVisibleRowCount(-1); - } - } - - DeviceList visible_devices; - - DeviceList known_devices; - Thread bt_thread; - - public Iterator iterator() { - return known_devices.iterator(); - } - - public void commit() { - bt_known.set(this); - } - - public void add_known() { - try { - for (AltosBTDevice device : visible_devices.selected_list()) { - known_devices.add(device); - visible_devices.remove(device); - } - } catch (InterruptedException ie) { - } - } - - public void remove_known() { - try { - for (AltosBTDevice device : known_devices.selected_list()) { - known_devices.remove(device); - visible_devices.add(device); - } - } catch (InterruptedException ie) { - } - } - - public void addActionListener(ActionListener l) { - listeners.add(l); - } - - private void forwardAction(ActionEvent e) { - for (ActionListener l : listeners) - l.actionPerformed(e); - } - - public void actionPerformed(ActionEvent e) { - String command = e.getActionCommand(); - if ("ok".equals(command)) { - bt_thread.interrupt(); - commit(); - setVisible(false); - forwardAction(e); - } else if ("cancel".equals(command)) { - bt_thread.interrupt(); - setVisible(false); - forwardAction(e); - } else if ("select".equals(command)) { - add_known(); - } else if ("deselect".equals(command)) { - remove_known(); - } - } - - public void got_visible_device() { - while (!found_devices.isEmpty()) { - AltosBTDevice device = found_devices.remove(); - if (!known_devices.contains(device)) - visible_devices.add(device); - } - } - - class BTGetVisibleDevices implements Runnable { - public void run () { - for (;;) - for (int time = 1; time <= 8; time <<= 1) { - AltosBTDeviceIterator i = new AltosBTDeviceIterator(time); - AltosBTDevice device; - - if (Thread.interrupted()) - return; - try { - while ((device = i.next()) != null) { - Runnable r; - - if (Thread.interrupted()) - return; - found_devices.add(device); - r = new Runnable() { - public void run() { - got_visible_device(); - } - }; - SwingUtilities.invokeLater(r); - } - } catch (Exception e) { - System.out.printf("uh-oh, exception %s\n", e.toString()); - } - } - } - } - - public static void show(Component frameComp, AltosBTKnown known) { - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosBTManage dialog; - - dialog = new AltosBTManage(frame, known); - dialog.setVisible(true); - } - - public AltosBTManage(Frame in_frame, AltosBTKnown in_known) { - super(in_frame, "Manage Bluetooth Devices", true); - - frame = in_frame; - bt_known = in_known; - BTGetVisibleDevices get_visible_devices = new BTGetVisibleDevices(); - bt_thread = new Thread(get_visible_devices); - bt_thread.start(); - - listeners = new LinkedList(); - - found_devices = new LinkedBlockingQueue(); - - Container pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(4,4,4,4); - - /* - * Known devices label and list - */ - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(new JLabel("Known Devices"), c); - - known_devices = new DeviceList(); - for (AltosBTDevice device : bt_known) - known_devices.add(device); - - JScrollPane known_list_scroller = new JScrollPane(known_devices); - known_list_scroller.setPreferredSize(new Dimension(400, 80)); - known_list_scroller.setAlignmentX(LEFT_ALIGNMENT); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 1; - c.gridheight = 2; - c.weightx = 1; - c.weighty = 1; - pane.add(known_list_scroller, c); - - /* - * Visible devices label and list - */ - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 2; - c.gridy = 0; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - - pane.add(new JLabel("Visible Devices"), c); - - visible_devices = new DeviceList(); - JScrollPane visible_list_scroller = new JScrollPane(visible_devices); - visible_list_scroller.setPreferredSize(new Dimension(400, 80)); - visible_list_scroller.setAlignmentX(LEFT_ALIGNMENT); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - c.gridx = 2; - c.gridy = 1; - c.gridheight = 2; - c.gridwidth = 1; - c.weightx = 1; - c.weighty = 1; - pane.add(visible_list_scroller, c); - - /* - * Arrows between the two lists - */ - BasicArrowButton select_arrow = new BasicArrowButton(SwingConstants.WEST); - select_arrow.setActionCommand("select"); - select_arrow.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.SOUTH; - c.gridx = 1; - c.gridy = 1; - c.gridheight = 1; - c.gridwidth = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(select_arrow, c); - - BasicArrowButton deselect_arrow = new BasicArrowButton(SwingConstants.EAST); - deselect_arrow.setActionCommand("deselect"); - deselect_arrow.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.NORTH; - c.gridx = 1; - c.gridy = 2; - c.gridheight = 1; - c.gridwidth = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(deselect_arrow, c); - - JButton cancel_button = new JButton("Cancel"); - cancel_button.setActionCommand("cancel"); - cancel_button.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; - c.gridy = 3; - c.gridheight = 1; - c.gridwidth = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(cancel_button, c); - - JButton ok_button = new JButton("OK"); - ok_button.setActionCommand("ok"); - ok_button.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 2; - c.gridy = 3; - c.gridheight = 1; - c.gridwidth = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(ok_button, c); - - getRootPane().setDefaultButton(ok_button); - - pack(); - setLocationRelativeTo(frame); - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - bt_thread.interrupt(); - setVisible(false); - } - }); - } -} diff --git a/altosui/AltosDeviceUIDialog.java b/altosui/AltosDeviceUIDialog.java deleted file mode 100644 index 307c77f8..00000000 --- a/altosui/AltosDeviceUIDialog.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosDeviceUIDialog extends AltosDeviceDialog { - - public AltosDevice[] devices() { - java.util.List usb_devices = AltosUSBDevice.list(product); - int num_devices = usb_devices.size(); - java.util.List bt_devices = AltosBTKnown.bt_known().list(product); - num_devices += bt_devices.size(); - AltosDevice[] devices = new AltosDevice[num_devices]; - - for (int i = 0; i < usb_devices.size(); i++) - devices[i] = usb_devices.get(i); - int off = usb_devices.size(); - for (int j = 0; j < bt_devices.size(); j++) - devices[off + j] = bt_devices.get(j); - return devices; - } - - public void add_bluetooth() { - JButton manage_bluetooth_button = new JButton("Manage Bluetooth"); - manage_bluetooth_button.setActionCommand("manage"); - manage_bluetooth_button.addActionListener(this); - buttonPane.add(manage_bluetooth_button); - buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - } - - public void actionPerformed(ActionEvent e) { - super.actionPerformed(e); - if ("manage".equals(e.getActionCommand())) { - AltosBTManage.show(frame, AltosBTKnown.bt_known()); - update_devices(); - } - } - - public AltosDeviceUIDialog (Frame in_frame, Component location, int in_product) { - super(in_frame, location, in_product); - } - - public static AltosDevice show (Component frameComp, int product) { - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosDeviceUIDialog dialog; - - dialog = new AltosDeviceUIDialog(frame, frameComp, product); - dialog.setVisible(true); - return dialog.getValue(); - } -} diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index b6ac7edb..df2ade78 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -21,6 +21,7 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; +import org.altusmetrum.altosuilib_2.*; import org.altusmetrum.altoslib_4.*; public class AltosEepromDelete implements Runnable { @@ -140,4 +141,4 @@ public class AltosEepromDelete implements Runnable { flights = given_flights; success = false; } -} \ No newline at end of file +} diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java deleted file mode 100644 index 9b2180ba..00000000 --- a/altosui/AltosSerial.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Deal with TeleDongle on a serial port - */ - -package altosui; - -import java.io.*; -import java.util.*; -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -import libaltosJNI.*; - -/* - * This class reads from the serial port and places each received - * line in a queue. Dealing with that queue is left up to other - * threads. - */ - -public class AltosSerial extends AltosLink { - - static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); - - AltosDevice device; - SWIGTYPE_p_altos_file altos; - Thread input_thread; - String line; - byte[] line_bytes; - int line_count; - Frame frame; - - public int getchar() { - if (altos == null) - return ERROR; - return libaltos.altos_getchar(altos, 0); - } - - public void flush_output() { - super.flush_output(); - if (altos != null) { - if (libaltos.altos_flush(altos) != 0) - close_serial(); - } - } - - JDialog timeout_dialog; - - private void start_timeout_dialog_internal() { - - Object[] options = { "Cancel" }; - - JOptionPane pane = new JOptionPane(); - pane.setMessage(String.format("Connecting to %s, %7.3f MHz as %s", device.toShortString(), frequency, callsign)); - pane.setOptions(options); - pane.setInitialValue(null); - - timeout_dialog = pane.createDialog(frame, "Connecting..."); - - timeout_dialog.setVisible(true); - - Object o = pane.getValue(); - if (o == null) - return; - if (options[0].equals(o)) - reply_abort = true; - timeout_dialog.dispose(); - timeout_dialog = null; - } - - /* - * These are required by the AltosLink implementation - */ - - public boolean can_cancel_reply() { - /* - * Can cancel any replies not called from the dispatch thread - */ - return !SwingUtilities.isEventDispatchThread(); - } - - public boolean show_reply_timeout() { - if (!SwingUtilities.isEventDispatchThread() && frame != null) { - Runnable r = new Runnable() { - public void run() { - start_timeout_dialog_internal(); - } - }; - SwingUtilities.invokeLater(r); - return true; - } - return false; - } - - public void hide_reply_timeout() { - Runnable r = new Runnable() { - public void run() { - timeout_dialog.setVisible(false); - } - }; - SwingUtilities.invokeLater(r); - } - - private void close_serial() { - synchronized (devices_opened) { - devices_opened.remove(device.getPath()); - } - if (altos != null) { - libaltos.altos_free(altos); - altos = null; - } - abort_reply(); - } - - public void close() { - if (remote) { - try { - stop_remote(); - } catch (InterruptedException ie) { - } - } - if (in_reply != 0) - System.out.printf("Uh-oh. Closing active serial device\n"); - - close_serial(); - - if (input_thread != null) { - try { - input_thread.interrupt(); - input_thread.join(); - } catch (InterruptedException ie) { - } - input_thread = null; - } - if (debug) - System.out.printf("Closing %s\n", device.getPath()); - } - - private void putc(char c) { - if (altos != null) - if (libaltos.altos_putchar(altos, c) != 0) - close_serial(); - } - - public void putchar(byte c) { - if (altos != null) { - if (debug) - System.out.printf(" %02x", (int) c & 0xff); - if (libaltos.altos_putchar(altos, (char) c) != 0) - close_serial(); - } - } - - public void print(String data) { - for (int i = 0; i < data.length(); i++) - putc(data.charAt(i)); - } - - private void open() throws FileNotFoundException, AltosSerialInUseException { - synchronized (devices_opened) { - if (devices_opened.contains(device.getPath())) - throw new AltosSerialInUseException(device); - devices_opened.add(device.getPath()); - } - altos = device.open(); - if (altos == null) { - final String message = device.getErrorString(); - close(); - throw new FileNotFoundException(String.format("%s (%s)", - device.toShortString(), message)); - } - if (debug) - System.out.printf("Open %s\n", device.getPath()); - input_thread = new Thread(this); - input_thread.start(); - print("~\nE 0\n"); - set_monitor(false); - flush_output(); - } - - public void set_frame(Frame in_frame) { - frame = in_frame; - } - - public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { - device = in_device; - frame = null; - serial = device.getSerial(); - name = device.toShortString(); - open(); - } -} diff --git a/altosui/AltosSerialInUseException.java b/altosui/AltosSerialInUseException.java deleted file mode 100644 index 318155c8..00000000 --- a/altosui/AltosSerialInUseException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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_2.*; - -public class AltosSerialInUseException extends Exception { - public AltosDevice device; - - public AltosSerialInUseException (AltosDevice in_device) { - device = in_device; - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index df9fe5d1..6f491d7d 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -10,12 +10,6 @@ CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../altoslib/*:../alto bin_SCRIPTS=altosui -altosui_BT = \ - AltosBTDevice.java \ - AltosBTDeviceIterator.java \ - AltosBTManage.java \ - AltosBTKnown.java - altosui_JAVA = \ AltosAscent.java \ AltosChannelMenu.java \ @@ -29,7 +23,6 @@ altosui_JAVA = \ AltosConfigTDUI.java \ AltosCSVUI.java \ AltosDescent.java \ - AltosDeviceUIDialog.java \ AltosEepromDelete.java \ AltosEepromManage.java \ AltosEepromMonitorUI.java \ @@ -54,15 +47,12 @@ altosui_JAVA = \ AltosUIPreferencesBackend.java \ AltosRomconfigUI.java \ AltosScanUI.java \ - AltosSerial.java \ - AltosSerialInUseException.java \ AltosUI.java \ AltosGraph.java \ AltosGraphDataPoint.java \ AltosGraphDataSet.java \ AltosGraphUI.java \ - AltosDataChooser.java \ - $(altosui_BT) + AltosDataChooser.java JFREECHART_CLASS= \ jfreechart.jar diff --git a/altosuilib/AltosBTDevice.java b/altosuilib/AltosBTDevice.java new file mode 100644 index 00000000..beefa532 --- /dev/null +++ b/altosuilib/AltosBTDevice.java @@ -0,0 +1,125 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import libaltosJNI.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosBTDevice extends altos_bt_device implements AltosDevice { + + public String getProductName() { + String name = getName(); + if (name == null) + return "Altus Metrum"; + int dash = name.lastIndexOf("-"); + if (dash < 0) + return name; + return name.substring(0,dash); + } + + public int getProduct() { + if (AltosLib.bt_product_telebt.equals(getProductName())) + return AltosLib.product_telebt; + return 0; + } + + public String getPath() { + return getAddr(); + } + + public String getErrorString() { + altos_error error = new altos_error(); + + libaltos.altos_get_last_error(error); + return String.format("%s (%d)", error.getString(), error.getCode()); + } + + public int getSerial() { + String name = getName(); + if (name == null) + return 0; + int dash = name.lastIndexOf("-"); + if (dash < 0 || dash >= name.length()) + return 0; + String sn = name.substring(dash + 1, name.length()); + try { + return Integer.parseInt(sn); + } catch (NumberFormatException ne) { + return 0; + } + } + + public String toString() { + return String.format("%-20.20s %4d %s", + getProductName(), getSerial(), getAddr()); + } + + public String toShortString() { + return String.format("%s %d %s", + getProductName(), getSerial(), getAddr()); + + } + + public SWIGTYPE_p_altos_file open() { + return libaltos.altos_bt_open(this); + } + + /* + private boolean isAltusMetrum() { + if (getName().startsWith(Altos.bt_product_telebt)) + return true; + return false; + } + */ + + public boolean matchProduct(int want_product) { + +// if (!isAltusMetrum()) +// return false; + + if (want_product == AltosLib.product_any) + return true; + + if (want_product == AltosLib.product_basestation) + return matchProduct(AltosLib.product_telebt); + + if (want_product == getProduct()) + return true; + + return false; + } + + public boolean equals(Object o) { + if (!(o instanceof AltosBTDevice)) + return false; + AltosBTDevice other = (AltosBTDevice) o; + return getName().equals(other.getName()) && getAddr().equals(other.getAddr()); + } + + public int hashCode() { + return getName().hashCode() ^ getAddr().hashCode(); + } + + public AltosBTDevice(String name, String addr) { + AltosUILib.load_library(); + libaltos.altos_bt_fill_in(name, addr,this); + } + + public AltosBTDevice() { + } +} diff --git a/altosuilib/AltosBTDeviceIterator.java b/altosuilib/AltosBTDeviceIterator.java new file mode 100644 index 00000000..cad60ffb --- /dev/null +++ b/altosuilib/AltosBTDeviceIterator.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.util.*; +import libaltosJNI.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosBTDeviceIterator implements Iterator { + AltosBTDevice current; + boolean done; + SWIGTYPE_p_altos_bt_list list; + + public boolean hasNext() { + if (list == null) + return false; + if (current != null) + return true; + if (done) + return false; + current = new AltosBTDevice(); + while (libaltos.altos_bt_list_next(list, current) != 0) { +// if (current.matchProduct(product)) + return true; + } + current = null; + done = true; + return false; + } + + public AltosBTDevice next() { + if (hasNext()) { + AltosBTDevice next = current; + current = null; + return next; + } + return null; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public AltosBTDeviceIterator(int inquiry_time) { + done = false; + current = null; + list = libaltos.altos_bt_list_start(inquiry_time); + } +} diff --git a/altosuilib/AltosBTKnown.java b/altosuilib/AltosBTKnown.java new file mode 100644 index 00000000..02883c75 --- /dev/null +++ b/altosuilib/AltosBTKnown.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.util.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosBTKnown implements Iterable { + LinkedList devices = new LinkedList(); + AltosPreferencesBackend bt_pref = AltosUIPreferences.bt_devices(); + + private String get_address(String name) { + return bt_pref.getString(name, ""); + } + + private void set_address(String name, String addr) { + bt_pref.putString(name, addr); + } + + private void remove(String name) { + bt_pref.remove(name); + } + + private void load() { + try { + String[] names = bt_pref.keys(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + String addr = get_address(name); + devices.add(new AltosBTDevice(name, addr)); + } + } catch (IllegalStateException ie) { + } + } + + public Iterator iterator() { + return devices.iterator(); + } + + private void flush() { + AltosUIPreferences.flush_preferences(); + } + + public void set(Iterable new_devices) { + for (AltosBTDevice old : devices) { + boolean found = false; + for (AltosBTDevice new_device : new_devices) { + if (new_device.equals(old)) { + found = true; + break; + } + } + if (!found) + remove(old.getName()); + } + devices = new LinkedList(); + for (AltosBTDevice new_device : new_devices) { + devices.add(new_device); + set_address(new_device.getName(), new_device.getAddr()); + } + flush(); + } + + public List list(int product) { + LinkedList list = new LinkedList(); + for (AltosBTDevice device : devices) { + if (device.matchProduct(product)) + list.add(device); + } + return list; + } + + public AltosBTKnown() { + devices = new LinkedList(); + bt_pref = AltosUIPreferences.bt_devices(); + load(); + } + + static AltosBTKnown known; + + static public AltosBTKnown bt_known() { + if (known == null) + known = new AltosBTKnown(); + return known; + } +} diff --git a/altosuilib/AltosBTManage.java b/altosuilib/AltosBTManage.java new file mode 100644 index 00000000..6da0a3eb --- /dev/null +++ b/altosuilib/AltosBTManage.java @@ -0,0 +1,353 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.plaf.basic.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable { + LinkedBlockingQueue found_devices; + Frame frame; + LinkedList listeners; + AltosBTKnown bt_known; + + class DeviceList extends JList implements Iterable { + LinkedList devices; + DefaultListModel list_model; + + public void add (AltosBTDevice device) { + if (!devices.contains(device)) { + devices.add(device); + list_model.addElement(device); + } + } + + public void remove (AltosBTDevice device) { + if (devices.contains(device)) { + devices.remove(device); + list_model.removeElement(device); + } + } + + public boolean contains(AltosBTDevice device) { + return devices.contains(device); + } + + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + + public Iterator iterator() { + return devices.iterator(); + } + + public java.util.List selected_list() throws InterruptedException { + return getSelectedValuesList(); + } + + public DeviceList() { + devices = new LinkedList(); + list_model = new DefaultListModel(); + setModel(list_model); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + setLayoutOrientation(JList.HORIZONTAL_WRAP); + setVisibleRowCount(-1); + } + } + + DeviceList visible_devices; + + DeviceList known_devices; + Thread bt_thread; + + public Iterator iterator() { + return known_devices.iterator(); + } + + public void commit() { + bt_known.set(this); + } + + public void add_known() { + try { + for (AltosBTDevice device : visible_devices.selected_list()) { + known_devices.add(device); + visible_devices.remove(device); + } + } catch (InterruptedException ie) { + } + } + + public void remove_known() { + try { + for (AltosBTDevice device : known_devices.selected_list()) { + known_devices.remove(device); + visible_devices.add(device); + } + } catch (InterruptedException ie) { + } + } + + public void addActionListener(ActionListener l) { + listeners.add(l); + } + + private void forwardAction(ActionEvent e) { + for (ActionListener l : listeners) + l.actionPerformed(e); + } + + public void actionPerformed(ActionEvent e) { + String command = e.getActionCommand(); + if ("ok".equals(command)) { + bt_thread.interrupt(); + commit(); + setVisible(false); + forwardAction(e); + } else if ("cancel".equals(command)) { + bt_thread.interrupt(); + setVisible(false); + forwardAction(e); + } else if ("select".equals(command)) { + add_known(); + } else if ("deselect".equals(command)) { + remove_known(); + } + } + + public void got_visible_device() { + while (!found_devices.isEmpty()) { + AltosBTDevice device = found_devices.remove(); + if (!known_devices.contains(device)) + visible_devices.add(device); + } + } + + class BTGetVisibleDevices implements Runnable { + public void run () { + for (;;) + for (int time = 1; time <= 8; time <<= 1) { + AltosBTDeviceIterator i = new AltosBTDeviceIterator(time); + AltosBTDevice device; + + if (Thread.interrupted()) + return; + try { + while ((device = i.next()) != null) { + Runnable r; + + if (Thread.interrupted()) + return; + found_devices.add(device); + r = new Runnable() { + public void run() { + got_visible_device(); + } + }; + SwingUtilities.invokeLater(r); + } + } catch (Exception e) { + System.out.printf("uh-oh, exception %s\n", e.toString()); + } + } + } + } + + public static void show(Component frameComp, AltosBTKnown known) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosBTManage dialog; + + dialog = new AltosBTManage(frame, known); + dialog.setVisible(true); + } + + public AltosBTManage(Frame in_frame, AltosBTKnown in_known) { + super(in_frame, "Manage Bluetooth Devices", true); + + frame = in_frame; + bt_known = in_known; + BTGetVisibleDevices get_visible_devices = new BTGetVisibleDevices(); + bt_thread = new Thread(get_visible_devices); + bt_thread.start(); + + listeners = new LinkedList(); + + found_devices = new LinkedBlockingQueue(); + + Container pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(4,4,4,4); + + /* + * Known devices label and list + */ + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(new JLabel("Known Devices"), c); + + known_devices = new DeviceList(); + for (AltosBTDevice device : bt_known) + known_devices.add(device); + + JScrollPane known_list_scroller = new JScrollPane(known_devices); + known_list_scroller.setPreferredSize(new Dimension(400, 80)); + known_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.gridheight = 2; + c.weightx = 1; + c.weighty = 1; + pane.add(known_list_scroller, c); + + /* + * Visible devices label and list + */ + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 2; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + + pane.add(new JLabel("Visible Devices"), c); + + visible_devices = new DeviceList(); + JScrollPane visible_list_scroller = new JScrollPane(visible_devices); + visible_list_scroller.setPreferredSize(new Dimension(400, 80)); + visible_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + c.gridx = 2; + c.gridy = 1; + c.gridheight = 2; + c.gridwidth = 1; + c.weightx = 1; + c.weighty = 1; + pane.add(visible_list_scroller, c); + + /* + * Arrows between the two lists + */ + BasicArrowButton select_arrow = new BasicArrowButton(SwingConstants.WEST); + select_arrow.setActionCommand("select"); + select_arrow.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.SOUTH; + c.gridx = 1; + c.gridy = 1; + c.gridheight = 1; + c.gridwidth = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(select_arrow, c); + + BasicArrowButton deselect_arrow = new BasicArrowButton(SwingConstants.EAST); + deselect_arrow.setActionCommand("deselect"); + deselect_arrow.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTH; + c.gridx = 1; + c.gridy = 2; + c.gridheight = 1; + c.gridwidth = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(deselect_arrow, c); + + JButton cancel_button = new JButton("Cancel"); + cancel_button.setActionCommand("cancel"); + cancel_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; + c.gridy = 3; + c.gridheight = 1; + c.gridwidth = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(cancel_button, c); + + JButton ok_button = new JButton("OK"); + ok_button.setActionCommand("ok"); + ok_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 2; + c.gridy = 3; + c.gridheight = 1; + c.gridwidth = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(ok_button, c); + + getRootPane().setDefaultButton(ok_button); + + pack(); + setLocationRelativeTo(frame); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + bt_thread.interrupt(); + setVisible(false); + } + }); + } +} diff --git a/altosuilib/AltosDeviceUIDialog.java b/altosuilib/AltosDeviceUIDialog.java new file mode 100644 index 00000000..3013612a --- /dev/null +++ b/altosuilib/AltosDeviceUIDialog.java @@ -0,0 +1,69 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class AltosDeviceUIDialog extends AltosDeviceDialog { + + public AltosDevice[] devices() { + java.util.List usb_devices = AltosUSBDevice.list(product); + int num_devices = usb_devices.size(); + java.util.List bt_devices = AltosBTKnown.bt_known().list(product); + num_devices += bt_devices.size(); + AltosDevice[] devices = new AltosDevice[num_devices]; + + for (int i = 0; i < usb_devices.size(); i++) + devices[i] = usb_devices.get(i); + int off = usb_devices.size(); + for (int j = 0; j < bt_devices.size(); j++) + devices[off + j] = bt_devices.get(j); + return devices; + } + + public void add_bluetooth() { + JButton manage_bluetooth_button = new JButton("Manage Bluetooth"); + manage_bluetooth_button.setActionCommand("manage"); + manage_bluetooth_button.addActionListener(this); + buttonPane.add(manage_bluetooth_button); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + } + + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + if ("manage".equals(e.getActionCommand())) { + AltosBTManage.show(frame, AltosBTKnown.bt_known()); + update_devices(); + } + } + + public AltosDeviceUIDialog (Frame in_frame, Component location, int in_product) { + super(in_frame, location, in_product); + } + + public static AltosDevice show (Component frameComp, int product) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosDeviceUIDialog dialog; + + dialog = new AltosDeviceUIDialog(frame, frameComp, product); + dialog.setVisible(true); + return dialog.getValue(); + } +} diff --git a/altosuilib/AltosSerial.java b/altosuilib/AltosSerial.java new file mode 100644 index 00000000..0632ca70 --- /dev/null +++ b/altosuilib/AltosSerial.java @@ -0,0 +1,208 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Deal with TeleDongle on a serial port + */ + +package org.altusmetrum.altosuilib_2; + +import java.io.*; +import java.util.*; +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; +import libaltosJNI.*; + +/* + * This class reads from the serial port and places each received + * line in a queue. Dealing with that queue is left up to other + * threads. + */ + +public class AltosSerial extends AltosLink { + + static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); + + public AltosDevice device; + SWIGTYPE_p_altos_file altos; + Thread input_thread; + String line; + byte[] line_bytes; + int line_count; + Frame frame; + + public int getchar() { + if (altos == null) + return ERROR; + return libaltos.altos_getchar(altos, 0); + } + + public void flush_output() { + super.flush_output(); + if (altos != null) { + if (libaltos.altos_flush(altos) != 0) + close_serial(); + } + } + + JDialog timeout_dialog; + + private void start_timeout_dialog_internal() { + + Object[] options = { "Cancel" }; + + JOptionPane pane = new JOptionPane(); + pane.setMessage(String.format("Connecting to %s, %7.3f MHz as %s", device.toShortString(), frequency, callsign)); + pane.setOptions(options); + pane.setInitialValue(null); + + timeout_dialog = pane.createDialog(frame, "Connecting..."); + + timeout_dialog.setVisible(true); + + Object o = pane.getValue(); + if (o == null) + return; + if (options[0].equals(o)) + reply_abort = true; + timeout_dialog.dispose(); + timeout_dialog = null; + } + + /* + * These are required by the AltosLink implementation + */ + + public boolean can_cancel_reply() { + /* + * Can cancel any replies not called from the dispatch thread + */ + return !SwingUtilities.isEventDispatchThread(); + } + + public boolean show_reply_timeout() { + if (!SwingUtilities.isEventDispatchThread() && frame != null) { + Runnable r = new Runnable() { + public void run() { + start_timeout_dialog_internal(); + } + }; + SwingUtilities.invokeLater(r); + return true; + } + return false; + } + + public void hide_reply_timeout() { + Runnable r = new Runnable() { + public void run() { + timeout_dialog.setVisible(false); + } + }; + SwingUtilities.invokeLater(r); + } + + private void close_serial() { + synchronized (devices_opened) { + devices_opened.remove(device.getPath()); + } + if (altos != null) { + libaltos.altos_free(altos); + altos = null; + } + abort_reply(); + } + + public void close() { + if (remote) { + try { + stop_remote(); + } catch (InterruptedException ie) { + } + } + if (in_reply != 0) + System.out.printf("Uh-oh. Closing active serial device\n"); + + close_serial(); + + if (input_thread != null) { + try { + input_thread.interrupt(); + input_thread.join(); + } catch (InterruptedException ie) { + } + input_thread = null; + } + if (debug) + System.out.printf("Closing %s\n", device.getPath()); + } + + private void putc(char c) { + if (altos != null) + if (libaltos.altos_putchar(altos, c) != 0) + close_serial(); + } + + public void putchar(byte c) { + if (altos != null) { + if (debug) + System.out.printf(" %02x", (int) c & 0xff); + if (libaltos.altos_putchar(altos, (char) c) != 0) + close_serial(); + } + } + + public void print(String data) { + for (int i = 0; i < data.length(); i++) + putc(data.charAt(i)); + } + + private void open() throws FileNotFoundException, AltosSerialInUseException { + synchronized (devices_opened) { + if (devices_opened.contains(device.getPath())) + throw new AltosSerialInUseException(device); + devices_opened.add(device.getPath()); + } + altos = device.open(); + if (altos == null) { + final String message = device.getErrorString(); + close(); + throw new FileNotFoundException(String.format("%s (%s)", + device.toShortString(), message)); + } + if (debug) + System.out.printf("Open %s\n", device.getPath()); + input_thread = new Thread(this); + input_thread.start(); + print("~\nE 0\n"); + set_monitor(false); + flush_output(); + } + + public void set_frame(Frame in_frame) { + frame = in_frame; + } + + public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + device = in_device; + frame = null; + serial = device.getSerial(); + name = device.toShortString(); + open(); + } +} diff --git a/altosuilib/AltosSerialInUseException.java b/altosuilib/AltosSerialInUseException.java new file mode 100644 index 00000000..1e8207d1 --- /dev/null +++ b/altosuilib/AltosSerialInUseException.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +public class AltosSerialInUseException extends Exception { + public AltosDevice device; + + public AltosSerialInUseException (AltosDevice in_device) { + device = in_device; + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 10b756b8..fe0c3ec7 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -40,7 +40,15 @@ altosuilib_JAVA = \ AltosSiteMapImage.java \ AltosVoice.java \ AltosDisplayThread.java \ - AltosFreqList.java + AltosDeviceUIDialog.java \ + AltosFreqList.java \ + AltosSerial.java \ + AltosSerialInUseException.java \ + AltosBTDevice.java \ + AltosBTDeviceIterator.java \ + AltosBTManage.java \ + AltosBTKnown.java + JAR=altosuilib_$(ALTOSUILIB_VERSION).jar -- cgit v1.2.3 From 82a69777c67128192b50bbf77ace0a6525f49cac Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 20:24:04 -0700 Subject: telegps: Add preferences dialog Signed-off-by: Keith Packard --- altosui/AltosConfigFreqUI.java | 412 -------------------------------------- altosuilib/AltosConfigFreqUI.java | 411 +++++++++++++++++++++++++++++++++++++ altosuilib/Makefile.am | 1 + telegps/Makefile.am | 3 +- telegps/TeleGPS.java | 1 + telegps/TeleGPSPreferences.java | 150 ++++++++++++++ 6 files changed, 565 insertions(+), 413 deletions(-) delete mode 100644 altosui/AltosConfigFreqUI.java create mode 100644 altosuilib/AltosConfigFreqUI.java create mode 100644 telegps/TeleGPSPreferences.java (limited to 'altosuilib') diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java deleted file mode 100644 index c7181e14..00000000 --- a/altosui/AltosConfigFreqUI.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import java.util.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -class AltosEditFreqUI extends AltosUIDialog implements ActionListener { - Frame frame; - JTextField frequency; - JTextField description; - JButton ok_button, cancel_button; - boolean got_ok; - - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - - if ("ok".equals(cmd)) { - got_ok = true; - setVisible(false); - } - if ("cancel".equals(cmd)) { - got_ok = false; - setVisible(false); - } - } - - public AltosFrequency get() { - if (!got_ok) - return null; - - String f_s = frequency.getText(); - String d_s = description.getText(); - - try { - double f_d = Double.parseDouble(f_s); - - return new AltosFrequency(f_d, d_s); - } catch (NumberFormatException ne) { - } - return null; - } - - public AltosEditFreqUI(Frame in_frame, AltosFrequency existing) { - super(in_frame, true); - - got_ok = false; - frame = in_frame; - - Container pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets (4,4,4,4); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(new JLabel("Frequency"), c); - - frequency = new JTextField(12); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 1; - c.gridy = 0; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(frequency, c); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(new JLabel("Description"), c); - - description = new JTextField(12); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 1; - c.gridy = 1; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(description, c); - - ok_button = new JButton("OK"); - ok_button.setActionCommand("ok"); - ok_button.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 0; - c.gridy = 2; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(ok_button, c); - - cancel_button = new JButton("Cancel"); - cancel_button.setActionCommand("cancel"); - cancel_button.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 1; - c.gridy = 2; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(cancel_button, c); - - if (existing == null) - setTitle("Add New Frequency"); - else { - setTitle("Edit Existing Frequency"); - frequency.setText(String.format("%7.3f", existing.frequency)); - description.setText(existing.description); - } - getRootPane().setDefaultButton(ok_button); - - pack(); - setLocationRelativeTo(frame); - - } - - public AltosEditFreqUI(Frame in_frame) { - this(in_frame, (AltosFrequency) null); - } -} - -public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener { - - Frame frame; - LinkedList listeners; - - class FrequencyList extends JList { - DefaultListModel list_model; - - public void add(AltosFrequency frequency) { - int i; - for (i = 0; i < list_model.size(); i++) { - AltosFrequency f = (AltosFrequency) list_model.get(i); - if (frequency.frequency == f.frequency) - return; - if (frequency.frequency < f.frequency) - break; - } - list_model.insertElementAt(frequency, i); - } - - public void remove(AltosFrequency frequency) { - list_model.removeElement(frequency); - } - - //Subclass JList to workaround bug 4832765, which can cause the - //scroll pane to not let the user easily scroll up to the beginning - //of the list. An alternative would be to set the unitIncrement - //of the JScrollBar to a fixed value. You wouldn't get the nice - //aligned scrolling, but it should work. - public int getScrollableUnitIncrement(Rectangle visibleRect, - int orientation, - int direction) { - int row; - if (orientation == SwingConstants.VERTICAL && - direction < 0 && (row = getFirstVisibleIndex()) != -1) { - Rectangle r = getCellBounds(row, row); - if ((r.y == visibleRect.y) && (row != 0)) { - Point loc = r.getLocation(); - loc.y--; - int prevIndex = locationToIndex(loc); - Rectangle prevR = getCellBounds(prevIndex, prevIndex); - - if (prevR == null || prevR.y >= r.y) { - return 0; - } - return prevR.height; - } - } - return super.getScrollableUnitIncrement( - visibleRect, orientation, direction); - } - - public AltosFrequency selected() { - AltosFrequency f = (AltosFrequency) getSelectedValue(); - return f; - } - - public AltosFrequency[] frequencies() { - AltosFrequency[] ret; - - ret = new AltosFrequency[list_model.size()]; - for (int i = 0; i < list_model.size(); i++) - ret[i] = (AltosFrequency) list_model.get(i); - return ret; - } - - public FrequencyList(AltosFrequency[] in_frequencies) { - list_model = new DefaultListModel(); - setModel(list_model); - setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - setLayoutOrientation(JList.HORIZONTAL_WRAP); - for (int i = 0; i < in_frequencies.length; i++) { - add(in_frequencies[i]); - } - setVisibleRowCount(in_frequencies.length); - } - } - - FrequencyList frequencies; - - void save_frequencies() { - AltosUIPreferences.set_common_frequencies(frequencies.frequencies()); - } - - JButton add, edit, remove; - - JButton cancel, ok; - - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - - if ("ok".equals(cmd)) { - save_frequencies(); - setVisible(false); - } else if ("cancel".equals(cmd)) { - setVisible(false); - } else if ("add".equals(cmd)) { - AltosEditFreqUI ui = new AltosEditFreqUI(frame); - ui.setVisible(true); - AltosFrequency f = ui.get(); - if (f != null) - frequencies.add(f); - } else if ("edit".equals(cmd)) { - AltosFrequency old_f = frequencies.selected(); - if (old_f == null) - return; - AltosEditFreqUI ui = new AltosEditFreqUI(frame, old_f); - ui.setVisible(true); - AltosFrequency new_f = ui.get(); - if (new_f != null) { - if (old_f != null) - frequencies.remove(old_f); - frequencies.add(new_f); - } - } else if ("remove".equals(cmd)) { - AltosFrequency old_f = frequencies.selected(); - if (old_f == null) - return; - int ret = JOptionPane.showConfirmDialog(this, - String.format("Remove frequency \"%s\"?", - old_f.toShortString()), - "Remove Frequency", - JOptionPane.YES_NO_OPTION); - if (ret == JOptionPane.YES_OPTION) - frequencies.remove(old_f); - } - } - - public AltosFrequency[] frequencies() { - return frequencies.frequencies(); - } - - public AltosConfigFreqUI(Frame in_frame, - AltosFrequency[] in_frequencies) { - super(in_frame, "Manage Frequencies", true); - - frame = in_frame; - - listeners = new LinkedList(); - - frequencies = new FrequencyList(in_frequencies); - - Container pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(4,4,4,4); - - /* - * Frequencies label and list - */ - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 1; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(new JLabel("Frequencies"), c); - - JScrollPane list_scroller = new JScrollPane(frequencies); - list_scroller.setAlignmentX(LEFT_ALIGNMENT); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 6; - c.gridheight = 2; - c.weightx = 1; - c.weighty = 1; - pane.add(list_scroller, c); - - add = new JButton("Add"); - add.setActionCommand("add"); - add.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; - c.gridy = 3; - c.gridwidth = 2; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(add, c); - - edit = new JButton("Edit"); - edit.setActionCommand("edit"); - edit.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 2; - c.gridy = 3; - c.gridwidth = 2; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(edit, c); - - remove = new JButton("Remove"); - remove.setActionCommand("remove"); - remove.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 4; - c.gridy = 3; - c.gridwidth = 2; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(remove, c); - - ok = new JButton("OK"); - ok.setActionCommand("ok"); - ok.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; - c.gridy = 4; - c.gridwidth = 3; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(ok, c); - - cancel = new JButton("Cancel"); - cancel.setActionCommand("cancel"); - cancel.addActionListener(this); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 3; - c.gridy = 4; - c.gridwidth = 3; - c.gridheight = 1; - c.weightx = 0; - c.weighty = 0; - pane.add(cancel, c); - - pack(); - setLocationRelativeTo(frame); - } - - public static void show(Component frameComp) { - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosConfigFreqUI dialog; - - dialog = new AltosConfigFreqUI(frame, AltosUIPreferences.common_frequencies()); - dialog.setVisible(true); - } - -} diff --git a/altosuilib/AltosConfigFreqUI.java b/altosuilib/AltosConfigFreqUI.java new file mode 100644 index 00000000..6dcd63b8 --- /dev/null +++ b/altosuilib/AltosConfigFreqUI.java @@ -0,0 +1,411 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.*; +import org.altusmetrum.altoslib_4.*; + +class AltosEditFreqUI extends AltosUIDialog implements ActionListener { + Frame frame; + JTextField frequency; + JTextField description; + JButton ok_button, cancel_button; + boolean got_ok; + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if ("ok".equals(cmd)) { + got_ok = true; + setVisible(false); + } + if ("cancel".equals(cmd)) { + got_ok = false; + setVisible(false); + } + } + + public AltosFrequency get() { + if (!got_ok) + return null; + + String f_s = frequency.getText(); + String d_s = description.getText(); + + try { + double f_d = Double.parseDouble(f_s); + + return new AltosFrequency(f_d, d_s); + } catch (NumberFormatException ne) { + } + return null; + } + + public AltosEditFreqUI(Frame in_frame, AltosFrequency existing) { + super(in_frame, true); + + got_ok = false; + frame = in_frame; + + Container pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets (4,4,4,4); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(new JLabel("Frequency"), c); + + frequency = new JTextField(12); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 1; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(frequency, c); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(new JLabel("Description"), c); + + description = new JTextField(12); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(description, c); + + ok_button = new JButton("OK"); + ok_button.setActionCommand("ok"); + ok_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(ok_button, c); + + cancel_button = new JButton("Cancel"); + cancel_button.setActionCommand("cancel"); + cancel_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(cancel_button, c); + + if (existing == null) + setTitle("Add New Frequency"); + else { + setTitle("Edit Existing Frequency"); + frequency.setText(String.format("%7.3f", existing.frequency)); + description.setText(existing.description); + } + getRootPane().setDefaultButton(ok_button); + + pack(); + setLocationRelativeTo(frame); + + } + + public AltosEditFreqUI(Frame in_frame) { + this(in_frame, (AltosFrequency) null); + } +} + +public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener { + + Frame frame; + LinkedList listeners; + + class FrequencyList extends JList { + DefaultListModel list_model; + + public void add(AltosFrequency frequency) { + int i; + for (i = 0; i < list_model.size(); i++) { + AltosFrequency f = (AltosFrequency) list_model.get(i); + if (frequency.frequency == f.frequency) + return; + if (frequency.frequency < f.frequency) + break; + } + list_model.insertElementAt(frequency, i); + } + + public void remove(AltosFrequency frequency) { + list_model.removeElement(frequency); + } + + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + + public AltosFrequency selected() { + AltosFrequency f = (AltosFrequency) getSelectedValue(); + return f; + } + + public AltosFrequency[] frequencies() { + AltosFrequency[] ret; + + ret = new AltosFrequency[list_model.size()]; + for (int i = 0; i < list_model.size(); i++) + ret[i] = (AltosFrequency) list_model.get(i); + return ret; + } + + public FrequencyList(AltosFrequency[] in_frequencies) { + list_model = new DefaultListModel(); + setModel(list_model); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + setLayoutOrientation(JList.HORIZONTAL_WRAP); + for (int i = 0; i < in_frequencies.length; i++) { + add(in_frequencies[i]); + } + setVisibleRowCount(in_frequencies.length); + } + } + + FrequencyList frequencies; + + void save_frequencies() { + AltosUIPreferences.set_common_frequencies(frequencies.frequencies()); + } + + JButton add, edit, remove; + + JButton cancel, ok; + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if ("ok".equals(cmd)) { + save_frequencies(); + setVisible(false); + } else if ("cancel".equals(cmd)) { + setVisible(false); + } else if ("add".equals(cmd)) { + AltosEditFreqUI ui = new AltosEditFreqUI(frame); + ui.setVisible(true); + AltosFrequency f = ui.get(); + if (f != null) + frequencies.add(f); + } else if ("edit".equals(cmd)) { + AltosFrequency old_f = frequencies.selected(); + if (old_f == null) + return; + AltosEditFreqUI ui = new AltosEditFreqUI(frame, old_f); + ui.setVisible(true); + AltosFrequency new_f = ui.get(); + if (new_f != null) { + if (old_f != null) + frequencies.remove(old_f); + frequencies.add(new_f); + } + } else if ("remove".equals(cmd)) { + AltosFrequency old_f = frequencies.selected(); + if (old_f == null) + return; + int ret = JOptionPane.showConfirmDialog(this, + String.format("Remove frequency \"%s\"?", + old_f.toShortString()), + "Remove Frequency", + JOptionPane.YES_NO_OPTION); + if (ret == JOptionPane.YES_OPTION) + frequencies.remove(old_f); + } + } + + public AltosFrequency[] frequencies() { + return frequencies.frequencies(); + } + + public AltosConfigFreqUI(Frame in_frame, + AltosFrequency[] in_frequencies) { + super(in_frame, "Manage Frequencies", true); + + frame = in_frame; + + listeners = new LinkedList(); + + frequencies = new FrequencyList(in_frequencies); + + Container pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(4,4,4,4); + + /* + * Frequencies label and list + */ + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(new JLabel("Frequencies"), c); + + JScrollPane list_scroller = new JScrollPane(frequencies); + list_scroller.setAlignmentX(LEFT_ALIGNMENT); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 6; + c.gridheight = 2; + c.weightx = 1; + c.weighty = 1; + pane.add(list_scroller, c); + + add = new JButton("Add"); + add.setActionCommand("add"); + add.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 2; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(add, c); + + edit = new JButton("Edit"); + edit.setActionCommand("edit"); + edit.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 2; + c.gridy = 3; + c.gridwidth = 2; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(edit, c); + + remove = new JButton("Remove"); + remove.setActionCommand("remove"); + remove.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 4; + c.gridy = 3; + c.gridwidth = 2; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(remove, c); + + ok = new JButton("OK"); + ok.setActionCommand("ok"); + ok.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 3; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(ok, c); + + cancel = new JButton("Cancel"); + cancel.setActionCommand("cancel"); + cancel.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 3; + c.gridy = 4; + c.gridwidth = 3; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(cancel, c); + + pack(); + setLocationRelativeTo(frame); + } + + public static void show(Component frameComp) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosConfigFreqUI dialog; + + dialog = new AltosConfigFreqUI(frame, AltosUIPreferences.common_frequencies()); + dialog.setVisible(true); + } + +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index fe0c3ec7..abf0d79c 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -44,6 +44,7 @@ altosuilib_JAVA = \ AltosFreqList.java \ AltosSerial.java \ AltosSerialInUseException.java \ + AltosConfigFreqUI.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ diff --git a/telegps/Makefile.am b/telegps/Makefile.am index 65d3b714..280b1e40 100644 --- a/telegps/Makefile.am +++ b/telegps/Makefile.am @@ -16,7 +16,8 @@ telegps_JAVA= \ TeleGPSStatus.java \ TeleGPSStatusUpdate.java \ TeleGPSConfig.java \ - TeleGPSConfigUI.java + TeleGPSConfigUI.java \ + TeleGPSPreferences.java JFREECHART_CLASS= \ jfreechart.jar diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index ca1e68bb..cceb79b9 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -151,6 +151,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo } void preferences() { + new TeleGPSPreferences(this, voice()); } void load_maps() { diff --git a/telegps/TeleGPSPreferences.java b/telegps/TeleGPSPreferences.java new file mode 100644 index 00000000..534cf550 --- /dev/null +++ b/telegps/TeleGPSPreferences.java @@ -0,0 +1,150 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.telegps; + +import java.awt.*; +import java.awt.event.*; +import java.beans.*; +import javax.swing.*; +import javax.swing.event.*; +import org.altusmetrum.altosuilib_2.*; + +public class TeleGPSPreferences + extends AltosUIConfigure + implements DocumentListener +{ + AltosVoice voice; + + public JTextField callsign_value; + public JComboBox position_value; + + /* DocumentListener interface methods */ + public void insertUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public void removeUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public void changedUpdate(DocumentEvent e) { + if (callsign_value != null) + AltosUIPreferences.set_callsign(callsign_value.getText()); + } + + public void add_voice() { + + /* Voice settings */ + pane.add(new JLabel("Voice"), constraints(0, 1)); + + JRadioButton enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice()); + enable_voice.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JRadioButton item = (JRadioButton) e.getSource(); + boolean enabled = item.isSelected(); + AltosUIPreferences.set_voice(enabled); + if (enabled) + voice.speak_always("Enable voice."); + else + voice.speak_always("Disable voice."); + } + }); + pane.add(enable_voice, constraints(1, 1)); + enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements"); + + JButton test_voice = new JButton("Test Voice"); + test_voice.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + voice.speak("That's one small step for man; one giant leap for mankind."); + } + }); + pane.add(test_voice, constraints(2, 1)); + test_voice.setToolTipText("Play a stock audio clip to check volume"); + row++; + } + + public void add_callsign() { + /* Callsign setting */ + pane.add(new JLabel("Callsign"), constraints(0, 1)); + + callsign_value = new JTextField(AltosUIPreferences.callsign()); + callsign_value.getDocument().addDocumentListener(this); + callsign_value.setToolTipText("Callsign sent in packet mode"); + pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH)); + row++; + } + + public void add_bluetooth() { + JButton manage_bluetooth = new JButton("Manage Bluetooth"); + manage_bluetooth.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosBTManage.show(owner, AltosBTKnown.bt_known()); + } + }); + pane.add(manage_bluetooth, constraints(0, 2)); + /* in the same row as add_frequencies, so don't bump row */ + } + + public void add_frequencies() { + JButton manage_frequencies = new JButton("Manage Frequencies"); + manage_frequencies.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosConfigFreqUI.show(owner); + } + }); + manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); + pane.add(manage_frequencies, constraints(2, 1)); + row++; + } + + final static String[] position_names = { + "Top left", + "Top", + "Top right", + "Left", + "Center", + "Right", + "Bottom left", + "Bottom", + "Bottom right", + }; + + public void add_position() { + pane.add(new JLabel ("Menu position"), constraints(0, 1)); + + position_value = new JComboBox(position_names); + position_value.setMaximumRowCount(position_names.length); + int position = AltosUIPreferences.position(); + position_value.setSelectedIndex(position); + position_value.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int position = position_value.getSelectedIndex(); + AltosUIPreferences.set_position(position); + } + }); + pane.add(position_value, constraints(1, 2, GridBagConstraints.BOTH)); + position_value.setToolTipText("Position of main AltosUI window"); + row++; + } + + public TeleGPSPreferences(JFrame owner, AltosVoice voice) { + super(owner); + + this.voice = voice; + } +} -- cgit v1.2.3 From 9a4c2c7fc6af922d052e23a1b99bf847fbf9b0e9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 20:48:59 -0700 Subject: telegps: Add scan UI Move scan UI bits into altosuilib, allow telegps to not show telemetry format options. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 551 ----------------------------------------- altosui/AltosUI.java | 6 +- altosui/Makefile.am | 2 - altosuilib/AltosScanUI.java | 569 +++++++++++++++++++++++++++++++++++++++++++ altosuilib/AltosUIFrame.java | 3 + altosuilib/Makefile.am | 1 + telegps/TeleGPS.java | 27 +- 7 files changed, 596 insertions(+), 563 deletions(-) delete mode 100644 altosui/AltosScanUI.java create mode 100644 altosuilib/AltosScanUI.java (limited to 'altosuilib') diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java deleted file mode 100644 index 1f1f59ad..00000000 --- a/altosui/AltosScanUI.java +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.event.*; -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -class AltosScanResult { - String callsign; - int serial; - int flight; - AltosFrequency frequency; - int telemetry; - - boolean interrupted = false; - - public String toString() { - return String.format("%-9.9s serial %-4d flight %-4d (%s %s)", - callsign, serial, flight, frequency.toShortString(), Altos.telemetry_name(telemetry)); - } - - public String toShortString() { - return String.format("%s %d %d %7.3f %d", - callsign, serial, flight, frequency, telemetry); - } - - public AltosScanResult(String in_callsign, int in_serial, - int in_flight, AltosFrequency in_frequency, int in_telemetry) { - callsign = in_callsign; - serial = in_serial; - flight = in_flight; - frequency = in_frequency; - telemetry = in_telemetry; - } - - public boolean equals(AltosScanResult other) { - return (serial == other.serial && - frequency.frequency == other.frequency.frequency && - telemetry == other.telemetry); - } - - public boolean up_to_date(AltosScanResult other) { - if (flight == 0 && other.flight != 0) { - flight = other.flight; - return false; - } - if (callsign.equals("N0CALL") && !other.callsign.equals("N0CALL")) { - callsign = other.callsign; - return false; - } - return true; - } -} - -class AltosScanResults extends LinkedList implements ListModel { - - LinkedList listeners = new LinkedList(); - - void changed(ListDataEvent de) { - for (ListDataListener l : listeners) - l.contentsChanged(de); - } - - public boolean add(AltosScanResult r) { - int i = 0; - for (AltosScanResult old : this) { - if (old.equals(r)) { - if (!old.up_to_date(r)) - changed (new ListDataEvent(this, - ListDataEvent.CONTENTS_CHANGED, - i, i)); - return true; - } - i++; - } - - super.add(r); - changed(new ListDataEvent(this, - ListDataEvent.INTERVAL_ADDED, - this.size() - 2, this.size() - 1)); - return true; - } - - public void addListDataListener(ListDataListener l) { - listeners.add(l); - } - - public void removeListDataListener(ListDataListener l) { - listeners.remove(l); - } - - public AltosScanResult getElementAt(int i) { - return this.get(i); - } - - public int getSize() { - return this.size(); - } -} - -public class AltosScanUI - extends AltosUIDialog - implements ActionListener -{ - AltosUI owner; - AltosDevice device; - AltosConfigData config_data; - AltosTelemetryReader reader; - private JList list; - private JLabel scanning_label; - private JLabel frequency_label; - private JLabel telemetry_label; - private JButton cancel_button; - private JButton monitor_button; - private JCheckBox[] telemetry_boxes; - javax.swing.Timer timer; - AltosScanResults results = new AltosScanResults(); - - int telemetry; - - final static int timeout = 1200; - TelemetryHandler handler; - Thread thread; - AltosFrequency[] frequencies; - int frequency_index; - - void scan_exception(Exception e) { - if (e instanceof FileNotFoundException) { - JOptionPane.showMessageDialog(owner, - ((FileNotFoundException) e).getMessage(), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } else if (e instanceof AltosSerialInUseException) { - JOptionPane.showMessageDialog(owner, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } else if (e instanceof IOException) { - IOException ee = (IOException) e; - JOptionPane.showMessageDialog(owner, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } else { - JOptionPane.showMessageDialog(owner, - String.format("Connection to \"%s\" failed", - device.toShortString()), - "Connection Failed", - JOptionPane.ERROR_MESSAGE); - } - close(); - } - - class TelemetryHandler implements Runnable { - - public void run() { - - boolean interrupted = false; - - try { - for (;;) { - try { - AltosState state = reader.read(); - if (state == null) - continue; - if (state.flight != AltosLib.MISSING) { - final AltosScanResult result = new AltosScanResult(state.callsign, - state.serial, - state.flight, - frequencies[frequency_index], - telemetry); - Runnable r = new Runnable() { - public void run() { - results.add(result); - } - }; - SwingUtilities.invokeLater(r); - } - } catch (ParseException pp) { - } catch (AltosCRCException ce) { - } - } - } catch (InterruptedException ee) { - interrupted = true; - } catch (IOException ie) { - } finally { - reader.close(interrupted); - } - } - } - - void set_label() { - frequency_label.setText(String.format("Frequency: %s", frequencies[frequency_index].toString())); - telemetry_label.setText(String.format("Telemetry: %s", Altos.telemetry_name(telemetry))); - } - - void set_telemetry() { - reader.set_telemetry(telemetry); - } - - void set_frequency() throws InterruptedException, TimeoutException { - reader.set_frequency(frequencies[frequency_index].frequency); - reader.reset(); - } - - void next() throws InterruptedException, TimeoutException { - reader.set_monitor(false); - Thread.sleep(100); - ++frequency_index; - if (frequency_index >= frequencies.length || - !telemetry_boxes[telemetry - Altos.ao_telemetry_min].isSelected()) - { - frequency_index = 0; - do { - ++telemetry; - if (telemetry > Altos.ao_telemetry_max) - telemetry = Altos.ao_telemetry_min; - } while (!telemetry_boxes[telemetry - Altos.ao_telemetry_min].isSelected()); - set_telemetry(); - } - set_frequency(); - set_label(); - reader.set_monitor(true); - } - - - void close() { - if (thread != null && thread.isAlive()) { - thread.interrupt(); - try { - thread.join(); - } catch (InterruptedException ie) {} - } - thread = null; - if (timer != null) - timer.stop(); - setVisible(false); - dispose(); - } - - void tick_timer() throws InterruptedException, TimeoutException { - next(); - } - - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - - try { - if (cmd.equals("cancel")) - close(); - - if (cmd.equals("tick")) - tick_timer(); - - if (cmd.equals("telemetry")) { - int k; - int scanning_telemetry = 0; - for (k = Altos.ao_telemetry_min; k <= Altos.ao_telemetry_max; k++) { - int j = k - Altos.ao_telemetry_min; - if (telemetry_boxes[j].isSelected()) - scanning_telemetry |= (1 << k); - } - if (scanning_telemetry == 0) { - scanning_telemetry |= (1 << Altos.ao_telemetry_standard); - telemetry_boxes[Altos.ao_telemetry_standard - Altos.ao_telemetry_min].setSelected(true); - } - AltosUIPreferences.set_scanning_telemetry(scanning_telemetry); - } - - if (cmd.equals("monitor")) { - close(); - AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); - if (r != null) { - if (device != null) { - if (reader != null) { - reader.set_telemetry(r.telemetry); - reader.set_frequency(r.frequency.frequency); - reader.save_frequency(); - owner.telemetry_window(device); - } - } - } - } - } catch (TimeoutException te) { - close(); - } catch (InterruptedException ie) { - close(); - } - } - - /* A window listener to catch closing events and tell the config code */ - class ConfigListener extends WindowAdapter { - AltosScanUI ui; - - public ConfigListener(AltosScanUI this_ui) { - ui = this_ui; - } - - public void windowClosing(WindowEvent e) { - ui.actionPerformed(new ActionEvent(e.getSource(), - ActionEvent.ACTION_PERFORMED, - "close")); - } - } - - private boolean open() { - device = AltosDeviceUIDialog.show(owner, Altos.product_basestation); - if (device == null) - return false; - try { - reader = new AltosTelemetryReader(new AltosSerial(device)); - set_frequency(); - set_telemetry(); - try { - Thread.sleep(100); - } catch (InterruptedException ie) { - } - reader.flush(); - handler = new TelemetryHandler(); - thread = new Thread(handler); - thread.start(); - return true; - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(owner, - ee.getMessage(), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(owner, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(owner, - device.toShortString(), - "Unkonwn I/O error", - JOptionPane.ERROR_MESSAGE); - } catch (TimeoutException te) { - JOptionPane.showMessageDialog(owner, - device.toShortString(), - "Timeout error", - JOptionPane.ERROR_MESSAGE); - } catch (InterruptedException ie) { - JOptionPane.showMessageDialog(owner, - device.toShortString(), - "Interrupted exception", - JOptionPane.ERROR_MESSAGE); - } - if (reader != null) - reader.close(false); - return false; - } - - public AltosScanUI(AltosUI in_owner) { - - owner = in_owner; - - frequencies = AltosUIPreferences.common_frequencies(); - frequency_index = 0; - telemetry = Altos.ao_telemetry_min; - - if (!open()) - return; - - Container pane = getContentPane(); - GridBagConstraints c = new GridBagConstraints(); - Insets i = new Insets(4,4,4,4); - - timer = new javax.swing.Timer(timeout, this); - timer.setActionCommand("tick"); - timer.restart(); - - owner = in_owner; - - pane.setLayout(new GridBagLayout()); - - scanning_label = new JLabel("Scanning:"); - frequency_label = new JLabel(""); - telemetry_label = new JLabel(""); - - set_label(); - - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.WEST; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 2; - - pane.add(scanning_label, c); - c.gridy = 1; - pane.add(frequency_label, c); - c.gridy = 2; - pane.add(telemetry_label, c); - - int scanning_telemetry = AltosUIPreferences.scanning_telemetry(); - telemetry_boxes = new JCheckBox[Altos.ao_telemetry_max - Altos.ao_telemetry_min + 1]; - for (int k = Altos.ao_telemetry_min; k <= Altos.ao_telemetry_max; k++) { - int j = k - Altos.ao_telemetry_min; - telemetry_boxes[j] = new JCheckBox(AltosLib.telemetry_name(k)); - c.gridy = 3 + j; - pane.add(telemetry_boxes[j], c); - telemetry_boxes[j].setActionCommand("telemetry"); - telemetry_boxes[j].addActionListener(this); - telemetry_boxes[j].setSelected((scanning_telemetry & (1 << k)) != 0); - } - - int y_offset = 3 + (Altos.ao_telemetry_max - Altos.ao_telemetry_min + 1); - - list = new JList(results) { - //Subclass JList to workaround bug 4832765, which can cause the - //scroll pane to not let the user easily scroll up to the beginning - //of the list. An alternative would be to set the unitIncrement - //of the JScrollBar to a fixed value. You wouldn't get the nice - //aligned scrolling, but it should work. - public int getScrollableUnitIncrement(Rectangle visibleRect, - int orientation, - int direction) { - int row; - if (orientation == SwingConstants.VERTICAL && - direction < 0 && (row = getFirstVisibleIndex()) != -1) { - Rectangle r = getCellBounds(row, row); - if ((r.y == visibleRect.y) && (row != 0)) { - Point loc = r.getLocation(); - loc.y--; - int prevIndex = locationToIndex(loc); - Rectangle prevR = getCellBounds(prevIndex, prevIndex); - - if (prevR == null || prevR.y >= r.y) { - return 0; - } - return prevR.height; - } - } - return super.getScrollableUnitIncrement( - visibleRect, orientation, direction); - } - }; - - list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - list.setLayoutOrientation(JList.HORIZONTAL_WRAP); - list.setVisibleRowCount(-1); - - list.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - monitor_button.doClick(); //emulate button click - } - } - }); - JScrollPane listScroller = new JScrollPane(list); - listScroller.setPreferredSize(new Dimension(400, 80)); - listScroller.setAlignmentX(LEFT_ALIGNMENT); - - //Create a container so that we can add a title around - //the scroll pane. Can't add a title directly to the - //scroll pane because its background would be white. - //Lay out the label and scroll pane from top to bottom. - JPanel listPane = new JPanel(); - listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); - - JLabel label = new JLabel("Select Device"); - label.setLabelFor(list); - listPane.add(label); - listPane.add(Box.createRigidArea(new Dimension(0,5))); - listPane.add(listScroller); - listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = y_offset; - c.gridwidth = 2; - c.anchor = GridBagConstraints.CENTER; - - pane.add(listPane, c); - - cancel_button = new JButton("Cancel"); - cancel_button.addActionListener(this); - cancel_button.setActionCommand("cancel"); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = y_offset + 1; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(cancel_button, c); - - monitor_button = new JButton("Monitor"); - monitor_button.addActionListener(this); - monitor_button.setActionCommand("monitor"); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 1; - c.gridy = y_offset + 1; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(monitor_button, c); - - pack(); - setLocationRelativeTo(owner); - - addWindowListener(new ConfigListener(this)); - - setVisible(true); - } -} diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 9df02ec9..ad7964e9 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -74,6 +74,10 @@ public class AltosUI extends AltosUIFrame { } } + public void scan_device_selected(AltosDevice device) { + telemetry_window(device); + } + Container pane; GridBagLayout gridbag; @@ -272,7 +276,7 @@ public class AltosUI extends AltosUIFrame { } void ScanChannels() { - new AltosScanUI(AltosUI.this); + new AltosScanUI(AltosUI.this, true); } void LoadMaps() { diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 6f491d7d..cd6af84b 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -15,7 +15,6 @@ altosui_JAVA = \ AltosChannelMenu.java \ AltosCompanionInfo.java \ AltosConfig.java \ - AltosConfigFreqUI.java \ AltosConfigUI.java \ AltosConfigPyroUI.java \ AltosConfigureUI.java \ @@ -46,7 +45,6 @@ altosui_JAVA = \ AltosPad.java \ AltosUIPreferencesBackend.java \ AltosRomconfigUI.java \ - AltosScanUI.java \ AltosUI.java \ AltosGraph.java \ AltosGraphDataPoint.java \ diff --git a/altosuilib/AltosScanUI.java b/altosuilib/AltosScanUI.java new file mode 100644 index 00000000..b0cde059 --- /dev/null +++ b/altosuilib/AltosScanUI.java @@ -0,0 +1,569 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +class AltosScanResult { + String callsign; + int serial; + int flight; + AltosFrequency frequency; + int telemetry; + + boolean interrupted = false; + + public String toString() { + return String.format("%-9.9s serial %-4d flight %-4d (%s %s)", + callsign, serial, flight, frequency.toShortString(), AltosLib.telemetry_name(telemetry)); + } + + public String toShortString() { + return String.format("%s %d %d %7.3f %d", + callsign, serial, flight, frequency, telemetry); + } + + public AltosScanResult(String in_callsign, int in_serial, + int in_flight, AltosFrequency in_frequency, int in_telemetry) { + callsign = in_callsign; + serial = in_serial; + flight = in_flight; + frequency = in_frequency; + telemetry = in_telemetry; + } + + public boolean equals(AltosScanResult other) { + return (serial == other.serial && + frequency.frequency == other.frequency.frequency && + telemetry == other.telemetry); + } + + public boolean up_to_date(AltosScanResult other) { + if (flight == 0 && other.flight != 0) { + flight = other.flight; + return false; + } + if (callsign.equals("N0CALL") && !other.callsign.equals("N0CALL")) { + callsign = other.callsign; + return false; + } + return true; + } +} + +class AltosScanResults extends LinkedList implements ListModel { + + LinkedList listeners = new LinkedList(); + + void changed(ListDataEvent de) { + for (ListDataListener l : listeners) + l.contentsChanged(de); + } + + public boolean add(AltosScanResult r) { + int i = 0; + for (AltosScanResult old : this) { + if (old.equals(r)) { + if (!old.up_to_date(r)) + changed (new ListDataEvent(this, + ListDataEvent.CONTENTS_CHANGED, + i, i)); + return true; + } + i++; + } + + super.add(r); + changed(new ListDataEvent(this, + ListDataEvent.INTERVAL_ADDED, + this.size() - 2, this.size() - 1)); + return true; + } + + public void addListDataListener(ListDataListener l) { + listeners.add(l); + } + + public void removeListDataListener(ListDataListener l) { + listeners.remove(l); + } + + public AltosScanResult getElementAt(int i) { + return this.get(i); + } + + public int getSize() { + return this.size(); + } +} + +public class AltosScanUI + extends AltosUIDialog + implements ActionListener +{ + AltosUIFrame owner; + AltosDevice device; + AltosConfigData config_data; + AltosTelemetryReader reader; + private JList list; + private JLabel scanning_label; + private JLabel frequency_label; + private JLabel telemetry_label; + private JButton cancel_button; + private JButton monitor_button; + private JCheckBox[] telemetry_boxes; + javax.swing.Timer timer; + AltosScanResults results = new AltosScanResults(); + + int telemetry; + boolean select_telemetry = false; + + final static int timeout = 1200; + TelemetryHandler handler; + Thread thread; + AltosFrequency[] frequencies; + int frequency_index; + + void scan_exception(Exception e) { + if (e instanceof FileNotFoundException) { + JOptionPane.showMessageDialog(owner, + ((FileNotFoundException) e).getMessage(), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof AltosSerialInUseException) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof IOException) { + IOException ee = (IOException) e; + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } else { + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + close(); + } + + class TelemetryHandler implements Runnable { + + public void run() { + + boolean interrupted = false; + + try { + for (;;) { + try { + AltosState state = reader.read(); + if (state == null) + continue; + if (state.flight != AltosLib.MISSING) { + final AltosScanResult result = new AltosScanResult(state.callsign, + state.serial, + state.flight, + frequencies[frequency_index], + telemetry); + Runnable r = new Runnable() { + public void run() { + results.add(result); + } + }; + SwingUtilities.invokeLater(r); + } + } catch (ParseException pp) { + } catch (AltosCRCException ce) { + } + } + } catch (InterruptedException ee) { + interrupted = true; + } catch (IOException ie) { + } finally { + reader.close(interrupted); + } + } + } + + void set_label() { + frequency_label.setText(String.format("Frequency: %s", frequencies[frequency_index].toString())); + if (select_telemetry) + telemetry_label.setText(String.format("Telemetry: %s", AltosLib.telemetry_name(telemetry))); + } + + void set_telemetry() { + reader.set_telemetry(telemetry); + } + + void set_frequency() throws InterruptedException, TimeoutException { + reader.set_frequency(frequencies[frequency_index].frequency); + reader.reset(); + } + + void next() throws InterruptedException, TimeoutException { + reader.set_monitor(false); + Thread.sleep(100); + ++frequency_index; + if (select_telemetry) { + if (frequency_index >= frequencies.length || + !telemetry_boxes[telemetry - AltosLib.ao_telemetry_min].isSelected()) + { + frequency_index = 0; + do { + ++telemetry; + if (telemetry > AltosLib.ao_telemetry_max) + telemetry = AltosLib.ao_telemetry_min; + } while (!telemetry_boxes[telemetry - AltosLib.ao_telemetry_min].isSelected()); + set_telemetry(); + } + } else { + if (frequency_index >= frequencies.length) + frequency_index = 0; + } + set_frequency(); + set_label(); + reader.set_monitor(true); + } + + + void close() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException ie) {} + } + thread = null; + if (timer != null) + timer.stop(); + setVisible(false); + dispose(); + } + + void tick_timer() throws InterruptedException, TimeoutException { + next(); + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + try { + if (cmd.equals("cancel")) + close(); + + if (cmd.equals("tick")) + tick_timer(); + + if (cmd.equals("telemetry")) { + int k; + int scanning_telemetry = 0; + for (k = AltosLib.ao_telemetry_min; k <= AltosLib.ao_telemetry_max; k++) { + int j = k - AltosLib.ao_telemetry_min; + if (telemetry_boxes[j].isSelected()) + scanning_telemetry |= (1 << k); + } + if (scanning_telemetry == 0) { + scanning_telemetry |= (1 << AltosLib.ao_telemetry_standard); + telemetry_boxes[AltosLib.ao_telemetry_standard - AltosLib.ao_telemetry_min].setSelected(true); + } + AltosUIPreferences.set_scanning_telemetry(scanning_telemetry); + } + + if (cmd.equals("monitor")) { + close(); + AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); + if (r != null) { + if (device != null) { + if (reader != null) { + reader.set_telemetry(r.telemetry); + reader.set_frequency(r.frequency.frequency); + reader.save_frequency(); + owner.scan_device_selected(device); + } + } + } + } + } catch (TimeoutException te) { + close(); + } catch (InterruptedException ie) { + close(); + } + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosScanUI ui; + + public ConfigListener(AltosScanUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + private boolean open() { + device = AltosDeviceUIDialog.show(owner, AltosLib.product_basestation); + if (device == null) + return false; + try { + reader = new AltosTelemetryReader(new AltosSerial(device)); + set_frequency(); + set_telemetry(); + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } + reader.flush(); + handler = new TelemetryHandler(); + thread = new Thread(handler); + thread.start(); + return true; + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(owner, + ee.getMessage(), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + "Unkonwn I/O error", + JOptionPane.ERROR_MESSAGE); + } catch (TimeoutException te) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + "Timeout error", + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + "Interrupted exception", + JOptionPane.ERROR_MESSAGE); + } + if (reader != null) + reader.close(false); + return false; + } + + public AltosScanUI(AltosUIFrame in_owner, boolean in_select_telemetry) { + + owner = in_owner; + select_telemetry = in_select_telemetry; + + frequencies = AltosUIPreferences.common_frequencies(); + frequency_index = 0; + + telemetry = AltosLib.ao_telemetry_standard; + + if (!open()) + return; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + timer = new javax.swing.Timer(timeout, this); + timer.setActionCommand("tick"); + timer.restart(); + + owner = in_owner; + + pane.setLayout(new GridBagLayout()); + + scanning_label = new JLabel("Scanning:"); + frequency_label = new JLabel(""); + + if (select_telemetry) { + telemetry_label = new JLabel(""); + telemetry = AltosLib.ao_telemetry_min; + } else { + telemetry = AltosLib.ao_telemetry_standard; + } + + set_label(); + + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.WEST; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + + pane.add(scanning_label, c); + c.gridy = 1; + pane.add(frequency_label, c); + + int y_offset = 3; + + if (select_telemetry) { + c.gridy = 2; + pane.add(telemetry_label, c); + + int scanning_telemetry = AltosUIPreferences.scanning_telemetry(); + telemetry_boxes = new JCheckBox[AltosLib.ao_telemetry_max - AltosLib.ao_telemetry_min + 1]; + for (int k = AltosLib.ao_telemetry_min; k <= AltosLib.ao_telemetry_max; k++) { + int j = k - AltosLib.ao_telemetry_min; + telemetry_boxes[j] = new JCheckBox(AltosLib.telemetry_name(k)); + c.gridy = 3 + j; + pane.add(telemetry_boxes[j], c); + telemetry_boxes[j].setActionCommand("telemetry"); + telemetry_boxes[j].addActionListener(this); + telemetry_boxes[j].setSelected((scanning_telemetry & (1 << k)) != 0); + } + y_offset += (AltosLib.ao_telemetry_max - AltosLib.ao_telemetry_min + 1); + } + + list = new JList(results) { + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + }; + + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setLayoutOrientation(JList.HORIZONTAL_WRAP); + list.setVisibleRowCount(-1); + + list.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + monitor_button.doClick(); //emulate button click + } + } + }); + JScrollPane listScroller = new JScrollPane(list); + listScroller.setPreferredSize(new Dimension(400, 80)); + listScroller.setAlignmentX(LEFT_ALIGNMENT); + + //Create a container so that we can add a title around + //the scroll pane. Can't add a title directly to the + //scroll pane because its background would be white. + //Lay out the label and scroll pane from top to bottom. + JPanel listPane = new JPanel(); + listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); + + JLabel label = new JLabel("Select Device"); + label.setLabelFor(list); + listPane.add(label); + listPane.add(Box.createRigidArea(new Dimension(0,5))); + listPane.add(listScroller); + listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = y_offset; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + + pane.add(listPane, c); + + cancel_button = new JButton("Cancel"); + cancel_button.addActionListener(this); + cancel_button.setActionCommand("cancel"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = y_offset + 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(cancel_button, c); + + monitor_button = new JButton("Monitor"); + monitor_button.addActionListener(this); + monitor_button.setActionCommand("monitor"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 1; + c.gridy = y_offset + 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(monitor_button, c); + + pack(); + setLocationRelativeTo(owner); + + addWindowListener(new ConfigListener(this)); + + setVisible(true); + } +} diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java index ce86ad83..6e62c762 100644 --- a/altosuilib/AltosUIFrame.java +++ b/altosuilib/AltosUIFrame.java @@ -73,6 +73,9 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi super.setLocationByPlatform(lbp); } + public void scan_device_selected(AltosDevice device) { + } + public void setSize() { /* Smash sizes around so that the window comes up in the right shape */ Insets i = getInsets(); diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index abf0d79c..b4c4f79f 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -45,6 +45,7 @@ altosuilib_JAVA = \ AltosSerial.java \ AltosSerialInUseException.java \ AltosConfigFreqUI.java \ + AltosScanUI.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index cceb79b9..34509e4e 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -158,11 +158,13 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo new AltosSiteMapPreload(this); } - void monitor() { - AltosDevice device = AltosDeviceUIDialog.show(this, - AltosLib.product_basestation); - if (device == null) - return; + void disconnect() { + setTitle("TeleGPS"); + stop_display(); + remove_frequency_menu(); + } + + void connect(AltosDevice device) { if (reader != null) disconnect(); try { @@ -198,13 +200,20 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo } } - void disconnect() { - setTitle("TeleGPS"); - stop_display(); - remove_frequency_menu(); + void monitor() { + AltosDevice device = AltosDeviceUIDialog.show(this, + AltosLib.product_basestation); + if (device == null) + return; + connect(device); + } + + public void scan_device_selected(AltosDevice device) { + connect(device); } void scan() { + new AltosScanUI(this, false); } void download(){ -- cgit v1.2.3 From 4cec35564324f909dcddeb7c0d83a2daa8223042 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 20:58:01 -0700 Subject: telegps: Hook up data download dialog Signed-off-by: Keith Packard --- altosui/AltosEepromDelete.java | 144 ---------------- altosui/AltosEepromManage.java | 242 --------------------------- altosui/AltosEepromMonitor.java | 252 ---------------------------- altosui/AltosEepromMonitorUI.java | 311 ----------------------------------- altosui/AltosEepromSelect.java | 184 --------------------- altosui/AltosUI.java | 2 +- altosui/Makefile.am | 4 - altosuilib/AltosEepromDelete.java | 143 ++++++++++++++++ altosuilib/AltosEepromManage.java | 241 +++++++++++++++++++++++++++ altosuilib/AltosEepromMonitor.java | 251 ++++++++++++++++++++++++++++ altosuilib/AltosEepromMonitorUI.java | 310 ++++++++++++++++++++++++++++++++++ altosuilib/AltosEepromSelect.java | 183 +++++++++++++++++++++ altosuilib/Makefile.am | 4 + telegps/TeleGPS.java | 1 + 14 files changed, 1134 insertions(+), 1138 deletions(-) delete mode 100644 altosui/AltosEepromDelete.java delete mode 100644 altosui/AltosEepromManage.java delete mode 100644 altosui/AltosEepromMonitor.java delete mode 100644 altosui/AltosEepromMonitorUI.java delete mode 100644 altosui/AltosEepromSelect.java create mode 100644 altosuilib/AltosEepromDelete.java create mode 100644 altosuilib/AltosEepromManage.java create mode 100644 altosuilib/AltosEepromMonitor.java create mode 100644 altosuilib/AltosEepromMonitorUI.java create mode 100644 altosuilib/AltosEepromSelect.java (limited to 'altosuilib') diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java deleted file mode 100644 index df2ade78..00000000 --- a/altosui/AltosEepromDelete.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.event.*; -import javax.swing.*; -import java.io.*; -import java.util.concurrent.*; -import org.altusmetrum.altosuilib_2.*; -import org.altusmetrum.altoslib_4.*; - -public class AltosEepromDelete implements Runnable { - AltosEepromList flights; - Thread eeprom_thread; - AltosSerial serial_line; - boolean remote; - JFrame frame; - ActionListener listener; - boolean success; - - private void DeleteLog (AltosEepromLog log) - throws IOException, InterruptedException, TimeoutException { - - if (flights.config_data.flight_log_max != 0 || flights.config_data.log_format != 0) { - - /* Devices with newer firmware can erase the - * flash blocks containing each flight - */ - serial_line.flush_input(); - serial_line.printf("d %d\n", log.flight); - for (;;) { - /* It can take a while to erase the flash... */ - String line = serial_line.get_reply(20000); - if (line == null) - throw new TimeoutException(); - if (line.equals("Erased")) - break; - if (line.startsWith("No such")) - throw new IOException(line); - } - } - } - - private void show_error_internal(String message, String title) { - JOptionPane.showMessageDialog(frame, - message, - title, - JOptionPane.ERROR_MESSAGE); - } - - private void show_error(String in_message, String in_title) { - final String message = in_message; - final String title = in_title; - Runnable r = new Runnable() { - public void run() { - try { - show_error_internal(message, title); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - public void run () { - success = false; - try { - if (remote) - serial_line.start_remote(); - - for (AltosEepromLog log : flights) { - if (log.selected) { - DeleteLog(log); - } - } - success = true; - } catch (IOException ee) { - show_error (ee.getLocalizedMessage(), - serial_line.device.toShortString()); - } catch (InterruptedException ie) { - } catch (TimeoutException te) { - show_error (String.format("Connection to \"%s\" failed", - serial_line.device.toShortString()), - "Connection Failed"); - } finally { - try { - if (remote) - serial_line.stop_remote(); - } catch (InterruptedException ie) { - } finally { - serial_line.flush_output(); - serial_line.close(); - } - } - if (listener != null) { - Runnable r = new Runnable() { - public void run() { - try { - listener.actionPerformed(new ActionEvent(this, - success ? 1 : 0, - "delete")); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - } - - public void start() { - eeprom_thread = new Thread(this); - eeprom_thread.start(); - } - - public void addActionListener(ActionListener l) { - listener = l; - } - - public AltosEepromDelete(JFrame given_frame, - AltosSerial given_serial_line, - boolean given_remote, - AltosEepromList given_flights) { - frame = given_frame; - serial_line = given_serial_line; - remote = given_remote; - flights = given_flights; - success = false; - } -} diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java deleted file mode 100644 index aa43ab9e..00000000 --- a/altosui/AltosEepromManage.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.event.*; -import javax.swing.*; -import java.io.*; -import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosEepromManage implements ActionListener { - - JFrame frame; - boolean remote; - AltosDevice device; - AltosSerial serial_line; - AltosEepromList flights; - AltosEepromDownload download; - AltosEepromDelete delete; - - public void finish() { - if (serial_line != null) { - try { - serial_line.flush_input(); - } catch (InterruptedException ie) { - } - serial_line.close(); - serial_line = null; - } - } - - private int countDeletedFlights() { - int count = 0; - for (AltosEepromLog flight : flights) { - if (flight.selected) - count++; - } - return count; - } - - private String showDeletedFlights() { - String result = ""; - - for (AltosEepromLog flight : flights) { - if (flight.selected) { - if (result.equals("")) - result = String.format("%d", flight.flight); - else - result = String.format("%s, %d", result, flight.flight); - } - } - 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; - } - } - return false; - } - - 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(); - } else if (cmd.equals("delete")) { - if (success) { - JOptionPane.showMessageDialog(frame, - String.format("%d flights erased: %s", - countDeletedFlights(), - showDeletedFlights()), - serial_line.device.toShortString(), - JOptionPane.INFORMATION_MESSAGE); - } - } - if (!running) - finish(); - } - - public void got_flights(AltosEepromList in_flights) { - boolean running = false;; - - flights = in_flights; - try { - if (flights.size() == 0) { - JOptionPane.showMessageDialog(frame, - String.format("No flights available on %d", - device.getSerial()), - serial_line.device.toShortString(), - JOptionPane.INFORMATION_MESSAGE); - } else { - AltosEepromSelect select = new AltosEepromSelect(frame, flights, "Download"); - - if (select.run()) { - boolean any_selected = false; - for (AltosEepromLog flight : flights) - any_selected = any_selected || flight.selected; - if (any_selected) { - AltosEepromMonitorUI monitor = new AltosEepromMonitorUI(frame); - monitor.addActionListener(this); - serial_line.set_frame(frame); - download = new AltosEepromDownload(monitor, - serial_line, - remote, - flights); - /* - * Start flight log download - */ - - download.start(); - running = true; - } else { - running = download_done(); - } - } - } - if (!running) - finish(); - } catch (Exception e) { - got_exception(e); - } - } - - public void got_exception(Exception e) { - if (e instanceof IOException) { - IOException ee = (IOException) e; - JOptionPane.showMessageDialog(frame, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } else if (e instanceof TimeoutException) { - //TimeoutException te = (TimeoutException) e; - JOptionPane.showMessageDialog(frame, - String.format("Communications failed with \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } - finish(); - } - - class EepromGetList implements Runnable { - - AltosEepromManage manage; - - public void run () { - Runnable r; - try { - flights = new AltosEepromList(serial_line, remote); - r = new Runnable() { - public void run() { - got_flights(flights); - } - }; - } catch (Exception e) { - final Exception f_e = e; - r = new Runnable() { - public void run() { - got_exception(f_e); - } - }; - } - SwingUtilities.invokeLater(r); - } - - public EepromGetList(AltosEepromManage in_manage) { - manage = in_manage; - } - } - - public AltosEepromManage(JFrame given_frame) { - - //boolean running = false; - - frame = given_frame; - device = AltosDeviceUIDialog.show(frame, Altos.product_any); - - remote = false; - - if (device != null) { - try { - serial_line = new AltosSerial(device); - if (device.matchProduct(Altos.product_basestation)) - remote = true; - - serial_line.set_frame(frame); - - EepromGetList get_list = new EepromGetList(this); - Thread t = new Thread(get_list); - t.start(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - ee.getMessage(), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(frame, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } - } - } -} diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java deleted file mode 100644 index ce1c1625..00000000 --- a/altosui/AltosEepromMonitor.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosEepromMonitor extends AltosUIDialog { - - Container pane; - Box box; - JLabel serial_label; - JLabel flight_label; - JLabel file_label; - JLabel serial_value; - JLabel flight_value; - JLabel file_value; - JButton cancel; - JProgressBar pbar; - int min_state, max_state; - - public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) { - super (owner, "Download Flight Data", false); - - GridBagConstraints c; - Insets il = new Insets(4,4,4,4); - Insets ir = new Insets(4,4,4,4); - - pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 0; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - serial_label = new JLabel("Serial:"); - pane.add(serial_label, c); - - c = new GridBagConstraints(); - c.gridx = 1; c.gridy = 0; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - serial_value = new JLabel(""); - pane.add(serial_value, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.gridx = 0; c.gridy = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - flight_label = new JLabel("Flight:"); - pane.add(flight_label, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.gridx = 1; c.gridy = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - 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); - - min_state = in_min_state; - max_state = in_max_state; - pbar = new JProgressBar(); - pbar.setMinimum(0); - pbar.setMaximum(1000); - pbar.setValue(0); - pbar.setString("startup"); - pbar.setStringPainted(true); - pbar.setPreferredSize(new Dimension(600, 20)); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; c.gridy = 3; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ib = new Insets(4,4,4,4); - c.insets = ib; - pane.add(pbar, c); - - - cancel = new JButton("Cancel"); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; c.gridy = 4; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ic = new Insets(4,4,4,4); - c.insets = ic; - pane.add(cancel, c); - - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } - - public void addActionListener (ActionListener l) { - cancel.addActionListener(l); - } - - private void set_value_internal(String state_name, int state, int state_block, int block) { - if (state_block > 100) - state_block = 100; - if (state < min_state) state = min_state; - if (state >= max_state) state = max_state - 1; - state -= min_state; - - int pos = state * 100 + state_block; - - pbar.setString(String.format("block %d state %s", block, state_name)); - pbar.setValue(pos); - } - - public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) { - final String state_name = in_state_name; - final int state = in_state; - final int state_block = in_state_block; - final int block = in_block; - Runnable r = new Runnable() { - public void run() { - try { - set_value_internal(state_name, state, state_block, block); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void set_serial_internal(int serial) { - serial_value.setText(String.format("%d", serial)); - } - - public void set_serial(int in_serial) { - final int serial = in_serial; - Runnable r = new Runnable() { - public void run() { - try { - set_serial_internal(serial); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void set_flight_internal(int flight) { - flight_value.setText(String.format("%d", flight)); - } - - public void set_flight(int in_flight) { - final int flight = in_flight; - Runnable r = new Runnable() { - public void run() { - try { - set_flight_internal(flight); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void set_file_internal(String file) { - file_value.setText(String.format("%s", file)); - } - - public void set_file(String in_file) { - final String file = in_file; - Runnable r = new Runnable() { - public void run() { - try { - set_file_internal(file); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void done_internal() { - setVisible(false); - dispose(); - } - - public void done() { - Runnable r = new Runnable() { - public void run() { - try { - done_internal(); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void reset_internal() { - set_value_internal("startup",min_state,0, 0); - set_flight_internal(0); - set_file_internal(""); - } - - public void reset() { - Runnable r = new Runnable() { - public void run() { - try { - reset_internal(); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } -} diff --git a/altosui/AltosEepromMonitorUI.java b/altosui/AltosEepromMonitorUI.java deleted file mode 100644 index c1c1eb25..00000000 --- a/altosui/AltosEepromMonitorUI.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import org.altusmetrum.altosuilib_2.*; -import org.altusmetrum.altoslib_4.*; - -public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor { - JFrame owner; - Container pane; - Box box; - JLabel serial_label; - JLabel flight_label; - JLabel file_label; - JLabel serial_value; - JLabel flight_value; - JLabel file_value; - JButton cancel; - JProgressBar pbar; - int min_state, max_state; - ActionListener listener; - - public AltosEepromMonitorUI(JFrame owner) { - super (owner, "Download Flight Data", false); - - this.owner = owner; - - GridBagConstraints c; - Insets il = new Insets(4,4,4,4); - Insets ir = new Insets(4,4,4,4); - - pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 0; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - serial_label = new JLabel("Serial:"); - pane.add(serial_label, c); - - c = new GridBagConstraints(); - c.gridx = 1; c.gridy = 0; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - serial_value = new JLabel(""); - pane.add(serial_value, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.gridx = 0; c.gridy = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - flight_label = new JLabel("Flight:"); - pane.add(flight_label, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.gridx = 1; c.gridy = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - 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(1000); - pbar.setValue(0); - pbar.setString("startup"); - pbar.setStringPainted(true); - pbar.setPreferredSize(new Dimension(600, 20)); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; c.gridy = 3; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ib = new Insets(4,4,4,4); - c.insets = ib; - pane.add(pbar, c); - - - cancel = new JButton("Cancel"); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; c.gridy = 4; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ic = new Insets(4,4,4,4); - c.insets = ic; - pane.add(cancel, c); - - pack(); - setLocationRelativeTo(owner); - } - - public void addActionListener(ActionListener l) { - listener = l; - } - - public void set_states(int min_state, int max_state) { - this.min_state = min_state; - this.max_state = max_state; - } - - public void set_thread(Thread in_eeprom_thread) { - final Thread eeprom_thread = in_eeprom_thread; - cancel.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (eeprom_thread != null) - eeprom_thread.interrupt(); - } - }); - } - - public void start() { - setVisible(true); - } - - private void set_value_internal(String state_name, int state, int state_block, int block) { - if (state_block > 100) - state_block = 100; - if (state < min_state) state = min_state; - if (state >= max_state) state = max_state - 1; - state -= min_state; - - int pos = state * 100 + state_block; - - pbar.setString(String.format("block %d state %s", block, state_name)); - pbar.setValue(pos); - } - - public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) { - final String state_name = in_state_name; - final int state = in_state; - final int state_block = in_state_block; - final int block = in_block; - Runnable r = new Runnable() { - public void run() { - try { - set_value_internal(state_name, state, state_block, block); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void set_serial_internal(int serial) { - serial_value.setText(String.format("%d", serial)); - } - - public void set_serial(int in_serial) { - final int serial = in_serial; - Runnable r = new Runnable() { - public void run() { - try { - set_serial_internal(serial); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void set_flight_internal(int flight) { - flight_value.setText(String.format("%d", flight)); - } - - public void set_flight(int in_flight) { - final int flight = in_flight; - Runnable r = new Runnable() { - public void run() { - try { - set_flight_internal(flight); - } catch (Exception ex) { - } - } - }; - 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, - "download")); - setVisible(false); - dispose(); - } - - public void done(boolean in_success) { - final boolean success = in_success; - Runnable r = new Runnable() { - public void run() { - try { - done_internal(success); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void reset_internal() { - set_value_internal("startup",min_state,0, 0); - set_flight_internal(0); - set_filename_internal(""); - } - - public void reset() { - Runnable r = new Runnable() { - public void run() { - try { - reset_internal(); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void show_message_internal(String message, String title, int message_type) { - int joption_message_type = JOptionPane.ERROR_MESSAGE; - - switch (message_type) { - case INFO_MESSAGE: - joption_message_type = JOptionPane.INFORMATION_MESSAGE; - break; - case WARNING_MESSAGE: - joption_message_type = JOptionPane.WARNING_MESSAGE; - break; - case ERROR_MESSAGE: - joption_message_type = JOptionPane.ERROR_MESSAGE; - break; - } - JOptionPane.showMessageDialog(owner, - message, - title, - joption_message_type); - } - - public void show_message(String in_message, String in_title, int in_message_type) { - final String message = in_message; - final String title = in_title; - final int message_type = in_message_type; - Runnable r = new Runnable() { - public void run() { - try { - show_message_internal(message, title, message_type); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } -} diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java deleted file mode 100644 index 66a197c9..00000000 --- a/altosui/AltosEepromSelect.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 javax.swing.*; -import javax.swing.border.*; -import java.awt.*; -import java.awt.event.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -class AltosEepromItem implements ActionListener { - AltosEepromLog log; - JLabel label; - JCheckBox action; - JCheckBox delete; - - public void actionPerformed(ActionEvent e) { - log.selected = action.isSelected(); - } - - public AltosEepromItem(AltosEepromLog in_log) { - log = in_log; - - String text; - if (log.year != 0) - text = String.format("Flight #%02d - %04d-%02d-%02d", - log.flight, log.year, log.month, log.day); - else - text = String.format("Flight #%02d", log.flight); - - label = new JLabel(text); - - action = new JCheckBox("", log.selected); - action.addActionListener(this); - } -} - -public class AltosEepromSelect extends AltosUIDialog implements ActionListener { - //private JList list; - private JFrame frame; - JButton ok; - JButton cancel; - boolean success; - - /* Listen for events from our buttons */ - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - - if (cmd.equals("ok")) - success = true; - setVisible(false); - } - - public boolean run() { - success = false; - setLocationRelativeTo(frame); - setVisible(true); - return success; - } - - public AltosEepromSelect (JFrame in_frame, - AltosEepromList flights, - String action) { - - super(in_frame, String.format("Flight list for serial %d", flights.config_data.serial), true); - frame = in_frame; - - /* Create the container for the dialog */ - 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); - - JPanel labelPane = new JPanel(); - labelPane.setLayout(new BoxLayout(labelPane, BoxLayout.X_AXIS)); - labelPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); - labelPane.add(Box.createHorizontalGlue()); - labelPane.add(selectLabel); - labelPane.add(Box.createHorizontalGlue()); - - /* Add the header to the container. */ - contentPane.add(labelPane, BorderLayout.PAGE_START); - - - /* Now we create the evilness that is a GridBag for the flight details */ - GridBagConstraints c; - Insets i = new Insets(4,4,4,4); - JPanel flightPane = new JPanel(); - flightPane.setLayout(new GridBagLayout()); - flightPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); - - /* Flight Header */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 0; - c.fill = GridBagConstraints.NONE; - c.weightx = 0.5; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - JLabel flightHeaderLabel = new JLabel("Flight"); - flightPane.add(flightHeaderLabel, c); - - /* Download Header */ - c = new GridBagConstraints(); - c.gridx = 1; c.gridy = 0; - c.fill = GridBagConstraints.NONE; - c.weightx = 0.5; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - JLabel downloadHeaderLabel = new JLabel(action); - flightPane.add(downloadHeaderLabel, c); - - /* Add the flights to the GridBag */ - AltosEepromItem item; - int itemNumber = 1; - for (AltosEepromLog flight : flights) { - /* Create a flight object with handlers and - * appropriate UI items - */ - item = new AltosEepromItem(flight); - - /* Add a decriptive label for the flight */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = itemNumber; - c.fill = GridBagConstraints.NONE; - c.weightx = 0.5; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - flightPane.add(item.label, c); - - /* Add action 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); - - itemNumber++; - } - - /* Add the GridBag to the container */ - contentPane.add(flightPane, BorderLayout.CENTER); - - /* Create the dialog buttons */ - ok = new JButton("OK"); - ok.addActionListener(this); - ok.setActionCommand("ok"); - - cancel = new JButton("Cancel"); - cancel.addActionListener(this); - cancel.setActionCommand("cancel"); - - JPanel buttonPane = new JPanel(); - buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS)); - buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - buttonPane.add(Box.createHorizontalGlue()); - buttonPane.add(cancel); - buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(ok); - - /* Add the buttons to the container */ - contentPane.add(buttonPane, BorderLayout.PAGE_END); - - /* Pack the window! */ - pack(); - } -} diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index ad7964e9..302f623f 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -306,7 +306,7 @@ public class AltosUI extends AltosUIFrame { * a TeleDongle over the packet link */ private void SaveFlightData() { - new AltosEepromManage(AltosUI.this); + new AltosEepromManage(AltosUI.this, AltosLib.product_any); } /* Load a flight log file and write out a CSV file containing diff --git a/altosui/Makefile.am b/altosui/Makefile.am index cd6af84b..c834646d 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -22,10 +22,6 @@ altosui_JAVA = \ AltosConfigTDUI.java \ AltosCSVUI.java \ AltosDescent.java \ - AltosEepromDelete.java \ - AltosEepromManage.java \ - AltosEepromMonitorUI.java \ - AltosEepromSelect.java \ AltosFlashUI.java \ AltosFlightInfoTableModel.java \ AltosFlightStatsTable.java \ diff --git a/altosuilib/AltosEepromDelete.java b/altosuilib/AltosEepromDelete.java new file mode 100644 index 00000000..981daddf --- /dev/null +++ b/altosuilib/AltosEepromDelete.java @@ -0,0 +1,143 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosEepromDelete implements Runnable { + AltosEepromList flights; + Thread eeprom_thread; + AltosSerial serial_line; + boolean remote; + JFrame frame; + ActionListener listener; + boolean success; + + private void DeleteLog (AltosEepromLog log) + throws IOException, InterruptedException, TimeoutException { + + if (flights.config_data.flight_log_max != 0 || flights.config_data.log_format != 0) { + + /* Devices with newer firmware can erase the + * flash blocks containing each flight + */ + serial_line.flush_input(); + serial_line.printf("d %d\n", log.flight); + for (;;) { + /* It can take a while to erase the flash... */ + String line = serial_line.get_reply(20000); + if (line == null) + throw new TimeoutException(); + if (line.equals("Erased")) + break; + if (line.startsWith("No such")) + throw new IOException(line); + } + } + } + + private void show_error_internal(String message, String title) { + JOptionPane.showMessageDialog(frame, + message, + title, + JOptionPane.ERROR_MESSAGE); + } + + private void show_error(String in_message, String in_title) { + final String message = in_message; + final String title = in_title; + Runnable r = new Runnable() { + public void run() { + try { + show_error_internal(message, title); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + public void run () { + success = false; + try { + if (remote) + serial_line.start_remote(); + + for (AltosEepromLog log : flights) { + if (log.selected) { + DeleteLog(log); + } + } + success = true; + } catch (IOException ee) { + show_error (ee.getLocalizedMessage(), + serial_line.device.toShortString()); + } catch (InterruptedException ie) { + } catch (TimeoutException te) { + show_error (String.format("Connection to \"%s\" failed", + serial_line.device.toShortString()), + "Connection Failed"); + } finally { + try { + if (remote) + serial_line.stop_remote(); + } catch (InterruptedException ie) { + } finally { + serial_line.flush_output(); + serial_line.close(); + } + } + if (listener != null) { + Runnable r = new Runnable() { + public void run() { + try { + listener.actionPerformed(new ActionEvent(this, + success ? 1 : 0, + "delete")); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + } + + public void start() { + eeprom_thread = new Thread(this); + eeprom_thread.start(); + } + + public void addActionListener(ActionListener l) { + listener = l; + } + + public AltosEepromDelete(JFrame given_frame, + AltosSerial given_serial_line, + boolean given_remote, + AltosEepromList given_flights) { + frame = given_frame; + serial_line = given_serial_line; + remote = given_remote; + flights = given_flights; + success = false; + } +} diff --git a/altosuilib/AltosEepromManage.java b/altosuilib/AltosEepromManage.java new file mode 100644 index 00000000..2b967339 --- /dev/null +++ b/altosuilib/AltosEepromManage.java @@ -0,0 +1,241 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosEepromManage implements ActionListener { + + JFrame frame; + boolean remote; + AltosDevice device; + AltosSerial serial_line; + AltosEepromList flights; + AltosEepromDownload download; + AltosEepromDelete delete; + + public void finish() { + if (serial_line != null) { + try { + serial_line.flush_input(); + } catch (InterruptedException ie) { + } + serial_line.close(); + serial_line = null; + } + } + + private int countDeletedFlights() { + int count = 0; + for (AltosEepromLog flight : flights) { + if (flight.selected) + count++; + } + return count; + } + + private String showDeletedFlights() { + String result = ""; + + for (AltosEepromLog flight : flights) { + if (flight.selected) { + if (result.equals("")) + result = String.format("%d", flight.flight); + else + result = String.format("%s, %d", result, flight.flight); + } + } + 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; + } + } + return false; + } + + 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(); + } else if (cmd.equals("delete")) { + if (success) { + JOptionPane.showMessageDialog(frame, + String.format("%d flights erased: %s", + countDeletedFlights(), + showDeletedFlights()), + serial_line.device.toShortString(), + JOptionPane.INFORMATION_MESSAGE); + } + } + if (!running) + finish(); + } + + public void got_flights(AltosEepromList in_flights) { + boolean running = false;; + + flights = in_flights; + try { + if (flights.size() == 0) { + JOptionPane.showMessageDialog(frame, + String.format("No flights available on %d", + device.getSerial()), + serial_line.device.toShortString(), + JOptionPane.INFORMATION_MESSAGE); + } else { + AltosEepromSelect select = new AltosEepromSelect(frame, flights, "Download"); + + if (select.run()) { + boolean any_selected = false; + for (AltosEepromLog flight : flights) + any_selected = any_selected || flight.selected; + if (any_selected) { + AltosEepromMonitorUI monitor = new AltosEepromMonitorUI(frame); + monitor.addActionListener(this); + serial_line.set_frame(frame); + download = new AltosEepromDownload(monitor, + serial_line, + remote, + flights); + /* + * Start flight log download + */ + + download.start(); + running = true; + } else { + running = download_done(); + } + } + } + if (!running) + finish(); + } catch (Exception e) { + got_exception(e); + } + } + + public void got_exception(Exception e) { + if (e instanceof IOException) { + IOException ee = (IOException) e; + JOptionPane.showMessageDialog(frame, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof TimeoutException) { + //TimeoutException te = (TimeoutException) e; + JOptionPane.showMessageDialog(frame, + String.format("Communications failed with \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } + finish(); + } + + class EepromGetList implements Runnable { + + AltosEepromManage manage; + + public void run () { + Runnable r; + try { + flights = new AltosEepromList(serial_line, remote); + r = new Runnable() { + public void run() { + got_flights(flights); + } + }; + } catch (Exception e) { + final Exception f_e = e; + r = new Runnable() { + public void run() { + got_exception(f_e); + } + }; + } + SwingUtilities.invokeLater(r); + } + + public EepromGetList(AltosEepromManage in_manage) { + manage = in_manage; + } + } + + public AltosEepromManage(JFrame given_frame, int product) { + + //boolean running = false; + + frame = given_frame; + device = AltosDeviceUIDialog.show(frame, product); + + remote = false; + + if (device != null) { + try { + serial_line = new AltosSerial(device); + if (device.matchProduct(AltosLib.product_basestation)) + remote = true; + + serial_line.set_frame(frame); + + EepromGetList get_list = new EepromGetList(this); + Thread t = new Thread(get_list); + t.start(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + ee.getMessage(), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(frame, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } + } + } +} diff --git a/altosuilib/AltosEepromMonitor.java b/altosuilib/AltosEepromMonitor.java new file mode 100644 index 00000000..b1e85622 --- /dev/null +++ b/altosuilib/AltosEepromMonitor.java @@ -0,0 +1,251 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +public class AltosEepromMonitor extends AltosUIDialog { + + Container pane; + Box box; + JLabel serial_label; + JLabel flight_label; + JLabel file_label; + JLabel serial_value; + JLabel flight_value; + JLabel file_value; + JButton cancel; + JProgressBar pbar; + int min_state, max_state; + + public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) { + super (owner, "Download Flight Data", false); + + GridBagConstraints c; + Insets il = new Insets(4,4,4,4); + Insets ir = new Insets(4,4,4,4); + + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + serial_label = new JLabel("Serial:"); + pane.add(serial_label, c); + + c = new GridBagConstraints(); + c.gridx = 1; c.gridy = 0; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + serial_value = new JLabel(""); + pane.add(serial_value, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.gridx = 0; c.gridy = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + flight_label = new JLabel("Flight:"); + pane.add(flight_label, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 1; c.gridy = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + 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); + + min_state = in_min_state; + max_state = in_max_state; + pbar = new JProgressBar(); + pbar.setMinimum(0); + pbar.setMaximum(1000); + pbar.setValue(0); + pbar.setString("startup"); + pbar.setStringPainted(true); + pbar.setPreferredSize(new Dimension(600, 20)); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; c.gridy = 3; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ib = new Insets(4,4,4,4); + c.insets = ib; + pane.add(pbar, c); + + + cancel = new JButton("Cancel"); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; c.gridy = 4; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ic = new Insets(4,4,4,4); + c.insets = ic; + pane.add(cancel, c); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } + + public void addActionListener (ActionListener l) { + cancel.addActionListener(l); + } + + private void set_value_internal(String state_name, int state, int state_block, int block) { + if (state_block > 100) + state_block = 100; + if (state < min_state) state = min_state; + if (state >= max_state) state = max_state - 1; + state -= min_state; + + int pos = state * 100 + state_block; + + pbar.setString(String.format("block %d state %s", block, state_name)); + pbar.setValue(pos); + } + + public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) { + final String state_name = in_state_name; + final int state = in_state; + final int state_block = in_state_block; + final int block = in_block; + Runnable r = new Runnable() { + public void run() { + try { + set_value_internal(state_name, state, state_block, block); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void set_serial_internal(int serial) { + serial_value.setText(String.format("%d", serial)); + } + + public void set_serial(int in_serial) { + final int serial = in_serial; + Runnable r = new Runnable() { + public void run() { + try { + set_serial_internal(serial); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void set_flight_internal(int flight) { + flight_value.setText(String.format("%d", flight)); + } + + public void set_flight(int in_flight) { + final int flight = in_flight; + Runnable r = new Runnable() { + public void run() { + try { + set_flight_internal(flight); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void set_file_internal(String file) { + file_value.setText(String.format("%s", file)); + } + + public void set_file(String in_file) { + final String file = in_file; + Runnable r = new Runnable() { + public void run() { + try { + set_file_internal(file); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void done_internal() { + setVisible(false); + dispose(); + } + + public void done() { + Runnable r = new Runnable() { + public void run() { + try { + done_internal(); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void reset_internal() { + set_value_internal("startup",min_state,0, 0); + set_flight_internal(0); + set_file_internal(""); + } + + public void reset() { + Runnable r = new Runnable() { + public void run() { + try { + reset_internal(); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } +} diff --git a/altosuilib/AltosEepromMonitorUI.java b/altosuilib/AltosEepromMonitorUI.java new file mode 100644 index 00000000..02c71cd9 --- /dev/null +++ b/altosuilib/AltosEepromMonitorUI.java @@ -0,0 +1,310 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor { + JFrame owner; + Container pane; + Box box; + JLabel serial_label; + JLabel flight_label; + JLabel file_label; + JLabel serial_value; + JLabel flight_value; + JLabel file_value; + JButton cancel; + JProgressBar pbar; + int min_state, max_state; + ActionListener listener; + + public AltosEepromMonitorUI(JFrame owner) { + super (owner, "Download Flight Data", false); + + this.owner = owner; + + GridBagConstraints c; + Insets il = new Insets(4,4,4,4); + Insets ir = new Insets(4,4,4,4); + + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + serial_label = new JLabel("Serial:"); + pane.add(serial_label, c); + + c = new GridBagConstraints(); + c.gridx = 1; c.gridy = 0; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + serial_value = new JLabel(""); + pane.add(serial_value, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.gridx = 0; c.gridy = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + flight_label = new JLabel("Flight:"); + pane.add(flight_label, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 1; c.gridy = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + 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(1000); + pbar.setValue(0); + pbar.setString("startup"); + pbar.setStringPainted(true); + pbar.setPreferredSize(new Dimension(600, 20)); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; c.gridy = 3; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ib = new Insets(4,4,4,4); + c.insets = ib; + pane.add(pbar, c); + + + cancel = new JButton("Cancel"); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; c.gridy = 4; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ic = new Insets(4,4,4,4); + c.insets = ic; + pane.add(cancel, c); + + pack(); + setLocationRelativeTo(owner); + } + + public void addActionListener(ActionListener l) { + listener = l; + } + + public void set_states(int min_state, int max_state) { + this.min_state = min_state; + this.max_state = max_state; + } + + public void set_thread(Thread in_eeprom_thread) { + final Thread eeprom_thread = in_eeprom_thread; + cancel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (eeprom_thread != null) + eeprom_thread.interrupt(); + } + }); + } + + public void start() { + setVisible(true); + } + + private void set_value_internal(String state_name, int state, int state_block, int block) { + if (state_block > 100) + state_block = 100; + if (state < min_state) state = min_state; + if (state >= max_state) state = max_state - 1; + state -= min_state; + + int pos = state * 100 + state_block; + + pbar.setString(String.format("block %d state %s", block, state_name)); + pbar.setValue(pos); + } + + public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) { + final String state_name = in_state_name; + final int state = in_state; + final int state_block = in_state_block; + final int block = in_block; + Runnable r = new Runnable() { + public void run() { + try { + set_value_internal(state_name, state, state_block, block); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void set_serial_internal(int serial) { + serial_value.setText(String.format("%d", serial)); + } + + public void set_serial(int in_serial) { + final int serial = in_serial; + Runnable r = new Runnable() { + public void run() { + try { + set_serial_internal(serial); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void set_flight_internal(int flight) { + flight_value.setText(String.format("%d", flight)); + } + + public void set_flight(int in_flight) { + final int flight = in_flight; + Runnable r = new Runnable() { + public void run() { + try { + set_flight_internal(flight); + } catch (Exception ex) { + } + } + }; + 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, + "download")); + setVisible(false); + dispose(); + } + + public void done(boolean in_success) { + final boolean success = in_success; + Runnable r = new Runnable() { + public void run() { + try { + done_internal(success); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void reset_internal() { + set_value_internal("startup",min_state,0, 0); + set_flight_internal(0); + set_filename_internal(""); + } + + public void reset() { + Runnable r = new Runnable() { + public void run() { + try { + reset_internal(); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void show_message_internal(String message, String title, int message_type) { + int joption_message_type = JOptionPane.ERROR_MESSAGE; + + switch (message_type) { + case INFO_MESSAGE: + joption_message_type = JOptionPane.INFORMATION_MESSAGE; + break; + case WARNING_MESSAGE: + joption_message_type = JOptionPane.WARNING_MESSAGE; + break; + case ERROR_MESSAGE: + joption_message_type = JOptionPane.ERROR_MESSAGE; + break; + } + JOptionPane.showMessageDialog(owner, + message, + title, + joption_message_type); + } + + public void show_message(String in_message, String in_title, int in_message_type) { + final String message = in_message; + final String title = in_title; + final int message_type = in_message_type; + Runnable r = new Runnable() { + public void run() { + try { + show_message_internal(message, title, message_type); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } +} diff --git a/altosuilib/AltosEepromSelect.java b/altosuilib/AltosEepromSelect.java new file mode 100644 index 00000000..293d3045 --- /dev/null +++ b/altosuilib/AltosEepromSelect.java @@ -0,0 +1,183 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.*; +import javax.swing.border.*; +import java.awt.*; +import java.awt.event.*; +import org.altusmetrum.altoslib_4.*; + +class AltosEepromItem implements ActionListener { + AltosEepromLog log; + JLabel label; + JCheckBox action; + JCheckBox delete; + + public void actionPerformed(ActionEvent e) { + log.selected = action.isSelected(); + } + + public AltosEepromItem(AltosEepromLog in_log) { + log = in_log; + + String text; + if (log.year != 0) + text = String.format("Flight #%02d - %04d-%02d-%02d", + log.flight, log.year, log.month, log.day); + else + text = String.format("Flight #%02d", log.flight); + + label = new JLabel(text); + + action = new JCheckBox("", log.selected); + action.addActionListener(this); + } +} + +public class AltosEepromSelect extends AltosUIDialog implements ActionListener { + //private JList list; + private JFrame frame; + JButton ok; + JButton cancel; + boolean success; + + /* Listen for events from our buttons */ + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("ok")) + success = true; + setVisible(false); + } + + public boolean run() { + success = false; + setLocationRelativeTo(frame); + setVisible(true); + return success; + } + + public AltosEepromSelect (JFrame in_frame, + AltosEepromList flights, + String action) { + + super(in_frame, String.format("Flight list for serial %d", flights.config_data.serial), true); + frame = in_frame; + + /* Create the container for the dialog */ + 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); + + JPanel labelPane = new JPanel(); + labelPane.setLayout(new BoxLayout(labelPane, BoxLayout.X_AXIS)); + labelPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + labelPane.add(Box.createHorizontalGlue()); + labelPane.add(selectLabel); + labelPane.add(Box.createHorizontalGlue()); + + /* Add the header to the container. */ + contentPane.add(labelPane, BorderLayout.PAGE_START); + + + /* Now we create the evilness that is a GridBag for the flight details */ + GridBagConstraints c; + Insets i = new Insets(4,4,4,4); + JPanel flightPane = new JPanel(); + flightPane.setLayout(new GridBagLayout()); + flightPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); + + /* Flight Header */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + JLabel flightHeaderLabel = new JLabel("Flight"); + flightPane.add(flightHeaderLabel, c); + + /* Download Header */ + c = new GridBagConstraints(); + c.gridx = 1; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + JLabel downloadHeaderLabel = new JLabel(action); + flightPane.add(downloadHeaderLabel, c); + + /* Add the flights to the GridBag */ + AltosEepromItem item; + int itemNumber = 1; + for (AltosEepromLog flight : flights) { + /* Create a flight object with handlers and + * appropriate UI items + */ + item = new AltosEepromItem(flight); + + /* Add a decriptive label for the flight */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = itemNumber; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + flightPane.add(item.label, c); + + /* Add action 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); + + itemNumber++; + } + + /* Add the GridBag to the container */ + contentPane.add(flightPane, BorderLayout.CENTER); + + /* Create the dialog buttons */ + ok = new JButton("OK"); + ok.addActionListener(this); + ok.setActionCommand("ok"); + + cancel = new JButton("Cancel"); + cancel.addActionListener(this); + cancel.setActionCommand("cancel"); + + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS)); + buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + buttonPane.add(Box.createHorizontalGlue()); + buttonPane.add(cancel); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPane.add(ok); + + /* Add the buttons to the container */ + contentPane.add(buttonPane, BorderLayout.PAGE_END); + + /* Pack the window! */ + pack(); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index b4c4f79f..4dc4c47f 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -46,6 +46,10 @@ altosuilib_JAVA = \ AltosSerialInUseException.java \ AltosConfigFreqUI.java \ AltosScanUI.java \ + AltosEepromDelete.java \ + AltosEepromManage.java \ + AltosEepromMonitorUI.java \ + AltosEepromSelect.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index 34509e4e..ad46fbdd 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -217,6 +217,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo } void download(){ + new AltosEepromManage(this, AltosLib.product_telegps); } void configure() { -- cgit v1.2.3 From 3871b9ac036e3adfa1da089245fc7973b268c921 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 21:56:52 -0700 Subject: telegps: Add 'Info' tab This contains a summary of the tracking info, including position, speed and course. Signed-off-by: Keith Packard --- altoslib/AltosConvert.java | 26 ++ altoslib/AltosGreatCircle.java | 26 +- altoslib/AltosState.java | 24 ++ altosui/AltosCSVUI.java | 104 -------- altosui/AltosDataChooser.java | 83 ------- altosui/AltosLed.java | 45 ---- altosui/AltosLights.java | 65 ----- altosui/Makefile.am | 15 +- altosuilib/AltosCSVUI.java | 103 ++++++++ altosuilib/AltosDataChooser.java | 82 +++++++ altosuilib/AltosLed.java | 45 ++++ altosuilib/AltosLights.java | 65 +++++ altosuilib/Makefile.am | 20 +- icon/telegps-128.png | Bin 0 -> 8736 bytes icon/telegps-16.png | Bin 0 -> 507 bytes icon/telegps-256.png | Bin 0 -> 21589 bytes icon/telegps-32.png | Bin 0 -> 1475 bytes icon/telegps-48.png | Bin 0 -> 2507 bytes icon/telegps-512.png | Bin 0 -> 56581 bytes icon/telegps-64.png | Bin 0 -> 3678 bytes icon/telegps.ico | Bin 0 -> 285478 bytes icon/telegps.svg | 215 ++++++++++++++++ telegps/Makefile.am | 1 + telegps/TeleGPS.java | 13 + telegps/TeleGPSInfo.java | 511 +++++++++++++++++++++++++++++++++++++++ 25 files changed, 1109 insertions(+), 334 deletions(-) delete mode 100644 altosui/AltosCSVUI.java delete mode 100644 altosui/AltosDataChooser.java delete mode 100644 altosui/AltosLed.java delete mode 100644 altosui/AltosLights.java create mode 100644 altosuilib/AltosCSVUI.java create mode 100644 altosuilib/AltosDataChooser.java create mode 100644 altosuilib/AltosLed.java create mode 100644 altosuilib/AltosLights.java create mode 100644 icon/telegps-128.png create mode 100644 icon/telegps-16.png create mode 100644 icon/telegps-256.png create mode 100644 icon/telegps-32.png create mode 100644 icon/telegps-48.png create mode 100644 icon/telegps-512.png create mode 100644 icon/telegps-64.png create mode 100644 icon/telegps.ico create mode 100644 icon/telegps.svg create mode 100644 telegps/TeleGPSInfo.java (limited to 'altosuilib') diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 484f6213..a65669da 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -371,4 +371,30 @@ public class AltosConvert { return 94; return (int) Math.floor (1.0/2.0 * (24.0e6/32.0) / freq + 0.5); } + + public static final int BEARING_LONG = 0; + public static final int BEARING_SHORT = 1; + public static final int BEARING_VOICE = 2; + + public static String bearing_to_words(int length, double bearing) { + String [][] bearing_string = { + { + "North", "North North East", "North East", "East North East", + "East", "East South East", "South East", "South South East", + "South", "South South West", "South West", "West South West", + "West", "West North West", "North West", "North North West" + }, { + "N", "NNE", "NE", "ENE", + "E", "ESE", "SE", "SSE", + "S", "SSW", "SW", "WSW", + "W", "WNW", "NW", "NNW" + }, { + "north", "nor nor east", "north east", "east nor east", + "east", "east sow east", "south east", "sow sow east", + "south", "sow sow west", "south west", "west sow west", + "west", "west nor west", "north west", "nor nor west " + } + }; + return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; + } } diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java index 39df4fc8..4782c34d 100644 --- a/altoslib/AltosGreatCircle.java +++ b/altoslib/AltosGreatCircle.java @@ -30,30 +30,12 @@ public class AltosGreatCircle implements Cloneable { static final double rad = Math.PI / 180; static final double earth_radius = 6371.2 * 1000; /* in meters */ - public static final int BEARING_LONG = 0; - public static final int BEARING_SHORT = 1; - public static final int BEARING_VOICE = 2; + public static final int BEARING_LONG = AltosConvert.BEARING_LONG; + public static final int BEARING_SHORT = AltosConvert.BEARING_SHORT; + public static final int BEARING_VOICE = AltosConvert.BEARING_VOICE; public String bearing_words(int length) { - String [][] bearing_string = { - { - "North", "North North East", "North East", "East North East", - "East", "East South East", "South East", "South South East", - "South", "South South West", "South West", "West South West", - "West", "West North West", "North West", "North North West" - }, { - "N", "NNE", "NE", "ENE", - "E", "ESE", "SE", "SSE", - "S", "SSW", "SW", "WSW", - "W", "WNW", "NW", "NNW" - }, { - "north", "nor nor east", "north east", "east nor east", - "east", "east sow east", "south east", "sow sow east", - "south", "sow sow west", "south west", "west sow west", - "west", "west nor west", "north west", "nor nor west " - } - }; - return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; + return AltosConvert.bearing_to_words(length, bearing); } public AltosGreatCircle (double start_lat, double start_lon, double start_alt, diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 9e8e22ac..1162e522 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -389,6 +389,10 @@ public class AltosState implements Cloneable { private AltosGpsAltitude gps_altitude; + private AltosValue gps_ground_speed; + private AltosValue gps_ascent_rate; + private AltosValue gps_course; + public double altitude() { double a = altitude.value(); if (a != AltosLib.MISSING) @@ -419,6 +423,18 @@ public class AltosState implements Cloneable { gps_altitude.set(new_gps_altitude, time); } + public double gps_ground_speed() { + return gps_ground_speed.value(); + } + + public double gps_ascent_rate() { + return gps_ascent_rate.value(); + } + + public double gps_course() { + return gps_course.value(); + } + class AltosPressure extends AltosValue { void set(double p, double time) { super.set(p, time); @@ -695,6 +711,8 @@ public class AltosState implements Cloneable { gps_altitude = new AltosGpsAltitude(); gps_ground_altitude = new AltosGpsGroundAltitude(); + gps_ground_speed = new AltosValue(); + gps_ascent_rate = new AltosValue(); speak_tick = AltosLib.MISSING; speak_altitude = AltosLib.MISSING; @@ -877,6 +895,12 @@ public class AltosState implements Cloneable { gps_ground_altitude.set(gps.alt, time); } gps_altitude.set(gps.alt, time); + if (gps.climb_rate != AltosLib.MISSING) + gps_ascent_rate.set(gps.climb_rate, time); + if (gps.ground_speed != AltosLib.MISSING) + gps_ground_speed.set(gps.ground_speed, time); + if (gps.course != AltosLib.MISSING) + gps_course.set(gps.course, time); } if (gps.lat != 0 && gps.lon != 0 && pad_lat != AltosLib.MISSING && diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java deleted file mode 100644 index a0fceee5..00000000 --- a/altosui/AltosCSVUI.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import java.io.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosCSVUI - extends AltosUIDialog - implements ActionListener -{ - JFileChooser csv_chooser; - JPanel accessory; - JComboBox combo_box; - Iterable states; - AltosWriter writer; - - static String[] combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" }; - - void set_default_file() { - File current = csv_chooser.getSelectedFile(); - String current_name = current.getName(); - String new_name = null; - String selected = (String) combo_box.getSelectedItem(); - - if (selected.contains("CSV")) - new_name = Altos.replace_extension(current_name, ".csv"); - else if (selected.contains("KML")) - new_name = Altos.replace_extension(current_name, ".kml"); - if (new_name != null) - csv_chooser.setSelectedFile(new File(new_name)); - } - - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("comboBoxChanged")) - set_default_file(); - } - - public AltosCSVUI(JFrame frame, AltosStateIterable states, File source_file) { - this.states = states; - csv_chooser = new JFileChooser(source_file); - - accessory = new JPanel(); - accessory.setLayout(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.weightx = 1; - c.weighty = 0; - c.insets = new Insets (4, 4, 4, 4); - - JLabel accessory_label = new JLabel("Export File Type"); - c.gridx = 0; - c.gridy = 0; - accessory.add(accessory_label, c); - - combo_box = new JComboBox(combo_box_items); - combo_box.addActionListener(this); - c.gridx = 0; - c.gridy = 1; - accessory.add(combo_box, c); - - csv_chooser.setAccessory(accessory); - csv_chooser.setSelectedFile(source_file); - set_default_file(); - int ret = csv_chooser.showSaveDialog(frame); - if (ret == JFileChooser.APPROVE_OPTION) { - File file = csv_chooser.getSelectedFile(); - String type = (String) combo_box.getSelectedItem(); - try { - if (type.contains("CSV")) - writer = new AltosCSV(file); - else - writer = new AltosKML(file); - writer.write(states); - writer.close(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - ee.getMessage(), - "Cannot open file", - JOptionPane.ERROR_MESSAGE); - } - } - } -} diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java deleted file mode 100644 index 43726a44..00000000 --- a/altosui/AltosDataChooser.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 javax.swing.*; -import javax.swing.filechooser.FileNameExtensionFilter; -import java.io.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosDataChooser extends JFileChooser { - JFrame frame; - String filename; - File file; - - public String filename() { - return filename; - } - - public File file() { - return file; - } - - public AltosStateIterable runDialog() { - int ret; - - ret = showOpenDialog(frame); - if (ret == APPROVE_OPTION) { - file = getSelectedFile(); - if (file == null) - return null; - filename = file.getName(); - try { - if (filename.endsWith("eeprom")) { - FileInputStream in = new FileInputStream(file); - return new AltosEepromFile(in); - } else if (filename.endsWith("telem")) { - FileInputStream in = new FileInputStream(file); - return new AltosTelemetryFile(in); - } else { - throw new FileNotFoundException(); - } - } catch (FileNotFoundException fe) { - JOptionPane.showMessageDialog(frame, - fe.getMessage(), - "Cannot open file", - JOptionPane.ERROR_MESSAGE); - } - } - return null; - } - - public AltosDataChooser(JFrame in_frame) { - frame = in_frame; - setDialogTitle("Select Flight Record File"); - setFileFilter(new FileNameExtensionFilter("TeleMetrum eeprom file", - "eeprom")); - setFileFilter(new FileNameExtensionFilter("Telemetry file", - "telem")); - setFileFilter(new FileNameExtensionFilter("TeleMega eeprom file", - "mega")); - setFileFilter(new FileNameExtensionFilter("EasyMini eeprom file", - "mini")); - setFileFilter(new FileNameExtensionFilter("Flight data file", - "telem", "eeprom", "mega", "mini")); - setCurrentDirectory(AltosUIPreferences.logdir()); - } -} diff --git a/altosui/AltosLed.java b/altosui/AltosLed.java deleted file mode 100644 index 93064f1e..00000000 --- a/altosui/AltosLed.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 javax.swing.*; - -public class AltosLed extends JLabel { - ImageIcon on, off; - - ImageIcon create_icon(String path) { - java.net.URL imgURL = AltosUI.class.getResource(path); - if (imgURL != null) - return new ImageIcon(imgURL); - System.err.printf("Cannot find icon \"%s\"\n", path); - return null; - } - - public void set(boolean set) { - if (set) - setIcon(on); - else - setIcon(off); - } - - public AltosLed(String on_path, String off_path) { - on = create_icon(on_path); - off = create_icon(off_path); - setIcon(off); - } -} diff --git a/altosui/AltosLights.java b/altosui/AltosLights.java deleted file mode 100644 index 7ad22f3e..00000000 --- a/altosui/AltosLights.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import javax.swing.*; - -public class AltosLights extends JComponent { - - GridBagLayout gridbag; - - AltosLed red, green; - - ImageIcon create_icon(String path, String description) { - java.net.URL imgURL = AltosUI.class.getResource(path); - if (imgURL != null) - return new ImageIcon(imgURL, description); - System.err.printf("Cannot find icon \"%s\"\n", path); - return null; - } - - public void set (boolean on) { - if (on) { - red.set(false); - green.set(true); - } else { - red.set(true); - green.set(false); - } - } - - public AltosLights() { - GridBagConstraints c; - gridbag = new GridBagLayout(); - setLayout(gridbag); - - c = new GridBagConstraints(); - red = new AltosLed("/redled.png", "/grayled.png"); - c.gridx = 0; c.gridy = 0; - c.insets = new Insets (0, 5, 0, 5); - gridbag.setConstraints(red, c); - add(red); - red.set(true); - green = new AltosLed("/greenled.png", "/grayled.png"); - c.gridx = 1; c.gridy = 0; - gridbag.setConstraints(green, c); - add(green); - green.set(false); - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index c834646d..9eff1614 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -20,7 +20,6 @@ altosui_JAVA = \ AltosConfigureUI.java \ AltosConfigTD.java \ AltosConfigTDUI.java \ - AltosCSVUI.java \ AltosDescent.java \ AltosFlashUI.java \ AltosFlightInfoTableModel.java \ @@ -36,8 +35,6 @@ altosui_JAVA = \ AltosLaunchUI.java \ AltosInfoTable.java \ AltosLanded.java \ - AltosLed.java \ - AltosLights.java \ AltosPad.java \ AltosUIPreferencesBackend.java \ AltosRomconfigUI.java \ @@ -45,8 +42,7 @@ altosui_JAVA = \ AltosGraph.java \ AltosGraphDataPoint.java \ AltosGraphDataSet.java \ - AltosGraphUI.java \ - AltosDataChooser.java + AltosGraphUI.java JFREECHART_CLASS= \ jfreechart.jar @@ -94,20 +90,13 @@ JAVA_ICONS=\ $(ICONDIR)/altus-metrum-128.png \ $(ICONDIR)/altus-metrum-256.png -ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \ - $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \ - $(ICONDIR)/grayled.png $(ICONDIR)/grayoff.png - # icon base names for jar ICONJAR= -C $(ICONDIR) altus-metrum-16.png \ -C $(ICONDIR) altus-metrum-32.png \ -C $(ICONDIR) altus-metrum-48.png \ -C $(ICONDIR) altus-metrum-64.png \ -C $(ICONDIR) altus-metrum-128.png \ - -C $(ICONDIR) altus-metrum-256.png \ - -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \ - -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \ - -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png + -C $(ICONDIR) altus-metrum-256.png WINDOWS_ICON=$(ICONDIR)/altus-metrum.ico diff --git a/altosuilib/AltosCSVUI.java b/altosuilib/AltosCSVUI.java new file mode 100644 index 00000000..0a5e4fa2 --- /dev/null +++ b/altosuilib/AltosCSVUI.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosCSVUI + extends AltosUIDialog + implements ActionListener +{ + JFileChooser csv_chooser; + JPanel accessory; + JComboBox combo_box; + Iterable states; + AltosWriter writer; + + static String[] combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" }; + + void set_default_file() { + File current = csv_chooser.getSelectedFile(); + String current_name = current.getName(); + String new_name = null; + String selected = (String) combo_box.getSelectedItem(); + + if (selected.contains("CSV")) + new_name = AltosLib.replace_extension(current_name, ".csv"); + else if (selected.contains("KML")) + new_name = AltosLib.replace_extension(current_name, ".kml"); + if (new_name != null) + csv_chooser.setSelectedFile(new File(new_name)); + } + + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("comboBoxChanged")) + set_default_file(); + } + + public AltosCSVUI(JFrame frame, AltosStateIterable states, File source_file) { + this.states = states; + csv_chooser = new JFileChooser(source_file); + + accessory = new JPanel(); + accessory.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.weightx = 1; + c.weighty = 0; + c.insets = new Insets (4, 4, 4, 4); + + JLabel accessory_label = new JLabel("Export File Type"); + c.gridx = 0; + c.gridy = 0; + accessory.add(accessory_label, c); + + combo_box = new JComboBox(combo_box_items); + combo_box.addActionListener(this); + c.gridx = 0; + c.gridy = 1; + accessory.add(combo_box, c); + + csv_chooser.setAccessory(accessory); + csv_chooser.setSelectedFile(source_file); + set_default_file(); + int ret = csv_chooser.showSaveDialog(frame); + if (ret == JFileChooser.APPROVE_OPTION) { + File file = csv_chooser.getSelectedFile(); + String type = (String) combo_box.getSelectedItem(); + try { + if (type.contains("CSV")) + writer = new AltosCSV(file); + else + writer = new AltosKML(file); + writer.write(states); + writer.close(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + ee.getMessage(), + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + } +} diff --git a/altosuilib/AltosDataChooser.java b/altosuilib/AltosDataChooser.java new file mode 100644 index 00000000..14d28115 --- /dev/null +++ b/altosuilib/AltosDataChooser.java @@ -0,0 +1,82 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosDataChooser extends JFileChooser { + JFrame frame; + String filename; + File file; + + public String filename() { + return filename; + } + + public File file() { + return file; + } + + public AltosStateIterable runDialog() { + int ret; + + ret = showOpenDialog(frame); + if (ret == APPROVE_OPTION) { + file = getSelectedFile(); + if (file == null) + return null; + filename = file.getName(); + try { + if (filename.endsWith("eeprom")) { + FileInputStream in = new FileInputStream(file); + return new AltosEepromFile(in); + } else if (filename.endsWith("telem")) { + FileInputStream in = new FileInputStream(file); + return new AltosTelemetryFile(in); + } else { + throw new FileNotFoundException(); + } + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + fe.getMessage(), + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + return null; + } + + public AltosDataChooser(JFrame in_frame) { + frame = in_frame; + setDialogTitle("Select Flight Record File"); + setFileFilter(new FileNameExtensionFilter("TeleMetrum eeprom file", + "eeprom")); + setFileFilter(new FileNameExtensionFilter("Telemetry file", + "telem")); + setFileFilter(new FileNameExtensionFilter("TeleMega eeprom file", + "mega")); + setFileFilter(new FileNameExtensionFilter("EasyMini eeprom file", + "mini")); + setFileFilter(new FileNameExtensionFilter("Flight data file", + "telem", "eeprom", "mega", "mini")); + setCurrentDirectory(AltosUIPreferences.logdir()); + } +} diff --git a/altosuilib/AltosLed.java b/altosuilib/AltosLed.java new file mode 100644 index 00000000..2debb62a --- /dev/null +++ b/altosuilib/AltosLed.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.*; + +public class AltosLed extends JLabel { + ImageIcon on, off; + + ImageIcon create_icon(String path) { + java.net.URL imgURL = AltosUILib.class.getResource(path); + if (imgURL != null) + return new ImageIcon(imgURL); + System.err.printf("Cannot find icon \"%s\"\n", path); + return null; + } + + public void set(boolean set) { + if (set) + setIcon(on); + else + setIcon(off); + } + + public AltosLed(String on_path, String off_path) { + on = create_icon(on_path); + off = create_icon(off_path); + setIcon(off); + } +} diff --git a/altosuilib/AltosLights.java b/altosuilib/AltosLights.java new file mode 100644 index 00000000..c91b70e9 --- /dev/null +++ b/altosuilib/AltosLights.java @@ -0,0 +1,65 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import javax.swing.*; + +public class AltosLights extends JComponent { + + GridBagLayout gridbag; + + AltosLed red, green; + + ImageIcon create_icon(String path, String description) { + java.net.URL imgURL = AltosUILib.class.getResource(path); + if (imgURL != null) + return new ImageIcon(imgURL, description); + System.err.printf("Cannot find icon \"%s\"\n", path); + return null; + } + + public void set (boolean on) { + if (on) { + red.set(false); + green.set(true); + } else { + red.set(true); + green.set(false); + } + } + + public AltosLights() { + GridBagConstraints c; + gridbag = new GridBagLayout(); + setLayout(gridbag); + + c = new GridBagConstraints(); + red = new AltosLed("/redled.png", "/grayled.png"); + c.gridx = 0; c.gridy = 0; + c.insets = new Insets (0, 5, 0, 5); + gridbag.setConstraints(red, c); + add(red); + red.set(true); + green = new AltosLed("/greenled.png", "/grayled.png"); + c.gridx = 1; c.gridy = 0; + gridbag.setConstraints(green, c); + add(green); + green.set(false); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 4dc4c47f..f554fd74 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -50,6 +50,10 @@ altosuilib_JAVA = \ AltosEepromManage.java \ AltosEepromMonitorUI.java \ AltosEepromSelect.java \ + AltosCSVUI.java \ + AltosDataChooser.java \ + AltosLights.java \ + AltosLed.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ @@ -58,6 +62,18 @@ altosuilib_JAVA = \ JAR=altosuilib_$(ALTOSUILIB_VERSION).jar +# Icons +ICONDIR=$(top_srcdir)/icon + +ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \ + $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \ + $(ICONDIR)/grayon.png $(ICONDIR)/grayled.png + +# icon base names for jar +ICONJAR= -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \ + -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \ + -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png + all-local: $(JAR) clean-local: @@ -72,5 +88,5 @@ install-altosuilibJAVA: $(JAR) $(JAVAROOT): mkdir -p $(JAVAROOT) -$(JAR): classaltosuilib.stamp - jar cf $@ -C $(JAVAROOT) . +$(JAR): classaltosuilib.stamp $(ICONS) + jar cf $@ $(ICONJAR) -C $(JAVAROOT) . diff --git a/icon/telegps-128.png b/icon/telegps-128.png new file mode 100644 index 00000000..f1343d9e Binary files /dev/null and b/icon/telegps-128.png differ diff --git a/icon/telegps-16.png b/icon/telegps-16.png new file mode 100644 index 00000000..5bd45999 Binary files /dev/null and b/icon/telegps-16.png differ diff --git a/icon/telegps-256.png b/icon/telegps-256.png new file mode 100644 index 00000000..46e1670a Binary files /dev/null and b/icon/telegps-256.png differ diff --git a/icon/telegps-32.png b/icon/telegps-32.png new file mode 100644 index 00000000..c8588899 Binary files /dev/null and b/icon/telegps-32.png differ diff --git a/icon/telegps-48.png b/icon/telegps-48.png new file mode 100644 index 00000000..3bee98e6 Binary files /dev/null and b/icon/telegps-48.png differ diff --git a/icon/telegps-512.png b/icon/telegps-512.png new file mode 100644 index 00000000..47c47003 Binary files /dev/null and b/icon/telegps-512.png differ diff --git a/icon/telegps-64.png b/icon/telegps-64.png new file mode 100644 index 00000000..0ee086a6 Binary files /dev/null and b/icon/telegps-64.png differ diff --git a/icon/telegps.ico b/icon/telegps.ico new file mode 100644 index 00000000..bedf04ef Binary files /dev/null and b/icon/telegps.ico differ diff --git a/icon/telegps.svg b/icon/telegps.svg new file mode 100644 index 00000000..256b8c5a --- /dev/null +++ b/icon/telegps.svg @@ -0,0 +1,215 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/telegps/Makefile.am b/telegps/Makefile.am index 280b1e40..f8e2e63c 100644 --- a/telegps/Makefile.am +++ b/telegps/Makefile.am @@ -15,6 +15,7 @@ telegps_JAVA= \ TeleGPS.java \ TeleGPSStatus.java \ TeleGPSStatusUpdate.java \ + TeleGPSInfo.java \ TeleGPSConfig.java \ TeleGPSConfigUI.java \ TeleGPSPreferences.java diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index ad46fbdd..1bb505e0 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -53,6 +53,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo JTabbedPane pane; AltosSiteMap sitemap; + TeleGPSInfo gps_info; boolean has_map; JMenuBar menu_bar; @@ -115,10 +116,12 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo public void reset() { sitemap.reset(); + gps_info.reset(); } public void set_font() { sitemap.set_font(); + gps_info.set_font(); } public void font_size_changed(int font_size) { @@ -135,6 +138,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo state = new AltosState(); sitemap.show(state, listener_state); + gps_info.show(state, listener_state); telegps_status.show(state, listener_state); } @@ -225,6 +229,12 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo } void export() { + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosStateIterable states = chooser.runDialog(); + if (states == null) + return; + new AltosCSVUI(this, states, chooser.file()); } void graph() { @@ -394,6 +404,9 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo sitemap = new AltosSiteMap(); pane.add("Site Map", sitemap); + gps_info = new TeleGPSInfo(); + pane.add("Info", gps_info); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); AltosUIPreferences.register_font_listener(this); diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java new file mode 100644 index 00000000..0fba77d5 --- /dev/null +++ b/telegps/TeleGPSInfo.java @@ -0,0 +1,511 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.telegps; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; + +public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + JLabel cur, max; + + public class Info { + JLabel label; + JTextField value; + AltosLights lights; + + void show() { + value.setVisible(true); + lights.setVisible(true); + label.setVisible(true); + } + + void hide() { + value.setVisible(false); + lights.setVisible(false); + label.setVisible(false); + } + + void show(AltosState state, AltosListenerState listener_state) {} + + void show(String s) { + show(); + value.setText(s); + } + + void show(AltosUnits units, double v) { + show(units.show(8, v)); + } + + void show(String format, double v) { + show(String.format(format, v)); + } + + void reset() { + lights.set(false); + value.setText(""); + } + + void set_font() { + label.setFont(AltosUILib.label_font); + value.setFont(AltosUILib.value_font); + } + + public Info (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + add(lights); + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(AltosUILib.text_width); + value.setFont(AltosUILib.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.gridwidth = 2; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + + public class Value { + JLabel label; + JTextField value; + void show(AltosState state, AltosListenerState listener_state) {} + + void reset() { + value.setText(""); + } + + void show() { + label.setVisible(true); + value.setVisible(true); + } + + void show(String s) { + show(); + value.setText(s); + } + + void show(AltosUnits units, double v) { + show(units.show(8, v)); + } + + void show(String format, double v) { + show(String.format(format, v)); + } + + void hide() { + label.setVisible(false); + value.setVisible(false); + } + void set_font() { + label.setFont(AltosUILib.label_font); + value.setFont(AltosUILib.value_font); + } + + public Value (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(AltosUILib.text_width); + value.setFont(AltosUILib.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.gridwidth = 2; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + + public abstract class DualValue { + JLabel label; + JTextField value1; + JTextField value2; + + void reset() { + value1.setText(""); + value2.setText(""); + } + + void show() { + label.setVisible(true); + value1.setVisible(true); + value2.setVisible(true); + } + + void hide() { + label.setVisible(false); + value1.setVisible(false); + value2.setVisible(false); + } + + void set_font() { + label.setFont(AltosUILib.label_font); + value1.setFont(AltosUILib.value_font); + value2.setFont(AltosUILib.value_font); + } + + abstract void show(AltosState state, AltosListenerState listener_state); + + void show(String v1, String v2) { + show(); + value1.setText(v1); + value2.setText(v2); + } + void show(String f1, double v1, String f2, double v2) { + show(); + value1.setText(String.format(f1, v1)); + value2.setText(String.format(f2, v2)); + } + + public DualValue (GridBagLayout layout, int x, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = x + 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value1 = new JTextField(AltosUILib.text_width); + value1.setFont(AltosUILib.value_font); + value1.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value1, c); + add(value1); + + value2 = new JTextField(AltosUILib.text_width); + value2.setFont(AltosUILib.value_font); + value2.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 3; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.gridwidth = 1; + layout.setConstraints(value2, c); + add(value2); + } + } + + public class ValueHold { + JLabel label; + JTextField value; + JTextField max_value; + double max; + + void show(AltosState state, AltosListenerState listener_state) {} + + void reset() { + value.setText(""); + max_value.setText(""); + max = AltosLib.MISSING; + } + + void set_font() { + label.setFont(AltosUILib.label_font); + value.setFont(AltosUILib.value_font); + max_value.setFont(AltosUILib.value_font); + } + + void show(AltosUnits units, double v) { + if (v == AltosLib.MISSING) { + value.setText("Missing"); + max_value.setText("Missing"); + } else { + value.setText(units.show(8, v)); + if (v > max || max == AltosLib.MISSING) { + max_value.setText(units.show(8, v)); + max = v; + } + } + } + + void hide() { + label.setVisible(false); + value.setVisible(false); + max_value.setVisible(false); + } + + public ValueHold (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(AltosUILib.text_width); + value.setFont(AltosUILib.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + + max_value = new JTextField(AltosUILib.text_width); + max_value.setFont(AltosUILib.value_font); + max_value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 3; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(max_value, c); + add(max_value); + } + } + + + class Altitude extends ValueHold { + void show (AltosState state, AltosListenerState listener_state) { + show(AltosConvert.height, state.altitude()); + } + public Altitude (GridBagLayout layout, int y) { + super (layout, y, "Altitude"); + } + } + + Altitude altitude; + + class AscentRate extends ValueHold { + void show (AltosState state, AltosListenerState listener_state) { + show(AltosConvert.speed, state.gps_ascent_rate()); + } + public AscentRate (GridBagLayout layout, int y) { + super (layout, y, "Ascent Rate"); + } + } + + AscentRate ascent_rate; + + class GroundSpeed extends ValueHold { + void show (AltosState state, AltosListenerState listener_state) { + show(AltosConvert.speed, state.gps_ground_speed()); + } + public GroundSpeed (GridBagLayout layout, int y) { + super (layout, y, "Ground Speed"); + } + } + + GroundSpeed ground_speed; + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class Course extends DualValue { + void show (AltosState state, AltosListenerState listener_state) { + double course = state.gps_course(); + if (course != AltosLib.MISSING) + show( String.format("%3.0f°", course), + AltosConvert.bearing_to_words( + AltosConvert.BEARING_LONG, + course)); + } + public Course (GridBagLayout layout, int y) { + super (layout, 0, y, "Course"); + } + } + + Course course; + + class Lat extends Value { + void show (AltosState state, AltosListenerState listener_state) { + if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING) + show(pos(state.gps.lat,"N", "S")); + else + show("???"); + } + public Lat (GridBagLayout layout, int y) { + super (layout, y, "Latitude"); + } + } + + Lat lat; + + class Lon extends Value { + void show (AltosState state, AltosListenerState listener_state) { + if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING) + show(pos(state.gps.lon,"E", "W")); + else + show("???"); + } + public Lon (GridBagLayout layout, int y) { + super (layout, y, "Longitude"); + } + } + + Lon lon; + + class GPSLocked extends Info { + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.gps == null) + hide(); + else { + show("%4d sats", state.gps.nsat); + lights.set(state.gps.locked && state.gps.nsat >= 4); + } + } + public GPSLocked (GridBagLayout layout, int y) { + super (layout, y, "GPS Locked"); + } + } + + GPSLocked gps_locked; + + public void reset() { + lat.reset(); + lon.reset(); + altitude.reset(); + ground_speed.reset(); + ascent_rate.reset(); + course.reset(); + gps_locked.reset(); + } + + public void set_font() { + cur.setFont(AltosUILib.label_font); + max.setFont(AltosUILib.label_font); + lat.set_font(); + lon.set_font(); + altitude.set_font(); + ground_speed.set_font(); + ascent_rate.set_font(); + course.set_font(); + gps_locked.set_font(); + } + + public void show(AltosState state, AltosListenerState listener_state) { + if (state.gps != null && state.gps.connected) { + lat.show(state, listener_state); + lon.show(state, listener_state); + } else { + lat.hide(); + lon.hide(); + } + altitude.show(state, listener_state); + ground_speed.show(state, listener_state); + ascent_rate.show(state, listener_state); + course.show(state, listener_state); + gps_locked.show(state, listener_state); + } + + public void labels(GridBagLayout layout, int y) { + GridBagConstraints c; + + cur = new JLabel("Current"); + cur.setFont(AltosUILib.label_font); + c = new GridBagConstraints(); + c.gridx = 2; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + layout.setConstraints(cur, c); + add(cur); + + max = new JLabel("Maximum"); + max.setFont(AltosUILib.label_font); + c.gridx = 3; c.gridy = y; + layout.setConstraints(max, c); + add(max); + } + + public String getName() { + return "Info"; + } + + public TeleGPSInfo() { + layout = new GridBagLayout(); + + setLayout(layout); + + /* Elements in ascent display: + * + * lat + * lon + * height + */ + int y = 0; + labels(layout, y++); + altitude = new Altitude(layout, y++); + ground_speed = new GroundSpeed(layout, y++); + ascent_rate = new AscentRate(layout, y++); + course = new Course(layout, y++); + lat = new Lat(layout, y++); + lon = new Lon(layout, y++); + gps_locked = new GPSLocked(layout, y++); + } +} -- cgit v1.2.3 From 13f84be8d1568a3fc2ed5eef5dcc2093c149285e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 May 2014 22:53:06 -0700 Subject: telegps: Add flash device functionality Move bits from altosui to altosuilib and use those. Signed-off-by: Keith Packard --- altosui/AltosFlashUI.java | 440 --------------------------------------- altosui/AltosRomconfigUI.java | 191 ----------------- altosui/Makefile.am | 2 - altosuilib/AltosFlashUI.java | 438 ++++++++++++++++++++++++++++++++++++++ altosuilib/AltosRomconfigUI.java | 190 +++++++++++++++++ altosuilib/Makefile.am | 2 + telegps/TeleGPS.java | 16 +- 7 files changed, 641 insertions(+), 638 deletions(-) delete mode 100644 altosui/AltosFlashUI.java delete mode 100644 altosui/AltosRomconfigUI.java create mode 100644 altosuilib/AltosFlashUI.java create mode 100644 altosuilib/AltosRomconfigUI.java (limited to 'altosuilib') diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java deleted file mode 100644 index d8c70a06..00000000 --- a/altosui/AltosFlashUI.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.filechooser.FileNameExtensionFilter; -import java.io.*; -import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosFlashUI - extends AltosUIDialog - implements ActionListener -{ - Container pane; - Box box; - JLabel serial_label; - JLabel serial_value; - JLabel file_label; - JLabel file_value; - JProgressBar pbar; - JButton cancel; - - JFrame frame; - - // Hex file with rom image - File file; - - // Debug connection - AltosDevice device; - - AltosLink link; - - // Desired Rom configuration - AltosRomconfig rom_config; - - // Flash controller - AltosProgrammer programmer; - - private static String[] pair_programmed = { - "teleballoon", - "telebt", - "teledongle", - "telefire", - "telemetrum-v0", - "telemetrum-v1", - "telemini", - "telenano", - "teleshield", - "teleterra" - }; - - private boolean is_pair_programmed() { - - if (file != null) { - String name = file.getName(); - for (int i = 0; i < pair_programmed.length; i++) { - if (name.startsWith(pair_programmed[i])) - return true; - } - } - if (device != null) { - if (!device.matchProduct(AltosLib.product_altusmetrum) && - (device.matchProduct(AltosLib.product_teledongle) || - device.matchProduct(AltosLib.product_telebt))) - return true; - } - return false; - } - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == cancel) { - if (programmer != null) - programmer.abort(); - setVisible(false); - dispose(); - } else { - String cmd = e.getActionCommand(); - if (e.getID() == -1) { - JOptionPane.showMessageDialog(frame, - e.getActionCommand(), - file.toString(), - JOptionPane.ERROR_MESSAGE); - setVisible(false); - dispose(); - } else if (cmd.equals("done")) { - setVisible(false); - dispose(); - } else if (cmd.equals("start")) { - setVisible(true); - } else { - pbar.setValue(e.getID()); - pbar.setString(cmd); - } - } - } - - public void build_dialog() { - GridBagConstraints c; - Insets il = new Insets(4,4,4,4); - Insets ir = new Insets(4,4,4,4); - - pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 0; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - serial_label = new JLabel("Serial:"); - pane.add(serial_label, c); - - c = new GridBagConstraints(); - c.gridx = 1; c.gridy = 0; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - serial_value = new JLabel(""); - pane.add(serial_value, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.gridx = 0; c.gridy = 1; - 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 = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - file_value = new JLabel(file.toString()); - pane.add(file_value, c); - - pbar = new JProgressBar(); - pbar.setMinimum(0); - pbar.setMaximum(100); - pbar.setValue(0); - pbar.setString(""); - pbar.setStringPainted(true); - pbar.setPreferredSize(new Dimension(600, 20)); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; c.gridy = 2; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ib = new Insets(4,4,4,4); - c.insets = ib; - pane.add(pbar, c); - - cancel = new JButton("Cancel"); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; c.gridy = 3; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ic = new Insets(4,4,4,4); - c.insets = ic; - pane.add(cancel, c); - cancel.addActionListener(this); - pack(); - setLocationRelativeTo(frame); - } - - void set_serial(int serial_number) { - serial_value.setText(String.format("%d", serial_number)); - } - - static class AltosHexfileFilter extends javax.swing.filechooser.FileFilter { - int product; - String head; - String description; - - public AltosHexfileFilter(int product, String head, String description) { - this.product = product; - this.head = head; - this.description = description; - } - - public boolean accept(File file) { - return !file.isFile() || (file.getName().startsWith(head) && file.getName().endsWith(".ihx")); - } - - public String getDescription() { - return description; - } - } - - static AltosHexfileFilter[] filters = { - new AltosHexfileFilter(AltosLib.product_telemetrum, "telemetrum", "TeleMetrum Image"), - new AltosHexfileFilter(AltosLib.product_teledongle, "teledongle", "TeleDongle Image"), - new AltosHexfileFilter(AltosLib.product_telemega, "telemega", "TeleMega Image"), - new AltosHexfileFilter(AltosLib.product_easymini, "easymini", "EasyMini Image"), - }; - - boolean select_source_file() { - JFileChooser hexfile_chooser = new JFileChooser(); - - File firmwaredir = AltosUIPreferences.firmwaredir(); - if (firmwaredir != null) - hexfile_chooser.setCurrentDirectory(firmwaredir); - - hexfile_chooser.setDialogTitle("Select Flash Image"); - - for (int i = 0; i < filters.length; i++) { - hexfile_chooser.addChoosableFileFilter(filters[i]); - } - javax.swing.filechooser.FileFilter ihx_filter = new FileNameExtensionFilter("Flash Image", "ihx"); - hexfile_chooser.addChoosableFileFilter(ihx_filter); - hexfile_chooser.setFileFilter(ihx_filter); - - if (!is_pair_programmed() && !device.matchProduct(AltosLib.product_altusmetrum)) { - for (int i = 0; i < filters.length; i++) { - if (device != null && device.matchProduct(filters[i].product)) - hexfile_chooser.setFileFilter(filters[i]); - } - } - - int returnVal = hexfile_chooser.showOpenDialog(frame); - - if (returnVal != JFileChooser.APPROVE_OPTION) - return false; - file = hexfile_chooser.getSelectedFile(); - if (file == null) - return false; - AltosUIPreferences.set_firmwaredir(file.getParentFile()); - - return true; - } - - boolean select_device() { - int product = Altos.product_any; - - device = AltosDeviceUIDialog.show(frame, Altos.product_any); - - if (device == null) - return false; - return true; - } - - boolean update_rom_config_info(AltosRomconfig existing_config) { - AltosRomconfig new_config; - new_config = AltosRomconfigUI.show(frame, existing_config); - if (new_config == null) - return false; - rom_config = new_config; - set_serial(rom_config.serial_number); - setVisible(true); - return true; - } - - void exception (Exception e) { - if (e instanceof FileNotFoundException) { - JOptionPane.showMessageDialog(frame, - ((FileNotFoundException) e).getMessage(), - "Cannot open file", - JOptionPane.ERROR_MESSAGE); - } else if (e instanceof AltosSerialInUseException) { - JOptionPane.showMessageDialog(frame, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } else if (e instanceof IOException) { - JOptionPane.showMessageDialog(frame, - e.getMessage(), - file.toString(), - JOptionPane.ERROR_MESSAGE); - } - } - - class flash_task implements Runnable, AltosFlashListener { - AltosFlashUI ui; - Thread t; - AltosProgrammer programmer; - - public void position(String in_s, int in_percent) { - final String s = in_s; - final int percent = in_percent; - Runnable r = new Runnable() { - public void run() { - try { - ui.actionPerformed(new ActionEvent(this, - percent, - s)); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - public void run () { - try { - if (ui.is_pair_programmed()) - programmer = new AltosFlash(ui.file, link, this); - else - programmer = new AltosSelfFlash(ui.file, link, this); - - final AltosRomconfig current_config = programmer.romconfig(); - - final Semaphore await_rom_config = new Semaphore(0); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - ui.programmer = programmer; - ui.update_rom_config_info(current_config); - await_rom_config.release(); - } - }); - await_rom_config.acquire(); - - if (ui.rom_config != null) { - programmer.set_romconfig(ui.rom_config); - programmer.flash(); - } - } catch (InterruptedException ee) { - final Exception e = ee; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - ui.exception(e); - } - }); - } catch (IOException ee) { - final Exception e = ee; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - ui.exception(e); - } - }); - } finally { - if (programmer != null) - programmer.close(); - } - } - - public flash_task(AltosFlashUI in_ui) { - ui = in_ui; - t = new Thread(this); - t.start(); - } - } - - flash_task flasher; - - private boolean open_device() throws InterruptedException { - try { - link = new AltosSerial(device); - if (is_pair_programmed()) - return true; - - if (link == null) - throw new IOException(String.format("%s: open failed", device.toShortString())); - - while (!link.is_loader()) { - link.to_loader(); - - java.util.List devices = null; - - for (int tries = 0; tries < 10; tries++) { - Thread.sleep(100); - devices = AltosUSBDevice.list(AltosLib.product_altusmetrum); - if (devices.size() != 0) - break; - } - - if (devices.size() == 1) - device = devices.get(0); - else { - device = AltosDeviceUIDialog.show(frame, AltosLib.product_altusmetrum); - if (device == null) - return false; - } - link = new AltosSerial(device); - } - return true; - } catch (AltosSerialInUseException ee) { - exception(ee); - } catch (FileNotFoundException fe) { - exception(fe); - } catch (IOException ie) { - exception (ie); - } - return false; - } - - /* - * Execute the steps for flashing - * a device. Note that this returns immediately; - * this dialog is not modal - */ - void showDialog() { - if (!select_device()) - return; - if (!select_source_file()) - return; - try { - if (!open_device()) - return; - } catch (InterruptedException ie) { - return; - } - build_dialog(); - flash_task f = new flash_task(this); - } - - static void show(JFrame frame) { - AltosFlashUI ui = new AltosFlashUI(frame); - - ui.showDialog(); - } - - public AltosFlashUI(JFrame in_frame) { - super(in_frame, "Program Altusmetrum Device", false); - - frame = in_frame; - } -} diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java deleted file mode 100644 index d2fe54d9..00000000 --- a/altosui/AltosRomconfigUI.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosRomconfigUI - extends AltosUIDialog - implements ActionListener -{ - Container pane; - Box box; - JLabel serial_label; - JLabel radio_calibration_label; - - JFrame owner; - JTextField serial_value; - JTextField radio_calibration_value; - - JButton ok; - JButton cancel; - - /* Build the UI using a grid bag */ - public AltosRomconfigUI(JFrame in_owner) { - super (in_owner, "Configure TeleMetrum Rom Values", true); - - owner = in_owner; - GridBagConstraints c; - - Insets il = new Insets(4,4,4,4); - Insets ir = new Insets(4,4,4,4); - - pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - /* Serial */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 0; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - serial_label = new JLabel("Serial:"); - pane.add(serial_label, c); - - c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 0; - c.gridwidth = 3; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - serial_value = new JTextField("00000000"); - pane.add(serial_value, c); - - /* Radio calibration value */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 1; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - c.ipady = 5; - radio_calibration_label = new JLabel("Radio Calibration:"); - pane.add(radio_calibration_label, c); - - c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 1; - c.gridwidth = 3; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - c.ipady = 5; - radio_calibration_value = new JTextField("00000000"); - pane.add(radio_calibration_value, c); - - /* Buttons */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 2; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = il; - ok = new JButton("OK"); - pane.add(ok, c); - ok.addActionListener(this); - ok.setActionCommand("ok"); - - c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 2; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = il; - cancel = new JButton("Cancel"); - pane.add(cancel, c); - cancel.addActionListener(this); - cancel.setActionCommand("cancel"); - - pack(); - setLocationRelativeTo(owner); - } - - public AltosRomconfigUI(JFrame frame, AltosRomconfig config) { - this(frame); - set(config); - } - - boolean selected; - - /* Listen for events from our buttons */ - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - - if (cmd.equals("ok")) { - AltosRomconfig romconfig = romconfig(); - if (romconfig == null || !romconfig.valid()) { - JOptionPane.showMessageDialog(this, - "Invalid serial number or radio calibration value", - "Invalid rom configuration", - JOptionPane.ERROR_MESSAGE); - return; - } - selected = true; - } - setVisible(false); - } - - int serial() { - return Integer.parseInt(serial_value.getText()); - } - - void set_serial(int serial) { - serial_value.setText(String.format("%d", serial)); - } - - int radio_calibration() { - return Integer.parseInt(radio_calibration_value.getText()); - } - - void set_radio_calibration(int calibration) { - radio_calibration_value.setText(String.format("%d", calibration)); - } - - public void set(AltosRomconfig config) { - if (config != null && config.valid()) { - set_serial(config.serial_number); - set_radio_calibration(config.radio_calibration); - } - } - - AltosRomconfig romconfig() { - try { - return new AltosRomconfig(serial(), radio_calibration()); - } catch (NumberFormatException ne) { - return null; - } - } - - public AltosRomconfig showDialog() { - setVisible(true); - if (selected) - return romconfig(); - return null; - } - - public static AltosRomconfig show(JFrame frame, AltosRomconfig config) { - AltosRomconfigUI ui = new AltosRomconfigUI(frame, config); - return ui.showDialog(); - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 9eff1614..686b5967 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -21,7 +21,6 @@ altosui_JAVA = \ AltosConfigTD.java \ AltosConfigTDUI.java \ AltosDescent.java \ - AltosFlashUI.java \ AltosFlightInfoTableModel.java \ AltosFlightStatsTable.java \ AltosFlightStatus.java \ @@ -37,7 +36,6 @@ altosui_JAVA = \ AltosLanded.java \ AltosPad.java \ AltosUIPreferencesBackend.java \ - AltosRomconfigUI.java \ AltosUI.java \ AltosGraph.java \ AltosGraphDataPoint.java \ diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java new file mode 100644 index 00000000..3f120617 --- /dev/null +++ b/altosuilib/AltosFlashUI.java @@ -0,0 +1,438 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosFlashUI + extends AltosUIDialog + implements ActionListener +{ + Container pane; + Box box; + JLabel serial_label; + JLabel serial_value; + JLabel file_label; + JLabel file_value; + JProgressBar pbar; + JButton cancel; + + AltosUIFrame frame; + + // Hex file with rom image + File file; + + // Debug connection + AltosDevice device; + + AltosLink link; + + // Desired Rom configuration + AltosRomconfig rom_config; + + // Flash controller + AltosProgrammer programmer; + + private static String[] pair_programmed = { + "teleballoon", + "telebt", + "teledongle", + "telefire", + "telemetrum-v0", + "telemetrum-v1", + "telemini", + "telenano", + "teleshield", + "teleterra" + }; + + private boolean is_pair_programmed() { + + if (file != null) { + String name = file.getName(); + for (int i = 0; i < pair_programmed.length; i++) { + if (name.startsWith(pair_programmed[i])) + return true; + } + } + if (device != null) { + if (!device.matchProduct(AltosLib.product_altusmetrum) && + (device.matchProduct(AltosLib.product_teledongle) || + device.matchProduct(AltosLib.product_telebt))) + return true; + } + return false; + } + + public void actionPerformed(ActionEvent e) { + if (e.getSource() == cancel) { + if (programmer != null) + programmer.abort(); + setVisible(false); + dispose(); + } else { + String cmd = e.getActionCommand(); + if (e.getID() == -1) { + JOptionPane.showMessageDialog(frame, + e.getActionCommand(), + file.toString(), + JOptionPane.ERROR_MESSAGE); + setVisible(false); + dispose(); + } else if (cmd.equals("done")) { + setVisible(false); + dispose(); + } else if (cmd.equals("start")) { + setVisible(true); + } else { + pbar.setValue(e.getID()); + pbar.setString(cmd); + } + } + } + + public void build_dialog() { + GridBagConstraints c; + Insets il = new Insets(4,4,4,4); + Insets ir = new Insets(4,4,4,4); + + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + serial_label = new JLabel("Serial:"); + pane.add(serial_label, c); + + c = new GridBagConstraints(); + c.gridx = 1; c.gridy = 0; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + serial_value = new JLabel(""); + pane.add(serial_value, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.gridx = 0; c.gridy = 1; + 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 = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + file_value = new JLabel(file.toString()); + pane.add(file_value, c); + + pbar = new JProgressBar(); + pbar.setMinimum(0); + pbar.setMaximum(100); + pbar.setValue(0); + pbar.setString(""); + pbar.setStringPainted(true); + pbar.setPreferredSize(new Dimension(600, 20)); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; c.gridy = 2; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ib = new Insets(4,4,4,4); + c.insets = ib; + pane.add(pbar, c); + + cancel = new JButton("Cancel"); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; c.gridy = 3; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ic = new Insets(4,4,4,4); + c.insets = ic; + pane.add(cancel, c); + cancel.addActionListener(this); + pack(); + setLocationRelativeTo(frame); + } + + void set_serial(int serial_number) { + serial_value.setText(String.format("%d", serial_number)); + } + + static class AltosHexfileFilter extends javax.swing.filechooser.FileFilter { + int product; + String head; + String description; + + public AltosHexfileFilter(int product, String head, String description) { + this.product = product; + this.head = head; + this.description = description; + } + + public boolean accept(File file) { + return !file.isFile() || (file.getName().startsWith(head) && file.getName().endsWith(".ihx")); + } + + public String getDescription() { + return description; + } + } + + static AltosHexfileFilter[] filters = { + new AltosHexfileFilter(AltosLib.product_telemetrum, "telemetrum", "TeleMetrum Image"), + new AltosHexfileFilter(AltosLib.product_teledongle, "teledongle", "TeleDongle Image"), + new AltosHexfileFilter(AltosLib.product_telemega, "telemega", "TeleMega Image"), + new AltosHexfileFilter(AltosLib.product_easymini, "easymini", "EasyMini Image"), + }; + + boolean select_source_file() { + JFileChooser hexfile_chooser = new JFileChooser(); + + File firmwaredir = AltosUIPreferences.firmwaredir(); + if (firmwaredir != null) + hexfile_chooser.setCurrentDirectory(firmwaredir); + + hexfile_chooser.setDialogTitle("Select Flash Image"); + + for (int i = 0; i < filters.length; i++) { + hexfile_chooser.addChoosableFileFilter(filters[i]); + } + javax.swing.filechooser.FileFilter ihx_filter = new FileNameExtensionFilter("Flash Image", "ihx"); + hexfile_chooser.addChoosableFileFilter(ihx_filter); + hexfile_chooser.setFileFilter(ihx_filter); + + if (!is_pair_programmed() && !device.matchProduct(AltosLib.product_altusmetrum)) { + for (int i = 0; i < filters.length; i++) { + if (device != null && device.matchProduct(filters[i].product)) + hexfile_chooser.setFileFilter(filters[i]); + } + } + + int returnVal = hexfile_chooser.showOpenDialog(frame); + + if (returnVal != JFileChooser.APPROVE_OPTION) + return false; + file = hexfile_chooser.getSelectedFile(); + if (file == null) + return false; + AltosUIPreferences.set_firmwaredir(file.getParentFile()); + + return true; + } + + boolean select_device() { + int product = AltosLib.product_any; + + device = AltosDeviceUIDialog.show(frame, AltosLib.product_any); + + if (device == null) + return false; + return true; + } + + boolean update_rom_config_info(AltosRomconfig existing_config) { + AltosRomconfig new_config; + new_config = AltosRomconfigUI.show(frame, existing_config); + if (new_config == null) + return false; + rom_config = new_config; + set_serial(rom_config.serial_number); + setVisible(true); + return true; + } + + void exception (Exception e) { + if (e instanceof FileNotFoundException) { + JOptionPane.showMessageDialog(frame, + ((FileNotFoundException) e).getMessage(), + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof AltosSerialInUseException) { + JOptionPane.showMessageDialog(frame, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof IOException) { + JOptionPane.showMessageDialog(frame, + e.getMessage(), + file.toString(), + JOptionPane.ERROR_MESSAGE); + } + } + + class flash_task implements Runnable, AltosFlashListener { + AltosFlashUI ui; + Thread t; + AltosProgrammer programmer; + + public void position(String in_s, int in_percent) { + final String s = in_s; + final int percent = in_percent; + Runnable r = new Runnable() { + public void run() { + try { + ui.actionPerformed(new ActionEvent(this, + percent, + s)); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + public void run () { + try { + if (ui.is_pair_programmed()) + programmer = new AltosFlash(ui.file, link, this); + else + programmer = new AltosSelfFlash(ui.file, link, this); + + final AltosRomconfig current_config = programmer.romconfig(); + + final Semaphore await_rom_config = new Semaphore(0); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ui.programmer = programmer; + ui.update_rom_config_info(current_config); + await_rom_config.release(); + } + }); + await_rom_config.acquire(); + + if (ui.rom_config != null) { + programmer.set_romconfig(ui.rom_config); + programmer.flash(); + } + } catch (InterruptedException ee) { + final Exception e = ee; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ui.exception(e); + } + }); + } catch (IOException ee) { + final Exception e = ee; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ui.exception(e); + } + }); + } finally { + if (programmer != null) + programmer.close(); + } + } + + public flash_task(AltosFlashUI in_ui) { + ui = in_ui; + t = new Thread(this); + t.start(); + } + } + + flash_task flasher; + + private boolean open_device() throws InterruptedException { + try { + link = new AltosSerial(device); + if (is_pair_programmed()) + return true; + + if (link == null) + throw new IOException(String.format("%s: open failed", device.toShortString())); + + while (!link.is_loader()) { + link.to_loader(); + + java.util.List devices = null; + + for (int tries = 0; tries < 10; tries++) { + Thread.sleep(100); + devices = AltosUSBDevice.list(AltosLib.product_altusmetrum); + if (devices.size() != 0) + break; + } + + if (devices.size() == 1) + device = devices.get(0); + else { + device = AltosDeviceUIDialog.show(frame, AltosLib.product_altusmetrum); + if (device == null) + return false; + } + link = new AltosSerial(device); + } + return true; + } catch (AltosSerialInUseException ee) { + exception(ee); + } catch (FileNotFoundException fe) { + exception(fe); + } catch (IOException ie) { + exception (ie); + } + return false; + } + + /* + * Execute the steps for flashing + * a device. Note that this returns immediately; + * this dialog is not modal + */ + void showDialog() { + if (!select_device()) + return; + if (!select_source_file()) + return; + try { + if (!open_device()) + return; + } catch (InterruptedException ie) { + return; + } + build_dialog(); + flash_task f = new flash_task(this); + } + + public static void show(AltosUIFrame frame) { + AltosFlashUI ui = new AltosFlashUI(frame); + ui.showDialog(); + } + + public AltosFlashUI(AltosUIFrame in_frame) { + super(in_frame, "Program Altusmetrum Device", false); + + frame = in_frame; + } +} diff --git a/altosuilib/AltosRomconfigUI.java b/altosuilib/AltosRomconfigUI.java new file mode 100644 index 00000000..8f002c4a --- /dev/null +++ b/altosuilib/AltosRomconfigUI.java @@ -0,0 +1,190 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosRomconfigUI + extends AltosUIDialog + implements ActionListener +{ + Container pane; + Box box; + JLabel serial_label; + JLabel radio_calibration_label; + + JFrame owner; + JTextField serial_value; + JTextField radio_calibration_value; + + JButton ok; + JButton cancel; + + /* Build the UI using a grid bag */ + public AltosRomconfigUI(JFrame in_owner) { + super (in_owner, "Configure TeleMetrum Rom Values", true); + + owner = in_owner; + GridBagConstraints c; + + Insets il = new Insets(4,4,4,4); + Insets ir = new Insets(4,4,4,4); + + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + /* Serial */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + serial_label = new JLabel("Serial:"); + pane.add(serial_label, c); + + c = new GridBagConstraints(); + c.gridx = 3; c.gridy = 0; + c.gridwidth = 3; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + serial_value = new JTextField("00000000"); + pane.add(serial_value, c); + + /* Radio calibration value */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 1; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + radio_calibration_label = new JLabel("Radio Calibration:"); + pane.add(radio_calibration_label, c); + + c = new GridBagConstraints(); + c.gridx = 3; c.gridy = 1; + c.gridwidth = 3; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_calibration_value = new JTextField("00000000"); + pane.add(radio_calibration_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 2; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = il; + ok = new JButton("OK"); + pane.add(ok, c); + ok.addActionListener(this); + ok.setActionCommand("ok"); + + c = new GridBagConstraints(); + c.gridx = 3; c.gridy = 2; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = il; + cancel = new JButton("Cancel"); + pane.add(cancel, c); + cancel.addActionListener(this); + cancel.setActionCommand("cancel"); + + pack(); + setLocationRelativeTo(owner); + } + + public AltosRomconfigUI(JFrame frame, AltosRomconfig config) { + this(frame); + set(config); + } + + boolean selected; + + /* Listen for events from our buttons */ + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("ok")) { + AltosRomconfig romconfig = romconfig(); + if (romconfig == null || !romconfig.valid()) { + JOptionPane.showMessageDialog(this, + "Invalid serial number or radio calibration value", + "Invalid rom configuration", + JOptionPane.ERROR_MESSAGE); + return; + } + selected = true; + } + setVisible(false); + } + + int serial() { + return Integer.parseInt(serial_value.getText()); + } + + void set_serial(int serial) { + serial_value.setText(String.format("%d", serial)); + } + + int radio_calibration() { + return Integer.parseInt(radio_calibration_value.getText()); + } + + void set_radio_calibration(int calibration) { + radio_calibration_value.setText(String.format("%d", calibration)); + } + + public void set(AltosRomconfig config) { + if (config != null && config.valid()) { + set_serial(config.serial_number); + set_radio_calibration(config.radio_calibration); + } + } + + AltosRomconfig romconfig() { + try { + return new AltosRomconfig(serial(), radio_calibration()); + } catch (NumberFormatException ne) { + return null; + } + } + + public AltosRomconfig showDialog() { + setVisible(true); + if (selected) + return romconfig(); + return null; + } + + public static AltosRomconfig show(JFrame frame, AltosRomconfig config) { + AltosRomconfigUI ui = new AltosRomconfigUI(frame, config); + return ui.showDialog(); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index f554fd74..e697b17c 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -54,6 +54,8 @@ altosuilib_JAVA = \ AltosDataChooser.java \ AltosLights.java \ AltosLed.java \ + AltosFlashUI.java \ + AltosRomconfigUI.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index de2b4aa3..7f34c763 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -89,21 +89,19 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo /* Device menu */ final static String download_command = "download"; - final static String configure_command = "configure"; final static String export_command = "export"; final static String graph_command = "graph"; + final static String configure_command = "configure"; + final static String flash_command = "flash"; static final String[][] device_menu_entries = new String[][] { { "Download Data", download_command }, { "Configure Device", configure_command }, { "Export Data", export_command }, { "Graph Data", graph_command }, + { "Flash Device", flash_command }, }; -// private AltosInfoTable flightInfo; - - boolean exit_on_close = false; - void stop_display() { if (thread != null && thread.isAlive()) { thread.interrupt(); @@ -240,6 +238,10 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo void graph() { } + void flash() { + AltosFlashUI.show(this); + } + public void actionPerformed(ActionEvent ev) { /* File menu */ @@ -293,6 +295,10 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo graph(); return; } + if (flash_command.equals(ev.getActionCommand())) { + flash(); + return; + } } void add_frequency_menu(int serial, final AltosFlightReader reader) { -- cgit v1.2.3 From 71715337eb532a1fbe1a753240e7417d5223489f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 May 2014 10:16:15 -0700 Subject: telegps: Add info table Move a couple of files from altosui to altosuilib, hook up the info table after changing it to implement the AltosFlightDisplay interface Signed-off-by: Keith Packard --- altoslib/AltosState.java | 4 + altosui/AltosCompanionInfo.java | 7 +- altosui/AltosFlightInfoTableModel.java | 75 ---------- altosui/AltosIdleMonitorUI.java | 4 +- altosui/AltosInfoTable.java | 236 ------------------------------ altosui/Makefile.am | 2 - altosuilib/AltosFlightInfoTableModel.java | 75 ++++++++++ altosuilib/AltosInfoTable.java | 236 ++++++++++++++++++++++++++++++ altosuilib/Makefile.am | 2 + telegps/TeleGPS.java | 72 +++++---- telegps/TeleGPSInfo.java | 4 + 11 files changed, 371 insertions(+), 346 deletions(-) delete mode 100644 altosui/AltosFlightInfoTableModel.java delete mode 100644 altosui/AltosInfoTable.java create mode 100644 altosuilib/AltosFlightInfoTableModel.java create mode 100644 altosuilib/AltosInfoTable.java (limited to 'altosuilib') diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 1162e522..ddda82b9 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -713,6 +713,7 @@ public class AltosState implements Cloneable { gps_ground_altitude = new AltosGpsGroundAltitude(); gps_ground_speed = new AltosValue(); gps_ascent_rate = new AltosValue(); + gps_course = new AltosValue(); speak_tick = AltosLib.MISSING; speak_altitude = AltosLib.MISSING; @@ -842,6 +843,9 @@ public class AltosState implements Cloneable { gps_altitude.copy(old.gps_altitude); gps_ground_altitude.copy(old.gps_ground_altitude); + gps_ground_speed.copy(old.gps_ground_speed); + gps_ascent_rate.copy(old.gps_ascent_rate); + gps_course.copy(old.gps_course); pad_lat = old.pad_lat; pad_lon = old.pad_lon; diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index 42413a57..f8d033a8 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -20,8 +20,9 @@ package altosui; import java.awt.*; import javax.swing.*; import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; -public class AltosCompanionInfo extends JTable { +public class AltosCompanionInfo extends JTable implements AltosFlightDisplay { private AltosFlightInfoTableModel model; static final int info_columns = 2; @@ -50,7 +51,7 @@ public class AltosCompanionInfo extends JTable { return getPreferredSize(); } - void info_reset() { + public void reset() { model.reset(); } @@ -88,7 +89,7 @@ public class AltosCompanionInfo extends JTable { return; if (state.companion != null) companion = state.companion; - info_reset(); + reset(); info_add_row(0, "Companion board", "%s", board_name()); if (companion != null) { info_add_row(0, "Last Data", "%5d", companion.tick); diff --git a/altosui/AltosFlightInfoTableModel.java b/altosui/AltosFlightInfoTableModel.java deleted file mode 100644 index 249f6497..00000000 --- a/altosui/AltosFlightInfoTableModel.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 javax.swing.table.*; - -public class AltosFlightInfoTableModel extends AbstractTableModel { - final static private String[] columnNames = {"Field", "Value"}; - - int rows; - int cols; - private String[][] data; - - public int getColumnCount() { return cols; } - public int getRowCount() { return rows; } - public String getColumnName(int col) { return columnNames[col & 1]; } - - public Object getValueAt(int row, int col) { - if (row >= rows || col >= cols) - return ""; - return data[row][col]; - } - - int[] current_row; - - public void reset() { - for (int i = 0; i < cols / 2; i++) - current_row[i] = 0; - } - - public void clear() { - reset(); - for (int c = 0; c < cols; c++) - for (int r = 0; r < rows; r++) - data[r][c] = ""; - fireTableDataChanged(); - } - - public void addRow(int col, String name, String value) { - if (current_row[col] < rows) { - data[current_row[col]][col * 2] = name; - data[current_row[col]][col * 2 + 1] = value; - } - current_row[col]++; - } - - public void finish() { - for (int c = 0; c < cols / 2; c++) - while (current_row[c] < rows) - addRow(c, "", ""); - fireTableDataChanged(); - } - - public AltosFlightInfoTableModel (int in_rows, int in_cols) { - rows = in_rows; - cols = in_cols * 2; - data = new String[rows][cols]; - current_row = new int[in_cols]; - } -} diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 62b50568..b5652df3 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -234,7 +234,9 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl try { disconnect(); } catch (Exception ex) { - System.out.println(Arrays.toString(ex.getStackTrace())); + System.out.printf("Exception %s\n", ex.toString()); + for (StackTraceElement e : ex.getStackTrace()) + System.out.printf("%s\n", e.toString()); } setVisible(false); dispose(); diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java deleted file mode 100644 index 125fa94c..00000000 --- a/altosui/AltosInfoTable.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import javax.swing.*; -import javax.swing.table.*; -import org.altusmetrum.altoslib_4.*; - -public class AltosInfoTable extends JTable { - private AltosFlightInfoTableModel model; - - static final int info_columns = 3; - static final int info_rows = 17; - - int desired_row_height() { - FontMetrics infoValueMetrics = getFontMetrics(Altos.table_value_font); - return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; - } - - int text_width(String t) { - FontMetrics infoValueMetrics = getFontMetrics(Altos.table_value_font); - - return infoValueMetrics.stringWidth(t); - } - - void set_layout() { - setRowHeight(desired_row_height()); - for (int i = 0; i < info_columns * 2; i++) - { - TableColumn column = getColumnModel().getColumn(i); - - if ((i & 1) == 0) - column.setPreferredWidth(text_width(" Satellites Visible")); - else - column.setPreferredWidth(text_width("W 179°59.99999' ")); - } - } - - public AltosInfoTable() { - super(new AltosFlightInfoTableModel(info_rows, info_columns)); - model = (AltosFlightInfoTableModel) getModel(); - setFont(Altos.table_value_font); - setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); - setShowGrid(true); - set_layout(); - doLayout(); - } - - public void set_font() { - setFont(Altos.table_value_font); - set_layout(); - doLayout(); - } - - public Dimension getPreferredScrollableViewportSize() { - return getPreferredSize(); - } - - void info_reset() { - model.reset(); - } - - void info_add_row(int col, String name, String value) { - model.addRow(col, name, value); - } - - void info_add_row(int col, String name, String format, Object... parameters) { - info_add_row (col, name, String.format(format, parameters)); - } - - void info_add_deg(int col, String name, double v, int pos, int neg) { - int c = pos; - if (v < 0) { - c = neg; - v = -v; - } - double deg = Math.floor(v); - double min = (v - deg) * 60; - - info_add_row(col, name, String.format("%c %3.0f°%08.5f'", c, deg, min)); - } - - void info_finish() { - model.finish(); - } - - public void clear() { - model.clear(); - } - - public void show(AltosState state, AltosListenerState listener_state) { - info_reset(); - if (state != null) { - if (state.device_type != AltosLib.MISSING) - info_add_row(0, "Device", "%s", AltosLib.product_name(state.device_type)); - if (state.altitude() != AltosLib.MISSING) - info_add_row(0, "Altitude", "%6.0f m", state.altitude()); - if (state.ground_altitude() != AltosLib.MISSING) - info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude()); - if (state.height() != AltosLib.MISSING) - info_add_row(0, "Height", "%6.0f m", state.height()); - if (state.max_height() != AltosLib.MISSING) - info_add_row(0, "Max height", "%6.0f m", state.max_height()); - if (state.acceleration() != AltosLib.MISSING) - info_add_row(0, "Acceleration", "%8.1f m/s²", state.acceleration()); - if (state.max_acceleration() != AltosLib.MISSING) - info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration()); - if (state.speed() != AltosLib.MISSING) - info_add_row(0, "Speed", "%8.1f m/s", state.speed()); - if (state.max_speed() != AltosLib.MISSING) - info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed()); - if (state.orient() != AltosLib.MISSING) - info_add_row(0, "Tilt", "%4.0f °", state.orient()); - if (state.max_orient() != AltosLib.MISSING) - info_add_row(0, "Max Tilt", "%4.0f °", state.max_orient()); - if (state.temperature != AltosLib.MISSING) - info_add_row(0, "Temperature", "%9.2f °C", state.temperature); - if (state.battery_voltage != AltosLib.MISSING) - info_add_row(0, "Battery", "%9.2f V", state.battery_voltage); - if (state.apogee_voltage != AltosLib.MISSING) - info_add_row(0, "Drogue", "%9.2f V", state.apogee_voltage); - if (state.main_voltage != AltosLib.MISSING) - info_add_row(0, "Main", "%9.2f V", state.main_voltage); - } - if (listener_state != null) { - info_add_row(0, "CRC Errors", "%6d", listener_state.crc_errors); - - if (listener_state.battery != AltosLib.MISSING) - info_add_row(0, "Receiver Battery", "%9.2f", listener_state.battery); - } - - if (state != null) { - if (state.gps == null || !state.gps.connected) { - info_add_row(1, "GPS", "not available"); - } else { - if (state.gps_ready) - info_add_row(1, "GPS state", "%s", "ready"); - else - info_add_row(1, "GPS state", "wait (%d)", - state.gps_waiting); - if (state.gps.locked) - info_add_row(1, "GPS", " locked"); - else if (state.gps.connected) - info_add_row(1, "GPS", " unlocked"); - else - info_add_row(1, "GPS", " missing"); - info_add_row(1, "Satellites", "%6d", state.gps.nsat); - if (state.gps.lat != AltosLib.MISSING) - info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); - if (state.gps.lon != AltosLib.MISSING) - info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); - if (state.gps.alt != AltosLib.MISSING) - info_add_row(1, "GPS altitude", "%8.1f", state.gps.alt); - if (state.gps_height != AltosLib.MISSING) - info_add_row(1, "GPS height", "%8.1f", state.gps_height); - - /* The SkyTraq GPS doesn't report these values */ - /* - if (false) { - info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", - state.gps.ground_speed, - state.gps.course); - info_add_row(1, "GPS climb rate", "%8.1f m/s", - state.gps.climb_rate); - info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", - state.gps.h_error, state.gps.v_error); - } - */ - - info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); - - if (state.npad > 0) { - if (state.from_pad != null) { - info_add_row(1, "Distance from pad", "%6d m", - (int) (state.from_pad.distance + 0.5)); - info_add_row(1, "Direction from pad", "%6d°", - (int) (state.from_pad.bearing + 0.5)); - info_add_row(1, "Elevation from pad", "%6d°", - (int) (state.elevation + 0.5)); - info_add_row(1, "Range from pad", "%6d m", - (int) (state.range + 0.5)); - } else { - info_add_row(1, "Distance from pad", "unknown"); - info_add_row(1, "Direction from pad", "unknown"); - info_add_row(1, "Elevation from pad", "unknown"); - info_add_row(1, "Range from pad", "unknown"); - } - info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S'); - info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W'); - info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); - } - if (state.gps.year != AltosLib.MISSING) - info_add_row(1, "GPS date", "%04d-%02d-%02d", - state.gps.year, - state.gps.month, - state.gps.day); - if (state.gps.hour != AltosLib.MISSING) - info_add_row(1, "GPS time", " %02d:%02d:%02d", - state.gps.hour, - state.gps.minute, - state.gps.second); - //int nsat_vis = 0; - int c; - - if (state.gps.cc_gps_sat == null) - info_add_row(2, "Satellites Visible", "%4d", 0); - else { - info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); - for (c = 0; c < state.gps.cc_gps_sat.length; c++) { - info_add_row(2, "Satellite id,C/N0", - "%4d, %4d", - state.gps.cc_gps_sat[c].svid, - state.gps.cc_gps_sat[c].c_n0); - } - } - } - } - info_finish(); - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 686b5967..add46825 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -21,7 +21,6 @@ altosui_JAVA = \ AltosConfigTD.java \ AltosConfigTDUI.java \ AltosDescent.java \ - AltosFlightInfoTableModel.java \ AltosFlightStatsTable.java \ AltosFlightStatus.java \ AltosFlightStatusUpdate.java \ @@ -32,7 +31,6 @@ altosui_JAVA = \ AltosIgnitor.java \ AltosLaunch.java \ AltosLaunchUI.java \ - AltosInfoTable.java \ AltosLanded.java \ AltosPad.java \ AltosUIPreferencesBackend.java \ diff --git a/altosuilib/AltosFlightInfoTableModel.java b/altosuilib/AltosFlightInfoTableModel.java new file mode 100644 index 00000000..3995efb3 --- /dev/null +++ b/altosuilib/AltosFlightInfoTableModel.java @@ -0,0 +1,75 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.table.*; + +public class AltosFlightInfoTableModel extends AbstractTableModel { + final static private String[] columnNames = {"Field", "Value"}; + + int rows; + int cols; + private String[][] data; + + public int getColumnCount() { return cols; } + public int getRowCount() { return rows; } + public String getColumnName(int col) { return columnNames[col & 1]; } + + public Object getValueAt(int row, int col) { + if (row >= rows || col >= cols) + return ""; + return data[row][col]; + } + + int[] current_row; + + public void reset() { + for (int i = 0; i < cols / 2; i++) + current_row[i] = 0; + } + + public void clear() { + reset(); + for (int c = 0; c < cols; c++) + for (int r = 0; r < rows; r++) + data[r][c] = ""; + fireTableDataChanged(); + } + + public void addRow(int col, String name, String value) { + if (current_row[col] < rows) { + data[current_row[col]][col * 2] = name; + data[current_row[col]][col * 2 + 1] = value; + } + current_row[col]++; + } + + public void finish() { + for (int c = 0; c < cols / 2; c++) + while (current_row[c] < rows) + addRow(c, "", ""); + fireTableDataChanged(); + } + + public AltosFlightInfoTableModel (int in_rows, int in_cols) { + rows = in_rows; + cols = in_cols * 2; + data = new String[rows][cols]; + current_row = new int[in_cols]; + } +} diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java new file mode 100644 index 00000000..0d8779d1 --- /dev/null +++ b/altosuilib/AltosInfoTable.java @@ -0,0 +1,236 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import javax.swing.*; +import javax.swing.table.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosInfoTable extends JTable implements AltosFlightDisplay { + private AltosFlightInfoTableModel model; + + static final int info_columns = 3; + static final int info_rows = 17; + + int desired_row_height() { + FontMetrics infoValueMetrics = getFontMetrics(AltosUILib.table_value_font); + return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; + } + + int text_width(String t) { + FontMetrics infoValueMetrics = getFontMetrics(AltosUILib.table_value_font); + + return infoValueMetrics.stringWidth(t); + } + + void set_layout() { + setRowHeight(desired_row_height()); + for (int i = 0; i < info_columns * 2; i++) + { + TableColumn column = getColumnModel().getColumn(i); + + if ((i & 1) == 0) + column.setPreferredWidth(text_width(" Satellites Visible")); + else + column.setPreferredWidth(text_width("W 179°59.99999' ")); + } + } + + public AltosInfoTable() { + super(new AltosFlightInfoTableModel(info_rows, info_columns)); + model = (AltosFlightInfoTableModel) getModel(); + setFont(AltosUILib.table_value_font); + setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); + setShowGrid(true); + set_layout(); + doLayout(); + } + + public void set_font() { + setFont(AltosUILib.table_value_font); + set_layout(); + doLayout(); + } + + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } + + public void reset() { + model.reset(); + } + + void info_add_row(int col, String name, String value) { + model.addRow(col, name, value); + } + + void info_add_row(int col, String name, String format, Object... parameters) { + info_add_row (col, name, String.format(format, parameters)); + } + + void info_add_deg(int col, String name, double v, int pos, int neg) { + int c = pos; + if (v < 0) { + c = neg; + v = -v; + } + double deg = Math.floor(v); + double min = (v - deg) * 60; + + info_add_row(col, name, String.format("%c %3.0f°%08.5f'", c, deg, min)); + } + + void info_finish() { + model.finish(); + } + + public void clear() { + model.clear(); + } + + public void show(AltosState state, AltosListenerState listener_state) { + reset(); + if (state != null) { + if (state.device_type != AltosLib.MISSING) + info_add_row(0, "Device", "%s", AltosLib.product_name(state.device_type)); + if (state.altitude() != AltosLib.MISSING) + info_add_row(0, "Altitude", "%6.0f m", state.altitude()); + if (state.ground_altitude() != AltosLib.MISSING) + info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude()); + if (state.height() != AltosLib.MISSING) + info_add_row(0, "Height", "%6.0f m", state.height()); + if (state.max_height() != AltosLib.MISSING) + info_add_row(0, "Max height", "%6.0f m", state.max_height()); + if (state.acceleration() != AltosLib.MISSING) + info_add_row(0, "Acceleration", "%8.1f m/s²", state.acceleration()); + if (state.max_acceleration() != AltosLib.MISSING) + info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration()); + if (state.speed() != AltosLib.MISSING) + info_add_row(0, "Speed", "%8.1f m/s", state.speed()); + if (state.max_speed() != AltosLib.MISSING) + info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed()); + if (state.orient() != AltosLib.MISSING) + info_add_row(0, "Tilt", "%4.0f °", state.orient()); + if (state.max_orient() != AltosLib.MISSING) + info_add_row(0, "Max Tilt", "%4.0f °", state.max_orient()); + if (state.temperature != AltosLib.MISSING) + info_add_row(0, "Temperature", "%9.2f °C", state.temperature); + if (state.battery_voltage != AltosLib.MISSING) + info_add_row(0, "Battery", "%9.2f V", state.battery_voltage); + if (state.apogee_voltage != AltosLib.MISSING) + info_add_row(0, "Drogue", "%9.2f V", state.apogee_voltage); + if (state.main_voltage != AltosLib.MISSING) + info_add_row(0, "Main", "%9.2f V", state.main_voltage); + } + if (listener_state != null) { + info_add_row(0, "CRC Errors", "%6d", listener_state.crc_errors); + + if (listener_state.battery != AltosLib.MISSING) + info_add_row(0, "Receiver Battery", "%9.2f", listener_state.battery); + } + + if (state != null) { + if (state.gps == null || !state.gps.connected) { + info_add_row(1, "GPS", "not available"); + } else { + if (state.gps_ready) + info_add_row(1, "GPS state", "%s", "ready"); + else + info_add_row(1, "GPS state", "wait (%d)", + state.gps_waiting); + if (state.gps.locked) + info_add_row(1, "GPS", " locked"); + else if (state.gps.connected) + info_add_row(1, "GPS", " unlocked"); + else + info_add_row(1, "GPS", " missing"); + info_add_row(1, "Satellites", "%6d", state.gps.nsat); + if (state.gps.lat != AltosLib.MISSING) + info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); + if (state.gps.lon != AltosLib.MISSING) + info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); + if (state.gps.alt != AltosLib.MISSING) + info_add_row(1, "GPS altitude", "%8.1f", state.gps.alt); + if (state.gps_height != AltosLib.MISSING) + info_add_row(1, "GPS height", "%8.1f", state.gps_height); + + /* The SkyTraq GPS doesn't report these values */ + /* + if (false) { + info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", + state.gps.ground_speed, + state.gps.course); + info_add_row(1, "GPS climb rate", "%8.1f m/s", + state.gps.climb_rate); + info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", + state.gps.h_error, state.gps.v_error); + } + */ + + info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); + + if (state.npad > 0) { + if (state.from_pad != null) { + info_add_row(1, "Distance from pad", "%6d m", + (int) (state.from_pad.distance + 0.5)); + info_add_row(1, "Direction from pad", "%6d°", + (int) (state.from_pad.bearing + 0.5)); + info_add_row(1, "Elevation from pad", "%6d°", + (int) (state.elevation + 0.5)); + info_add_row(1, "Range from pad", "%6d m", + (int) (state.range + 0.5)); + } else { + info_add_row(1, "Distance from pad", "unknown"); + info_add_row(1, "Direction from pad", "unknown"); + info_add_row(1, "Elevation from pad", "unknown"); + info_add_row(1, "Range from pad", "unknown"); + } + info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S'); + info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W'); + info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); + } + if (state.gps.year != AltosLib.MISSING) + info_add_row(1, "GPS date", "%04d-%02d-%02d", + state.gps.year, + state.gps.month, + state.gps.day); + if (state.gps.hour != AltosLib.MISSING) + info_add_row(1, "GPS time", " %02d:%02d:%02d", + state.gps.hour, + state.gps.minute, + state.gps.second); + //int nsat_vis = 0; + int c; + + if (state.gps.cc_gps_sat == null) + info_add_row(2, "Satellites Visible", "%4d", 0); + else { + info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); + for (c = 0; c < state.gps.cc_gps_sat.length; c++) { + info_add_row(2, "Satellite id,C/N0", + "%4d, %4d", + state.gps.cc_gps_sat[c].svid, + state.gps.cc_gps_sat[c].c_n0); + } + } + } + } + info_finish(); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index e697b17c..65a8228a 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -56,6 +56,8 @@ altosuilib_JAVA = \ AltosLed.java \ AltosFlashUI.java \ AltosRomconfigUI.java \ + AltosInfoTable.java \ + AltosFlightInfoTableModel.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index 7f34c763..d30d8dc5 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -50,16 +50,25 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo AltosFlightReader reader; AltosDisplayThread thread; - JTabbedPane pane; + JMenuBar menu_bar; - AltosSiteMap sitemap; - TeleGPSInfo gps_info; - boolean has_map; + JMenu file_menu; + JMenu monitor_menu; + JMenu device_menu; + AltosFreqList frequencies; + + Container bag; + + TeleGPSStatus telegps_status; + TeleGPSStatusUpdate status_update; + + JTabbedPane pane; + + AltosSiteMap sitemap; + TeleGPSInfo gps_info; + AltosInfoTable info_table; - JMenuBar menu_bar; - JMenu file_menu; - JMenu monitor_menu; - JMenu device_menu; + LinkedList displays; /* File menu */ final static String new_command = "new"; @@ -113,41 +122,38 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo } public void reset() { - sitemap.reset(); - gps_info.reset(); + for (AltosFlightDisplay display : displays) + display.reset(); } public void set_font() { - sitemap.set_font(); - gps_info.set_font(); + for (AltosFlightDisplay display : displays) + display.set_font(); } public void font_size_changed(int font_size) { set_font(); } - -// AltosFlightStatusUpdate status_update; - public void show(AltosState state, AltosListenerState listener_state) { -// status_update.saved_state = state; + try { + status_update.saved_state = state; - if (state == null) - state = new AltosState(); + if (state == null) + state = new AltosState(); - sitemap.show(state, listener_state); - gps_info.show(state, listener_state); - telegps_status.show(state, listener_state); + int i = 0; + for (AltosFlightDisplay display : displays) { + display.show(state, listener_state); + i++; + } + } catch (Exception ex) { + System.out.printf("Exception %s\n", ex.toString()); + for (StackTraceElement e : ex.getStackTrace()) + System.out.printf("%s\n", e.toString()); + } } - Container bag; - AltosFreqList frequencies; - JLabel telemetry; - TeleGPSStatus telegps_status; - TeleGPSStatusUpdate status_update; - - ActionListener show_timer; - void new_window() { new TeleGPS(); } @@ -379,6 +385,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo file_menu = make_menu("File", file_menu_entries); monitor_menu = make_menu("Monitor", monitor_menu_entries); device_menu = make_menu("Device", device_menu_entries); + displays = new LinkedList(); int serial = -1; @@ -391,6 +398,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo c.gridwidth = 2; bag.add(telegps_status, c); c.gridwidth = 1; + displays.add(telegps_status); /* The rest of the window uses a tabbed pane to @@ -409,9 +417,15 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo sitemap = new AltosSiteMap(); pane.add("Site Map", sitemap); + displays.add(sitemap); gps_info = new TeleGPSInfo(); pane.add("Info", gps_info); + displays.add(gps_info); + + info_table = new AltosInfoTable(); + pane.add("Table", info_table); + displays.add(info_table); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java index 0fba77d5..da3df44e 100644 --- a/telegps/TeleGPSInfo.java +++ b/telegps/TeleGPSInfo.java @@ -58,6 +58,10 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { show(String.format(format, v)); } + void show(String format, int v) { + show(String.format(format, v)); + } + void reset() { lights.set(false); value.setText(""); -- cgit v1.2.3 From f80075be4ebb9c5fe00c24b8c7638fad23267424 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 May 2014 14:03:58 -0700 Subject: java: Refactor AltosFlightDisplay units and font update handling Make AltosFlightDisplay explicitly implement AltosFontListener and AltosUnitsListener interfaces to make everyone use the same API. Then, actually go implement units listeners so that changing units updates all of the active displays immediately Signed-off-by: Keith Packard --- altosui/AltosAscent.java | 116 ++++++++++++++++++--------- altosui/AltosCompanionInfo.java | 7 +- altosui/AltosDescent.java | 86 +++++++++++++------- altosui/AltosFlightStatus.java | 5 +- altosui/AltosFlightUI.java | 37 +++++---- altosui/AltosIdleMonitorUI.java | 17 ++-- altosui/AltosIgnitor.java | 14 +++- altosui/AltosLanded.java | 67 +++++++++++----- altosui/AltosPad.java | 71 ++++++++++++----- altosuilib/AltosFlightDisplay.java | 4 +- altosuilib/AltosInfoTable.java | 5 +- altosuilib/AltosSiteMap.java | 6 +- telegps/TeleGPS.java | 16 ++-- telegps/TeleGPSInfo.java | 157 +++++++++++++++++++++++++++---------- telegps/TeleGPSStatus.java | 17 ++-- 15 files changed, 431 insertions(+), 194 deletions(-) (limited to 'altosuilib') diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index f6ccbf0c..fb05fe11 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -26,10 +26,12 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; JLabel cur, max; - public class AscentStatus { + public class AscentStatus implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; AltosLights lights; + double v; + AltosUnits units; void show() { value.setVisible(true); @@ -50,7 +52,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { value.setText(s); } - void show(AltosUnits units, double v) { + void show(double v) { + this.v = v; show(units.show(8, v)); } @@ -63,12 +66,18 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { lights.set(false); } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); } - public AscentStatus (GridBagLayout layout, int y, String text) { + public void units_changed(boolean imperial_units) { + if (units != null) + show(v); + } + + public AscentStatus (GridBagLayout layout, int y, AltosUnits units, String text) { + this.units = units; GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -105,10 +114,13 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } } - public class AscentValue { + public abstract class AscentValue implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; - void show(AltosState state, AltosListenerState listener_state) {} + double v; + AltosUnits units; + + abstract void show(AltosState state, AltosListenerState listener_state); void reset() { value.setText(""); @@ -124,7 +136,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { value.setText(s); } - void show(AltosUnits units, double v) { + void show(double v) { + this.v = v; show(units.show(8, v)); } @@ -136,12 +149,18 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { label.setVisible(false); value.setVisible(false); } - void set_font() { + + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); } - public AscentValue (GridBagLayout layout, int y, String text) { + public void units_changed(boolean imperial_units) { + if (units != null) + show(v); + } + + public AscentValue (GridBagLayout layout, int y, AltosUnits units, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -167,13 +186,19 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(value, c); add(value); } + + public AscentValue (GridBagLayout layout, int y, String text) { + this(layout, y, null, text); + } } - public class AscentValueHold { + public class AscentValueHold implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; JTextField max_value; double max; + AltosUnits units; + double v; void show(AltosState state, AltosListenerState listener_state) {} @@ -183,23 +208,29 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { max = AltosLib.MISSING; } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); max_value.setFont(Altos.value_font); } - void show(AltosUnits units, double v) { + public void units_changed(boolean imperial_units) { + show(v); + } + + void show(double v) { + this.v = v; if (v == AltosLib.MISSING) { value.setText("Missing"); - max_value.setText("Missing"); } else { value.setText(units.show(8, v)); - if (v > max || max == AltosLib.MISSING) { - max_value.setText(units.show(8, v)); + if (v > max || max == AltosLib.MISSING) max = v; - } } + if (max == AltosLib.MISSING) + max_value.setText("Missing"); + else + max_value.setText(units.show(8, v)); } void hide() { @@ -208,7 +239,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { max_value.setVisible(false); } - public AscentValueHold (GridBagLayout layout, int y, String text) { + public AscentValueHold (GridBagLayout layout, int y, AltosUnits units, String text) { + this.units = units; GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -245,13 +277,12 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } } - class Height extends AscentValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.height, state.height()); + show(state.height()); } public Height (GridBagLayout layout, int y) { - super (layout, y, "Height"); + super (layout, y, AltosConvert.height, "Height"); } } @@ -259,10 +290,10 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Speed extends AscentValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.speed, state.speed()); + show(state.speed()); } public Speed (GridBagLayout layout, int y) { - super (layout, y, "Speed"); + super (layout, y, AltosConvert.speed, "Speed"); } } @@ -270,10 +301,10 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Accel extends AscentValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.accel, state.acceleration()); + show(state.acceleration()); } public Accel (GridBagLayout layout, int y) { - super (layout, y, "Acceleration"); + super (layout, y, AltosConvert.accel, "Acceleration"); } } @@ -281,10 +312,10 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Orient extends AscentValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.orient, state.orient()); + show(state.orient()); } public Orient (GridBagLayout layout, int y) { - super (layout, y, "Tilt Angle"); + super (layout, y, AltosConvert.orient, "Tilt Angle"); } } @@ -307,7 +338,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { lights.set(state.apogee_voltage >= AltosLib.ao_igniter_good); } public Apogee (GridBagLayout layout, int y) { - super(layout, y, "Apogee Igniter Voltage"); + super(layout, y, null, "Apogee Igniter Voltage"); } } @@ -319,7 +350,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { lights.set(state.main_voltage >= AltosLib.ao_igniter_good); } public Main (GridBagLayout layout, int y) { - super(layout, y, "Main Igniter Voltage"); + super(layout, y, null, "Main Igniter Voltage"); } } @@ -364,17 +395,28 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { orient.reset(); } - public void set_font() { + public void font_size_changed(int font_size) { cur.setFont(Altos.label_font); max.setFont(Altos.label_font); - lat.set_font(); - lon.set_font(); - main.set_font(); - apogee.set_font(); - height.set_font(); - speed.set_font(); - accel.set_font(); - orient.set_font(); + lat.font_size_changed(font_size); + lon.font_size_changed(font_size); + main.font_size_changed(font_size); + apogee.font_size_changed(font_size); + height.font_size_changed(font_size); + speed.font_size_changed(font_size); + accel.font_size_changed(font_size); + orient.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + lat.units_changed(imperial_units); + lon.units_changed(imperial_units); + main.units_changed(imperial_units); + apogee.units_changed(imperial_units); + height.units_changed(imperial_units); + speed.units_changed(imperial_units); + accel.units_changed(imperial_units); + orient.units_changed(imperial_units); } public void show(AltosState state, AltosListenerState listener_state) { diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index f8d033a8..514ce611 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -33,18 +33,21 @@ public class AltosCompanionInfo extends JTable implements AltosFlightDisplay { return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; } - public void set_font() { + public void font_size_changed(int font_size) { setFont(Altos.table_value_font); setRowHeight(desired_row_height()); doLayout(); } + public void units_changed(boolean imperial_units) { + } + public AltosCompanionInfo() { super(new AltosFlightInfoTableModel(info_rows, info_columns)); model = (AltosFlightInfoTableModel) getModel(); setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); setShowGrid(true); - set_font(); + font_size_changed(AltosUIPreferences.font_size()); } public Dimension getPreferredScrollableViewportSize() { diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 5cb693fe..e6710524 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -25,7 +25,7 @@ import org.altusmetrum.altosuilib_2.*; public class AltosDescent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - public abstract class DescentStatus { + public abstract class DescentStatus implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; AltosLights lights; @@ -58,11 +58,14 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { lights.set(false); } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); } + public void units_changed(boolean imperial_units) { + } + public DescentStatus (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -101,9 +104,11 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } } - public abstract class DescentValue { + public abstract class DescentValue implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; + AltosUnits units; + double v; void reset() { value.setText(""); @@ -126,7 +131,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setText(v); } - void show(AltosUnits units, double v) { + void show(double v) { + this.v = v; show(units.show(8, v)); } @@ -134,12 +140,18 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { show(String.format(format, v)); } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); } - public DescentValue (GridBagLayout layout, int x, int y, String text) { + public void units_changed(boolean imperial_units) { + if (units != null) + show(v); + } + + public DescentValue (GridBagLayout layout, int x, int y, AltosUnits units, String text) { + this.units = units; GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -163,9 +175,13 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { c.weightx = 1; add(value, c); } + + public DescentValue (GridBagLayout layout, int x, int y, String text) { + this(layout, x, y, null, text); + } } - public abstract class DescentDualValue { + public abstract class DescentDualValue implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value1; JTextField value2; @@ -187,12 +203,15 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value2.setVisible(false); } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value1.setFont(Altos.value_font); value2.setFont(Altos.value_font); } + public void units_changed(boolean imperial_units) { + } + abstract void show(AltosState state, AltosListenerState listener_state); void show(String v1, String v2) { @@ -246,10 +265,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Height extends DescentValue { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.height, state.height()); + show(state.height()); } public Height (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Height"); + super (layout, x, y, AltosConvert.height, "Height"); } } @@ -257,10 +276,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Speed extends DescentValue { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.speed, state.speed()); + show(state.speed()); } public Speed (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Speed"); + super (layout, x, y, AltosConvert.speed, "Speed"); } } @@ -308,13 +327,13 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Distance extends DescentValue { void show(AltosState state, AltosListenerState listener_state) { if (state.from_pad != null) - show(AltosConvert.distance, state.from_pad.distance); + show(state.from_pad.distance); else show("???"); } public Distance (GridBagLayout layout, int x, int y) { - super(layout, x, y, "Ground Distance"); + super(layout, x, y, AltosConvert.distance, "Ground Distance"); } } @@ -364,10 +383,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Range extends DescentValue { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.distance, state.range); + show(state.range); } public Range (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Range"); + super (layout, x, y, AltosConvert.distance, "Range"); } } @@ -397,17 +416,30 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { apogee.reset(); } - public void set_font() { - lat.set_font(); - lon.set_font(); - height.set_font(); - speed.set_font(); - bearing.set_font(); - range.set_font(); - distance.set_font(); - elevation.set_font(); - main.set_font(); - apogee.set_font(); + public void font_size_changed(int font_size) { + lat.font_size_changed(font_size); + lon.font_size_changed(font_size); + height.font_size_changed(font_size); + speed.font_size_changed(font_size); + bearing.font_size_changed(font_size); + range.font_size_changed(font_size); + distance.font_size_changed(font_size); + elevation.font_size_changed(font_size); + main.font_size_changed(font_size); + apogee.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + lat.units_changed(imperial_units); + lon.units_changed(imperial_units); + height.units_changed(imperial_units); + speed.units_changed(imperial_units); + bearing.units_changed(imperial_units); + range.units_changed(imperial_units); + distance.units_changed(imperial_units); + elevation.units_changed(imperial_units); + main.units_changed(imperial_units); + apogee.units_changed(imperial_units); } public void show(AltosState state, AltosListenerState listener_state) { diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 73b84f8d..459b0495 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -159,7 +159,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay last_packet.reset(); } - public void set_font () { + public void font_size_changed(int font_size) { call.set_font(); serial.set_font(); flight.set_font(); @@ -168,6 +168,9 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay last_packet.set_font(); } + public void units_changed(boolean imperial_units) { + } + public void show (AltosState state, AltosListenerState listener_state) { call.show(state, listener_state); serial.show(state, listener_state); diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 2bd60d6c..baa18686 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -24,7 +24,7 @@ import java.util.concurrent.*; import org.altusmetrum.altoslib_4.*; import org.altusmetrum.altosuilib_2.*; -public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener { +public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { AltosVoice voice; AltosFlightReader reader; AltosDisplayThread thread; @@ -83,22 +83,29 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A sitemap.reset(); } - public void set_font() { - pad.set_font(); - ignitor.set_font(); - ascent.set_font(); - descent.set_font(); - landed.set_font(); - flightStatus.set_font(); - flightInfo.set_font(); - sitemap.set_font(); - companion.set_font(); - } - public void font_size_changed(int font_size) { - set_font(); + pad.font_size_changed(font_size); + ignitor.font_size_changed(font_size); + ascent.font_size_changed(font_size); + descent.font_size_changed(font_size); + landed.font_size_changed(font_size); + flightStatus.font_size_changed(font_size); + flightInfo.font_size_changed(font_size); + sitemap.font_size_changed(font_size); + companion.font_size_changed(font_size); } + public void units_changed(boolean imperial_units) { + pad.units_changed(imperial_units); + ignitor.units_changed(imperial_units); + ascent.units_changed(imperial_units); + descent.units_changed(imperial_units); + landed.units_changed(imperial_units); + flightStatus.units_changed(imperial_units); + flightInfo.units_changed(imperial_units); + sitemap.units_changed(imperial_units); + companion.units_changed(imperial_units); + } AltosFlightStatusUpdate status_update; @@ -318,6 +325,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); AltosUIPreferences.register_font_listener(this); + AltosPreferences.register_units_listener(this); addWindowListener(new WindowAdapter() { @Override @@ -326,6 +334,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A setVisible(false); dispose(); AltosUIPreferences.unregister_font_listener(AltosFlightUI.this); + AltosPreferences.unregister_units_listener(AltosFlightUI.this); if (exit_on_close) System.exit(0); } diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index b5652df3..042111ec 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -27,7 +27,7 @@ import java.util.Arrays; import org.altusmetrum.altoslib_4.*; import org.altusmetrum.altosuilib_2.*; -public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener, AltosIdleMonitorListener, DocumentListener { +public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener { AltosDevice device; JTabbedPane pane; AltosPad pad; @@ -56,13 +56,14 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl flightInfo.clear(); } - public void set_font() { - pad.set_font(); - flightInfo.set_font(); + public void font_size_changed(int font_size) { + pad.font_size_changed(font_size); + flightInfo.font_size_changed(font_size); } - public void font_size_changed(int font_size) { - set_font(); + public void units_changed(boolean imperial_units) { + pad.units_changed(imperial_units); + flightInfo.units_changed(imperial_units); } AltosFlightStatusUpdate status_update; @@ -235,8 +236,8 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl disconnect(); } catch (Exception ex) { System.out.printf("Exception %s\n", ex.toString()); - for (StackTraceElement e : ex.getStackTrace()) - System.out.printf("%s\n", e.toString()); + for (StackTraceElement el : ex.getStackTrace()) + System.out.printf("%s\n", el.toString()); } setVisible(false); dispose(); diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java index 7f79f42b..27917b30 100644 --- a/altosui/AltosIgnitor.java +++ b/altosui/AltosIgnitor.java @@ -25,7 +25,7 @@ import org.altusmetrum.altosuilib_2.*; public class AltosIgnitor extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - public class LaunchStatus { + public class LaunchStatus implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; AltosLights lights; @@ -66,11 +66,14 @@ public class AltosIgnitor extends JComponent implements AltosFlightDisplay { hide(); } - public void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); } + public void units_changed(boolean imperial_units) { + } + public void set_label(String text) { label.setText(text); } @@ -142,11 +145,14 @@ public class AltosIgnitor extends JComponent implements AltosFlightDisplay { ignitors[i].reset(); } - public void set_font() { + public void font_size_changed(int font_size) { if (ignitors == null) return; for (int i = 0; i < ignitors.length; i++) - ignitors[i].set_font(); + ignitors[i].font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { } public void show(AltosState state, AltosListenerState listener_state) { diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 707d8fcc..bb52fe2b 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -27,10 +27,13 @@ import org.altusmetrum.altosuilib_2.*; public class AltosLanded extends JComponent implements AltosFlightDisplay, ActionListener { GridBagLayout layout; - public class LandedValue { + public abstract class LandedValue implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; - void show(AltosState state, AltosListenerState listener_state) {} + AltosUnits units; + double v; + + abstract void show(AltosState state, AltosListenerState listener_state); void reset() { value.setText(""); @@ -46,7 +49,8 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio value.setText(s); } - void show(AltosUnits units, double v) { + void show(double v) { + this.v = v; show(units.show(8, v)); } @@ -54,17 +58,24 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio show(String.format(format, v)); } - public void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); } + public void units_changed(boolean imperial_units) { + if (units != null) + show(v); + } + void hide() { label.setVisible(false); value.setVisible(false); } - public LandedValue (GridBagLayout layout, int y, String text) { + public LandedValue (GridBagLayout layout, int y, AltosUnits units, String text) { + this.units = units; + GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -89,6 +100,10 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio layout.setConstraints(value, c); add(value); } + + public LandedValue (GridBagLayout layout, int y, String text) { + this(layout, y, null, text); + } } String pos(double p, String pos, String neg) { @@ -151,12 +166,12 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio void show (AltosState state, AltosListenerState listener_state) { show(); if (state.from_pad != null) - show(AltosConvert.distance, state.from_pad.distance); + show(state.from_pad.distance); else show("???"); } public Distance (GridBagLayout layout, int y) { - super (layout, y, "Distance"); + super (layout, y, AltosConvert.distance, "Distance"); } } @@ -164,10 +179,10 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio class Height extends LandedValue { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.height, state.max_height()); + show(state.max_height()); } public Height (GridBagLayout layout, int y) { - super (layout, y, "Maximum Height"); + super (layout, y, AltosConvert.height, "Maximum Height"); } } @@ -175,10 +190,10 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio class Speed extends LandedValue { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.speed, state.max_speed()); + show(state.max_speed()); } public Speed (GridBagLayout layout, int y) { - super (layout, y, "Maximum Speed"); + super (layout, y, AltosConvert.speed, "Maximum Speed"); } } @@ -186,10 +201,10 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio class Accel extends LandedValue { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.accel, state.max_acceleration()); + show(state.max_acceleration()); } public Accel (GridBagLayout layout, int y) { - super (layout, y, "Maximum Acceleration"); + super (layout, y, AltosConvert.accel, "Maximum Acceleration"); } } @@ -205,14 +220,24 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio accel.reset(); } - public void set_font() { - lat.set_font(); - lon.set_font(); - bearing.set_font(); - distance.set_font(); - height.set_font(); - speed.set_font(); - accel.set_font(); + public void font_size_changed(int font_size) { + lat.font_size_changed(font_size); + lon.font_size_changed(font_size); + bearing.font_size_changed(font_size); + distance.font_size_changed(font_size); + height.font_size_changed(font_size); + speed.font_size_changed(font_size); + accel.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + lat.units_changed(imperial_units); + lon.units_changed(imperial_units); + bearing.units_changed(imperial_units); + distance.units_changed(imperial_units); + height.units_changed(imperial_units); + speed.units_changed(imperial_units); + accel.units_changed(imperial_units); } public void show(AltosState state, AltosListenerState listener_state) { diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index a6ac70db..ce1f2ab7 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -25,7 +25,7 @@ import org.altusmetrum.altosuilib_2.*; public class AltosPad extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - public class LaunchStatus { + public class LaunchStatus implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; AltosLights lights; @@ -62,11 +62,14 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { lights.setVisible(false); } - public void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); } + public void units_changed(boolean imperial_units) { + } + public void set_label(String text) { label.setText(text); } @@ -107,10 +110,13 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } } - public class LaunchValue { + public abstract class LaunchValue implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; - void show(AltosState state, AltosListenerState listener_state) {} + AltosUnits units; + double v; + + abstract void show(AltosState state, AltosListenerState listener_state); void show() { label.setVisible(true); @@ -122,17 +128,23 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { value.setVisible(false); } - public void set_font() { + public void font_size_changed(int font_size) { label.setFont(Altos.label_font); value.setFont(Altos.value_font); } + public void units_changed(boolean imperial_units) { + if (units != null) + show(v); + } + void show(String s) { show(); value.setText(s); } - void show(AltosUnits units, double v) { + void show(double v) { + this.v = v; show(units.show(8, v)); } @@ -148,7 +160,9 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { value.setText(""); } - public LaunchValue (GridBagLayout layout, int y, String text) { + public LaunchValue (GridBagLayout layout, int y, AltosUnits units, String text) { + this.units = units; + GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.weighty = 1; @@ -173,6 +187,10 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { layout.setConstraints(value, c); add(value); } + + public LaunchValue (GridBagLayout layout, int y, String text) { + this(layout, y, null, text); + } } class Battery extends LaunchStatus { @@ -378,13 +396,13 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } } if (alt != AltosLib.MISSING) { - show("%4.0f m", state.gps.alt); + show(alt); set_label(label); } else hide(); } public PadAlt (GridBagLayout layout, int y) { - super (layout, y, "Pad Altitude"); + super (layout, y, AltosConvert.height, "Pad Altitude"); } } @@ -403,17 +421,30 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { pad_alt.reset(); } - public void set_font() { - battery.set_font(); - apogee.set_font(); - main.set_font(); - logging_ready.set_font(); - gps_locked.set_font(); - gps_ready.set_font(); - receiver_battery.set_font(); - pad_lat.set_font(); - pad_lon.set_font(); - pad_alt.set_font(); + public void font_size_changed(int font_size) { + battery.font_size_changed(font_size); + apogee.font_size_changed(font_size); + main.font_size_changed(font_size); + logging_ready.font_size_changed(font_size); + gps_locked.font_size_changed(font_size); + gps_ready.font_size_changed(font_size); + receiver_battery.font_size_changed(font_size); + pad_lat.font_size_changed(font_size); + pad_lon.font_size_changed(font_size); + pad_alt.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + battery.units_changed(imperial_units); + apogee.units_changed(imperial_units); + main.units_changed(imperial_units); + logging_ready.units_changed(imperial_units); + gps_locked.units_changed(imperial_units); + gps_ready.units_changed(imperial_units); + receiver_battery.units_changed(imperial_units); + pad_lat.units_changed(imperial_units); + pad_lon.units_changed(imperial_units); + pad_alt.units_changed(imperial_units); } public void show(AltosState state, AltosListenerState listener_state) { diff --git a/altosuilib/AltosFlightDisplay.java b/altosuilib/AltosFlightDisplay.java index 5695a015..5fb0cab7 100644 --- a/altosuilib/AltosFlightDisplay.java +++ b/altosuilib/AltosFlightDisplay.java @@ -19,10 +19,8 @@ package org.altusmetrum.altosuilib_2; import org.altusmetrum.altoslib_4.*; -public interface AltosFlightDisplay { +public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener { void reset(); void show(AltosState state, AltosListenerState listener_state); - - void set_font(); } diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java index 0d8779d1..24a895eb 100644 --- a/altosuilib/AltosInfoTable.java +++ b/altosuilib/AltosInfoTable.java @@ -62,12 +62,15 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay { doLayout(); } - public void set_font() { + public void font_size_changed(int font_size) { setFont(AltosUILib.table_value_font); set_layout(); doLayout(); } + public void units_changed(boolean imperial_units) { + } + public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index 7f0e1844..ed77beff 100644 --- a/altosuilib/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -192,11 +192,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous // nothing } - public void set_font() { + public void font_size_changed(int font_size) { for (AltosSiteMapTile tile : mapTiles.values()) tile.set_font(AltosUILib.value_font); } + public void units_changed(boolean imperial_units) { + set_line(); + } + static final int load_mode_cached = 1; static final int load_mode_uncached = 2; diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index d30d8dc5..bef0bbc6 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -26,7 +26,10 @@ import java.util.*; import org.altusmetrum.altoslib_4.*; import org.altusmetrum.altosuilib_2.*; -public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener, ActionListener { +public class TeleGPS + extends AltosUIFrame + implements AltosFlightDisplay, AltosFontListener, AltosUnitsListener, ActionListener +{ static String[] telegps_icon_names = { "/telegps-16.png", @@ -126,13 +129,14 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo display.reset(); } - public void set_font() { + public void font_size_changed(int font_size) { for (AltosFlightDisplay display : displays) - display.set_font(); + display.font_size_changed(font_size); } - public void font_size_changed(int font_size) { - set_font(); + public void units_changed(boolean imperial_units) { + for (AltosFlightDisplay display : displays) + display.units_changed(imperial_units); } public void show(AltosState state, AltosListenerState listener_state) { @@ -343,6 +347,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo private void close() { AltosUIPreferences.unregister_font_listener(this); + AltosPreferences.unregister_units_listener(this); setVisible(false); dispose(); --number_of_windows; @@ -430,6 +435,7 @@ public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFo setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); AltosUIPreferences.register_font_listener(this); + AltosPreferences.register_units_listener(this); addWindowListener(new WindowAdapter() { @Override diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java index da3df44e..2765f5ab 100644 --- a/telegps/TeleGPSInfo.java +++ b/telegps/TeleGPSInfo.java @@ -26,10 +26,12 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { GridBagLayout layout; JLabel cur, max; - public class Info { + public abstract class Info implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; AltosLights lights; + double v; + AltosUnits units; void show() { value.setVisible(true); @@ -43,14 +45,15 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { label.setVisible(false); } - void show(AltosState state, AltosListenerState listener_state) {} + abstract void show(AltosState state, AltosListenerState listener_state); void show(String s) { show(); value.setText(s); } - void show(AltosUnits units, double v) { + void show(double v) { + this.v = v; show(units.show(8, v)); } @@ -67,12 +70,19 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { value.setText(""); } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(AltosUILib.label_font); value.setFont(AltosUILib.value_font); } - public Info (GridBagLayout layout, int y, String text) { + public void units_changed(boolean imperial_units) { + if (units != null) + show(v); + } + + public Info (GridBagLayout layout, int y, AltosUnits units, String text) { + this.units = units; + GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -106,12 +116,19 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { layout.setConstraints(value, c); add(value); } + + public Info (GridBagLayout layout, int y, String text) { + this(layout, y, null, text); + } } - public class Value { + public abstract class Value implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; - void show(AltosState state, AltosListenerState listener_state) {} + AltosUnits units; + double v = AltosLib.MISSING; + + abstract void show(AltosState state, AltosListenerState listener_state); void reset() { value.setText(""); @@ -127,7 +144,8 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { value.setText(s); } - void show(AltosUnits units, double v) { + void show(double v) { + this.v = v; show(units.show(8, v)); } @@ -139,10 +157,14 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { label.setVisible(false); value.setVisible(false); } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(AltosUILib.label_font); value.setFont(AltosUILib.value_font); } + public void units_changed(boolean imperial_units) { + if (units != null) + show(v); + } public Value (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); @@ -172,34 +194,44 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { } } - public abstract class DualValue { + public abstract class DualValue implements AltosFontListener, AltosUnitsListener { + AltosLights lights; JLabel label; JTextField value1; JTextField value2; void reset() { + if (lights != null) + lights.set(false); value1.setText(""); value2.setText(""); } void show() { + if (lights != null) + lights.setVisible(true); label.setVisible(true); value1.setVisible(true); value2.setVisible(true); } void hide() { + if (lights != null) + lights.setVisible(false); label.setVisible(false); value1.setVisible(false); value2.setVisible(false); } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(AltosUILib.label_font); value1.setFont(AltosUILib.value_font); value2.setFont(AltosUILib.value_font); } + public void units_changed(boolean imperial_units) { + } + abstract void show(AltosState state, AltosListenerState listener_state); void show(String v1, String v2) { @@ -207,20 +239,37 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { value1.setText(v1); value2.setText(v2); } + void show(String f1, double v1, String f2, double v2) { show(); value1.setText(String.format(f1, v1)); value2.setText(String.format(f2, v2)); } - public DualValue (GridBagLayout layout, int x, int y, String text) { + void show(String f1, int v1, String f2, int v2) { + show(); + value1.setText(String.format(f1, v1)); + value2.setText(String.format(f2, v2)); + } + + public DualValue (GridBagLayout layout, int y, String text, boolean want_lights) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; + if (want_lights) { + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + add(lights); + } + label = new JLabel(text); label.setFont(AltosUILib.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = x + 1; c.gridy = y; + c.gridx = 1; c.gridy = y; c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; @@ -231,7 +280,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { value1 = new JTextField(AltosUILib.text_width); value1.setFont(AltosUILib.value_font); value1.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 2; c.gridy = y; + c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -241,7 +290,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { value2 = new JTextField(AltosUILib.text_width); value2.setFont(AltosUILib.value_font); value2.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 3; c.gridy = y; + c.gridx = 3; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -251,13 +300,15 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { } } - public class ValueHold { + abstract public class ValueHold implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; JTextField max_value; + double v; double max; + AltosUnits units; - void show(AltosState state, AltosListenerState listener_state) {} + abstract void show(AltosState state, AltosListenerState listener_state); void reset() { value.setText(""); @@ -265,23 +316,29 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { max = AltosLib.MISSING; } - void set_font() { + public void font_size_changed(int font_size) { label.setFont(AltosUILib.label_font); value.setFont(AltosUILib.value_font); max_value.setFont(AltosUILib.value_font); } - void show(AltosUnits units, double v) { + public void units_changed(boolean imperial_units) { + show(v); + } + + void show(double v) { + this.v = v; if (v == AltosLib.MISSING) { value.setText("Missing"); - max_value.setText("Missing"); } else { value.setText(units.show(8, v)); - if (v > max || max == AltosLib.MISSING) { - max_value.setText(units.show(8, v)); + if (v > max || max == AltosLib.MISSING) max = v; - } } + if (max == AltosLib.MISSING) + max_value.setText("Missing"); + else + max_value.setText(units.show(8, max)); } void hide() { @@ -290,7 +347,8 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { max_value.setVisible(false); } - public ValueHold (GridBagLayout layout, int y, String text) { + public ValueHold (GridBagLayout layout, int y, AltosUnits units, String text) { + this.units = units; GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -330,10 +388,10 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { class Altitude extends ValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.height, state.altitude()); + show(state.altitude()); } public Altitude (GridBagLayout layout, int y) { - super (layout, y, "Altitude"); + super (layout, y, AltosConvert.height, "Altitude"); } } @@ -341,10 +399,10 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { class AscentRate extends ValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.speed, state.gps_ascent_rate()); + show(state.gps_ascent_rate()); } public AscentRate (GridBagLayout layout, int y) { - super (layout, y, "Ascent Rate"); + super (layout, y, AltosConvert.speed, "Ascent Rate"); } } @@ -352,10 +410,10 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { class GroundSpeed extends ValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(AltosConvert.speed, state.gps_ground_speed()); + show(state.gps_ground_speed()); } public GroundSpeed (GridBagLayout layout, int y) { - super (layout, y, "Ground Speed"); + super (layout, y, AltosConvert.speed, "Ground Speed"); } } @@ -382,7 +440,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { course)); } public Course (GridBagLayout layout, int y) { - super (layout, 0, y, "Course"); + super (layout, y, "Course", false); } } @@ -416,17 +474,20 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { Lon lon; - class GPSLocked extends Info { + class GPSLocked extends DualValue { void show (AltosState state, AltosListenerState listener_state) { if (state == null || state.gps == null) hide(); else { - show("%4d sats", state.gps.nsat); - lights.set(state.gps.locked && state.gps.nsat >= 4); + int soln = state.gps.nsat; + int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0; + show("%4d in solution", soln, + "%4d in view", nsat); + lights.set(state.gps.locked && soln >= 4); } } public GPSLocked (GridBagLayout layout, int y) { - super (layout, y, "GPS Locked"); + super (layout, y, "GPS Locked", true); } } @@ -442,16 +503,26 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { gps_locked.reset(); } - public void set_font() { + public void font_size_changed(int font_size) { cur.setFont(AltosUILib.label_font); max.setFont(AltosUILib.label_font); - lat.set_font(); - lon.set_font(); - altitude.set_font(); - ground_speed.set_font(); - ascent_rate.set_font(); - course.set_font(); - gps_locked.set_font(); + lat.font_size_changed(font_size); + lon.font_size_changed(font_size); + altitude.font_size_changed(font_size); + ground_speed.font_size_changed(font_size); + ascent_rate.font_size_changed(font_size); + course.font_size_changed(font_size); + gps_locked.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + lat.units_changed(imperial_units); + lon.units_changed(imperial_units); + altitude.units_changed(imperial_units); + ground_speed.units_changed(imperial_units); + ascent_rate.units_changed(imperial_units); + course.units_changed(imperial_units); + gps_locked.units_changed(imperial_units); } public void show(AltosState state, AltosListenerState listener_state) { diff --git a/telegps/TeleGPSStatus.java b/telegps/TeleGPSStatus.java index fd66b279..37cfae37 100644 --- a/telegps/TeleGPSStatus.java +++ b/telegps/TeleGPSStatus.java @@ -25,7 +25,7 @@ import org.altusmetrum.altosuilib_2.*; public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - public class FlightValue { + public class Value { JLabel label; JTextField value; @@ -45,7 +45,7 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { value.setVisible(visible); } - public FlightValue (GridBagLayout layout, int x, String text) { + public Value (GridBagLayout layout, int x, String text) { GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.CENTER; @@ -69,7 +69,7 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { } } - class Call extends FlightValue { + class Call extends Value { void show(AltosState state, AltosListenerState listener_state) { value.setText(state.callsign); if (state.callsign == null) @@ -84,7 +84,7 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { Call call; - class Serial extends FlightValue { + class Serial extends Value { void show(AltosState state, AltosListenerState listener_state) { if (state.serial == AltosLib.MISSING) value.setText("none"); @@ -98,7 +98,7 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { Serial serial; - class RSSI extends FlightValue { + class RSSI extends Value { void show(AltosState state, AltosListenerState listener_state) { value.setText(String.format("%d", state.rssi())); if (state.rssi == AltosLib.MISSING) @@ -113,7 +113,7 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { RSSI rssi; - class LastPacket extends FlightValue { + class LastPacket extends Value { void show(AltosState state, AltosListenerState listener_state) { long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000; value.setText(String.format("%d", secs)); @@ -132,13 +132,16 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { last_packet.reset(); } - public void set_font () { + public void font_size_changed(int font_size) { call.set_font(); serial.set_font(); rssi.set_font(); last_packet.set_font(); } + public void units_changed(boolean imperial_units) { + } + public void show (AltosState state, AltosListenerState listener_state) { call.show(state, listener_state); serial.show(state, listener_state); -- cgit v1.2.3 From bf684a4c290573a3aa627fd8ddf6f6ebbe5fa057 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 May 2014 14:36:14 -0700 Subject: telegps: Add graph display Moved the altosui graph files to altosuilib and fixed things up. Signed-off-by: Keith Packard --- altoslib/AltosLib.java | 4 + altosui/AltosGraph.java | 429 ------------------------------------ altosui/AltosGraphDataPoint.java | 242 -------------------- altosui/AltosGraphDataSet.java | 95 -------- altosui/AltosGraphUI.java | 19 +- altosui/AltosIgnitor.java | 6 +- altosui/Makefile.am | 3 - altosuilib/AltosGraph.java | 428 +++++++++++++++++++++++++++++++++++ altosuilib/AltosGraphDataPoint.java | 241 ++++++++++++++++++++ altosuilib/AltosGraphDataSet.java | 94 ++++++++ altosuilib/AltosUIGraph.java | 4 +- altosuilib/Makefile.am | 3 + telegps/Makefile.am | 5 +- telegps/TeleGPS.java | 10 + 14 files changed, 801 insertions(+), 782 deletions(-) delete mode 100644 altosui/AltosGraph.java delete mode 100644 altosui/AltosGraphDataPoint.java delete mode 100644 altosui/AltosGraphDataSet.java create mode 100644 altosuilib/AltosGraph.java create mode 100644 altosuilib/AltosGraphDataPoint.java create mode 100644 altosuilib/AltosGraphDataSet.java (limited to 'altosuilib') diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 5e18202f..3aef077a 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -479,4 +479,8 @@ public class AltosLib { default: return "unknown"; } } + + public static String ignitor_name(int i) { + return String.format("Ignitor %c", 'A' + i); + } } diff --git a/altosui/AltosGraph.java b/altosui/AltosGraph.java deleted file mode 100644 index ba3875c6..00000000 --- a/altosui/AltosGraph.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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_4.*; -import org.altusmetrum.altosuilib_2.*; - -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, boolean imperial_units) { - return v; - } - - public double inverse(double v, boolean imperial_units) { - return v; - } - - public String show_units(boolean imperial_units) { - return "V"; - } - - public String say_units(boolean imperial_units) { - return "volts"; - } - - public int show_fraction(int width, boolean imperial_units) { - return width / 2; - } -} - -class AltosNsat extends AltosUnits { - - public double value(double v, boolean imperial_units) { - return v; - } - - public double inverse(double v, boolean imperial_units) { - return v; - } - - public String show_units(boolean imperial_units) { - return "Sats"; - } - - public String say_units(boolean imperial_units) { - return "Satellites"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 0; - } -} - -class AltosPressure extends AltosUnits { - - public double value(double p, boolean imperial_units) { - return p; - } - - public double inverse(double p, boolean imperial_units) { - return p; - } - - public String show_units(boolean imperial_units) { - return "Pa"; - } - - public String say_units(boolean imperial_units) { - return "pascals"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 0; - } -} - -class AltosDbm extends AltosUnits { - - public double value(double d, boolean imperial_units) { - return d; - } - - public double inverse(double d, boolean imperial_units) { - return d; - } - - public String show_units(boolean imperial_units) { - return "dBm"; - } - - public String say_units(boolean imperial_units) { - return "D B M"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 0; - } -} - -class AltosGyroUnits extends AltosUnits { - - public double value(double p, boolean imperial_units) { - return p; - } - - public double inverse(double p, boolean imperial_units) { - return p; - } - - public String show_units(boolean imperial_units) { - return "°/sec"; - } - - public String say_units(boolean imperial_units) { - return "degrees per second"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 1; - } -} - -class AltosMagUnits extends AltosUnits { - - public double value(double p, boolean imperial_units) { - return p; - } - - public double inverse(double p, boolean imperial_units) { - return p; - } - - public String show_units(boolean imperial_units) { - return "Ga"; - } - - public String say_units(boolean imperial_units) { - return "gauss"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 2; - } -} - -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 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 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 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_climb_rate_color = new Color (31, 31, 112); - 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_x_color = new Color(255, 0, 0); - static final private Color accel_y_color = new Color(0, 255, 0); - static final private Color accel_z_color = new Color(0, 0, 255); - static final private Color gyro_x_color = new Color(192, 0, 0); - static final private Color gyro_y_color = new Color(0, 192, 0); - static final private Color gyro_z_color = new Color(0, 0, 192); - static final private Color mag_x_color = new Color(128, 0, 0); - static final private Color mag_y_color = new Color(0, 128, 0); - static final private Color mag_z_color = new Color(0, 0, 128); - static final private Color orient_color = new Color(31, 31, 31); - - static AltosVoltage voltage_units = new AltosVoltage(); - static AltosPressure pressure_units = new AltosPressure(); - static AltosNsat nsat_units = new AltosNsat(); - static AltosDbm dbm_units = new AltosDbm(); - static AltosGyroUnits gyro_units = new AltosGyroUnits(); - static AltosOrient orient_units = new AltosOrient(); - static AltosMagUnits mag_units = new AltosMagUnits(); - - AltosUIAxis height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis; - AltosUIAxis distance_axis, pressure_axis; - AltosUIAxis gyro_axis, orient_axis, mag_axis; - AltosUIAxis course_axis; - - public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosGraphDataSet dataSet) { - super(enable); - - height_axis = newAxis("Height", AltosConvert.height, height_color); - pressure_axis = newAxis("Pressure", pressure_units, pressure_color, 0); - 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); - - gyro_axis = newAxis("Rotation Rate", gyro_units, gyro_z_color, 0); - orient_axis = newAxis("Tilt Angle", orient_units, orient_color, 0); - mag_axis = newAxis("Magnetic Field", mag_units, mag_x_color, 0); - course_axis = newAxis("Course", orient_units, gps_course_color, 0); - - addMarker("State", AltosGraphDataPoint.data_state, state_color); - addSeries("Height", - AltosGraphDataPoint.data_height, - AltosConvert.height, - height_color, - true, - height_axis); - addSeries("Pressure", - AltosGraphDataPoint.data_pressure, - pressure_units, - pressure_color, - false, - pressure_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); - if (stats.has_gps) { - 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("GPS Course", - AltosGraphDataPoint.data_gps_course, - orient_units, - gps_course_color, - false, - course_axis); - addSeries("GPS Ground Speed", - AltosGraphDataPoint.data_gps_ground_speed, - AltosConvert.speed, - gps_ground_speed_color, - false, - speed_axis); - addSeries("GPS Climb Rate", - AltosGraphDataPoint.data_gps_climb_rate, - AltosConvert.speed, - gps_climb_rate_color, - false, - speed_axis); - } - if (stats.has_rssi) - addSeries("Received Signal Strength", - AltosGraphDataPoint.data_rssi, - dbm_units, - dbm_color, - false, - dbm_axis); - if (stats.has_other_adc) { - 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); - } - - if (stats.has_imu) { - addSeries("Acceleration X", - AltosGraphDataPoint.data_accel_x, - AltosConvert.accel, - accel_x_color, - false, - accel_axis); - addSeries("Acceleration Y", - AltosGraphDataPoint.data_accel_y, - AltosConvert.accel, - accel_y_color, - false, - accel_axis); - addSeries("Acceleration Z", - AltosGraphDataPoint.data_accel_z, - AltosConvert.accel, - accel_z_color, - false, - accel_axis); - addSeries("Rotation Rate X", - AltosGraphDataPoint.data_gyro_x, - gyro_units, - gyro_x_color, - false, - gyro_axis); - addSeries("Rotation Rate Y", - AltosGraphDataPoint.data_gyro_y, - gyro_units, - gyro_y_color, - false, - gyro_axis); - addSeries("Rotation Rate Z", - AltosGraphDataPoint.data_gyro_z, - gyro_units, - gyro_z_color, - false, - gyro_axis); - } - if (stats.has_mag) { - addSeries("Magnetometer X", - AltosGraphDataPoint.data_mag_x, - mag_units, - mag_x_color, - false, - mag_axis); - addSeries("Magnetometer Y", - AltosGraphDataPoint.data_mag_y, - mag_units, - mag_y_color, - false, - mag_axis); - addSeries("Magnetometer Z", - AltosGraphDataPoint.data_mag_z, - mag_units, - mag_z_color, - false, - mag_axis); - } - if (stats.has_orient) - addSeries("Tilt Angle", - AltosGraphDataPoint.data_orient, - orient_units, - orient_color, - false, - orient_axis); - if (stats.num_ignitor > 0) { - for (int i = 0; i < stats.num_ignitor; i++) - addSeries(AltosIgnitor.ignitor_name(i), - AltosGraphDataPoint.data_ignitor_0 + i, - voltage_units, - main_voltage_color, - false, - voltage_axis); - for (int i = 0; i < stats.num_ignitor; i++) - addMarker(AltosIgnitor.ignitor_name(i), AltosGraphDataPoint.data_ignitor_fired_0 + i, state_color); - } - - setDataSet(dataSet); - } -} diff --git a/altosui/AltosGraphDataPoint.java b/altosui/AltosGraphDataPoint.java deleted file mode 100644 index 06a9b62d..00000000 --- a/altosui/AltosGraphDataPoint.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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_2.*; -import org.altusmetrum.altoslib_4.*; - -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 static final int data_pressure = 15; - public static final int data_accel_x = 16; - public static final int data_accel_y = 17; - public static final int data_accel_z = 18; - public static final int data_gyro_x = 19; - public static final int data_gyro_y = 20; - public static final int data_gyro_z = 21; - public static final int data_mag_x = 22; - public static final int data_mag_y = 23; - public static final int data_mag_z = 24; - public static final int data_orient = 25; - public static final int data_gps_course = 26; - public static final int data_gps_ground_speed = 27; - public static final int data_gps_climb_rate = 28; - public static final int data_ignitor_0 = 29; - public static final int data_ignitor_num = 32; - public static final int data_ignitor_max = data_ignitor_0 + data_ignitor_num - 1; - public static final int data_ignitor_fired_0 = data_ignitor_0 + data_ignitor_num; - public static final int data_ignitor_fired_max = data_ignitor_fired_0 + data_ignitor_num - 1; - - public double x() throws AltosUIDataMissing { - double time = state.time_since_boost(); - if (time < -2) - throw new AltosUIDataMissing(-1); - return time; - } - - public double y(int index) throws AltosUIDataMissing { - double y = AltosLib.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_voltage; - break; - case data_drogue_voltage: - y = state.apogee_voltage; - break; - case data_main_voltage: - y = state.main_voltage; - break; - case data_rssi: - y = state.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; - case data_pressure: - y = state.pressure(); - break; - - case data_accel_x: - case data_accel_y: - case data_accel_z: - case data_gyro_x: - case data_gyro_y: - case data_gyro_z: - AltosIMU imu = state.imu; - if (imu == null) - break; - switch (index) { - case data_accel_x: - y = imu.accel_x; - break; - case data_accel_y: - y = imu.accel_y; - break; - case data_accel_z: - y = imu.accel_z; - break; - case data_gyro_x: - y = imu.gyro_x; - break; - case data_gyro_y: - y = imu.gyro_y; - break; - case data_gyro_z: - y = imu.gyro_z; - break; - } - break; - case data_mag_x: - case data_mag_y: - case data_mag_z: - AltosMag mag = state.mag; - if (mag == null) - break; - switch (index) { - case data_mag_x: - y = mag.x; - break; - case data_mag_y: - y = mag.y; - break; - case data_mag_z: - y = mag.z; - break; - } - break; - case data_orient: - y = state.orient(); - break; - case data_gps_course: - if (state.gps != null) - y = state.gps.course; - else - y = AltosLib.MISSING; - break; - case data_gps_ground_speed: - if (state.gps != null) - y = state.gps.ground_speed; - else - y = AltosLib.MISSING; - break; - case data_gps_climb_rate: - if (state.gps != null) - y = state.gps.climb_rate; - else - y = AltosLib.MISSING; - break; - default: - if (data_ignitor_0 <= index && index <= data_ignitor_max) { - int ignitor = index - data_ignitor_0; - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) - y = state.ignitor_voltage[ignitor]; - } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { - int ignitor = index - data_ignitor_fired_0; - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { - if ((state.pyro_fired & (1 << ignitor)) != 0) - y = 1; - else - y = 0; - } - } - break; - } - if (y == AltosLib.MISSING) - throw new AltosUIDataMissing(index); - return y; - } - - public int id(int index) { - if (index == data_state) { - int s = state.state; - if (Altos.ao_flight_boost <= s && s <= Altos.ao_flight_landed) - return s; - } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { - int ignitor = index - data_ignitor_fired_0; - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { - if ((state.pyro_fired & (1 << ignitor)) != 0) - return 1; - } - } - } - return -1; - } - - public String id_name(int index) { - if (index == data_state) { - return state.state_name(); - } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { - int ignitor = index - data_ignitor_fired_0; - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) - return AltosIgnitor.ignitor_name(ignitor); - } - return ""; - } - - public AltosGraphDataPoint (AltosState state) { - this.state = state; - } -} diff --git a/altosui/AltosGraphDataSet.java b/altosui/AltosGraphDataSet.java deleted file mode 100644 index a90c2563..00000000 --- a/altosui/AltosGraphDataSet.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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_4.*; -import org.altusmetrum.altosuilib_2.*; - -class AltosGraphIterator implements Iterator { - AltosGraphDataSet dataSet; - Iterator iterator; - - public boolean hasNext() { - return iterator.hasNext(); - } - - public AltosUIDataPoint next() { - AltosState state = iterator.next(); - - if (state.flight != AltosLib.MISSING) { - if (dataSet.callsign == null && state.callsign != null) - dataSet.callsign = state.callsign; - - if (dataSet.serial == 0 && state.serial != 0) - dataSet.serial = state.serial; - - if (dataSet.flight == 0 && state.flight != 0) - dataSet.flight = state.flight; - } - - return new AltosGraphDataPoint(state); - } - - public AltosGraphIterator (Iterator iterator, AltosGraphDataSet dataSet) { - this.iterator = iterator; - this.dataSet = dataSet; - } - - public void remove() { - } -} - -class AltosGraphIterable implements Iterable { - AltosGraphDataSet dataSet; - - public Iterator iterator() { - return new AltosGraphIterator(dataSet.states.iterator(), dataSet); - } - - public AltosGraphIterable(AltosGraphDataSet dataSet) { - this.dataSet = dataSet; - } -} - -public class AltosGraphDataSet implements AltosUIDataSet { - String callsign; - int serial; - int flight; - AltosStateIterable states; - - 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 dataPoints() { - return new AltosGraphIterable(this); - } - - public AltosGraphDataSet (AltosStateIterable states) { - this.states = states; - this.callsign = null; - this.serial = 0; - this.flight = 0; - } -} diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 33e12130..9e8a1939 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -1,6 +1,19 @@ - -// Copyright (c) 2010 Anthony Towns -// GPL v2 or later +/* + * Copyright © 2010 Anthony Towns + * + * 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 or any later version 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; diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java index 27917b30..7f62938d 100644 --- a/altosui/AltosIgnitor.java +++ b/altosui/AltosIgnitor.java @@ -114,10 +114,6 @@ public class AltosIgnitor extends JComponent implements AltosFlightDisplay { } } - public static String ignitor_name(int i) { - return String.format("Ignitor %c", 'A' + i); - } - class Ignitor extends LaunchStatus { int ignitor; @@ -131,7 +127,7 @@ public class AltosIgnitor extends JComponent implements AltosFlightDisplay { } public Ignitor (GridBagLayout layout, int y) { - super(layout, y, String.format ("%s Voltage", ignitor_name(y))); + super(layout, y, String.format ("%s Voltage", AltosLib.ignitor_name(y))); ignitor = y; } } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index add46825..1eb2d967 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -35,9 +35,6 @@ altosui_JAVA = \ AltosPad.java \ AltosUIPreferencesBackend.java \ AltosUI.java \ - AltosGraph.java \ - AltosGraphDataPoint.java \ - AltosGraphDataSet.java \ AltosGraphUI.java JFREECHART_CLASS= \ diff --git a/altosuilib/AltosGraph.java b/altosuilib/AltosGraph.java new file mode 100644 index 00000000..5e5a35cf --- /dev/null +++ b/altosuilib/AltosGraph.java @@ -0,0 +1,428 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.io.*; +import java.util.ArrayList; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +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, boolean imperial_units) { + return v; + } + + public double inverse(double v, boolean imperial_units) { + return v; + } + + public String show_units(boolean imperial_units) { + return "V"; + } + + public String say_units(boolean imperial_units) { + return "volts"; + } + + public int show_fraction(int width, boolean imperial_units) { + return width / 2; + } +} + +class AltosNsat extends AltosUnits { + + public double value(double v, boolean imperial_units) { + return v; + } + + public double inverse(double v, boolean imperial_units) { + return v; + } + + public String show_units(boolean imperial_units) { + return "Sats"; + } + + public String say_units(boolean imperial_units) { + return "Satellites"; + } + + public int show_fraction(int width, boolean imperial_units) { + return 0; + } +} + +class AltosPressure extends AltosUnits { + + public double value(double p, boolean imperial_units) { + return p; + } + + public double inverse(double p, boolean imperial_units) { + return p; + } + + public String show_units(boolean imperial_units) { + return "Pa"; + } + + public String say_units(boolean imperial_units) { + return "pascals"; + } + + public int show_fraction(int width, boolean imperial_units) { + return 0; + } +} + +class AltosDbm extends AltosUnits { + + public double value(double d, boolean imperial_units) { + return d; + } + + public double inverse(double d, boolean imperial_units) { + return d; + } + + public String show_units(boolean imperial_units) { + return "dBm"; + } + + public String say_units(boolean imperial_units) { + return "D B M"; + } + + public int show_fraction(int width, boolean imperial_units) { + return 0; + } +} + +class AltosGyroUnits extends AltosUnits { + + public double value(double p, boolean imperial_units) { + return p; + } + + public double inverse(double p, boolean imperial_units) { + return p; + } + + public String show_units(boolean imperial_units) { + return "°/sec"; + } + + public String say_units(boolean imperial_units) { + return "degrees per second"; + } + + public int show_fraction(int width, boolean imperial_units) { + return 1; + } +} + +class AltosMagUnits extends AltosUnits { + + public double value(double p, boolean imperial_units) { + return p; + } + + public double inverse(double p, boolean imperial_units) { + return p; + } + + public String show_units(boolean imperial_units) { + return "Ga"; + } + + public String say_units(boolean imperial_units) { + return "gauss"; + } + + public int show_fraction(int width, boolean imperial_units) { + return 2; + } +} + +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 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 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 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_climb_rate_color = new Color (31, 31, 112); + 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_x_color = new Color(255, 0, 0); + static final private Color accel_y_color = new Color(0, 255, 0); + static final private Color accel_z_color = new Color(0, 0, 255); + static final private Color gyro_x_color = new Color(192, 0, 0); + static final private Color gyro_y_color = new Color(0, 192, 0); + static final private Color gyro_z_color = new Color(0, 0, 192); + static final private Color mag_x_color = new Color(128, 0, 0); + static final private Color mag_y_color = new Color(0, 128, 0); + static final private Color mag_z_color = new Color(0, 0, 128); + static final private Color orient_color = new Color(31, 31, 31); + + static AltosVoltage voltage_units = new AltosVoltage(); + static AltosPressure pressure_units = new AltosPressure(); + static AltosNsat nsat_units = new AltosNsat(); + static AltosDbm dbm_units = new AltosDbm(); + static AltosGyroUnits gyro_units = new AltosGyroUnits(); + static AltosOrient orient_units = new AltosOrient(); + static AltosMagUnits mag_units = new AltosMagUnits(); + + AltosUIAxis height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis; + AltosUIAxis distance_axis, pressure_axis; + AltosUIAxis gyro_axis, orient_axis, mag_axis; + AltosUIAxis course_axis; + + public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosGraphDataSet dataSet) { + super(enable); + + height_axis = newAxis("Height", AltosConvert.height, height_color); + pressure_axis = newAxis("Pressure", pressure_units, pressure_color, 0); + 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); + + gyro_axis = newAxis("Rotation Rate", gyro_units, gyro_z_color, 0); + orient_axis = newAxis("Tilt Angle", orient_units, orient_color, 0); + mag_axis = newAxis("Magnetic Field", mag_units, mag_x_color, 0); + course_axis = newAxis("Course", orient_units, gps_course_color, 0); + + addMarker("State", AltosGraphDataPoint.data_state, state_color); + addSeries("Height", + AltosGraphDataPoint.data_height, + AltosConvert.height, + height_color, + true, + height_axis); + addSeries("Pressure", + AltosGraphDataPoint.data_pressure, + pressure_units, + pressure_color, + false, + pressure_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); + if (stats.has_gps) { + 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("GPS Course", + AltosGraphDataPoint.data_gps_course, + orient_units, + gps_course_color, + false, + course_axis); + addSeries("GPS Ground Speed", + AltosGraphDataPoint.data_gps_ground_speed, + AltosConvert.speed, + gps_ground_speed_color, + false, + speed_axis); + addSeries("GPS Climb Rate", + AltosGraphDataPoint.data_gps_climb_rate, + AltosConvert.speed, + gps_climb_rate_color, + false, + speed_axis); + } + if (stats.has_rssi) + addSeries("Received Signal Strength", + AltosGraphDataPoint.data_rssi, + dbm_units, + dbm_color, + false, + dbm_axis); + if (stats.has_other_adc) { + 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); + } + + if (stats.has_imu) { + addSeries("Acceleration X", + AltosGraphDataPoint.data_accel_x, + AltosConvert.accel, + accel_x_color, + false, + accel_axis); + addSeries("Acceleration Y", + AltosGraphDataPoint.data_accel_y, + AltosConvert.accel, + accel_y_color, + false, + accel_axis); + addSeries("Acceleration Z", + AltosGraphDataPoint.data_accel_z, + AltosConvert.accel, + accel_z_color, + false, + accel_axis); + addSeries("Rotation Rate X", + AltosGraphDataPoint.data_gyro_x, + gyro_units, + gyro_x_color, + false, + gyro_axis); + addSeries("Rotation Rate Y", + AltosGraphDataPoint.data_gyro_y, + gyro_units, + gyro_y_color, + false, + gyro_axis); + addSeries("Rotation Rate Z", + AltosGraphDataPoint.data_gyro_z, + gyro_units, + gyro_z_color, + false, + gyro_axis); + } + if (stats.has_mag) { + addSeries("Magnetometer X", + AltosGraphDataPoint.data_mag_x, + mag_units, + mag_x_color, + false, + mag_axis); + addSeries("Magnetometer Y", + AltosGraphDataPoint.data_mag_y, + mag_units, + mag_y_color, + false, + mag_axis); + addSeries("Magnetometer Z", + AltosGraphDataPoint.data_mag_z, + mag_units, + mag_z_color, + false, + mag_axis); + } + if (stats.has_orient) + addSeries("Tilt Angle", + AltosGraphDataPoint.data_orient, + orient_units, + orient_color, + false, + orient_axis); + if (stats.num_ignitor > 0) { + for (int i = 0; i < stats.num_ignitor; i++) + addSeries(AltosLib.ignitor_name(i), + AltosGraphDataPoint.data_ignitor_0 + i, + voltage_units, + main_voltage_color, + false, + voltage_axis); + for (int i = 0; i < stats.num_ignitor; i++) + addMarker(AltosLib.ignitor_name(i), AltosGraphDataPoint.data_ignitor_fired_0 + i, state_color); + } + + setDataSet(dataSet); + } +} diff --git a/altosuilib/AltosGraphDataPoint.java b/altosuilib/AltosGraphDataPoint.java new file mode 100644 index 00000000..a64a9d14 --- /dev/null +++ b/altosuilib/AltosGraphDataPoint.java @@ -0,0 +1,241 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import org.altusmetrum.altoslib_4.*; + +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 static final int data_pressure = 15; + public static final int data_accel_x = 16; + public static final int data_accel_y = 17; + public static final int data_accel_z = 18; + public static final int data_gyro_x = 19; + public static final int data_gyro_y = 20; + public static final int data_gyro_z = 21; + public static final int data_mag_x = 22; + public static final int data_mag_y = 23; + public static final int data_mag_z = 24; + public static final int data_orient = 25; + public static final int data_gps_course = 26; + public static final int data_gps_ground_speed = 27; + public static final int data_gps_climb_rate = 28; + public static final int data_ignitor_0 = 29; + public static final int data_ignitor_num = 32; + public static final int data_ignitor_max = data_ignitor_0 + data_ignitor_num - 1; + public static final int data_ignitor_fired_0 = data_ignitor_0 + data_ignitor_num; + public static final int data_ignitor_fired_max = data_ignitor_fired_0 + data_ignitor_num - 1; + + public double x() throws AltosUIDataMissing { + double time = state.time_since_boost(); + if (time < -2) + throw new AltosUIDataMissing(-1); + return time; + } + + public double y(int index) throws AltosUIDataMissing { + double y = AltosLib.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_voltage; + break; + case data_drogue_voltage: + y = state.apogee_voltage; + break; + case data_main_voltage: + y = state.main_voltage; + break; + case data_rssi: + y = state.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; + case data_pressure: + y = state.pressure(); + break; + + case data_accel_x: + case data_accel_y: + case data_accel_z: + case data_gyro_x: + case data_gyro_y: + case data_gyro_z: + AltosIMU imu = state.imu; + if (imu == null) + break; + switch (index) { + case data_accel_x: + y = imu.accel_x; + break; + case data_accel_y: + y = imu.accel_y; + break; + case data_accel_z: + y = imu.accel_z; + break; + case data_gyro_x: + y = imu.gyro_x; + break; + case data_gyro_y: + y = imu.gyro_y; + break; + case data_gyro_z: + y = imu.gyro_z; + break; + } + break; + case data_mag_x: + case data_mag_y: + case data_mag_z: + AltosMag mag = state.mag; + if (mag == null) + break; + switch (index) { + case data_mag_x: + y = mag.x; + break; + case data_mag_y: + y = mag.y; + break; + case data_mag_z: + y = mag.z; + break; + } + break; + case data_orient: + y = state.orient(); + break; + case data_gps_course: + if (state.gps != null) + y = state.gps.course; + else + y = AltosLib.MISSING; + break; + case data_gps_ground_speed: + if (state.gps != null) + y = state.gps.ground_speed; + else + y = AltosLib.MISSING; + break; + case data_gps_climb_rate: + if (state.gps != null) + y = state.gps.climb_rate; + else + y = AltosLib.MISSING; + break; + default: + if (data_ignitor_0 <= index && index <= data_ignitor_max) { + int ignitor = index - data_ignitor_0; + if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) + y = state.ignitor_voltage[ignitor]; + } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { + int ignitor = index - data_ignitor_fired_0; + if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { + if ((state.pyro_fired & (1 << ignitor)) != 0) + y = 1; + else + y = 0; + } + } + break; + } + if (y == AltosLib.MISSING) + throw new AltosUIDataMissing(index); + return y; + } + + public int id(int index) { + if (index == data_state) { + int s = state.state; + if (AltosLib.ao_flight_boost <= s && s <= AltosLib.ao_flight_landed) + return s; + } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { + int ignitor = index - data_ignitor_fired_0; + if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { + if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { + if ((state.pyro_fired & (1 << ignitor)) != 0) + return 1; + } + } + } + return -1; + } + + public String id_name(int index) { + if (index == data_state) { + return state.state_name(); + } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { + int ignitor = index - data_ignitor_fired_0; + if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) + return AltosLib.ignitor_name(ignitor); + } + return ""; + } + + public AltosGraphDataPoint (AltosState state) { + this.state = state; + } +} diff --git a/altosuilib/AltosGraphDataSet.java b/altosuilib/AltosGraphDataSet.java new file mode 100644 index 00000000..36933e9b --- /dev/null +++ b/altosuilib/AltosGraphDataSet.java @@ -0,0 +1,94 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.lang.*; +import java.io.*; +import java.util.*; +import org.altusmetrum.altoslib_4.*; + +class AltosGraphIterator implements Iterator { + AltosGraphDataSet dataSet; + Iterator iterator; + + public boolean hasNext() { + return iterator.hasNext(); + } + + public AltosUIDataPoint next() { + AltosState state = iterator.next(); + + if (state.flight != AltosLib.MISSING) { + if (dataSet.callsign == null && state.callsign != null) + dataSet.callsign = state.callsign; + + if (dataSet.serial == 0 && state.serial != 0) + dataSet.serial = state.serial; + + if (dataSet.flight == 0 && state.flight != 0) + dataSet.flight = state.flight; + } + + return new AltosGraphDataPoint(state); + } + + public AltosGraphIterator (Iterator iterator, AltosGraphDataSet dataSet) { + this.iterator = iterator; + this.dataSet = dataSet; + } + + public void remove() { + } +} + +class AltosGraphIterable implements Iterable { + AltosGraphDataSet dataSet; + + public Iterator iterator() { + return new AltosGraphIterator(dataSet.states.iterator(), dataSet); + } + + public AltosGraphIterable(AltosGraphDataSet dataSet) { + this.dataSet = dataSet; + } +} + +public class AltosGraphDataSet implements AltosUIDataSet { + String callsign; + int serial; + int flight; + AltosStateIterable states; + + 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 dataPoints() { + return new AltosGraphIterable(this); + } + + public AltosGraphDataSet (AltosStateIterable states) { + this.states = states; + this.callsign = null; + this.serial = 0; + this.flight = 0; + } +} diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java index 909c471b..9cca088d 100644 --- a/altosuilib/AltosUIGraph.java +++ b/altosuilib/AltosUIGraph.java @@ -85,8 +85,6 @@ public class AltosUIGraph implements AltosUnitsListener { public void addMarker(String label, int fetch, Color color) { AltosUIMarker marker = new AltosUIMarker(fetch, color, plot); - if (enable != null) - enable.add(label, marker, true); this.graphers.add(marker); } @@ -158,4 +156,4 @@ public class AltosUIGraph implements AltosUnitsListener { AltosPreferences.register_units_listener(this); } -} \ No newline at end of file +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 65a8228a..e415fc5b 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -58,6 +58,9 @@ altosuilib_JAVA = \ AltosRomconfigUI.java \ AltosInfoTable.java \ AltosFlightInfoTableModel.java \ + AltosGraph.java \ + AltosGraphDataPoint.java \ + AltosGraphDataSet.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ diff --git a/telegps/Makefile.am b/telegps/Makefile.am index f064a488..87d8a66a 100644 --- a/telegps/Makefile.am +++ b/telegps/Makefile.am @@ -5,7 +5,7 @@ man_MANS=telegps.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar $(FREETTS)/freetts.jar" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" bin_SCRIPTS=telegps @@ -18,7 +18,8 @@ telegps_JAVA= \ TeleGPSInfo.java \ TeleGPSConfig.java \ TeleGPSConfigUI.java \ - TeleGPSPreferences.java + TeleGPSPreferences.java \ + TeleGPSGraphUI.java JFREECHART_CLASS= \ jfreechart.jar diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index bef0bbc6..5a707547 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -246,6 +246,16 @@ public class TeleGPS } void graph() { + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosStateIterable states = chooser.runDialog(); + if (states == null) + return; + try { + new TeleGPSGraphUI(states, chooser.file()); + } catch (InterruptedException ie) { + } catch (IOException ie) { + } } void flash() { -- cgit v1.2.3 From 1bcafc452f50e518c4d86cbd6b9057c4bf7e676f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Jun 2014 16:50:29 -0700 Subject: altosuilib: Let the user hand-edit the preload map radius In case they want more than 5 Signed-off-by: Keith Packard --- altosuilib/AltosSiteMapPreload.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMapPreload.java b/altosuilib/AltosSiteMapPreload.java index 6b8066b3..ed7ecbd3 100644 --- a/altosuilib/AltosSiteMapPreload.java +++ b/altosuilib/AltosSiteMapPreload.java @@ -556,7 +556,7 @@ public class AltosSiteMapPreload extends AltosUIFrame implements ActionListener, radius = new JComboBox(radii); radius.setSelectedItem(radii[4]); - radius.setEditable(false); + radius.setEditable(true); c.gridx = 5; c.gridy = 4; pane.add(radius, c); -- cgit v1.2.3 From 5617919091d4c4a1e627470ddab0b45cf649f7a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Jun 2014 11:49:14 -0700 Subject: altosuilib: Show GPS instead of (missing) flight data for TeleGPS graphs Signed-off-by: Keith Packard --- altosuilib/AltosGraph.java | 68 ++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 27 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosGraph.java b/altosuilib/AltosGraph.java index 5e5a35cf..73c53a22 100644 --- a/altosuilib/AltosGraph.java +++ b/altosuilib/AltosGraph.java @@ -238,31 +238,39 @@ public class AltosGraph extends AltosUIGraph { course_axis = newAxis("Course", orient_units, gps_course_color, 0); addMarker("State", AltosGraphDataPoint.data_state, state_color); - addSeries("Height", - AltosGraphDataPoint.data_height, - AltosConvert.height, - height_color, - true, - height_axis); - addSeries("Pressure", - AltosGraphDataPoint.data_pressure, - pressure_units, - pressure_color, - false, - pressure_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); + + if (stats.has_flight_data) { + addSeries("Height", + AltosGraphDataPoint.data_height, + AltosConvert.height, + height_color, + true, + height_axis); + addSeries("Pressure", + AltosGraphDataPoint.data_pressure, + pressure_units, + pressure_color, + false, + pressure_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); + } if (stats.has_gps) { + boolean enable_gps = false; + + if (!stats.has_flight_data) + enable_gps = true; + addSeries("Range", AltosGraphDataPoint.data_range, AltosConvert.distance, @@ -273,12 +281,18 @@ public class AltosGraph extends AltosUIGraph { AltosGraphDataPoint.data_distance, AltosConvert.distance, distance_color, - false, + enable_gps, distance_axis); addSeries("GPS Height", AltosGraphDataPoint.data_gps_height, AltosConvert.height, gps_height_color, + enable_gps, + height_axis); + addSeries("GPS Altitude", + AltosGraphDataPoint.data_gps_altitude, + AltosConvert.height, + gps_height_color, false, height_axis); addSeries("GPS Satellites in Solution", @@ -303,13 +317,13 @@ public class AltosGraph extends AltosUIGraph { AltosGraphDataPoint.data_gps_ground_speed, AltosConvert.speed, gps_ground_speed_color, - false, + enable_gps, speed_axis); addSeries("GPS Climb Rate", AltosGraphDataPoint.data_gps_climb_rate, AltosConvert.speed, gps_climb_rate_color, - false, + enable_gps, speed_axis); } if (stats.has_rssi) -- cgit v1.2.3 From 611dc26ab4a3ee303c0253698b1e12931aa3644f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Jun 2014 11:50:04 -0700 Subject: altosuilib: Add GPS altitude as a possible graph value Signed-off-by: Keith Packard --- altosuilib/AltosGraphDataPoint.java | 40 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosGraphDataPoint.java b/altosuilib/AltosGraphDataPoint.java index a64a9d14..446468d7 100644 --- a/altosuilib/AltosGraphDataPoint.java +++ b/altosuilib/AltosGraphDataPoint.java @@ -35,24 +35,25 @@ public class AltosGraphDataPoint implements AltosUIDataPoint { 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 static final int data_pressure = 15; - public static final int data_accel_x = 16; - public static final int data_accel_y = 17; - public static final int data_accel_z = 18; - public static final int data_gyro_x = 19; - public static final int data_gyro_y = 20; - public static final int data_gyro_z = 21; - public static final int data_mag_x = 22; - public static final int data_mag_y = 23; - public static final int data_mag_z = 24; - public static final int data_orient = 25; - public static final int data_gps_course = 26; - public static final int data_gps_ground_speed = 27; - public static final int data_gps_climb_rate = 28; - public static final int data_ignitor_0 = 29; + public static final int data_gps_altitude = 12; + public static final int data_temperature = 13; + public static final int data_range = 14; + public static final int data_distance = 15; + public static final int data_pressure = 16; + public static final int data_accel_x = 17; + public static final int data_accel_y = 18; + public static final int data_accel_z = 19; + public static final int data_gyro_x = 20; + public static final int data_gyro_y = 21; + public static final int data_gyro_z = 22; + public static final int data_mag_x = 23; + public static final int data_mag_y = 24; + public static final int data_mag_z = 25; + public static final int data_orient = 26; + public static final int data_gps_course = 27; + public static final int data_gps_ground_speed = 28; + public static final int data_gps_climb_rate = 29; + public static final int data_ignitor_0 = 30; public static final int data_ignitor_num = 32; public static final int data_ignitor_max = data_ignitor_0 + data_ignitor_num - 1; public static final int data_ignitor_fired_0 = data_ignitor_0 + data_ignitor_num; @@ -103,6 +104,9 @@ public class AltosGraphDataPoint implements AltosUIDataPoint { if (state.gps != null && state.gps.cc_gps_sat != null) y = state.gps.cc_gps_sat.length; break; + case data_gps_altitude: + y = state.gps_altitude(); + break; case data_temperature: y = state.temperature; break; -- cgit v1.2.3 From 9f2189e0b99aa32b788ecb4576dcb9bcc926f4e2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Jun 2014 11:50:42 -0700 Subject: altosuilib: Fix crash when initializing site map cache Signed-off-by: Keith Packard --- altosuilib/AltosSiteMapCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index 3e08e1b3..51778ce1 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -158,7 +158,7 @@ public class AltosSiteMapCache { for (int i = 0; i < cache_size; i++) { if (i < new_size) new_images[i] = images[i]; - else + else if (images[i] != null) images[i].flush(); } images = new_images; -- cgit v1.2.3 From 6fc58142d2a108c91d257eb0175098bf082834f9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jun 2014 11:30:36 -0700 Subject: altosuilib: Split battery graph enable out from other adc enables This lets TeleGPS just show the battery voltage values without also adding enable lines for the other flight computer ADC values like ignitor voltages. Signed-off-by: Keith Packard --- altoslib/AltosFlightStats.java | 30 ++++--- altosui/AltosFlightStatsTable.java | 144 ---------------------------------- altosuilib/AltosFlightStatsTable.java | 144 ++++++++++++++++++++++++++++++++++ altosuilib/AltosGraph.java | 17 ++-- 4 files changed, 173 insertions(+), 162 deletions(-) delete mode 100644 altosui/AltosFlightStatsTable.java create mode 100644 altosuilib/AltosFlightStatsTable.java (limited to 'altosuilib') diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java index b3305a05..56feb848 100644 --- a/altoslib/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -37,7 +37,8 @@ public class AltosFlightStats { public double pad_lat, pad_lon; public boolean has_flight_data; public boolean has_gps; - public boolean has_other_adc; + public boolean has_flight_adc; + public boolean has_battery; public boolean has_rssi; public boolean has_imu; public boolean has_mag; @@ -112,7 +113,8 @@ public class AltosFlightStats { lat = lon = AltosLib.MISSING; has_flight_data = false; has_gps = false; - has_other_adc = false; + has_flight_adc = false; + has_battery = false; has_rssi = false; has_imu = false; has_mag = false; @@ -123,7 +125,9 @@ public class AltosFlightStats { if (flight == AltosLib.MISSING && state.flight != AltosLib.MISSING) flight = state.flight; if (state.battery_voltage != AltosLib.MISSING) - has_other_adc = true; + has_battery = true; + if (state.main_voltage != AltosLib.MISSING) + has_flight_adc = true; if (state.rssi != AltosLib.MISSING) has_rssi = true; end_time = state.time; @@ -144,6 +148,11 @@ public class AltosFlightStats { minute = state.gps.minute; second = state.gps.second; } + max_height = state.max_height(); + max_speed = state.max_speed(); + max_acceleration = state.max_acceleration(); + max_gps_height = state.max_gps_height(); + if (0 <= state_id && state_id < AltosLib.ao_flight_invalid) { double acceleration = state.acceleration(); double speed = state.speed(); @@ -156,16 +165,12 @@ public class AltosFlightStats { state_start[state_id] = state.time; if (state_end[state_id] < state.time) state_end[state_id] = state.time; - max_height = state.max_height(); - max_speed = state.max_speed(); - max_acceleration = state.max_acceleration(); - max_gps_height = state.max_gps_height(); + } + if (state.pad_lat != AltosLib.MISSING) { + pad_lat = state.pad_lat; + pad_lon = state.pad_lon; } if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { - if (state_id <= AltosLib.ao_flight_pad) { - pad_lat = state.gps.lat; - pad_lon = state.gps.lon; - } lat = state.gps.lat; lon = state.gps.lon; has_gps = true; @@ -183,6 +188,9 @@ public class AltosFlightStats { if (state_count[s] > 0) { state_speed[s] /= state_count[s]; state_accel[s] /= state_count[s]; + } else { + state_speed[s] = AltosLib.MISSING; + state_accel[s] = AltosLib.MISSING; } if (state_start[s] == 0) state_start[s] = end_time; diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java deleted file mode 100644 index e7a8e728..00000000 --- a/altosui/AltosFlightStatsTable.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_4.*; - -public class AltosFlightStatsTable extends JComponent { - GridBagLayout layout; - - class FlightStat { - JLabel label; - JTextField value; - - public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) { - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.weighty = 1; - - label = new JLabel(label_text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 0; c.gridy = y; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - for (int j = 0; j < values.length; j++) { - value = new JTextField(values[j]); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = j+1; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(value, c); - add(value); - } - } - - } - - static String pos(double p, String pos, String neg) { - String h = pos; - if (p < 0) { - h = neg; - p = -p; - } - int deg = (int) Math.floor(p); - double min = (p - Math.floor(p)) * 60.0; - return String.format("%s %4d° %9.6f'", h, deg, min); - } - - public AltosFlightStatsTable(AltosFlightStats stats) { - layout = new GridBagLayout(); - - setLayout(layout); - int y = 0; - new FlightStat(layout, y++, "Serial", String.format("%d", stats.serial)); - new FlightStat(layout, y++, "Flight", String.format("%d", stats.flight)); - if (stats.year != AltosLib.MISSING && stats.hour != AltosLib.MISSING) - new FlightStat(layout, y++, "Date/Time", - String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day), - String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second)); - else { - if (stats.year != AltosLib.MISSING) - new FlightStat(layout, y++, "Date", - String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day)); - if (stats.hour != AltosLib.MISSING) - new FlightStat(layout, y++, "Time", - String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second)); - } - new FlightStat(layout, y++, "Maximum height", - String.format("%5.0f 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", - String.format("%5.0f m", stats.max_gps_height), - String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_gps_height))); - } - new FlightStat(layout, y++, "Maximum speed", - String.format("%5.0f m/s", stats.max_speed), - String.format("%5.0f mph", AltosConvert.meters_to_mph(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("%5.0f m/s²", stats.max_acceleration), - String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)), - String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration))); - new FlightStat(layout, y++, "Average boost acceleration", - String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]), - String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[Altos.ao_flight_boost])), - String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[Altos.ao_flight_boost]))); - } - new FlightStat(layout, y++, "Drogue descent rate", - String.format("%5.0f m/s", stats.state_speed[Altos.ao_flight_drogue]), - String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue]))); - new FlightStat(layout, y++, "Main descent rate", - String.format("%5.0f m/s", stats.state_speed[Altos.ao_flight_main]), - String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main]))); - new FlightStat(layout, y++, "Ascent time", - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost], - AltosLib.state_name(Altos.ao_flight_boost)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast], - AltosLib.state_name(Altos.ao_flight_fast)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast], - AltosLib.state_name(Altos.ao_flight_coast))); - new FlightStat(layout, y++, "Descent time", - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue], - AltosLib.state_name(Altos.ao_flight_drogue)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main], - AltosLib.state_name(Altos.ao_flight_main))); - new FlightStat(layout, y++, "Flight time", - String.format("%6.1f s", stats.state_end[Altos.ao_flight_main] - - stats.state_start[Altos.ao_flight_boost])); - if (stats.has_gps) { - new FlightStat(layout, y++, "Pad location", - pos(stats.pad_lat,"N","S"), - pos(stats.pad_lon,"E","W")); - new FlightStat(layout, y++, "Last reported location", - pos(stats.lat,"N","S"), - pos(stats.lon,"E","W")); - } - } - -} \ No newline at end of file diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java new file mode 100644 index 00000000..e7a8e728 --- /dev/null +++ b/altosuilib/AltosFlightStatsTable.java @@ -0,0 +1,144 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package altosui; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosFlightStatsTable extends JComponent { + GridBagLayout layout; + + class FlightStat { + JLabel label; + JTextField value; + + public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.weighty = 1; + + label = new JLabel(label_text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + for (int j = 0; j < values.length; j++) { + value = new JTextField(values[j]); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = j+1; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + + } + + static String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f'", h, deg, min); + } + + public AltosFlightStatsTable(AltosFlightStats stats) { + layout = new GridBagLayout(); + + setLayout(layout); + int y = 0; + new FlightStat(layout, y++, "Serial", String.format("%d", stats.serial)); + new FlightStat(layout, y++, "Flight", String.format("%d", stats.flight)); + if (stats.year != AltosLib.MISSING && stats.hour != AltosLib.MISSING) + new FlightStat(layout, y++, "Date/Time", + String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day), + String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second)); + else { + if (stats.year != AltosLib.MISSING) + new FlightStat(layout, y++, "Date", + String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day)); + if (stats.hour != AltosLib.MISSING) + new FlightStat(layout, y++, "Time", + String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second)); + } + new FlightStat(layout, y++, "Maximum height", + String.format("%5.0f 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", + String.format("%5.0f m", stats.max_gps_height), + String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_gps_height))); + } + new FlightStat(layout, y++, "Maximum speed", + String.format("%5.0f m/s", stats.max_speed), + String.format("%5.0f mph", AltosConvert.meters_to_mph(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("%5.0f m/s²", stats.max_acceleration), + String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)), + String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration))); + new FlightStat(layout, y++, "Average boost acceleration", + String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]), + String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[Altos.ao_flight_boost])), + String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[Altos.ao_flight_boost]))); + } + new FlightStat(layout, y++, "Drogue descent rate", + String.format("%5.0f m/s", stats.state_speed[Altos.ao_flight_drogue]), + String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue]))); + new FlightStat(layout, y++, "Main descent rate", + String.format("%5.0f m/s", stats.state_speed[Altos.ao_flight_main]), + String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main]))); + new FlightStat(layout, y++, "Ascent time", + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost], + AltosLib.state_name(Altos.ao_flight_boost)), + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast], + AltosLib.state_name(Altos.ao_flight_fast)), + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast], + AltosLib.state_name(Altos.ao_flight_coast))); + new FlightStat(layout, y++, "Descent time", + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue], + AltosLib.state_name(Altos.ao_flight_drogue)), + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main], + AltosLib.state_name(Altos.ao_flight_main))); + new FlightStat(layout, y++, "Flight time", + String.format("%6.1f s", stats.state_end[Altos.ao_flight_main] - + stats.state_start[Altos.ao_flight_boost])); + if (stats.has_gps) { + new FlightStat(layout, y++, "Pad location", + pos(stats.pad_lat,"N","S"), + pos(stats.pad_lon,"E","W")); + new FlightStat(layout, y++, "Last reported location", + pos(stats.lat,"N","S"), + pos(stats.lon,"E","W")); + } + } + +} \ No newline at end of file diff --git a/altosuilib/AltosGraph.java b/altosuilib/AltosGraph.java index 73c53a22..f8c8b27b 100644 --- a/altosuilib/AltosGraph.java +++ b/altosuilib/AltosGraph.java @@ -333,19 +333,22 @@ public class AltosGraph extends AltosUIGraph { dbm_color, false, dbm_axis); - if (stats.has_other_adc) { - addSeries("Temperature", - AltosGraphDataPoint.data_temperature, - AltosConvert.temperature, - temperature_color, - false, - temperature_axis); + + if (stats.has_battery) addSeries("Battery Voltage", AltosGraphDataPoint.data_battery_voltage, voltage_units, battery_voltage_color, false, voltage_axis); + + if (stats.has_flight_adc) { + addSeries("Temperature", + AltosGraphDataPoint.data_temperature, + AltosConvert.temperature, + temperature_color, + false, + temperature_axis); addSeries("Drogue Voltage", AltosGraphDataPoint.data_drogue_voltage, voltage_units, -- cgit v1.2.3 From 9ef32b103c5c312aaa90b6546e504f2edeb1f99a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jun 2014 11:34:21 -0700 Subject: altosuilib: Skip voice announcements for invalid values When height and speed values aren't available, don't say anything Signed-off-by: Keith Packard --- altosuilib/AltosDisplayThread.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java index e88a891e..06bc68a9 100644 --- a/altosuilib/AltosDisplayThread.java +++ b/altosuilib/AltosDisplayThread.java @@ -99,7 +99,7 @@ public class AltosDisplayThread extends Thread { (int) (state.from_pad.bearing + 0.5), (int) (state.elevation + 0.5), AltosConvert.distance.say(state.range)); - } else if (state.state > AltosLib.ao_flight_pad) { + } else if (state.state > AltosLib.ao_flight_pad && state.height() != AltosLib.MISSING) { voice.speak(AltosConvert.height.say_units(state.height())); } else { reported_landing = 0; @@ -109,7 +109,8 @@ public class AltosDisplayThread extends Thread { * either we've got a landed report or we haven't heard from it in * a long time */ - if (state.state >= AltosLib.ao_flight_drogue && + if (state.state != AltosLib.ao_flight_stateless && + state.state >= AltosLib.ao_flight_drogue && (last || System.currentTimeMillis() - state.received_time >= 15000 || state.state == AltosLib.ao_flight_landed)) @@ -182,16 +183,19 @@ public class AltosDisplayThread extends Thread { synchronized boolean tell() { boolean ret = false; if (old_state == null || old_state.state != state.state) { - voice.speak(state.state_name()); + if (state.state != AltosLib.ao_flight_stateless) + voice.speak(state.state_name()); if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) && state.state > AltosLib.ao_flight_boost) { - voice.speak("max speed: %s.", - AltosConvert.speed.say_units(state.max_speed() + 0.5)); + if (state.max_speed() != AltosLib.MISSING) + voice.speak("max speed: %s.", + AltosConvert.speed.say_units(state.max_speed() + 0.5)); ret = true; } else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) && state.state >= AltosLib.ao_flight_drogue) { - voice.speak("max height: %s.", - AltosConvert.height.say_units(state.max_height() + 0.5)); + if (state.max_height() != AltosLib.MISSING) + voice.speak("max height: %s.", + AltosConvert.height.say_units(state.max_height() + 0.5)); ret = true; } } -- cgit v1.2.3 From 73249dbf16382c91c2a220ff852a4f099fe0de3d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jun 2014 11:35:30 -0700 Subject: altosuilib: Move AltosFlightStatsTable to altosuilib So that TeleGPS can share it Signed-off-by: Keith Packard --- altosui/Makefile.am | 1 - altosuilib/AltosFlightStatsTable.java | 71 +++++++++++++++++++---------------- altosuilib/Makefile.am | 1 + 3 files changed, 40 insertions(+), 33 deletions(-) (limited to 'altosuilib') diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 1eb2d967..be817cb8 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -21,7 +21,6 @@ altosui_JAVA = \ AltosConfigTD.java \ AltosConfigTDUI.java \ AltosDescent.java \ - AltosFlightStatsTable.java \ AltosFlightStatus.java \ AltosFlightStatusUpdate.java \ AltosFlightUI.java \ diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java index e7a8e728..ec106cf1 100644 --- a/altosuilib/AltosFlightStatsTable.java +++ b/altosuilib/AltosFlightStatsTable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.altosuilib_2; import java.awt.*; import javax.swing.*; @@ -30,11 +30,11 @@ public class AltosFlightStatsTable extends JComponent { public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) { GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); c.weighty = 1; label = new JLabel(label_text); - label.setFont(Altos.label_font); + label.setFont(AltosUILib.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -45,7 +45,7 @@ public class AltosFlightStatsTable extends JComponent { for (int j = 0; j < values.length; j++) { value = new JTextField(values[j]); - value.setFont(Altos.value_font); + value.setFont(AltosUILib.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = j+1; c.gridy = y; c.anchor = GridBagConstraints.EAST; @@ -88,9 +88,11 @@ public class AltosFlightStatsTable extends JComponent { new FlightStat(layout, y++, "Time", String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second)); } - new FlightStat(layout, y++, "Maximum height", - String.format("%5.0f m", stats.max_height), - String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height))); + if (stats.max_height != AltosLib.MISSING) { + new FlightStat(layout, y++, "Maximum height", + String.format("%5.0f 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", String.format("%5.0f m", stats.max_gps_height), @@ -106,31 +108,36 @@ public class AltosFlightStatsTable extends JComponent { String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)), String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration))); new FlightStat(layout, y++, "Average boost acceleration", - String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]), - String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[Altos.ao_flight_boost])), - String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[Altos.ao_flight_boost]))); + String.format("%5.0f 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("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost]))); } - new FlightStat(layout, y++, "Drogue descent rate", - String.format("%5.0f m/s", stats.state_speed[Altos.ao_flight_drogue]), - String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue]))); - new FlightStat(layout, y++, "Main descent rate", - String.format("%5.0f m/s", stats.state_speed[Altos.ao_flight_main]), - String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main]))); - new FlightStat(layout, y++, "Ascent time", - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost], - AltosLib.state_name(Altos.ao_flight_boost)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast], - AltosLib.state_name(Altos.ao_flight_fast)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast], - AltosLib.state_name(Altos.ao_flight_coast))); - new FlightStat(layout, y++, "Descent time", - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue], - AltosLib.state_name(Altos.ao_flight_drogue)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main], - AltosLib.state_name(Altos.ao_flight_main))); - new FlightStat(layout, y++, "Flight time", - String.format("%6.1f s", stats.state_end[Altos.ao_flight_main] - - stats.state_start[Altos.ao_flight_boost])); + if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING) + new FlightStat(layout, y++, "Drogue descent rate", + String.format("%5.0f 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("%5.0f 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_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_coast]) + new FlightStat(layout, y++, "Ascent time", + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost], + AltosLib.state_name(AltosLib.ao_flight_boost)), + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast], + AltosLib.state_name(AltosLib.ao_flight_fast)), + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast], + AltosLib.state_name(AltosLib.ao_flight_coast))); + if (stats.state_start[AltosLib.ao_flight_drogue] < stats.state_end[AltosLib.ao_flight_main]) + new FlightStat(layout, y++, "Descent time", + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue], + AltosLib.state_name(AltosLib.ao_flight_drogue)), + String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main], + AltosLib.state_name(AltosLib.ao_flight_main))); + if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_main]) + new FlightStat(layout, y++, "Flight time", + String.format("%6.1f s", stats.state_end[AltosLib.ao_flight_main] - + stats.state_start[AltosLib.ao_flight_boost])); if (stats.has_gps) { new FlightStat(layout, y++, "Pad location", pos(stats.pad_lat,"N","S"), @@ -141,4 +148,4 @@ public class AltosFlightStatsTable extends JComponent { } } -} \ No newline at end of file +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index e415fc5b..b90669ce 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -58,6 +58,7 @@ altosuilib_JAVA = \ AltosRomconfigUI.java \ AltosInfoTable.java \ AltosFlightInfoTableModel.java \ + AltosFlightStatsTable.java \ AltosGraph.java \ AltosGraphDataPoint.java \ AltosGraphDataSet.java \ -- cgit v1.2.3 From db2443fdbf65b65703217174303027c439124a83 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jun 2014 18:46:47 -0700 Subject: altosuilib: Rewrite map GUI bits Use a single large Canvas and draw images on top by hand. Signed-off-by: Keith Packard --- altosui/AltosFlightUI.java | 4 +- altosui/AltosGraphUI.java | 4 +- altosui/AltosUI.java | 4 +- altosuilib/AltosUILatLon.java | 44 +++ altosuilib/AltosUIMap.java | 246 +++++++++++++ altosuilib/AltosUIMapCache.java | 112 ++++++ altosuilib/AltosUIMapImage.java | 113 ++++++ altosuilib/AltosUIMapLine.java | 116 ++++++ altosuilib/AltosUIMapMark.java | 59 ++++ altosuilib/AltosUIMapPath.java | 96 +++++ altosuilib/AltosUIMapPreload.java | 608 ++++++++++++++++++++++++++++++++ altosuilib/AltosUIMapRectangle.java | 45 +++ altosuilib/AltosUIMapStore.java | 203 +++++++++++ altosuilib/AltosUIMapStoreListener.java | 22 ++ altosuilib/AltosUIMapTile.java | 190 ++++++++++ altosuilib/AltosUIMapTileListener.java | 22 ++ altosuilib/AltosUIMapTransform.java | 106 ++++++ altosuilib/AltosUIMapView.java | 462 ++++++++++++++++++++++++ altosuilib/AltosUIMapZoomListener.java | 22 ++ altosuilib/Makefile.am | 24 +- telegps/TeleGPS.java | 12 +- telegps/TeleGPSGraphUI.java | 4 +- 22 files changed, 2497 insertions(+), 21 deletions(-) create mode 100644 altosuilib/AltosUILatLon.java create mode 100644 altosuilib/AltosUIMap.java create mode 100644 altosuilib/AltosUIMapCache.java create mode 100644 altosuilib/AltosUIMapImage.java create mode 100644 altosuilib/AltosUIMapLine.java create mode 100644 altosuilib/AltosUIMapMark.java create mode 100644 altosuilib/AltosUIMapPath.java create mode 100644 altosuilib/AltosUIMapPreload.java create mode 100644 altosuilib/AltosUIMapRectangle.java create mode 100644 altosuilib/AltosUIMapStore.java create mode 100644 altosuilib/AltosUIMapStoreListener.java create mode 100644 altosuilib/AltosUIMapTile.java create mode 100644 altosuilib/AltosUIMapTileListener.java create mode 100644 altosuilib/AltosUIMapTransform.java create mode 100644 altosuilib/AltosUIMapView.java create mode 100644 altosuilib/AltosUIMapZoomListener.java (limited to 'altosuilib') diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index baa18686..f2bd70a0 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -37,7 +37,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { AltosDescent descent; AltosLanded landed; AltosCompanionInfo companion; - AltosSiteMap sitemap; + AltosUIMap sitemap; boolean has_map; boolean has_companion; boolean has_state; @@ -310,7 +310,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { has_companion = false; has_state = false; - sitemap = new AltosSiteMap(); + sitemap = new AltosUIMap(); has_map = false; /* Make the tabbed pane use the rest of the window space */ diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 9e8a1939..0df92eae 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -34,7 +34,7 @@ public class AltosGraphUI extends AltosUIFrame JTabbedPane pane; AltosGraph graph; AltosUIEnable enable; - AltosSiteMap map; + AltosUIMap map; AltosState state; AltosGraphDataSet graphDataSet; AltosFlightStats stats; @@ -46,7 +46,7 @@ public class AltosGraphUI extends AltosUIFrame for (AltosState state : states) { if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { if (map == null) - map = new AltosSiteMap(); + map = new AltosUIMap(); map.show(state, null); has_gps = true; } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 302f623f..6137487c 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -280,7 +280,7 @@ public class AltosUI extends AltosUIFrame { } void LoadMaps() { - new AltosSiteMapPreload(AltosUI.this); + new AltosUIMapPreload(AltosUI.this); } void LaunchController() { @@ -578,7 +578,7 @@ public class AltosUI extends AltosUIFrame { } else { double lat = Double.parseDouble(args[i+1]); double lon = Double.parseDouble(args[i+2]); - AltosSiteMap.prefetchMaps(lat, lon); +// AltosSiteMap.prefetchMaps(lat, lon); i += 2; } } else if (args[i].equals("--replay")) diff --git a/altosuilib/AltosUILatLon.java b/altosuilib/AltosUILatLon.java new file mode 100644 index 00000000..688dd58b --- /dev/null +++ b/altosuilib/AltosUILatLon.java @@ -0,0 +1,44 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.lang.Math; +import java.awt.geom.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosUILatLon { + public double lat; + public double lon; + + public boolean equals(AltosUILatLon other) { + if (other == null) + return false; + return lat == other.lat && lon == other.lon; + } + + public AltosUILatLon(double lat, double lon) { + this.lat = lat; + this.lon = lon; + } +} diff --git a/altosuilib/AltosUIMap.java b/altosuilib/AltosUIMap.java new file mode 100644 index 00000000..fa974d36 --- /dev/null +++ b/altosuilib/AltosUIMap.java @@ -0,0 +1,246 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.lang.Math; +import java.awt.geom.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosUIMapZoomListener { + + static final int px_size = 512; + + static final int maptype_hybrid = 0; + static final int maptype_roadmap = 1; + static final int maptype_satellite = 2; + static final int maptype_terrain = 3; + static final int maptype_default = maptype_hybrid; + + static final String[] maptype_names = { + "hybrid", + "roadmap", + "satellite", + "terrain" + }; + + public static final String[] maptype_labels = { + "Hybrid", + "Roadmap", + "Satellite", + "Terrain" + }; + + public static final Color stateColors[] = { + Color.WHITE, // startup + Color.WHITE, // idle + Color.WHITE, // pad + Color.RED, // boost + Color.PINK, // fast + Color.YELLOW, // coast + Color.CYAN, // drogue + Color.BLUE, // main + Color.BLACK, // landed + Color.BLACK, // invalid + Color.CYAN, // stateless + }; + + public void reset() { + // nothing + } + + public void font_size_changed(int font_size) { + view.set_font(); + } + + public void units_changed(boolean imperial_units) { + repaint(); + } + + JLabel zoom_label; + + private void set_zoom_label() { + zoom_label.setText(String.format("Zoom %d", view.zoom() - view.default_zoom)); + } + + public void zoom_changed(int zoom) { + set_zoom_label(); + } + + public void set_zoom(int zoom) { + view.set_zoom(zoom); + } + + public int get_zoom() { + return view.zoom(); + } + + public void set_maptype(int type) { + view.set_maptype(type); + maptype_combo.setSelectedIndex(type); + } + + public void show(AltosState state, AltosListenerState listener_state) { + view.show(state, listener_state); + } + + public void centre(double lat, double lon) { + view.centre(lat, lon); + } + + public void centre(AltosState state) { + if (!state.gps.locked && state.gps.nsat < 4) + return; + centre(state.gps.lat, state.gps.lon); + } + + public void add_mark(double lat, double lon, int state) { + view.add_mark(lat, lon, state); + } + + public void clear_marks() { + view.clear_marks(); + } + + AltosUIMapView view; + + private GridBagLayout layout = new GridBagLayout(); + + JComboBox maptype_combo; + + public void set_load_params(double lat, double lon, int radius, AltosUIMapTileListener listener) { + view.set_load_params(lat, lon, radius, listener); + } + + public boolean all_fetched() { + return view.all_fetched(); + } + + public static void prefetch_maps(double lat, double lon) { + } + + public AltosUIMap() { + + view = new AltosUIMapView(); + + view.setPreferredSize(new Dimension(500,500)); + view.setVisible(true); + view.setEnabled(true); + view.add_zoom_listener(this); + + GridBagLayout my_layout = new GridBagLayout(); + + setLayout(my_layout); + + GridBagConstraints c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 10; + c.weightx = 1; + c.weighty = 1; + add(view, c); + + int y = 0; + + zoom_label = new JLabel("", JLabel.CENTER); + set_zoom_label(); + + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(zoom_label, c); + + JButton zoom_reset = new JButton("0"); + zoom_reset.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + set_zoom(view.default_zoom); + } + }); + + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(zoom_reset, c); + + JButton zoom_in = new JButton("+"); + zoom_in.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + set_zoom(get_zoom() + 1); + } + }); + + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(zoom_in, c); + + JButton zoom_out = new JButton("-"); + zoom_out.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + set_zoom(get_zoom() - 1); + } + }); + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(zoom_out, c); + + maptype_combo = new JComboBox(maptype_labels); + + maptype_combo.setEditable(false); + maptype_combo.setMaximumRowCount(maptype_combo.getItemCount()); + maptype_combo.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + view.set_maptype(maptype_combo.getSelectedIndex()); + } + }); + + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + c.gridy = y++; + c.weightx = 0; + c.weighty = 0; + add(maptype_combo, c); + } +} diff --git a/altosuilib/AltosUIMapCache.java b/altosuilib/AltosUIMapCache.java new file mode 100644 index 00000000..e849da79 --- /dev/null +++ b/altosuilib/AltosUIMapCache.java @@ -0,0 +1,112 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.*; +import javax.imageio.ImageIO; +import java.awt.image.*; +import java.awt.*; +import java.io.*; +import java.net.*; + +public class AltosUIMapCache { + static final int success = 0; + static final int loading = 1; + static final int failed = 2; + static final int bad_request = 3; + static final int forbidden = 4; + + static private Object fetch_lock = new Object(); + + static final int min_cache_size = 9; + static final int max_cache_size = 24; + + static int cache_size = min_cache_size; + + static AltosUIMapImage[] images = new AltosUIMapImage[cache_size]; + + static Object cache_lock = new Object(); + + public static void set_cache_size(int new_size) { + if (new_size < min_cache_size) + new_size = min_cache_size; + if (new_size > max_cache_size) + new_size = max_cache_size; + if (new_size == cache_size) + return; + + synchronized(cache_lock) { + AltosUIMapImage[] new_images = new AltosUIMapImage[new_size]; + + for (int i = 0; i < cache_size; i++) { + if (i < new_size) + new_images[i] = images[i]; + else if (images[i] != null) + images[i].flush(); + } + images = new_images; + cache_size = new_size; + } + } + + static long used; + + public static Image get(AltosUIMapTile tile, AltosUIMapStore store, int width, int height) { + int oldest = -1; + long age = used; + + synchronized(cache_lock) { + AltosUIMapImage image = null; + for (int i = 0; i < cache_size; i++) { + image = images[i]; + + if (image == null) { + oldest = i; + break; + } + if (store.equals(image.store)) { + image.used = used++; + return image.image; + } + if (image.used < age) { + oldest = i; + age = image.used; + } + } + + try { + image = new AltosUIMapImage(tile, store); + image.used = used++; + if (images[oldest] != null) + images[oldest].flush(); + + images[oldest] = image; + + if (image.image == null) + tile.set_status(loading); + else + tile.set_status(success); + + return image.image; + } catch (IOException e) { + tile.set_status(failed); + return null; + } + } + } +} diff --git a/altosuilib/AltosUIMapImage.java b/altosuilib/AltosUIMapImage.java new file mode 100644 index 00000000..3819d079 --- /dev/null +++ b/altosuilib/AltosUIMapImage.java @@ -0,0 +1,113 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import javax.swing.*; +import javax.imageio.ImageIO; +import java.awt.image.*; +import java.awt.*; +import java.io.*; +import java.net.*; + +public class AltosUIMapImage implements AltosUIMapStoreListener { + static final long google_maps_ratelimit_ms = 1200; + // Google limits static map queries to 50 per minute per IP, so + // each query should take at least 1.2 seconds. + + static final int success = 0; + static final int loading = 1; + static final int failed = 2; + static final int bad_request = 3; + static final int forbidden = 4; + + static long forbidden_time; + static boolean forbidden_set = false; + static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; + + AltosUIMapTile tile; /* Notify when image has been loaded */ + Image image; + AltosUIMapStore store; + long used; + + class loader implements Runnable { + public void run() { + if (image != null) + tile.notify_image(image); + try { + image = ImageIO.read(store.file); + } catch (Exception ex) { + } + if (image == null) + tile.set_status(failed); + else + tile.set_status(success); + tile.notify_image(image); + } + } + + private void load() { + loader l = new loader(); + Thread lt = new Thread(l); + lt.start(); + } + + public void flush() { + if (image != null) { + image.flush(); + image = null; + } + } + + public boolean has_map() { + return store.status() == AltosUIMapStore.success; + } + + public synchronized void notify_store(AltosUIMapStore store, int status) { + switch (status) { + case AltosUIMapStore.loading: + break; + case AltosUIMapStore.success: + load(); + break; + default: + tile.set_status(status); + tile.notify_image(null); + } + } + + public AltosUIMapImage(AltosUIMapTile tile, AltosUIMapStore store) throws IOException { + this.tile = tile; + this.image = null; + this.store = store; + this.used = 0; + + int status = store.status(); + switch (status) { + case AltosUIMapStore.loading: + store.add_listener(this); + break; + case AltosUIMapStore.success: + load(); + break; + default: + tile.set_status(status); + tile.notify_image(null); + break; + } + } +} diff --git a/altosuilib/AltosUIMapLine.java b/altosuilib/AltosUIMapLine.java new file mode 100644 index 00000000..e09a2d9f --- /dev/null +++ b/altosuilib/AltosUIMapLine.java @@ -0,0 +1,116 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.lang.Math; +import java.awt.geom.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosUIMapLine { + AltosUILatLon start, end; + + private Font font = null; + + public void set_font(Font font) { + this.font = font; + } + + private AltosUILatLon lat_lon(MouseEvent e, AltosUIMapTransform t) { + return t.screen_lat_lon(e.getPoint()); + } + + public void dragged(MouseEvent e, AltosUIMapTransform t) { + end = lat_lon(e, t); + } + + public void pressed(MouseEvent e, AltosUIMapTransform t) { + start = lat_lon(e, t); + end = null; + } + + private String line_dist() { + String format; + AltosGreatCircle g = new AltosGreatCircle(start.lat, start.lon, + end.lat, end.lon); + double distance = g.distance; + + if (AltosConvert.imperial_units) { + distance = AltosConvert.meters_to_feet(distance); + if (distance < 10000) { + format = "%4.0fft"; + } else { + distance /= 5280; + if (distance < 10) + format = "%5.3fmi"; + else if (distance < 100) + format = "%5.2fmi"; + else if (distance < 1000) + format = "%5.1fmi"; + else + format = "%5.0fmi"; + } + } else { + if (distance < 10000) { + format = "%4.0fm"; + } else { + distance /= 1000; + if (distance < 100) + format = "%5.2fkm"; + else if (distance < 1000) + format = "%5.1fkm"; + else + format = "%5.0fkm"; + } + } + return String.format(format, distance); + } + + public void paint(Graphics2D g, AltosUIMapTransform t) { + g.setColor(Color.BLUE); + + if (start == null || end == null) + return; + + Line2D.Double line = new Line2D.Double(t.screen(start), + t.screen(end)); + + g.draw(line); + + String message = line_dist(); + g.setFont(font); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + Rectangle2D bounds; + bounds = font.getStringBounds(message, g.getFontRenderContext()); + + float x = (float) line.x1; + float y = (float) line.y1 + (float) bounds.getHeight() / 2.0f; + + if (line.x1 < line.x2) { + x -= (float) bounds.getWidth() + 2.0f; + } else { + x += 2.0f; + } + g.drawString(message, x, y); + } +} diff --git a/altosuilib/AltosUIMapMark.java b/altosuilib/AltosUIMapMark.java new file mode 100644 index 00000000..8c640e5f --- /dev/null +++ b/altosuilib/AltosUIMapMark.java @@ -0,0 +1,59 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.lang.Math; +import java.awt.geom.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosUIMapMark { + + AltosUILatLon lat_lon; + int state; + + static public int stroke_width = 6; + + public void paint(Graphics2D g, AltosUIMapTransform t) { + + Point2D.Double pt = t.screen(lat_lon); + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + + if (0 <= state && state < AltosUIMap.stateColors.length) + g.setColor(AltosUIMap.stateColors[state]); + else + g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]); + + g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); + g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); + g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); + } + + public AltosUIMapMark (double lat, double lon, int state) { + lat_lon = new AltosUILatLon(lat, lon); + this.state = state; + } +} diff --git a/altosuilib/AltosUIMapPath.java b/altosuilib/AltosUIMapPath.java new file mode 100644 index 00000000..ff17be67 --- /dev/null +++ b/altosuilib/AltosUIMapPath.java @@ -0,0 +1,96 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.lang.Math; +import java.awt.geom.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +class PathPoint { + AltosUILatLon lat_lon; + int state; + + public PathPoint(AltosUILatLon lat_lon, int state) { + this.lat_lon = lat_lon; + this.state = state; + } + + public boolean equals(PathPoint other) { + if (other == null) + return false; + + return lat_lon.equals(other.lat_lon) && state == other.state; + } +} + +public class AltosUIMapPath { + + LinkedList points = new LinkedList(); + PathPoint last_point = null; + + static public int stroke_width = 6; + + public void paint(Graphics2D g, AltosUIMapTransform t) { + Point2D.Double prev = null; + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + + for (PathPoint point : points) { + Point2D.Double cur = t.screen(point.lat_lon); + if (prev != null) { + Line2D.Double line = new Line2D.Double (prev, cur); + Rectangle bounds = line.getBounds(); + + if (g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height)) { + if (0 <= point.state && point.state < AltosUIMap.stateColors.length) + g.setColor(AltosUIMap.stateColors[point.state]); + else + g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]); + + g.draw(line); + } + } + prev = cur; + } + } + + public AltosUIMapRectangle add(double lat, double lon, int state) { + PathPoint point = new PathPoint(new AltosUILatLon (lat, lon), state); + AltosUIMapRectangle rect = null; + + if (!point.equals(last_point)) { + if (last_point != null) + rect = new AltosUIMapRectangle(last_point.lat_lon, point.lat_lon); + points.add (point); + last_point = point; + } + return rect; + } + + public void clear () { + points = new LinkedList(); + } +} diff --git a/altosuilib/AltosUIMapPreload.java b/altosuilib/AltosUIMapPreload.java new file mode 100644 index 00000000..d702dddf --- /dev/null +++ b/altosuilib/AltosUIMapPreload.java @@ -0,0 +1,608 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.lang.Math; +import java.net.URL; +import java.net.URLConnection; +import org.altusmetrum.altoslib_4.*; + +class AltosUIMapPos extends Box { + AltosUIFrame owner; + JLabel label; + JComboBox hemi; + JTextField deg; + JLabel deg_label; + JTextField min; + JLabel min_label; + + public void set_value(double new_value) { + double d, m; + int h; + + h = 0; + if (new_value < 0) { + h = 1; + new_value = -new_value; + } + d = Math.floor(new_value); + deg.setText(String.format("%3.0f", d)); + m = (new_value - d) * 60.0; + min.setText(String.format("%7.4f", m)); + hemi.setSelectedIndex(h); + } + + public double get_value() throws NumberFormatException { + int h = hemi.getSelectedIndex(); + String d_t = deg.getText(); + String m_t = min.getText(); + double d, m, v; + try { + d = Double.parseDouble(d_t); + } catch (NumberFormatException ne) { + JOptionPane.showMessageDialog(owner, + String.format("Invalid degrees \"%s\"", + d_t), + "Invalid number", + JOptionPane.ERROR_MESSAGE); + throw ne; + } + try { + if (m_t.equals("")) + m = 0; + else + m = Double.parseDouble(m_t); + } catch (NumberFormatException ne) { + JOptionPane.showMessageDialog(owner, + String.format("Invalid minutes \"%s\"", + m_t), + "Invalid number", + JOptionPane.ERROR_MESSAGE); + throw ne; + } + v = d + m/60.0; + if (h == 1) + v = -v; + return v; + } + + public AltosUIMapPos(AltosUIFrame in_owner, + String label_value, + String[] hemi_names, + double default_value) { + super(BoxLayout.X_AXIS); + owner = in_owner; + label = new JLabel(label_value); + hemi = new JComboBox(hemi_names); + hemi.setEditable(false); + deg = new JTextField(5); + deg.setMinimumSize(deg.getPreferredSize()); + deg.setHorizontalAlignment(JTextField.RIGHT); + deg_label = new JLabel("°"); + min = new JTextField(9); + min.setMinimumSize(min.getPreferredSize()); + min_label = new JLabel("'"); + set_value(default_value); + add(label); + add(Box.createRigidArea(new Dimension(5, 0))); + add(hemi); + add(Box.createRigidArea(new Dimension(5, 0))); + add(deg); + add(Box.createRigidArea(new Dimension(5, 0))); + add(deg_label); + add(Box.createRigidArea(new Dimension(5, 0))); + add(min); + add(Box.createRigidArea(new Dimension(5, 0))); + add(min_label); + } +} + +class AltosUISite { + String name; + double latitude; + double longitude; + + public String toString() { + return name; + } + + public AltosUISite(String in_name, double in_latitude, double in_longitude) { + name = in_name; + latitude = in_latitude; + longitude = in_longitude; + } + + public AltosUISite(String line) throws ParseException { + String[] elements = line.split(":"); + + if (elements.length < 3) + throw new ParseException(String.format("Invalid site line %s", line), 0); + + name = elements[0]; + + try { + latitude = Double.parseDouble(elements[1]); + longitude = Double.parseDouble(elements[2]); + } catch (NumberFormatException ne) { + throw new ParseException(String.format("Invalid site line %s", line), 0); + } + } +} + +class AltosUISites extends Thread { + AltosUIMapPreload preload; + URL url; + LinkedList sites; + + void notify_complete() { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + preload.set_sites(); + } + }); + } + + void add(AltosUISite site) { + sites.add(site); + } + + void add(String line) { + try { + add(new AltosUISite(line)); + } catch (ParseException pe) { + } + } + + public void run() { + try { + URLConnection uc = url.openConnection(); + //int length = uc.getContentLength(); + + InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set); + BufferedReader in = new BufferedReader(in_stream); + + for (;;) { + String line = in.readLine(); + if (line == null) + break; + add(line); + } + } catch (IOException e) { + } finally { + notify_complete(); + } + } + + public AltosUISites(AltosUIMapPreload in_preload) { + sites = new LinkedList(); + preload = in_preload; + try { + url = new URL(AltosLib.launch_sites_url); + } catch (java.net.MalformedURLException e) { + notify_complete(); + } + start(); + } +} + +public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, ItemListener, AltosUIMapTileListener { + AltosUIFrame owner; + AltosUIMap map; + + AltosUIMapPos lat; + AltosUIMapPos lon; + + JProgressBar pbar; + int pbar_max; + int pbar_cur; + + AltosUISites sites; + JLabel site_list_label; + JComboBox site_list; + + JToggleButton load_button; + boolean loading; + JButton close_button; + + JCheckBox[] maptypes = new JCheckBox[AltosUIMap.maptype_terrain - AltosUIMap.maptype_hybrid + 1]; + + JComboBox min_zoom; + JComboBox max_zoom; + JComboBox radius; + + Integer[] zooms = { -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 }; + Integer[] radii = { 1, 2, 3, 4, 5 }; + + static final String[] lat_hemi_names = { "N", "S" }; + static final String[] lon_hemi_names = { "E", "W" }; + + class updatePbar implements Runnable { + String s; + + public updatePbar(String in_s) { + s = in_s; + } + + public void run() { + int n = ++pbar_cur; + + pbar.setMaximum(pbar_max); + pbar.setValue(n); + pbar.setString(s); + } + } + + double latitude, longitude; + int min_z; + int max_z; + int cur_z; + int all_types; + int cur_type; + int r; + + int tiles_per_layer; + int tiles_loaded; + int layers_total; + int layers_loaded; + + + private void do_load() { + tiles_loaded = 0; + map.set_zoom(cur_z + AltosUIMapView.default_zoom); + map.set_maptype(cur_type); + map.set_load_params(latitude, longitude, r, this); + } + + private int next_type(int start) { + int next_type; + for (next_type = start; + next_type <= AltosUIMap.maptype_terrain && (all_types & (1 << next_type)) == 0; + next_type++) + ; + return next_type; + } + + private void next_load() { + int next_type = next_type(cur_type + 1); + + if (next_type > AltosUIMap.maptype_terrain) { + if (cur_z == max_z) { + return; + } else { + cur_z++; + } + next_type = next_type(0); + } + cur_type = next_type; + do_load(); + } + + private void start_load() { + cur_z = min_z; + int ntype = 0; + all_types = 0; + for (int t = AltosUIMap.maptype_hybrid; t <= AltosUIMap.maptype_terrain; t++) + if (maptypes[t].isSelected()) { + all_types |= (1 << t); + ntype++; + } + if (ntype == 0) { + all_types |= (1 << AltosUIMap.maptype_hybrid); + ntype = 1; + } + + cur_type = next_type(0); + tiles_per_layer = (r * 2 + 1) * (r * 2 + 1); + layers_total = (max_z - min_z + 1) * ntype; + layers_loaded = 0; + pbar_max = layers_total * tiles_per_layer; + pbar_cur = 0; + + map.clear_marks(); + map.add_mark(latitude,longitude, AltosLib.ao_flight_boost); + do_load(); + } + + /* AltosUIMapTileListener methods */ + + public void notify_tile(AltosUIMapTile tile, int status) { + if (status == AltosUIMapStore.loading) + return; + + SwingUtilities.invokeLater(new updatePbar(tile.store.file.toString())); + ++tiles_loaded; + if (tiles_loaded == tiles_per_layer) { + ++layers_loaded; + if (layers_loaded == layers_total) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + pbar.setValue(0); + pbar.setString(""); + load_button.setSelected(false); + loading = false; + } + }); + } else { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + next_load(); + } + }); + } + } + } + + public void set_sites() { + int i = 1; + for (AltosUISite site : sites.sites) { + site_list.insertItemAt(site, i); + i++; + } + } + + public void itemStateChanged(ItemEvent e) { + int state = e.getStateChange(); + + if (state == ItemEvent.SELECTED) { + Object o = e.getItem(); + if (o instanceof AltosUISite) { + AltosUISite site = (AltosUISite) o; + lat.set_value(site.latitude); + lon.set_value(site.longitude); + } + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("close")) + setVisible(false); + + if (cmd.equals("load")) { + if (!loading) { + try { + latitude = lat.get_value(); + longitude = lon.get_value(); + min_z = (Integer) min_zoom.getSelectedItem(); + max_z = (Integer) max_zoom.getSelectedItem(); + if (max_z < min_z) + max_z = min_z; + r = (Integer) radius.getSelectedItem(); + loading = true; + } catch (NumberFormatException ne) { + load_button.setSelected(false); + } + start_load(); + } + } + } + + public AltosUIMapPreload(AltosUIFrame in_owner) { + System.out.printf("start creating preload ui\n"); + + owner = in_owner; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + setTitle("AltOS Load Maps"); + + pane.setLayout(new GridBagLayout()); + + map = new AltosUIMap(); + + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 10; + c.anchor = GridBagConstraints.CENTER; + + pane.add(map, c); + + pbar = new JProgressBar(); + pbar.setMinimum(0); + pbar.setMaximum(1); + pbar.setValue(0); + pbar.setString(""); + pbar.setStringPainted(true); + + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 10; + + pane.add(pbar, c); + + site_list_label = new JLabel ("Known Launch Sites:"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + + pane.add(site_list_label, c); + + site_list = new JComboBox(new AltosUISite[] { new AltosUISite("Site List", 0, 0) }); + site_list.addItemListener(this); + + sites = new AltosUISites(this); + + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + + pane.add(site_list, c); + + lat = new AltosUIMapPos(owner, + "Latitude:", + lat_hemi_names, + 37.167833333); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 0; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(lat, c); + + lon = new AltosUIMapPos(owner, + "Longitude:", + lon_hemi_names, + -97.73975); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 0; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(lon, c); + + load_button = new JToggleButton("Load Map"); + load_button.addActionListener(this); + load_button.setActionCommand("load"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(load_button, c); + + close_button = new JButton("Close"); + close_button.addActionListener(this); + close_button.setActionCommand("close"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(close_button, c); + + JLabel types_label = new JLabel("Map Types"); + c.gridx = 2; + c.gridwidth = 2; + c.gridy = 2; + pane.add(types_label, c); + + c.gridwidth = 1; + + for (int type = AltosUIMap.maptype_hybrid; type <= AltosUIMap.maptype_terrain; type++) { + maptypes[type] = new JCheckBox(AltosUIMap.maptype_labels[type], + type == AltosUIMap.maptype_hybrid); + c.gridx = 2 + (type >> 1); + c.fill = GridBagConstraints.HORIZONTAL; + c.gridy = (type & 1) + 3; + pane.add(maptypes[type], c); + } + + JLabel min_zoom_label = new JLabel("Minimum Zoom"); + c.gridx = 4; + c.gridy = 2; + pane.add(min_zoom_label, c); + + min_zoom = new JComboBox(zooms); + min_zoom.setSelectedItem(zooms[10]); + min_zoom.setEditable(false); + c.gridx = 5; + c.gridy = 2; + pane.add(min_zoom, c); + + JLabel max_zoom_label = new JLabel("Maximum Zoom"); + c.gridx = 4; + c.gridy = 3; + pane.add(max_zoom_label, c); + + max_zoom = new JComboBox(zooms); + max_zoom.setSelectedItem(zooms[14]); + max_zoom.setEditable(false); + c.gridx = 5; + c.gridy = 3; + pane.add(max_zoom, c); + + JLabel radius_label = new JLabel("Tile Radius"); + c.gridx = 4; + c.gridy = 4; + pane.add(radius_label, c); + + radius = new JComboBox(radii); + radius.setSelectedItem(radii[4]); + radius.setEditable(true); + c.gridx = 5; + c.gridy = 4; + pane.add(radius, c); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + + System.out.printf("done creating preload ui\n"); + } +} diff --git a/altosuilib/AltosUIMapRectangle.java b/altosuilib/AltosUIMapRectangle.java new file mode 100644 index 00000000..8a5b16e1 --- /dev/null +++ b/altosuilib/AltosUIMapRectangle.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +public class AltosUIMapRectangle { + AltosUILatLon ul, lr; + + public AltosUIMapRectangle(AltosUILatLon a, AltosUILatLon b) { + double ul_lat, ul_lon; + double lr_lat, lr_lon; + + if (a.lat > b.lat) { + ul_lat = a.lat; + lr_lat = b.lat; + } else { + ul_lat = b.lat; + lr_lat = a.lat; + } + if (a.lon < b.lon) { + ul_lon = a.lon; + lr_lon = b.lon; + } else { + ul_lon = b.lon; + lr_lon = a.lon; + } + + ul = new AltosUILatLon(ul_lat, ul_lon); + lr = new AltosUILatLon(lr_lat, lr_lon); + } +} diff --git a/altosuilib/AltosUIMapStore.java b/altosuilib/AltosUIMapStore.java new file mode 100644 index 00000000..4cecb54f --- /dev/null +++ b/altosuilib/AltosUIMapStore.java @@ -0,0 +1,203 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.io.*; +import java.net.*; +import java.util.*; + +public class AltosUIMapStore { + String url; + File file; + LinkedList listeners = new LinkedList(); + + static final int success = 0; + static final int loading = 1; + static final int failed = 2; + static final int bad_request = 3; + static final int forbidden = 4; + + int status; + + public int status() { + return status; + } + + public synchronized void add_listener(AltosUIMapStoreListener listener) { + if (!listeners.contains(listener)) + listeners.add(listener); + } + + public synchronized void remove_listener(AltosUIMapStoreListener listener) { + listeners.remove(listener); + } + + private synchronized void notify_listeners(int status) { + this.status = status; + for (AltosUIMapStoreListener listener : listeners) + listener.notify_store(this, status); + } + + static Object forbidden_lock = new Object(); + static long forbidden_time; + static boolean forbidden_set; + + private int fetch_url() { + URL u; + + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return bad_request; + } + + byte[] data; + URLConnection uc = null; + try { + uc = u.openConnection(); + String type = uc.getContentType(); + int contentLength = uc.getContentLength(); + if (uc instanceof HttpURLConnection) { + int response = ((HttpURLConnection) uc).getResponseCode(); + switch (response) { + case HttpURLConnection.HTTP_FORBIDDEN: + case HttpURLConnection.HTTP_PAYMENT_REQUIRED: + case HttpURLConnection.HTTP_UNAUTHORIZED: + synchronized (forbidden_lock) { + forbidden_time = System.nanoTime(); + forbidden_set = true; + return forbidden; + } + } + } + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); + + if (offset != contentLength) + return failed; + + } catch (IOException e) { + return failed; + } + + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return bad_request; + } catch (IOException e) { + if (file.exists()) + file.delete(); + return bad_request; + } + return success; + } + + static Object fetch_lock = new Object(); + + static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; + static final long google_maps_ratelimit_ms = 1200; + + class loader implements Runnable { + + public void run() { + if (file.exists()) { + notify_listeners(success); + return; + } + + synchronized(forbidden_lock) { + if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) { + notify_listeners(forbidden); + return; + } + } + + int new_status; + + if (!AltosUIVersion.has_google_maps_api_key()) { + synchronized (fetch_lock) { + long startTime = System.nanoTime(); + new_status = fetch_url(); + if (new_status == success) { + long duration_ms = (System.nanoTime() - startTime) / 1000000; + if (duration_ms < google_maps_ratelimit_ms) { + try { + Thread.sleep(google_maps_ratelimit_ms - duration_ms); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + } + } else { + new_status = fetch_url(); + } + notify_listeners(new_status); + } + } + + private void load() { + loader l = new loader(); + Thread lt = new Thread(l); + lt.start(); + } + + private AltosUIMapStore (String url, File file) { + this.url = url; + this.file = file; + + if (file.exists()) + status = success; + else { + status = loading; + load(); + } + } + + public boolean equals(AltosUIMapStore other) { + return url.equals(other.url); + } + + static HashMap stores = new HashMap(); + + public static AltosUIMapStore get(String url, File file) { + AltosUIMapStore store; + synchronized(stores) { + if (stores.containsKey(url)) { + store = stores.get(url); + } else { + store = new AltosUIMapStore(url, file); + stores.put(url, store); + } + } + return store; + } + +} diff --git a/altosuilib/AltosUIMapStoreListener.java b/altosuilib/AltosUIMapStoreListener.java new file mode 100644 index 00000000..91aff00c --- /dev/null +++ b/altosuilib/AltosUIMapStoreListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +public interface AltosUIMapStoreListener { + abstract void notify_store(AltosUIMapStore store, int status); +} diff --git a/altosuilib/AltosUIMapTile.java b/altosuilib/AltosUIMapTile.java new file mode 100644 index 00000000..6fbcdb4b --- /dev/null +++ b/altosuilib/AltosUIMapTile.java @@ -0,0 +1,190 @@ +/* + * Copyright © 2010 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.image.*; +import javax.swing.*; +import javax.imageio.*; +import java.awt.geom.*; +import java.io.*; +import java.util.*; +import java.awt.RenderingHints.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosUIMapTile { + AltosUIMapTileListener listener; + AltosUILatLon upper_left, center; + int px_size; + int zoom; + int maptype; + AltosUIMapStore store; + int status; + + private File map_file() { + double lat = center.lat; + double lon = center.lon; + char chlat = lat < 0 ? 'S' : 'N'; + char chlon = lon < 0 ? 'W' : 'E'; + + if (lat < 0) lat = -lat; + if (lon < 0) lon = -lon; + String maptype_string = String.format("%s-", AltosUIMap.maptype_names[maptype]); + String format_string; + if (maptype == AltosUIMap.maptype_hybrid || maptype == AltosUIMap.maptype_satellite || maptype == AltosUIMap.maptype_terrain) + format_string = "jpg"; + else + format_string = "png"; + return new File(AltosUIPreferences.mapdir(), + String.format("map-%c%.6f,%c%.6f-%s%d.%s", + chlat, lat, chlon, lon, maptype_string, zoom, format_string)); + } + + private String map_url() { + String format_string; + if (maptype == AltosUIMap.maptype_hybrid || maptype == AltosUIMap.maptype_satellite || maptype == AltosUIMap.maptype_terrain) + format_string = "jpg"; + else + format_string = "png32"; + + if (AltosUIVersion.has_google_maps_api_key()) + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s&key=%s", + center.lat, center.lon, zoom, px_size, px_size, AltosUIMap.maptype_names[maptype], format_string, AltosUIVersion.google_maps_api_key); + else + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s", + center.lat, center.lon, zoom, px_size, px_size, AltosUIMap.maptype_names[maptype], format_string); + } + private Font font = null; + + public void set_font(Font font) { + this.font = font; + } + + int painting_serial; + int painted_serial; + + Image image; + + public void paint_graphics(Graphics2D g2d, AltosUIMapTransform t, int serial) { + if (serial < painted_serial) + return; + + Point2D.Double point_double = t.screen(upper_left); + Point point = new Point((int) (point_double.x + 0.5), + (int) (point_double.y + 0.5)); + + painted_serial = serial; + + if (!g2d.hitClip(point.x, point.y, px_size, px_size)) + return; + + if (image != null) { + g2d.drawImage(image, point.x, point.y, null); + image = null; + } else { + g2d.setColor(Color.GRAY); + g2d.fillRect(point.x, point.y, px_size, px_size); + + if (t.has_location()) { + String message = null; + switch (status) { + case AltosUIMapCache.loading: + message = "Loading..."; + break; + case AltosUIMapCache.bad_request: + message = "Internal error"; + break; + case AltosUIMapCache.failed: + message = "Network error, check connection"; + break; + case AltosUIMapCache.forbidden: + message = "Too many requests, try later"; + break; + } + if (message != null && font != null) { + g2d.setFont(font); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + Rectangle2D bounds = font.getStringBounds(message, g2d.getFontRenderContext()); + + float x = px_size / 2.0f; + float y = px_size / 2.0f; + x = x - (float) bounds.getWidth() / 2.0f; + y = y + (float) bounds.getHeight() / 2.0f; + g2d.setColor(Color.BLACK); + g2d.drawString(message, (float) point_double.x + x, (float) point_double.y + y); + } + } + } + } + + public void set_status(int status) { + this.status = status; + listener.notify_tile(this, status); + } + + public void notify_image(Image image) { + listener.notify_tile(this, status); + } + + public void paint(Graphics g, AltosUIMapTransform t) { + Graphics2D g2d = (Graphics2D) g; + boolean queued = false; + + Point2D.Double point = t.screen(upper_left); + + if (!g.hitClip((int) (point.x + 0.5), (int) (point.y + 0.5), px_size, px_size)) + return; + + ++painting_serial; + + if (image == null && t.has_location()) + image = AltosUIMapCache.get(this, store, px_size, px_size); + + paint_graphics(g2d, t, painting_serial); + } + + public int store_status() { + return store.status(); + } + + public void add_store_listener(AltosUIMapStoreListener listener) { + store.add_listener(listener); + } + + public void remove_store_listener(AltosUIMapStoreListener listener) { + store.remove_listener(listener); + } + + public AltosUIMapTile(AltosUIMapTileListener listener, AltosUILatLon upper_left, AltosUILatLon center, int zoom, int maptype, int px_size, Font font) { + this.listener = listener; + this.upper_left = upper_left; + + while (center.lon < -180.0) + center.lon += 360.0; + while (center.lon > 180.0) + center.lon -= 360.0; + + this.center = center; + this.zoom = zoom; + this.maptype = maptype; + this.px_size = px_size; + this.font = font; + status = AltosUIMapCache.loading; + store = AltosUIMapStore.get(map_url(), map_file()); + } +} diff --git a/altosuilib/AltosUIMapTileListener.java b/altosuilib/AltosUIMapTileListener.java new file mode 100644 index 00000000..4cc3ff2f --- /dev/null +++ b/altosuilib/AltosUIMapTileListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +public interface AltosUIMapTileListener { + abstract public void notify_tile(AltosUIMapTile tile, int status); +} diff --git a/altosuilib/AltosUIMapTransform.java b/altosuilib/AltosUIMapTransform.java new file mode 100644 index 00000000..e6f1ffe3 --- /dev/null +++ b/altosuilib/AltosUIMapTransform.java @@ -0,0 +1,106 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.lang.Math; +import java.awt.geom.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosUIMapTransform { + + double scale_x, scale_y; + + double offset_x, offset_y; + + public AltosUILatLon lat_lon (Point2D.Double point) { + double lat, lon; + double rads; + + lon = point.x/scale_x; + rads = 2 * Math.atan(Math.exp(-point.y/scale_y)); + lat = Math.toDegrees(rads - Math.PI/2); + + return new AltosUILatLon(lat,lon); + } + + public Point2D.Double screen_point(Point screen) { + return new Point2D.Double(screen.x + offset_x, screen.y + offset_y); + } + + public AltosUILatLon screen_lat_lon(Point screen) { + return lat_lon(screen_point(screen)); + } + + public Point2D.Double point(AltosUILatLon lat_lon) { + double x, y; + double e; + + x = lat_lon.lon * scale_x; + + e = Math.sin(Math.toRadians(lat_lon.lat)); + e = Math.max(e,-(1-1.0E-15)); + e = Math.min(e, 1-1.0E-15 ); + + y = 0.5*Math.log((1+e)/(1-e))*-scale_y; + + return new Point2D.Double(x, y); + } + + public Point2D.Double screen(Point2D.Double point) { + return new Point2D.Double(point.x - offset_x, point.y - offset_y); + } + + public Point screen(Point point) { + return new Point((int) (point.x - offset_x + 0.5), + (int) (point.y - offset_y + 0.5)); + } + + public Rectangle screen(AltosUIMapRectangle map_rect) { + Point2D.Double ul = screen(map_rect.ul); + Point2D.Double lr = screen(map_rect.lr); + + return new Rectangle((int) ul.x, (int) ul.y, (int) (lr.x - ul.x), (int) (lr.y - ul.y)); + } + + public Point2D.Double screen(AltosUILatLon lat_lon) { + return screen(point(lat_lon)); + } + + private boolean has_location; + + public boolean has_location() { + return has_location; + } + + public AltosUIMapTransform(int width, int height, int zoom, AltosUILatLon centre_lat_lon) { + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + + Point2D.Double centre_pt = point(centre_lat_lon); + + has_location = (centre_lat_lon.lat != 0 || centre_lat_lon.lon != 0); + offset_x = centre_pt.x - width / 2.0; + offset_y = centre_pt.y - height / 2.0; + } +} diff --git a/altosuilib/AltosUIMapView.java b/altosuilib/AltosUIMapView.java new file mode 100644 index 00000000..c558118b --- /dev/null +++ b/altosuilib/AltosUIMapView.java @@ -0,0 +1,462 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import javax.swing.*; +import java.io.*; +import java.lang.*; +import java.awt.geom.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosUIMapView extends Canvas implements MouseMotionListener, MouseListener, MouseWheelListener, ComponentListener, AltosUIMapTileListener, AltosUIMapStoreListener { + + AltosUIMapPath path = new AltosUIMapPath(); + + AltosUIMapLine line = new AltosUIMapLine(); + + LinkedList marks = new LinkedList(); + + LinkedList zoom_listeners = new LinkedList(); + + boolean have_boost = false; + boolean have_landed = false; + + ConcurrentHashMap tiles = new ConcurrentHashMap(); + + static final int default_zoom = 15; + static final int min_zoom = 3; + static final int max_zoom = 21; + static final int px_size = 512; + + int load_radius; + AltosUILatLon load_centre = null; + AltosUIMapTileListener load_listener; + + int zoom = default_zoom; + int maptype = AltosUIMap.maptype_default; + + long user_input_time; + + /* Milliseconds to wait after user action before auto-scrolling + */ + static final long auto_scroll_delay = 20 * 1000; + + AltosUIMapTransform transform; + AltosUILatLon centre; + + public void set_font() { + line.set_font(AltosUILib.value_font); + for (AltosUIMapTile tile : tiles.values()) + tile.set_font(AltosUILib.value_font); + } + + private boolean is_drag_event(MouseEvent e) { + return e.getModifiers() == InputEvent.BUTTON1_MASK; + } + + Point drag_start; + + private void drag(MouseEvent e) { + if (drag_start == null) + return; + + int dx = e.getPoint().x - drag_start.x; + int dy = e.getPoint().y - drag_start.y; + + AltosUILatLon new_centre = transform.screen_lat_lon(new Point(getWidth() / 2 - dx, getHeight() / 2 - dy)); + centre (new_centre.lat, new_centre.lon); + drag_start = e.getPoint(); + } + + private void drag_start(MouseEvent e) { + drag_start = e.getPoint(); + } + + private void notice_user_input() { + user_input_time = System.currentTimeMillis(); + } + + private boolean recent_user_input() { + return (System.currentTimeMillis() - user_input_time) < auto_scroll_delay; + } + + /* MouseMotionListener methods */ + + public void mouseDragged(MouseEvent e) { + notice_user_input(); + if (is_drag_event(e)) + drag(e); + else { + line.dragged(e, transform); + repaint(); + } + } + + public void mouseMoved(MouseEvent e) { + } + + /* MouseListener methods */ + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + notice_user_input(); + if (is_drag_event(e)) + drag_start(e); + else + line.pressed(e, transform); + } + + public void mouseReleased(MouseEvent e) { + } + + /* MouseWheelListener methods */ + + public void mouseWheelMoved(MouseWheelEvent e) { + int zoom_change = e.getWheelRotation(); + + notice_user_input(); + AltosUILatLon mouse_lat_lon = transform.screen_lat_lon(e.getPoint()); + set_zoom(zoom() - zoom_change); + + Point2D.Double new_mouse = transform.screen(mouse_lat_lon); + + int dx = getWidth()/2 - e.getPoint().x; + int dy = getHeight()/2 - e.getPoint().y; + + AltosUILatLon new_centre = transform.screen_lat_lon(new Point((int) new_mouse.x + dx, (int) new_mouse.y + dy)); + + centre(new_centre.lat, new_centre.lon); + } + + /* ComponentListener methods */ + + public void componentHidden(ComponentEvent e) { + } + + public void componentMoved(ComponentEvent e) { + } + + public void componentResized(ComponentEvent e) { + set_transform(); + } + + public void componentShown(ComponentEvent e) { + set_transform(); + } + + public void repaint(Rectangle r, int pad) { + repaint(r.x - pad, r.y - pad, r.width + pad*2, r.height + pad*2); + } + + public void repaint(AltosUIMapRectangle rect, int pad) { + repaint (transform.screen(rect), pad); + } + + private boolean far_from_centre(AltosUILatLon lat_lon) { + + if (centre == null || transform == null) + return true; + + Point2D.Double screen = transform.screen(lat_lon); + + int width = getWidth(); + int dx = Math.abs ((int) screen.x - width/2); + + if (dx > width / 4) + return true; + + int height = getHeight(); + int dy = Math.abs ((int) screen.y - height/2); + + if (dy > height / 4) + return true; + + return false; + } + + public void show(AltosState state, AltosListenerState listener_state) { + + /* If insufficient gps data, nothing to update + */ + AltosGPS gps = state.gps; + + if (gps == null) + return; + + if (!gps.locked && gps.nsat < 4) + return; + + AltosUIMapRectangle damage = path.add(gps.lat, gps.lon, state.state); + + switch (state.state) { + case AltosLib.ao_flight_boost: + if (!have_boost) { + add_mark(gps.lat, gps.lon, state.state); + have_boost = true; + } + break; + case AltosLib.ao_flight_landed: + if (!have_landed) { + add_mark(gps.lat, gps.lon, state.state); + have_landed = true; + } + break; + } + + if (damage != null) + repaint(damage, AltosUIMapPath.stroke_width); + maybe_centre(gps.lat, gps.lon); + } + + private void set_transform() { + Rectangle bounds = getBounds(); + + transform = new AltosUIMapTransform(bounds.width, bounds.height, zoom, centre); + repaint(); + } + + public boolean set_zoom(int zoom) { + if (min_zoom <= zoom && zoom <= max_zoom && zoom != this.zoom) { + this.zoom = zoom; + tiles.clear(); + set_transform(); + + for (AltosUIMapZoomListener listener : zoom_listeners) + listener.zoom_changed(this.zoom); + + return true; + } + return false; + } + + public void add_zoom_listener(AltosUIMapZoomListener listener) { + if (!zoom_listeners.contains(listener)) + zoom_listeners.add(listener); + } + + public void remove_zoom_listener(AltosUIMapZoomListener listener) { + zoom_listeners.remove(listener); + } + + public void set_load_params(double lat, double lon, int radius, AltosUIMapTileListener listener) { + load_centre = new AltosUILatLon(lat, lon); + load_radius = radius; + load_listener = listener; + centre(lat, lon); + make_tiles(); + for (AltosUIMapTile tile : tiles.values()) { + tile.add_store_listener(this); + if (tile.store_status() != AltosUIMapStore.loading) + listener.notify_tile(tile, tile.store_status()); + } + repaint(); + } + + public boolean all_fetched() { + for (AltosUIMapTile tile : tiles.values()) { + if (tile.store_status() == AltosUIMapStore.loading) + return false; + } + return true; + } + + public boolean set_maptype(int maptype) { + if (maptype != this.maptype) { + this.maptype = maptype; + tiles.clear(); + repaint(); + return true; + } + return false; + } + + public int get_maptype() { + return maptype; + } + + public int zoom() { + return zoom; + } + + public void centre(AltosUILatLon lat_lon) { + centre = lat_lon; + set_transform(); + } + + public void centre(double lat, double lon) { + centre(new AltosUILatLon(lat, lon)); + } + + public void maybe_centre(double lat, double lon) { + AltosUILatLon lat_lon = new AltosUILatLon(lat, lon); + if (centre == null || (!recent_user_input() && far_from_centre(lat_lon))) + centre(lat_lon); + } + + private VolatileImage create_back_buffer() { + return getGraphicsConfiguration().createCompatibleVolatileImage(getWidth(), getHeight()); + } + + private Point floor(Point2D.Double point) { + return new Point ((int) Math.floor(point.x / px_size) * px_size, + (int) Math.floor(point.y / px_size) * px_size); + } + + private Point ceil(Point2D.Double point) { + return new Point ((int) Math.ceil(point.x / px_size) * px_size, + (int) Math.ceil(point.y / px_size) * px_size); + } + + private void make_tiles() { + Point upper_left; + Point lower_right; + + if (load_centre != null) { + Point centre = floor(transform.point(load_centre)); + + upper_left = new Point(centre.x - load_radius * px_size, + centre.y - load_radius * px_size); + lower_right = new Point(centre.x + load_radius * px_size, + centre.y + load_radius * px_size); + } else { + upper_left = floor(transform.screen_point(new Point(0, 0))); + lower_right = floor(transform.screen_point(new Point(getWidth(), getHeight()))); + } + LinkedList to_remove = new LinkedList(); + + for (Point point : tiles.keySet()) { + if (point.x < upper_left.x || lower_right.x < point.x || + point.y < upper_left.y || lower_right.y < point.y) { + to_remove.add(point); + } + } + + for (Point point : to_remove) + tiles.remove(point); + + AltosUIMapCache.set_cache_size(((lower_right.y - upper_left.y) / px_size + 1) * ((lower_right.x - upper_left.x) / px_size + 1)); + for (int y = upper_left.y; y <= lower_right.y; y += px_size) { + for (int x = upper_left.x; x <= lower_right.x; x += px_size) { + Point point = new Point(x, y); + + if (!tiles.containsKey(point)) { + AltosUILatLon ul = transform.lat_lon(new Point2D.Double(x, y)); + AltosUILatLon center = transform.lat_lon(new Point2D.Double(x + px_size/2, y + px_size/2)); + AltosUIMapTile tile = new AltosUIMapTile(this, ul, center, zoom, maptype, + px_size, AltosUILib.value_font); + tiles.put(point, tile); + } + } + } + } + + /* AltosUIMapTileListener methods */ + public void notify_tile(AltosUIMapTile tile, int status) { + for (Point point : tiles.keySet()) { + if (tile == tiles.get(point)) { + Point screen = transform.screen(point); + repaint(screen.x, screen.y, px_size, px_size); + } + } + } + + /* AltosUIMapStoreListener methods */ + public void notify_store(AltosUIMapStore store, int status) { + if (load_listener != null) { + for (AltosUIMapTile tile : tiles.values()) + if (store.equals(tile.store)) + load_listener.notify_tile(tile, status); + } + } + + private void do_paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + + make_tiles(); + + for (AltosUIMapTile tile : tiles.values()) + tile.paint(g2d, transform); + + synchronized(marks) { + for (AltosUIMapMark mark : marks) + mark.paint(g2d, transform); + } + + path.paint(g2d, transform); + + line.paint(g2d, transform); + } + + public void paint(Graphics g) { + + VolatileImage back_buffer = create_back_buffer(); + do { + GraphicsConfiguration gc = getGraphicsConfiguration(); + int code = back_buffer.validate(gc); + if (code == VolatileImage.IMAGE_INCOMPATIBLE) + back_buffer = create_back_buffer(); + + Graphics g_back = back_buffer.getGraphics(); + g_back.setClip(g.getClip()); + do_paint(g_back); + g_back.dispose(); + + g.drawImage(back_buffer, 0, 0, this); + } while (back_buffer.contentsLost()); + back_buffer.flush(); + } + + public void update(Graphics g) { + paint(g); + } + + public void add_mark(double lat, double lon, int state) { + synchronized(marks) { + marks.add(new AltosUIMapMark(lat, lon, state)); + } + repaint(); + } + + public void clear_marks() { + synchronized(marks) { + marks.clear(); + } + } + + public AltosUIMapView() { + centre(0, 0); + + addComponentListener(this); + addMouseMotionListener(this); + addMouseListener(this); + addMouseWheelListener(this); + set_font(); + } +} diff --git a/altosuilib/AltosUIMapZoomListener.java b/altosuilib/AltosUIMapZoomListener.java new file mode 100644 index 00000000..02e8bb51 --- /dev/null +++ b/altosuilib/AltosUIMapZoomListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +public interface AltosUIMapZoomListener { + abstract public void zoom_changed(int zoom); +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index b90669ce..466cfd99 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -33,11 +33,6 @@ altosuilib_JAVA = \ AltosUISeries.java \ AltosUIVersion.java \ AltosUSBDevice.java \ - AltosSiteMap.java \ - AltosSiteMapCache.java \ - AltosSiteMapPreload.java \ - AltosSiteMapTile.java \ - AltosSiteMapImage.java \ AltosVoice.java \ AltosDisplayThread.java \ AltosDeviceUIDialog.java \ @@ -65,8 +60,23 @@ altosuilib_JAVA = \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ - AltosBTKnown.java - + AltosBTKnown.java \ + AltosUIMap.java \ + AltosUIMapView.java \ + AltosUIMapLine.java \ + AltosUIMapMark.java \ + AltosUIMapPath.java \ + AltosUIMapTile.java \ + AltosUIMapCache.java \ + AltosUIMapImage.java \ + AltosUIMapTransform.java \ + AltosUIMapRectangle.java \ + AltosUIMapZoomListener.java \ + AltosUIMapTileListener.java \ + AltosUIMapPreload.java \ + AltosUIMapStore.java \ + AltosUIMapStoreListener.java \ + AltosUILatLon.java JAR=altosuilib_$(ALTOSUILIB_VERSION).jar diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index c61b245e..2503d53e 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -67,7 +67,7 @@ public class TeleGPS JTabbedPane pane; - AltosSiteMap sitemap; + AltosUIMap map; TeleGPSInfo gps_info; AltosInfoTable info_table; @@ -167,7 +167,7 @@ public class TeleGPS } void load_maps() { - new AltosSiteMapPreload(this); + new AltosUIMapPreload(this); } void disconnect() { @@ -438,9 +438,9 @@ public class TeleGPS c.gridwidth = 2; bag.add(pane, c); - sitemap = new AltosSiteMap(); - pane.add("Site Map", sitemap); - displays.add(sitemap); + map = new AltosUIMap(); + pane.add("Map", map); + displays.add(map); gps_info = new TeleGPSInfo(); pane.add("Info", gps_info); @@ -578,7 +578,7 @@ public class TeleGPS } else { double lat = Double.parseDouble(args[i+1]); double lon = Double.parseDouble(args[i+2]); - AltosSiteMap.prefetchMaps(lat, lon); + AltosUIMap.prefetch_maps(lat, lon); i += 2; } } else if (args[i].equals("--replay")) diff --git a/telegps/TeleGPSGraphUI.java b/telegps/TeleGPSGraphUI.java index b7fc4caa..fbc9657e 100644 --- a/telegps/TeleGPSGraphUI.java +++ b/telegps/TeleGPSGraphUI.java @@ -38,7 +38,7 @@ public class TeleGPSGraphUI extends AltosUIFrame JTabbedPane pane; AltosGraph graph; AltosUIEnable enable; - AltosSiteMap map; + AltosUIMap map; AltosState state; AltosFlightStats stats; AltosGraphDataSet graphDataSet; @@ -69,7 +69,7 @@ public class TeleGPSGraphUI extends AltosUIFrame graph = new AltosGraph(enable, stats, graphDataSet); statsTable = new AltosFlightStatsTable(stats); - map = new AltosSiteMap(); + map = new AltosUIMap(); pane.add("Flight Graph", graph.panel); pane.add("Configure Graph", enable); -- cgit v1.2.3 From ac5b15692874ea3f7b3814250ab49c68786aa982 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jun 2014 18:51:19 -0700 Subject: altosuilib: Remove old widget-based map UI Signed-off-by: Keith Packard --- altosuilib/AltosSiteMap.java | 892 ------------------------------------ altosuilib/AltosSiteMapCache.java | 253 ---------- altosuilib/AltosSiteMapImage.java | 82 ---- altosuilib/AltosSiteMapPreload.java | 568 ----------------------- altosuilib/AltosSiteMapTile.java | 293 ------------ 5 files changed, 2088 deletions(-) delete mode 100644 altosuilib/AltosSiteMap.java delete mode 100644 altosuilib/AltosSiteMapCache.java delete mode 100644 altosuilib/AltosSiteMapImage.java delete mode 100644 altosuilib/AltosSiteMapPreload.java delete mode 100644 altosuilib/AltosSiteMapTile.java (limited to 'altosuilib') diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java deleted file mode 100644 index ed77beff..00000000 --- a/altosuilib/AltosSiteMap.java +++ /dev/null @@ -1,892 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_2; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import java.io.*; -import java.lang.Math; -import java.awt.geom.*; -import java.util.*; -import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; - -class MapPoint { - double lat, lon; - int state; - - public MapPoint(double lat, double lon, int state) { - this.lat = lat; - this.lon = lon; - this.state = state; - } - - public boolean equals(MapPoint other) { - if (other == null) - return false; - if (other.lat != lat) - return false; - if (other.lon != lon) - return false; - if (other.state != state) - return false; - return true; - } -} - -public class AltosSiteMap extends JComponent implements AltosFlightDisplay, MouseMotionListener, MouseListener, HierarchyBoundsListener { - // preferred vertical step in a tile in naut. miles - // will actually choose a step size between x and 2x, where this - // is 1.5x - static final double tile_size_nmi = 0.75; - - static final int px_size = 512; - - static final int MAX_TILE_DELTA = 100; - - static final int maptype_hybrid = 0; - static final int maptype_roadmap = 1; - static final int maptype_satellite = 2; - static final int maptype_terrain = 3; - - int maptype = maptype_hybrid; - - static final String[] maptype_names = { - "hybrid", - "roadmap", - "satellite", - "terrain" - }; - - public static final String[] maptype_labels = { - "Hybrid", - "Roadmap", - "Satellite", - "Terrain" - }; - - LinkedList points = new LinkedList(); - - private static Point2D.Double translatePoint(Point2D.Double p, - Point2D.Double d) - { - return new Point2D.Double(p.x + d.x, p.y + d.y); - } - - static class LatLng { - public double lat, lng; - public LatLng(double lat, double lng) { - this.lat = lat; - this.lng = lng; - } - } - - // based on google js - // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js - // search for fromLatLngToPoint and fromPointToLatLng - /* - private static Point2D.Double pt(LatLng latlng, int zoom) { - double scale_x = 256/360.0 * Math.pow(2, zoom); - double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - return pt(latlng, scale_x, scale_y); - } - */ - - private static Point2D.Double pt(LatLng latlng, - double scale_x, double scale_y) - { - Point2D.Double res = new Point2D.Double(); - double e; - - res.x = latlng.lng * scale_x; - - e = Math.sin(Math.toRadians(latlng.lat)); - e = Math.max(e,-(1-1.0E-15)); - e = Math.min(e, 1-1.0E-15 ); - - res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y; - return res; - } - - static private LatLng latlng(Point2D.Double pt, - double scale_x, double scale_y) - { - double lat, lng; - double rads; - - lng = pt.x/scale_x; - rads = 2 * Math.atan(Math.exp(-pt.y/scale_y)); - lat = Math.toDegrees(rads - Math.PI/2); - - return new LatLng(lat,lng); - } - - static final int default_zoom = 15; - static final int min_zoom = 3; - static final int max_zoom = 21; - - int zoom = default_zoom; - - double scale_x, scale_y; - - int radius; /* half width/height of tiles to load */ - - private Point2D.Double pt(double lat, double lng) { - return pt(new LatLng(lat, lng), scale_x, scale_y); - } - - private LatLng latlng(double x, double y) { - return latlng(new Point2D.Double(x,y), scale_x, scale_y); - } - /* - private LatLng latlng(Point2D.Double pt) { - return latlng(pt, scale_x, scale_y); - } - */ - - private LatLng latlng(Point pt) { - return latlng(new Point2D.Double(pt.x, pt.y), scale_x, scale_y); - } - - ConcurrentHashMap mapTiles = new ConcurrentHashMap(); - Point2D.Double centre; - - private Point2D.Double tileCoordOffset(Point p) { - return new Point2D.Double(centre.x - p.x*px_size, - centre.y - p.y*px_size); - } - - private Point tileOffset(Point2D.Double p) { - return new Point((int)Math.floor((centre.x+p.x)/px_size), - (int)Math.floor((centre.y+p.y)/px_size)); - } - - private Point2D.Double getBaseLocation(double lat, double lng) { - Point2D.Double locn = pt(0,0), north_step; - - scale_x = 256/360.0 * Math.pow(2, zoom); - scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - locn = pt(lat, lng); - locn.x = -px_size * Math.floor(locn.x/px_size); - locn.y = -px_size * Math.floor(locn.y/px_size); - return locn; - } - - public void reset() { - // nothing - } - - public void font_size_changed(int font_size) { - for (AltosSiteMapTile tile : mapTiles.values()) - tile.set_font(AltosUILib.value_font); - } - - public void units_changed(boolean imperial_units) { - set_line(); - } - - static final int load_mode_cached = 1; - static final int load_mode_uncached = 2; - - private boolean load_map(final AltosSiteMapTile tile, - final File pngfile, String pngurl, - int load_mode) - { - boolean has_map = AltosSiteMapCache.has_map(pngfile, pngurl); - if ((load_mode & load_mode_uncached) == 0 && !has_map) - return false; - if ((load_mode & load_mode_cached) == 0 && has_map) - return false; - - tile.set_status(AltosSiteMapCache.loading); - int status = AltosSiteMapCache.fetch_map(pngfile, pngurl); - if (status == AltosSiteMapCache.success) { - if (SwingUtilities.isEventDispatchThread()) - tile.load_map(pngfile); - else { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - tile.load_map(pngfile); - } - }); - } - } else { - tile.set_status(status); - System.out.printf("# Failed to fetch file %s (status %d)\n", pngfile, status); - System.out.printf(" wget -O '%s' '%s'\n", pngfile, pngurl); - System.out.printf(" sleep 1\n"); - } - return true; - } - - - class AltosSiteMapPrefetch { - int x; - int y; - int result; - File pngfile; - String pngurl; - } - - private AltosSiteMapPrefetch prefetchMap(int x, int y) { - AltosSiteMapPrefetch prefetch = new AltosSiteMapPrefetch(); - LatLng map_latlng = latlng( - -centre.x + x*px_size + px_size/2, - -centre.y + y*px_size + px_size/2); - prefetch.pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom, maptype_hybrid); - prefetch.pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom, maptype_hybrid); - if (AltosSiteMapCache.has_map(prefetch.pngfile, prefetch.pngurl)) { - prefetch.result = 1; - } else if (AltosSiteMapCache.fetch_map(prefetch.pngfile, prefetch.pngurl) == AltosSiteMapCache.success) { - prefetch.result = 0; - } else { - prefetch.result = -1; - } - return prefetch; - } - - public static void prefetchMaps(double lat, double lng, int radius, int maptypes, int min_zoom, int max_zoom) { - AltosSiteMap asm = new AltosSiteMap(true); - - for (int z = min_zoom; z <= max_zoom; z++) { - asm.zoom = z; - asm.set_radius(radius); - asm.centre = asm.getBaseLocation(lat, lng); - for (int t = maptype_hybrid; t <= maptype_terrain; t++) { - if ((maptypes & (1 << t)) !=0) { - asm.maptype = t; - for (int y = -radius; y <= radius; y++) { - for (int x = -radius; x <= radius; x++) { - AltosSiteMapPrefetch prefetch = asm.prefetchMap(x, y); - switch (prefetch.result) { - case 1: - System.out.printf("Already have %s\n", prefetch.pngfile); - break; - case 0: - System.out.printf("Fetched map %s\n", prefetch.pngfile); - break; - case -1: - System.out.printf("# Failed to fetch file %s\n", prefetch.pngfile); - System.out.printf(" wget -O '%s' ''\n", - prefetch.pngfile, prefetch.pngurl); - break; - } - } - } - } - } - } - } - - public static void prefetchMaps(double lat, double lon) { - prefetchMaps(lat, lon, 2, 1 << maptype_hybrid, 0, 0); - } - - public File init_map(Point offset, int load_mode) { - AltosSiteMapTile tile = mapTiles.get(offset); - Point2D.Double coord = tileCoordOffset(offset); - - LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y); - - File pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom, maptype); - String pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom, maptype); - load_map(tile, pngfile, pngurl, load_mode); - return pngfile; - } - - private void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) { - Thread thread = new Thread() { - public void run() { - init_map(offset, load_mode_cached|load_mode_uncached); - SwingUtilities.invokeLater( new Runnable() { - public void run() { - addTileAt(tile, offset); - } - } ); - } - }; - thread.start(); - } - - double lat, lon; - boolean base_location_set = false; - - public void clear_base_location() { - base_location_set = false; - circle_set = false; - points = new LinkedList(); - line_start = line_end = null; - for (AltosSiteMapTile tile : mapTiles.values()) { - tile.clearMap(); - tile.set_status(AltosSiteMapCache.loading); - } - } - - public void setBaseLocation(double lat, double lng) { - this.lat = lat; - this.lon = lng; - base_location_set = true; - - centre = getBaseLocation(lat, lng); - scrollRocketToVisible(pt(lat,lng)); - } - - private void initMaps(double lat, double lng) { - setBaseLocation(lat, lng); - - for (AltosSiteMapTile tile : mapTiles.values()) { - tile.clearMap(); - tile.set_status(AltosSiteMapCache.loading); - } - Thread thread = new Thread() { - public void run() { - for (Point k : mapTiles.keySet()) - init_map(k, load_mode_cached); - for (Point k : mapTiles.keySet()) - init_map(k, load_mode_uncached); - } - }; - thread.start(); - } - - private static File MapFile(double lat, double lng, int zoom, int maptype) { - char chlat = lat < 0 ? 'S' : 'N'; - char chlng = lng < 0 ? 'W' : 'E'; - if (lat < 0) lat = -lat; - if (lng < 0) lng = -lng; - String maptype_string = String.format("%s-", maptype_names[maptype]); - String format_string; - if (maptype == maptype_hybrid || maptype == maptype_satellite || maptype == maptype_terrain) - format_string = "jpg"; - else - format_string = "png"; - return new File(AltosUIPreferences.mapdir(), - String.format("map-%c%.6f,%c%.6f-%s%d.%s", - chlat, lat, chlng, lng, maptype_string, zoom, format_string)); - } - - private static String MapURL(double lat, double lng, int zoom, int maptype) { - String format_string; - if (maptype == maptype_hybrid || maptype == maptype_satellite || maptype == maptype_terrain) - format_string = "jpg"; - else - format_string = "png32"; - - if (AltosUIVersion.has_google_maps_api_key()) - return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s&key=%s", - lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string, AltosUIVersion.google_maps_api_key); - else - return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s", - lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string); - } - - boolean initialised = false; - MapPoint last_point = null; - int last_state = -1; - - private void show(double lat, double lon) { - System.out.printf ("show %g %g\n", lat, lon); - return; -// initMaps(lat, lon); -// scrollRocketToVisible(pt(lat, lon)); - } - - JLabel zoom_label; - - private void set_zoom_label() { - zoom_label.setText(String.format("Zoom %d", zoom - default_zoom)); - } - - public void set_zoom(int zoom) { - if (min_zoom <= zoom && zoom <= max_zoom) { - this.zoom = zoom; - if (base_location_set) { - set_tiles(); - initMaps(lat, lon); - } - redraw(); - set_zoom_label(); - } - } - - public int get_zoom() { - return zoom; - } - - public void set_maptype(int type) { - maptype = type; - maptype_combo.setSelectedIndex(type); - if (base_location_set) - initMaps(lat, lon); - redraw(); - } - - private void draw(MapPoint last_point, MapPoint point) { - boolean force_ensure = false; - if (last_point == null) { - force_ensure = true; - last_point = point; - } - - Point2D.Double pt = pt(point.lat, point.lon); - Point2D.Double last_pt = pt(last_point.lat, last_point.lon); - - boolean in_any = false; - for (Point offset : mapTiles.keySet()) { - AltosSiteMapTile tile = mapTiles.get(offset); - Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(offset)); - lref = translatePoint(last_pt, tileCoordOffset(offset)); - tile.show(point.state, lref, ref); - if (0 <= ref.x && ref.x < px_size) - if (0 <= ref.y && ref.y < px_size) - in_any = true; - } - - Point offset = tileOffset(pt); - if (!in_any) { - Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(offset)); - lref = translatePoint(last_pt, tileCoordOffset(offset)); - - AltosSiteMapTile tile = createTile(offset); - tile.show(point.state, lref, ref); - initAndFinishMapAsync(tile, offset); - } - - scrollRocketToVisible(pt); - - if (force_ensure || offset != tileOffset(last_pt)) { - ensureTilesAround(offset); - } - } - - private void redraw() { - MapPoint last_point = null; - - for (MapPoint point : points) { - draw(last_point, point); - last_point = point; - } - if (circle_set) - draw_circle(circle_lat, circle_lon); - if (line_start != null) - set_line(); - } - - public void show(final AltosState state, final AltosListenerState listener_state) { - // if insufficient gps data, nothing to update - AltosGPS gps = state.gps; - - if (gps == null) - return; - - if (!gps.locked && gps.nsat < 4) - return; - - if (!initialised) { - if (state.pad_lat != AltosLib.MISSING && state.pad_lon != AltosLib.MISSING) { - initMaps(state.pad_lat, state.pad_lon); - initialised = true; - } else if (gps.lat != AltosLib.MISSING && gps.lon != AltosLib.MISSING) { - initMaps(gps.lat, gps.lon); - initialised = true; - } else { - return; - } - } - - MapPoint point = new MapPoint(gps.lat, gps.lon, state.state); - - if (point.equals(last_point)) - return; - - points.add(point); - - draw(last_point, point); - - last_point = point; - } - - public void centre(Point2D.Double pt) { - Rectangle r = comp.getVisibleRect(); - Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); - int dx = (int)copt.x - r.width/2 - r.x; - int dy = (int)copt.y - r.height/2 - r.y; - r.x += dx; - r.y += dy; - r.width = 1; - r.height = 1; - comp.scrollRectToVisible(r); - } - - public void centre(AltosState state) { - if (!state.gps.locked && state.gps.nsat < 4) - return; - centre(pt(state.gps.lat, state.gps.lon)); - } - - private double circle_lat, circle_lon; - private boolean circle_set = false; - - public void draw_circle(double lat, double lon) { - circle_lat = lat; - circle_lon = lon; - circle_set = true; - - Point2D.Double pt = pt(lat, lon); - - for (Point offset : mapTiles.keySet()) { - AltosSiteMapTile tile = mapTiles.get(offset); - Point2D.Double ref = translatePoint(pt, tileCoordOffset(offset)); - tile.set_boost(ref); - } - } - - private AltosSiteMapTile createTile(Point offset) { - AltosSiteMapTile tile = new AltosSiteMapTile(px_size); - tile.set_font(AltosUILib.value_font); - mapTiles.put(offset, tile); - return tile; - } - - private void ensureTilesAround(Point base_offset) { - for (int x = -radius; x <= radius; x++) { - for (int y = -radius; y <= radius; y++) { - Point offset = new Point(base_offset.x + x, base_offset.y + y); - if (mapTiles.containsKey(offset)) - continue; - AltosSiteMapTile tile = createTile(offset); - initAndFinishMapAsync(tile, offset); - } - } - } - - private void set_tiles() { - for (int x = -radius; x <= radius; x++) { - for (int y = -radius; y <= radius; y++) { - Point offset = new Point(x, y); - if (mapTiles.containsKey(offset)) - continue; - AltosSiteMapTile t = createTile(offset); - addTileAt(t, offset); - } - } - for (Point offset : mapTiles.keySet()) { - if (offset.x < -radius || offset.x > radius || - offset.y < -radius || offset.y > radius) - { - removeTileAt(offset); - } - } - } - - public void set_radius(int radius) { - if (radius != this.radius) { - this.radius = radius; - set_tiles(); - } - } - - private Point topleft = new Point(0,0); - private void scrollRocketToVisible(Point2D.Double pt) { - Rectangle r = comp.getVisibleRect(); - Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); - - int dx = (int)copt.x - r.width/2 - r.x; - int dy = (int)copt.y - r.height/2 - r.y; - if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) { - r.x += dx; - r.y += dy; - comp.scrollRectToVisible(r); - } - } - - private void addTileAt(AltosSiteMapTile tile, Point offset) { - if (Math.abs(offset.x) >= MAX_TILE_DELTA || - Math.abs(offset.y) >= MAX_TILE_DELTA) - { - System.out.printf("Rocket too far away from pad (tile %d,%d)\n", - offset.x, offset.y); - return; - } - - if (offset.x < topleft.x) - topleft.x = offset.x; - if (offset.y < topleft.y) - topleft.y = offset.y; - - GridBagConstraints c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.BOTH; - // put some space between the map tiles, debugging only - // c.insets = new Insets(5, 5, 5, 5); - - c.gridx = offset.x + MAX_TILE_DELTA; - c.gridy = offset.y + MAX_TILE_DELTA; - layout.setConstraints(tile, c); - - comp.add(tile); - } - - private AltosSiteMap(boolean knowWhatYouAreDoing) { - if (!knowWhatYouAreDoing) { - throw new RuntimeException("Arggh."); - } - } - - private void removeTileAt(Point offset) { - AltosSiteMapTile tile = mapTiles.get(offset); - - mapTiles.remove(offset); - comp.remove(tile); - - topleft = new Point(MAX_TILE_DELTA, MAX_TILE_DELTA); - for (Point o : mapTiles.keySet()) { - if (o.x < topleft.x) - topleft.x = o.x; - if (o.y < topleft.y) - topleft.y = o.y; - } - } - - JComponent comp; - - private GridBagLayout layout = new GridBagLayout(); - - LatLng line_start, line_end; - - private void set_line() { - if (line_start != null && line_end != null) { - Point2D.Double start = pt(line_start.lat, line_start.lng); - Point2D.Double end = pt(line_end.lat, line_end.lng); - AltosGreatCircle g = new AltosGreatCircle(line_start.lat, line_start.lng, - line_end.lat, line_end.lng); - - for (Point offset : mapTiles.keySet()) { - AltosSiteMapTile tile = mapTiles.get(offset); - Point2D.Double s, e; - s = translatePoint(start, tileCoordOffset(offset)); - e = translatePoint(end, tileCoordOffset(offset)); - tile.set_line(new Line2D.Double(s.x, s.y, e.x, e.y), g.distance); - } - } else { - for (AltosSiteMapTile tile : mapTiles.values()) - tile.set_line(null, 0); - } - } - - static void debug_component(Component who, String where) { -/* - Rectangle r = who.getBounds(); - int x = r.x / px_size; - int y = r.y / px_size; - - System.out.printf ("%3d, %3d: %s\n", x, y, where); -*/ - } - - LatLng latlng(MouseEvent e) { - if (!base_location_set) - return null; - - Rectangle zerozero = mapTiles.get(new Point(0, 0)).getBounds(); - - return latlng(-centre.x + e.getPoint().x - zerozero.x, -centre.y + e.getPoint().y - zerozero.y); - } - - /* MouseMotionListener methods */ - public void mouseDragged(MouseEvent e) { - if (!GrabNDrag.grab_n_drag(e)) { - LatLng loc = latlng(e); - line_end = loc; - set_line(); - } - } - - public void mouseMoved(MouseEvent e) { - } - - /* MouseListener methods */ - public void mouseClicked(MouseEvent e) { - } - - public void mouseEntered(MouseEvent e) { - } - - public void mouseExited(MouseEvent e) { - } - - public void mousePressed(MouseEvent e) { - if (!GrabNDrag.grab_n_drag(e)) { - LatLng loc = latlng(e); - line_start = loc; - line_end = null; - set_line(); - } - } - - public void mouseReleased(MouseEvent e) { - } - - private void set_cache_size() { - Rectangle r = comp.getVisibleRect(); - - int width_tiles = (r.width + 2*px_size) / px_size; - int height_tiles = (r.height + 2*px_size) / px_size; - int tiles = width_tiles * height_tiles; - AltosSiteMapCache.set_cache_size(tiles); - } - - /* HierarchyBoundsListener methods */ - public void ancestorMoved(HierarchyEvent e) { - set_cache_size(); - } - - public void ancestorResized(HierarchyEvent e) { - set_cache_size(); - } - - JScrollPane pane = new JScrollPane(); - - JComboBox maptype_combo; - - public AltosSiteMap(int in_radius) { - radius = in_radius; - - comp = new JComponent() { }; - - comp.addMouseMotionListener(this); - comp.addMouseListener(this); - comp.addHierarchyBoundsListener(this); - - GrabNDrag scroller = new GrabNDrag(comp); - - comp.setLayout(layout); - - set_tiles(); - - pane.setViewportView(comp); - pane.setPreferredSize(new Dimension(500,500)); - pane.setVisible(true); - pane.setEnabled(true); - - GridBagLayout my_layout = new GridBagLayout(); - - setLayout(my_layout); - - GridBagConstraints c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.BOTH; - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 1; - c.gridheight = 10; - c.weightx = 1; - c.weighty = 1; - add(pane, c); - - int y = 0; - - zoom_label = new JLabel("", JLabel.CENTER); - set_zoom_label(); - - c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.HORIZONTAL; - c.gridx = 1; - c.gridy = y++; - c.weightx = 0; - c.weighty = 0; - add(zoom_label, c); - - JButton zoom_reset = new JButton("0"); - zoom_reset.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - set_zoom(default_zoom); - } - }); - - c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.HORIZONTAL; - c.gridx = 1; - c.gridy = y++; - c.weightx = 0; - c.weighty = 0; - add(zoom_reset, c); - - JButton zoom_in = new JButton("+"); - zoom_in.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - set_zoom(get_zoom() + 1); - } - }); - - c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.HORIZONTAL; - c.gridx = 1; - c.gridy = y++; - c.weightx = 0; - c.weighty = 0; - add(zoom_in, c); - - JButton zoom_out = new JButton("-"); - zoom_out.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - set_zoom(get_zoom() - 1); - } - }); - c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.HORIZONTAL; - c.gridx = 1; - c.gridy = y++; - c.weightx = 0; - c.weighty = 0; - add(zoom_out, c); - - maptype_combo = new JComboBox(maptype_labels); - - maptype_combo.setEditable(false); - maptype_combo.setMaximumRowCount(maptype_combo.getItemCount()); - maptype_combo.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - maptype = maptype_combo.getSelectedIndex(); - if (base_location_set) - initMaps(lat, lon); - redraw(); - } - }); - - c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.HORIZONTAL; - c.gridx = 1; - c.gridy = y++; - c.weightx = 0; - c.weighty = 0; - add(maptype_combo, c); - } - - public AltosSiteMap() { - this(1); - } -} diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java deleted file mode 100644 index 51778ce1..00000000 --- a/altosuilib/AltosSiteMapCache.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_2; - -import javax.swing.*; -import javax.imageio.ImageIO; -import java.awt.image.*; -import java.awt.*; -import java.io.*; -import java.net.*; - -public class AltosSiteMapCache { - static final long google_maps_ratelimit_ms = 1200; - // Google limits static map queries to 50 per minute per IP, so - // each query should take at least 1.2 seconds. - - static final int success = 0; - static final int loading = 1; - static final int failed = 2; - static final int bad_request = 3; - static final int forbidden = 4; - - public static boolean has_map(File file, String url) { - return file.exists(); - } - - static long forbidden_time; - static boolean forbidden_set = false; - static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; - - static private Object fetch_lock = new Object(); - - private static int fetch_one(File file, String url) { - URL u; - - try { - u = new URL(url); - } catch (java.net.MalformedURLException e) { - return bad_request; - } - - byte[] data; - URLConnection uc = null; - try { - uc = u.openConnection(); - String type = uc.getContentType(); - int contentLength = uc.getContentLength(); - if (uc instanceof HttpURLConnection) { - int response = ((HttpURLConnection) uc).getResponseCode(); - switch (response) { - case HttpURLConnection.HTTP_FORBIDDEN: - case HttpURLConnection.HTTP_PAYMENT_REQUIRED: - case HttpURLConnection.HTTP_UNAUTHORIZED: - forbidden_time = System.nanoTime(); - forbidden_set = true; - return forbidden; - } - } - InputStream in = new BufferedInputStream(uc.getInputStream()); - int bytesRead = 0; - int offset = 0; - data = new byte[contentLength]; - while (offset < contentLength) { - bytesRead = in.read(data, offset, data.length - offset); - if (bytesRead == -1) - break; - offset += bytesRead; - } - in.close(); - - if (offset != contentLength) - return failed; - - } catch (IOException e) { - return failed; - } - - try { - FileOutputStream out = new FileOutputStream(file); - out.write(data); - out.flush(); - out.close(); - } catch (FileNotFoundException e) { - return bad_request; - } catch (IOException e) { - if (file.exists()) - file.delete(); - return bad_request; - } - return success; - } - - public static int fetch_map(File file, String url) { - if (file.exists()) - return success; - - if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) - return forbidden; - - int status = bad_request; - - if (!AltosUIVersion.has_google_maps_api_key()) { - synchronized (fetch_lock) { - long startTime = System.nanoTime(); - status = fetch_one(file, url); - if (status == success) { - long duration_ms = (System.nanoTime() - startTime) / 1000000; - if (duration_ms < google_maps_ratelimit_ms) { - try { - Thread.sleep(google_maps_ratelimit_ms - duration_ms); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - } else { - status = fetch_one(file, url); - } - return status; - } - - static final int min_cache_size = 9; - static final int max_cache_size = 24; - - static int cache_size = min_cache_size; - - static AltosSiteMapImage[] images = new AltosSiteMapImage[cache_size]; - - static Object cache_lock = new Object(); - - public static void set_cache_size(int new_size) { - if (new_size < min_cache_size) - new_size = min_cache_size; - if (new_size > max_cache_size) - new_size = max_cache_size; - if (new_size == cache_size) - return; - - synchronized(cache_lock) { - AltosSiteMapImage[] new_images = new AltosSiteMapImage[new_size]; - - for (int i = 0; i < cache_size; i++) { - if (i < new_size) - new_images[i] = images[i]; - else if (images[i] != null) - images[i].flush(); - } - images = new_images; - cache_size = new_size; - } - } - - static long used; - - private static Point tile_loc(AltosSiteMapTile tile) { - Rectangle r = tile.getBounds(); - int x = r.x / 512; - int y = r.y / 512; - - return new Point (x, y); - } - -/* - private static void dump_cache() { - int min_x = 1000, max_x = -1000, min_y = 1000, max_y = -1000; - - for (int i = 0; i < cache_size; i++) { - AltosSiteMapImage image = images[i]; - if (image != null) { - Point p = tile_loc(image.tile); - min_x = min_x < p.x ? min_x : p.x; - max_x = max_x > p.x ? max_x : p.x; - min_y = min_y < p.y ? min_y : p.y; - max_y = max_y > p.y ? max_y : p.y; - System.out.printf ("entry %d %d,%d used %d\n", i, p.x, p.y, image.used); - } else { - System.out.printf ("entry %d empty\n", i); - } - } - - int[][] map = new int[max_x - min_x + 1][max_y - min_y + 1]; - for (int i = 0; i < cache_size; i++) { - AltosSiteMapImage image = images[i]; - if (image != null) { - Point p = tile_loc(image.tile); - map[p.x - min_x][p.y - min_y]++; - } - } - - for (int y = min_y; y <= max_y; y++) { - for (int x = min_x; x <= max_x; x++) - System.out.printf (" %2d", map[x - min_x][y - min_y]); - System.out.printf("\n"); - } - } -*/ - - public static AltosSiteMapImage get_image(AltosSiteMapTile tile, File file, int width, int height) { - int oldest = -1; - long age = used; - - synchronized(cache_lock) { - AltosSiteMapImage image = null; - for (int i = 0; i < cache_size; i++) { - image = images[i]; - - if (image == null) { - oldest = i; - break; - } - if (image.tile == tile && file.equals(image.file)) { - image.used = used++; - return image; - } - if (image.used < age) { - oldest = i; - age = image.used; - } - } - - try { - image = new AltosSiteMapImage(tile, file, width, height); - image.used = used++; - if (images[oldest] != null) { -// dump_cache(); - AltosSiteMap.debug_component(images[oldest].tile, "replacing cache"); - AltosSiteMap.debug_component(tile, "replaced cache"); - images[oldest].flush(); - } - images[oldest] = image; - return image; - } catch (IOException e) { - return null; - } - } - } -} diff --git a/altosuilib/AltosSiteMapImage.java b/altosuilib/AltosSiteMapImage.java deleted file mode 100644 index f1cfa7c0..00000000 --- a/altosuilib/AltosSiteMapImage.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright © 2014 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_2; - -import java.awt.*; -import java.awt.image.*; -import javax.imageio.ImageIO; -import javax.swing.*; -import java.io.*; -import org.altusmetrum.altoslib_4.*; - -public class AltosSiteMapImage { - AltosSiteMapTile tile; - File file; - BufferedImage image; - int width; - int height; - long used; - - Thread load_thread; - - public boolean validate(final int serial) { - if (image != null) { - AltosSiteMap.debug_component(tile, "valid"); - return true; - } else { - AltosSiteMap.debug_component(tile, "loading"); - load_thread = new Thread() { - public void run() { - try { - image = ImageIO.read(file); - } catch (Exception e) { - } - SwingUtilities.invokeLater( new Runnable() { - public void run() { - AltosSiteMap.debug_component(tile, file.toString()); - Graphics2D g2d = (Graphics2D) tile.getGraphics(); - if (g2d != null) - tile.paint_graphics(g2d, image, serial); - load_thread = null; - } - }); - } - }; - load_thread.start(); - return false; - } - } - - public void flush() { - if (load_thread == null) { - AltosSiteMap.debug_component(tile, "flush"); - image.flush(); - image = null; - } - } - - public AltosSiteMapImage (AltosSiteMapTile tile, File file, int w, int h) throws IOException { - this.tile = tile; - this.file = file; - width = w; - height = h; - image = null; - used = 0; - } -} - diff --git a/altosuilib/AltosSiteMapPreload.java b/altosuilib/AltosSiteMapPreload.java deleted file mode 100644 index ed7ecbd3..00000000 --- a/altosuilib/AltosSiteMapPreload.java +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_2; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import java.io.*; -import java.util.*; -import java.text.*; -import java.lang.Math; -import java.net.URL; -import java.net.URLConnection; -import org.altusmetrum.altoslib_4.*; - -class AltosMapPos extends Box { - AltosUIFrame owner; - JLabel label; - JComboBox hemi; - JTextField deg; - JLabel deg_label; - JTextField min; - JLabel min_label; - - public void set_value(double new_value) { - double d, m; - int h; - - h = 0; - if (new_value < 0) { - h = 1; - new_value = -new_value; - } - d = Math.floor(new_value); - deg.setText(String.format("%3.0f", d)); - m = (new_value - d) * 60.0; - min.setText(String.format("%7.4f", m)); - hemi.setSelectedIndex(h); - } - - public double get_value() throws NumberFormatException { - int h = hemi.getSelectedIndex(); - String d_t = deg.getText(); - String m_t = min.getText(); - double d, m, v; - try { - d = Double.parseDouble(d_t); - } catch (NumberFormatException ne) { - JOptionPane.showMessageDialog(owner, - String.format("Invalid degrees \"%s\"", - d_t), - "Invalid number", - JOptionPane.ERROR_MESSAGE); - throw ne; - } - try { - if (m_t.equals("")) - m = 0; - else - m = Double.parseDouble(m_t); - } catch (NumberFormatException ne) { - JOptionPane.showMessageDialog(owner, - String.format("Invalid minutes \"%s\"", - m_t), - "Invalid number", - JOptionPane.ERROR_MESSAGE); - throw ne; - } - v = d + m/60.0; - if (h == 1) - v = -v; - return v; - } - - public AltosMapPos(AltosUIFrame in_owner, - String label_value, - String[] hemi_names, - double default_value) { - super(BoxLayout.X_AXIS); - owner = in_owner; - label = new JLabel(label_value); - hemi = new JComboBox(hemi_names); - hemi.setEditable(false); - deg = new JTextField(5); - deg.setMinimumSize(deg.getPreferredSize()); - deg.setHorizontalAlignment(JTextField.RIGHT); - deg_label = new JLabel("°"); - min = new JTextField(9); - min.setMinimumSize(min.getPreferredSize()); - min_label = new JLabel("'"); - set_value(default_value); - add(label); - add(Box.createRigidArea(new Dimension(5, 0))); - add(hemi); - add(Box.createRigidArea(new Dimension(5, 0))); - add(deg); - add(Box.createRigidArea(new Dimension(5, 0))); - add(deg_label); - add(Box.createRigidArea(new Dimension(5, 0))); - add(min); - add(Box.createRigidArea(new Dimension(5, 0))); - add(min_label); - } -} - -class AltosSite { - String name; - double latitude; - double longitude; - - public String toString() { - return name; - } - - public AltosSite(String in_name, double in_latitude, double in_longitude) { - name = in_name; - latitude = in_latitude; - longitude = in_longitude; - } - - public AltosSite(String line) throws ParseException { - String[] elements = line.split(":"); - - if (elements.length < 3) - throw new ParseException(String.format("Invalid site line %s", line), 0); - - name = elements[0]; - - try { - latitude = Double.parseDouble(elements[1]); - longitude = Double.parseDouble(elements[2]); - } catch (NumberFormatException ne) { - throw new ParseException(String.format("Invalid site line %s", line), 0); - } - } -} - -class AltosSites extends Thread { - AltosSiteMapPreload preload; - URL url; - LinkedList sites; - - void notify_complete() { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - preload.set_sites(); - } - }); - } - - void add(AltosSite site) { - sites.add(site); - } - - void add(String line) { - try { - add(new AltosSite(line)); - } catch (ParseException pe) { - } - } - - public void run() { - try { - URLConnection uc = url.openConnection(); - //int length = uc.getContentLength(); - - InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set); - BufferedReader in = new BufferedReader(in_stream); - - for (;;) { - String line = in.readLine(); - if (line == null) - break; - add(line); - } - } catch (IOException e) { - } finally { - notify_complete(); - } - } - - public AltosSites(AltosSiteMapPreload in_preload) { - sites = new LinkedList(); - preload = in_preload; - try { - url = new URL(AltosLib.launch_sites_url); - } catch (java.net.MalformedURLException e) { - notify_complete(); - } - start(); - } -} - -public class AltosSiteMapPreload extends AltosUIFrame implements ActionListener, ItemListener { - AltosUIFrame owner; - AltosSiteMap map; - - AltosMapPos lat; - AltosMapPos lon; - - JProgressBar pbar; - int pbar_max; - - AltosSites sites; - JLabel site_list_label; - JComboBox site_list; - - JToggleButton load_button; - boolean loading; - JButton close_button; - - JCheckBox[] maptypes = new JCheckBox[AltosSiteMap.maptype_terrain - AltosSiteMap.maptype_hybrid + 1]; - - JComboBox min_zoom; - JComboBox max_zoom; - JComboBox radius; - - Integer[] zooms = { -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 }; - Integer[] radii = { 1, 2, 3, 4, 5 }; - - static final String[] lat_hemi_names = { "N", "S" }; - static final String[] lon_hemi_names = { "E", "W" }; - - class updatePbar implements Runnable { - int n; - String s; - - public updatePbar(int n, String in_s) { - this.n = n; - s = in_s; - } - - public void run() { - pbar.setValue(n); - pbar.setString(s); - if (n < pbar_max) { - pbar.setMaximum(pbar_max); - pbar.setValue(n); - pbar.setString(s); - } else { - pbar.setValue(0); - pbar.setString(""); - load_button.setSelected(false); - loading = false; - } - } - } - - class bgLoad extends Thread { - - AltosSiteMap map; - - double lat, lon; - - int types = 0; - int r; - - int min_z = (Integer) min_zoom.getSelectedItem(); - int max_z = (Integer) max_zoom.getSelectedItem(); - - public bgLoad(AltosSiteMap in_map, double lat, double lon) { - map = in_map; - this.lat = lat; - this.lon = lon; - if (max_z < min_z) - max_z = min_z; - int ntype = 0; - for (int t = AltosSiteMap.maptype_hybrid; t <= AltosSiteMap.maptype_terrain; t++) - if (maptypes[t].isSelected()) { - types |= (1 << t); - ntype++; - } - if (ntype == 0) { - types |= (1 << AltosSiteMap.maptype_hybrid); - ntype = 1; - } - r = (Integer) radius.getSelectedItem(); - pbar_max = (max_z - min_z + 1) * ntype * (r * 2 + 1) * (r * 2 + 1); - } - - public void run() { - int i = 0; - for (int z = min_z; z <= max_z; z++) { - for (int t = AltosSiteMap.maptype_hybrid; t <= AltosSiteMap.maptype_terrain; t++) { - if ((types & (1 << t)) == 0) - continue; - map.clear_base_location(); - map.set_zoom(z + AltosSiteMap.default_zoom); - map.set_maptype(t); - map.set_radius(r); - map.setBaseLocation(lat, lon); - map.draw_circle(lat, lon); - for (int y = -r; y <= r; y++) { - for (int x = -r; x <= r; x++) { - File pngfile; - pngfile = map.init_map(new Point(x,y), - AltosSiteMap.load_mode_cached|AltosSiteMap.load_mode_uncached); - SwingUtilities.invokeLater(new updatePbar(++i, pngfile.toString())); - } - } - } - } - } - } - - public void set_sites() { - int i = 1; - for (AltosSite site : sites.sites) { - site_list.insertItemAt(site, i); - i++; - } - } - - public void itemStateChanged(ItemEvent e) { - int state = e.getStateChange(); - - if (state == ItemEvent.SELECTED) { - Object o = e.getItem(); - if (o instanceof AltosSite) { - AltosSite site = (AltosSite) o; - lat.set_value(site.latitude); - lon.set_value(site.longitude); - } - } - } - - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - - if (cmd.equals("close")) - setVisible(false); - - if (cmd.equals("load")) { - if (!loading) { - try { - final double latitude = lat.get_value(); - final double longitude = lon.get_value(); - map.clear_base_location(); - map.setBaseLocation(latitude,longitude); - map.draw_circle(latitude,longitude); - loading = true; - bgLoad thread = new bgLoad(map, latitude, longitude); - thread.start(); - } catch (NumberFormatException ne) { - load_button.setSelected(false); - } - } - } - } - - public AltosSiteMapPreload(AltosUIFrame in_owner) { - owner = in_owner; - - Container pane = getContentPane(); - GridBagConstraints c = new GridBagConstraints(); - Insets i = new Insets(4,4,4,4); - - setTitle("AltOS Load Maps"); - - pane.setLayout(new GridBagLayout()); - - map = new AltosSiteMap(2); - - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 10; - c.anchor = GridBagConstraints.CENTER; - - pane.add(map, c); - - pbar = new JProgressBar(); - pbar.setMinimum(0); - pbar.setMaximum(1); - pbar.setValue(0); - pbar.setString(""); - pbar.setStringPainted(true); - - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 10; - - pane.add(pbar, c); - - site_list_label = new JLabel ("Known Launch Sites:"); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 0; - c.gridy = 2; - c.gridwidth = 1; - - pane.add(site_list_label, c); - - site_list = new JComboBox(new AltosSite[] { new AltosSite("Site List", 0, 0) }); - site_list.addItemListener(this); - - sites = new AltosSites(this); - - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 1; - c.gridy = 2; - c.gridwidth = 1; - - pane.add(site_list, c); - - lat = new AltosMapPos(owner, - "Latitude:", - lat_hemi_names, - 37.167833333); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 0; - c.weighty = 0; - - c.gridx = 0; - c.gridy = 3; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(lat, c); - - lon = new AltosMapPos(owner, - "Longitude:", - lon_hemi_names, - -97.73975); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 0; - c.weighty = 0; - - c.gridx = 1; - c.gridy = 3; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(lon, c); - - load_button = new JToggleButton("Load Map"); - load_button.addActionListener(this); - load_button.setActionCommand("load"); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 0; - c.gridy = 4; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(load_button, c); - - close_button = new JButton("Close"); - close_button.addActionListener(this); - close_button.setActionCommand("close"); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 0; - - c.gridx = 1; - c.gridy = 4; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - - pane.add(close_button, c); - - JLabel types_label = new JLabel("Map Types"); - c.gridx = 2; - c.gridwidth = 2; - c.gridy = 2; - pane.add(types_label, c); - - c.gridwidth = 1; - - for (int type = AltosSiteMap.maptype_hybrid; type <= AltosSiteMap.maptype_terrain; type++) { - maptypes[type] = new JCheckBox(AltosSiteMap.maptype_labels[type], - type == AltosSiteMap.maptype_hybrid); - c.gridx = 2 + (type >> 1); - c.fill = GridBagConstraints.HORIZONTAL; - c.gridy = (type & 1) + 3; - pane.add(maptypes[type], c); - } - - JLabel min_zoom_label = new JLabel("Minimum Zoom"); - c.gridx = 4; - c.gridy = 2; - pane.add(min_zoom_label, c); - - min_zoom = new JComboBox(zooms); - min_zoom.setSelectedItem(zooms[10]); - min_zoom.setEditable(false); - c.gridx = 5; - c.gridy = 2; - pane.add(min_zoom, c); - - JLabel max_zoom_label = new JLabel("Maximum Zoom"); - c.gridx = 4; - c.gridy = 3; - pane.add(max_zoom_label, c); - - max_zoom = new JComboBox(zooms); - max_zoom.setSelectedItem(zooms[14]); - max_zoom.setEditable(false); - c.gridx = 5; - c.gridy = 3; - pane.add(max_zoom, c); - - JLabel radius_label = new JLabel("Tile Radius"); - c.gridx = 4; - c.gridy = 4; - pane.add(radius_label, c); - - radius = new JComboBox(radii); - radius.setSelectedItem(radii[4]); - radius.setEditable(true); - c.gridx = 5; - c.gridy = 4; - pane.add(radius, c); - - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } -} diff --git a/altosuilib/AltosSiteMapTile.java b/altosuilib/AltosSiteMapTile.java deleted file mode 100644 index f8b924a8..00000000 --- a/altosuilib/AltosSiteMapTile.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_2; - -import java.awt.*; -import java.awt.image.*; -import javax.swing.*; -import javax.imageio.*; -import java.awt.geom.*; -import java.io.*; -import java.util.*; -import java.awt.RenderingHints.*; -import org.altusmetrum.altoslib_4.*; - -class AltosPoint { - Point2D.Double pt; - int state; - - AltosPoint(Point2D.Double pt, int state) { - this.pt = pt; - this.state = state; - } -} - -public class AltosSiteMapTile extends JComponent { - int px_size; - File file; - int status; - - Point2D.Double boost; - Point2D.Double landed; - Line2D.Double line; - double line_course; - double line_dist; - - LinkedList points; - - public synchronized void queue_repaint() { - if (SwingUtilities.isEventDispatchThread()) - repaint(); - else { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - repaint(); - } - }); - } - } - - public void load_map(File pngFile) { - file = pngFile; - queue_repaint(); - } - - private Font font = null; - - public void set_font(Font font) { - this.font = font; - this.status = AltosSiteMapCache.success; - } - - public void set_status(int status) { - if (status != this.status || file != null) { - file = null; - this.status = status; - queue_repaint(); - } - } - - public void clearMap() { - boost = null; - landed = null; - points = null; - file = null; - status = AltosSiteMapCache.success; - line = null; - } - - static Color stateColors[] = { - Color.WHITE, // startup - Color.WHITE, // idle - Color.WHITE, // pad - Color.RED, // boost - Color.PINK, // fast - Color.YELLOW, // coast - Color.CYAN, // drogue - Color.BLUE, // main - Color.BLACK // landed - }; - - private void draw_circle(Graphics g, Point2D.Double pt) { - g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); - g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); - g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); - } - - public void set_boost(Point2D.Double boost) { - this.boost = boost; - queue_repaint(); - } - - public void set_line(Line2D.Double line, double distance) { - this.line = line; - line_dist = distance; - queue_repaint(); - } - - private String line_dist() { - String format; - double distance = line_dist; - - if (AltosConvert.imperial_units) { - distance = AltosConvert.meters_to_feet(distance); - if (distance < 10000) { - format = "%4.0fft"; - } else { - distance /= 5280; - if (distance < 10) - format = "%5.3fmi"; - else if (distance < 100) - format = "%5.2fmi"; - else if (distance < 1000) - format = "%5.1fmi"; - else - format = "%5.0fmi"; - } - } else { - if (distance < 10000) { - format = "%4.0fm"; - } else { - distance /= 1000; - if (distance < 100) - format = "%5.2fkm"; - else if (distance < 1000) - format = "%5.1fkm"; - else - format = "%5.0fkm"; - } - } - return String.format(format, distance); - } - - int painting_serial; - int painted_serial; - - public void paint_graphics(Graphics2D g2d, Image image, int serial) { - - if (serial < painted_serial) - return; - - painted_serial = serial; - - if (image != null) { - AltosSiteMap.debug_component(this, "paint_graphics"); - g2d.drawImage(image, 0, 0, null); - } else { - AltosSiteMap.debug_component(this, "erase_graphics"); - g2d.setColor(Color.GRAY); - g2d.fillRect(0, 0, getWidth(), getHeight()); - String message = null; - switch (status) { - case AltosSiteMapCache.loading: - message = "Loading..."; - break; - case AltosSiteMapCache.bad_request: - message = "Internal error"; - break; - case AltosSiteMapCache.failed: - message = "Network error, check connection"; - break; - case AltosSiteMapCache.forbidden: - message = "Too many requests, try later"; - break; - } - if (message != null && font != null) { - g2d.setFont(font); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - Rectangle2D bounds; - bounds = font.getStringBounds(message, g2d.getFontRenderContext()); - - float x = getWidth() / 2.0f; - float y = getHeight() / 2.0f; - x = x - (float) bounds.getWidth() / 2.0f; - y = y + (float) bounds.getHeight() / 2.0f; - g2d.setColor(Color.BLACK); - g2d.drawString(message, x, y); - } - } - - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - - if (points != null) { - AltosPoint prev = null; - for (AltosPoint point : points) { - if (prev != null) { - if (0 <= point.state && point.state < stateColors.length) - g2d.setColor(stateColors[point.state]); - g2d.draw(new Line2D.Double(prev.pt, point.pt)); - } - prev = point; - } - } - if (boost != null) { - g2d.setColor(Color.RED); - draw_circle(g2d, boost); - } - if (landed != null) { - g2d.setColor(Color.BLACK); - draw_circle(g2d, landed); - } - - if (line != null) { - g2d.setColor(Color.BLUE); - g2d.draw(line); - - String message = line_dist(); - g2d.setFont(font); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - Rectangle2D bounds; - bounds = font.getStringBounds(message, g2d.getFontRenderContext()); - - float x = (float) line.x1; - float y = (float) line.y1 + (float) bounds.getHeight() / 2.0f; - - if (line.x1 < line.x2) { - x -= (float) bounds.getWidth() + 2.0f; - } else { - x += 2.0f; - } - g2d.drawString(message, x, y); - } - } - - public void paint(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - Image image = null; - boolean queued = false; - - AltosSiteMap.debug_component(this, "paint"); - - ++painting_serial; - - if (file != null) { - AltosSiteMapImage aimage; - - aimage = AltosSiteMapCache.get_image(this, file, px_size, px_size); - if (aimage != null) { - if (aimage.validate(painting_serial)) - image = aimage.image; - else - queued = true; - } - } - if (!queued) - paint_graphics(g2d, image, painting_serial); - } - - public void show(int state, Point2D.Double last_pt, Point2D.Double pt) - { - if (points == null) - points = new LinkedList(); - - points.add(new AltosPoint(pt, state)); - - if (state == AltosLib.ao_flight_boost && boost == null) - boost = pt; - if (state == AltosLib.ao_flight_landed && landed == null) - landed = pt; - queue_repaint(); - } - - public AltosSiteMapTile(int in_px_size) { - px_size = in_px_size; - setPreferredSize(new Dimension(px_size, px_size)); - } -} -- cgit v1.2.3 From bfc0c65c9f9ec9547d71016fc897ba35bdb414f8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jun 2014 20:36:49 -0700 Subject: altosuilib: Handle font and units changes in maps and stats table Add AltosFontListener and AltosUnitsListener bits as needed Signed-off-by: Keith Packard --- altosui/AltosGraphUI.java | 25 +++++++++++++++++++++++-- altosuilib/AltosFlightStatsTable.java | 33 ++++++++++++++++++++++++--------- altosuilib/AltosUIMap.java | 2 +- altosuilib/AltosUIMapView.java | 5 +++++ 4 files changed, 53 insertions(+), 12 deletions(-) (limited to 'altosuilib') diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 0df92eae..07fe9317 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -21,6 +21,7 @@ import java.io.*; import java.util.ArrayList; import java.awt.*; +import java.awt.event.*; import javax.swing.*; import org.altusmetrum.altoslib_4.*; import org.altusmetrum.altosuilib_2.*; @@ -29,7 +30,7 @@ import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.ui.RefineryUtilities; -public class AltosGraphUI extends AltosUIFrame +public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener { JTabbedPane pane; AltosGraph graph; @@ -53,6 +54,15 @@ public class AltosGraphUI extends AltosUIFrame } } + public void font_size_changed(int font_size) { + map.font_size_changed(font_size); + statsTable.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + map.units_changed(imperial_units); + } + AltosGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException { super(file.getName()); state = null; @@ -79,9 +89,20 @@ public class AltosGraphUI extends AltosUIFrame setContentPane (pane); + AltosUIPreferences.register_font_listener(this); + AltosPreferences.register_units_listener(this); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + setVisible(false); + dispose(); + AltosUIPreferences.unregister_font_listener(AltosGraphUI.this); + AltosPreferences.unregister_units_listener(AltosGraphUI.this); + } + }); pack(); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); setVisible(true); if (state != null && has_gps) map.centre(state); diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java index ec106cf1..b32e92a0 100644 --- a/altosuilib/AltosFlightStatsTable.java +++ b/altosuilib/AltosFlightStatsTable.java @@ -19,14 +19,23 @@ package org.altusmetrum.altosuilib_2; import java.awt.*; import javax.swing.*; +import java.util.*; import org.altusmetrum.altoslib_4.*; -public class AltosFlightStatsTable extends JComponent { +public class AltosFlightStatsTable extends JComponent implements AltosFontListener { GridBagLayout layout; - class FlightStat { + LinkedList flight_stats = new LinkedList(); + + class FlightStat implements AltosFontListener { JLabel label; - JTextField value; + JTextField[] value; + + public void font_size_changed(int font_size) { + label.setFont(AltosUILib.label_font); + for (int i = 0; i < value.length; i++) + value[i].setFont(AltosUILib.value_font); + } public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) { GridBagConstraints c = new GridBagConstraints(); @@ -43,21 +52,28 @@ public class AltosFlightStatsTable extends JComponent { layout.setConstraints(label, c); add(label); + value = new JTextField[values.length]; for (int j = 0; j < values.length; j++) { - value = new JTextField(values[j]); - value.setFont(AltosUILib.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); + value[j] = new JTextField(values[j]); + value[j].setFont(AltosUILib.value_font); + value[j].setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = j+1; c.gridy = y; c.anchor = GridBagConstraints.EAST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; - layout.setConstraints(value, c); - add(value); + layout.setConstraints(value[j], c); + add(value[j]); } + flight_stats.add(this); } } + public void font_size_changed(int font_size) { + for (FlightStat f : flight_stats) + f.font_size_changed(font_size); + } + static String pos(double p, String pos, String neg) { String h = pos; if (p < 0) { @@ -147,5 +163,4 @@ public class AltosFlightStatsTable extends JComponent { pos(stats.lon,"E","W")); } } - } diff --git a/altosuilib/AltosUIMap.java b/altosuilib/AltosUIMap.java index fa974d36..91087469 100644 --- a/altosuilib/AltosUIMap.java +++ b/altosuilib/AltosUIMap.java @@ -74,7 +74,7 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosU } public void units_changed(boolean imperial_units) { - repaint(); + view.set_units(); } JLabel zoom_label; diff --git a/altosuilib/AltosUIMapView.java b/altosuilib/AltosUIMapView.java index c558118b..edae3e1e 100644 --- a/altosuilib/AltosUIMapView.java +++ b/altosuilib/AltosUIMapView.java @@ -68,6 +68,11 @@ public class AltosUIMapView extends Canvas implements MouseMotionListener, Mouse line.set_font(AltosUILib.value_font); for (AltosUIMapTile tile : tiles.values()) tile.set_font(AltosUILib.value_font); + repaint(); + } + + public void set_units() { + repaint(); } private boolean is_drag_event(MouseEvent e) { -- cgit v1.2.3 From 6f306b267f63d0f59fb77b1ce41c678042dd6802 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jun 2014 23:04:46 -0700 Subject: altosuilib: Repaint map when starting line draw Starting line draw will remove any existing line, so repaint to get rid of it Signed-off-by: Keith Packard --- altosuilib/AltosUIMapView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosUIMapView.java b/altosuilib/AltosUIMapView.java index edae3e1e..70198682 100644 --- a/altosuilib/AltosUIMapView.java +++ b/altosuilib/AltosUIMapView.java @@ -134,8 +134,10 @@ public class AltosUIMapView extends Canvas implements MouseMotionListener, Mouse notice_user_input(); if (is_drag_event(e)) drag_start(e); - else + else { line.pressed(e, transform); + repaint(); + } } public void mouseReleased(MouseEvent e) { -- cgit v1.2.3 From 8044eb8e23366e91c741060939baff5137f841c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Jun 2014 14:12:08 -0700 Subject: altosui/telegps: Reduce CPU time needed for flight displays Don't update displays which aren't shown; track hierarchy changes to trigger display from most recent state data. Don't update values which haven't changed; remember previous values and compare with new before updating widget contents. Signed-off-by: Keith Packard --- altosui/AltosAscent.java | 45 ++++++++++++---- altosui/AltosDescent.java | 35 ++++++++++++- altosui/AltosFlightStatus.java | 83 ++++++++++++++++++++++------- altosui/AltosIgnitor.java | 1 + altosui/AltosLanded.java | 30 ++++++++++- altosui/AltosPad.java | 116 +++++++++++++++++++++++++---------------- altosuilib/AltosInfoTable.java | 25 ++++++++- altosuilib/AltosUIMapView.java | 3 +- telegps/TeleGPSInfo.java | 46 ++++++++++++---- telegps/TeleGPSStatus.java | 46 ++++++++++++---- 10 files changed, 326 insertions(+), 104 deletions(-) (limited to 'altosuilib') diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index fb05fe11..c3225709 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -18,14 +18,18 @@ package altosui; import java.awt.*; +import java.awt.event.*; import javax.swing.*; import org.altusmetrum.altoslib_4.*; import org.altusmetrum.altosuilib_2.*; -public class AltosAscent extends JComponent implements AltosFlightDisplay { +public class AltosAscent extends JComponent implements AltosFlightDisplay, HierarchyListener { GridBagLayout layout; JLabel cur, max; + private AltosState last_state; + private AltosListenerState last_listener_state; + public class AscentStatus implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; @@ -101,6 +105,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -176,6 +181,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -215,22 +221,21 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } public void units_changed(boolean imperial_units) { - show(v); + show(v, max); } - void show(double v) { + void show(double v, double max) { this.v = v; + this.max = max; if (v == AltosLib.MISSING) { value.setText("Missing"); } else { value.setText(units.show(8, v)); - if (v > max || max == AltosLib.MISSING) - max = v; } if (max == AltosLib.MISSING) max_value.setText("Missing"); else - max_value.setText(units.show(8, v)); + max_value.setText(units.show(8, max)); } void hide() { @@ -256,6 +261,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -266,6 +272,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { add(value); max_value = new JTextField(Altos.text_width); + max_value.setEditable(false); max_value.setFont(Altos.value_font); max_value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 3; c.gridy = y; @@ -279,7 +286,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Height extends AscentValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(state.height()); + show(state.height(), state.max_height()); } public Height (GridBagLayout layout, int y) { super (layout, y, AltosConvert.height, "Height"); @@ -290,7 +297,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Speed extends AscentValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(state.speed()); + show(state.speed(), state.max_speed()); } public Speed (GridBagLayout layout, int y) { super (layout, y, AltosConvert.speed, "Speed"); @@ -301,7 +308,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Accel extends AscentValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(state.acceleration()); + show(state.acceleration(), state.max_acceleration()); } public Accel (GridBagLayout layout, int y) { super (layout, y, AltosConvert.accel, "Acceleration"); @@ -312,7 +319,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Orient extends AscentValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(state.orient()); + show(state.orient(), state.max_orient()); } public Orient (GridBagLayout layout, int y) { super (layout, y, AltosConvert.orient, "Tilt Angle"); @@ -420,6 +427,12 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, AltosListenerState listener_state) { + if (!isShowing()) { + last_state = state; + last_listener_state = listener_state; + return; + } + if (state.gps != null && state.gps.connected) { lat.show(state, listener_state); lon.show(state, listener_state); @@ -466,6 +479,17 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { return "Ascent"; } + public void hierarchyChanged(HierarchyEvent e) { + if (last_state != null && isShowing()) { + AltosState state = last_state; + AltosListenerState listener_state = last_listener_state; + + last_state = null; + last_listener_state = null; + show(state, listener_state); + } + } + public AltosAscent() { layout = new GridBagLayout(); @@ -487,5 +511,6 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { lon = new Lon(layout, y++); apogee = new Apogee(layout, y++); main = new Main(layout, y++); + addHierarchyListener(this); } } diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index b56a08bc..11bd6dbf 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -18,13 +18,17 @@ package altosui; import java.awt.*; +import java.awt.event.*; import javax.swing.*; import org.altusmetrum.altoslib_4.*; import org.altusmetrum.altosuilib_2.*; -public class AltosDescent extends JComponent implements AltosFlightDisplay { +public class AltosDescent extends JComponent implements AltosFlightDisplay, HierarchyListener { GridBagLayout layout; + private AltosState last_state; + private AltosListenerState last_listener_state; + public abstract class DescentStatus implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; @@ -91,6 +95,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 4; c.gridy = y; @@ -109,6 +114,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { JTextField value; AltosUnits units; double v; + String last_value = ""; void reset() { value.setText(""); @@ -128,7 +134,11 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { void show(String v) { show(); - value.setText(v); + + if (!last_value.equals(v)) { + value.setText(v); + last_value = v; + } } void show(double v) { @@ -172,6 +182,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { add(label, c); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = x + 2; c.gridy = y; @@ -247,6 +258,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { add(label); value1 = new JTextField(Altos.text_width); + value1.setEditable(false); value1.setFont(Altos.value_font); value1.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = x + 2; c.gridy = y; @@ -257,6 +269,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { add(value1); value2 = new JTextField(Altos.text_width); + value2.setEditable(false); value2.setFont(Altos.value_font); value2.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = x + 4; c.gridy = y; @@ -449,6 +462,12 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, AltosListenerState listener_state) { + if (!isShowing()) { + last_state = state; + last_listener_state = listener_state; + return; + } + height.show(state, listener_state); speed.show(state, listener_state); if (state.gps != null && state.gps.connected) { @@ -480,6 +499,17 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { return "Descent"; } + public void hierarchyChanged(HierarchyEvent e) { + if (last_state != null && isShowing()) { + AltosState state = last_state; + AltosListenerState listener_state = last_listener_state; + + last_state = null; + last_listener_state = null; + show(state, listener_state); + } + } + public AltosDescent() { layout = new GridBagLayout(); @@ -497,5 +527,6 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { apogee = new Apogee(layout, 5); main = new Main(layout, 6); + addHierarchyListener(this); } } diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 459b0495..b27deba9 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -61,6 +61,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay add(label); value = new JTextField(""); + value.setEditable(false); value.setFont(Altos.status_font); value.setHorizontalAlignment(SwingConstants.CENTER); c.gridx = x; c.gridy = 1; @@ -70,12 +71,25 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay } class Call extends FlightValue { - void show(AltosState state, AltosListenerState listener_state) { - value.setText(state.callsign); - if (state.callsign == null) - setVisible(false); + + String last_call = ""; + + boolean same_call(String call) { + if (last_call == null) + return call == null; else - setVisible(true); + return last_call.equals(call); + } + + void show(AltosState state, AltosListenerState listener_state) { + if (!same_call(state.callsign)) { + value.setText(state.callsign); + if (state.callsign == null) + setVisible(false); + else + setVisible(true); + last_call = state.callsign; + } } public Call (GridBagLayout layout, int x) { super (layout, x, "Callsign"); @@ -85,11 +99,16 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay Call call; class Serial extends FlightValue { + + int last_serial = -1; void show(AltosState state, AltosListenerState listener_state) { - if (state.serial == AltosLib.MISSING) - value.setText("none"); - else - value.setText(String.format("%d", state.serial)); + if (state.serial != last_serial) { + if (state.serial == AltosLib.MISSING) + value.setText("none"); + else + value.setText(String.format("%d", state.serial)); + last_serial = state.serial; + } } public Serial (GridBagLayout layout, int x) { super (layout, x, "Serial"); @@ -99,11 +118,17 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay Serial serial; class Flight extends FlightValue { + + int last_flight = -1; + void show(AltosState state, AltosListenerState listener_state) { - if (state.flight == AltosLib.MISSING) - value.setText("none"); - else - value.setText(String.format("%d", state.flight)); + if (state.flight != last_flight) { + if (state.flight == AltosLib.MISSING) + value.setText("none"); + else + value.setText(String.format("%d", state.flight)); + last_flight = state.flight; + } } public Flight (GridBagLayout layout, int x) { super (layout, x, "Flight"); @@ -113,8 +138,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay Flight flight; class FlightState extends FlightValue { + + int last_state = -1; + void show(AltosState state, AltosListenerState listener_state) { - value.setText(state.state_name()); + if (state.state != last_state) { + value.setText(state.state_name()); + last_state = state.state; + } } public FlightState (GridBagLayout layout, int x) { super (layout, x, "State"); @@ -124,12 +155,18 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay FlightState flight_state; class RSSI extends FlightValue { + + int last_rssi = 10000; + void show(AltosState state, AltosListenerState listener_state) { - value.setText(String.format("%d", state.rssi())); - if (state.rssi == AltosLib.MISSING) - setVisible(false); - else - setVisible(true); + if (state.rssi() != last_rssi) { + value.setText(String.format("%d", state.rssi())); + if (state.rssi == AltosLib.MISSING) + setVisible(false); + else + setVisible(true); + last_rssi = state.rssi(); + } } public RSSI (GridBagLayout layout, int x) { super (layout, x, "RSSI"); @@ -139,9 +176,15 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay RSSI rssi; class LastPacket extends FlightValue { + + long last_secs = -1; + void show(AltosState state, AltosListenerState listener_state) { long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000; - value.setText(String.format("%d", secs)); + if (secs != last_secs) { + value.setText(String.format("%d", secs)); + last_secs = secs; + } } public LastPacket(GridBagLayout layout, int x) { super (layout, x, "Age"); diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java index 7f62938d..73318117 100644 --- a/altosui/AltosIgnitor.java +++ b/altosui/AltosIgnitor.java @@ -102,6 +102,7 @@ public class AltosIgnitor extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index d2628fb0..760b2d64 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -24,14 +24,18 @@ import java.io.*; import org.altusmetrum.altoslib_4.*; import org.altusmetrum.altosuilib_2.*; -public class AltosLanded extends JComponent implements AltosFlightDisplay, ActionListener { +public class AltosLanded extends JComponent implements AltosFlightDisplay, ActionListener, HierarchyListener { GridBagLayout layout; + private AltosState last_state; + private AltosListenerState last_listener_state; + public abstract class LandedValue implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; AltosUnits units; double v; + String last_value = ""; abstract void show(AltosState state, AltosListenerState listener_state); @@ -46,7 +50,10 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio void show(String s) { show(); - value.setText(s); + if (!last_value.equals(s)) { + value.setText(s); + last_value = s; + } } void show(double v) { @@ -94,6 +101,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio add(label); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; @@ -244,6 +252,12 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio } public void show(AltosState state, AltosListenerState listener_state) { + if (!isShowing()) { + last_state = state; + last_listener_state = listener_state; + return; + } + if (state.gps != null && state.gps.connected) { bearing.show(state, listener_state); distance.show(state, listener_state); @@ -302,6 +316,17 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio return "Landed"; } + public void hierarchyChanged(HierarchyEvent e) { + if (last_state != null && isShowing()) { + AltosState state = last_state; + AltosListenerState listener_state = last_listener_state; + + last_state = null; + last_listener_state = null; + show(state, listener_state); + } + } + public AltosLanded(AltosFlightReader in_reader) { layout = new GridBagLayout(); @@ -332,5 +357,6 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio c.weighty = 0; c.fill = GridBagConstraints.VERTICAL; add(graph, c); + addHierarchyListener(this); } } diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index ce1f2ab7..3294949c 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -98,6 +98,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -178,6 +179,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(Altos.text_width); + value.setEditable(false); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -193,50 +195,56 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } } - class Battery extends LaunchStatus { + class Voltage extends LaunchStatus { + + double voltage(AltosState state) { return AltosLib.MISSING; }; + double good() { return 0; }; + + double last_voltage = -1; + void show (AltosState state, AltosListenerState listener_state) { - if (state == null || state.battery_voltage == AltosLib.MISSING) - hide(); - else { - show("%4.2f V", state.battery_voltage); - lights.set(state.battery_voltage >= AltosLib.ao_battery_good); + double voltage = AltosLib.MISSING; + if (state != null) + voltage = voltage(state); + + if (voltage != last_voltage) { + if (voltage == AltosLib.MISSING) + hide(); + else { + show("%4.2f V", voltage); + lights.set(voltage >= good()); + } + last_voltage = voltage; } } + public Voltage (GridBagLayout layout, int y, String name) { super(layout, y, name); } + } + + + class Battery extends Voltage { + double voltage(AltosState state) { return state.battery_voltage; } + double good() { return AltosLib.ao_battery_good; } + public Battery (GridBagLayout layout, int y) { super(layout, y, "Battery Voltage"); } + } Battery battery; - class Apogee extends LaunchStatus { - void show (AltosState state, AltosListenerState listener_state) { - if (state == null || state.apogee_voltage == AltosLib.MISSING) - hide(); - else { - show("%4.2f V", state.apogee_voltage); - lights.set(state.apogee_voltage >= AltosLib.ao_igniter_good); - } - } - public Apogee (GridBagLayout layout, int y) { - super(layout, y, "Apogee Igniter Voltage"); - } + class Apogee extends Voltage { + double voltage(AltosState state) { return state.apogee_voltage; } + double good() { return AltosLib.ao_igniter_good; } + public Apogee (GridBagLayout layout, int y) { super(layout, y, "Apogee Igniter Voltage"); } } Apogee apogee; - class Main extends LaunchStatus { - void show (AltosState state, AltosListenerState listener_state) { - if (state == null || state.main_voltage == AltosLib.MISSING) - hide(); - else { - show("%4.2f V", state.main_voltage); - lights.set(state.main_voltage >= AltosLib.ao_igniter_good); - } - } - public Main (GridBagLayout layout, int y) { - super(layout, y, "Main Igniter Voltage"); - } + class Main extends Voltage { + double voltage(AltosState state) { return state.main_voltage; } + double good() { return AltosLib.ao_igniter_good; } + public Main (GridBagLayout layout, int y) { super(layout, y, "Main Igniter Voltage"); } } Main main; @@ -328,6 +336,9 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } class PadLat extends LaunchValue { + + double last_lat = 1000; + void show (AltosState state, AltosListenerState listener_state) { double lat = AltosLib.MISSING; String label = null; @@ -341,11 +352,14 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { label = "Pad Latitude"; } } - if (lat != AltosLib.MISSING) { - show(pos(lat,"N", "S")); - set_label(label); - } else - hide(); + if (lat != last_lat) { + if (lat != AltosLib.MISSING) { + show(pos(lat,"N", "S")); + set_label(label); + } else + hide(); + last_lat = lat; + } } public PadLat (GridBagLayout layout, int y) { super (layout, y, "Pad Latitude"); @@ -355,6 +369,9 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { PadLat pad_lat; class PadLon extends LaunchValue { + + double last_lon = 1000; + void show (AltosState state, AltosListenerState listener_state) { double lon = AltosLib.MISSING; String label = null; @@ -368,11 +385,14 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { label = "Pad Longitude"; } } - if (lon != AltosLib.MISSING) { - show(pos(lon,"E", "W")); - set_label(label); - } else - hide(); + if (lon != last_lon) { + if (lon != AltosLib.MISSING) { + show(pos(lon,"E", "W")); + set_label(label); + } else + hide(); + last_lon = lon; + } } public PadLon (GridBagLayout layout, int y) { super (layout, y, "Pad Longitude"); @@ -382,6 +402,9 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { PadLon pad_lon; class PadAlt extends LaunchValue { + + double last_alt = -1000000; + void show (AltosState state, AltosListenerState listener_state) { double alt = AltosLib.MISSING; String label = null; @@ -395,11 +418,14 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { label = "Pad Altitude"; } } - if (alt != AltosLib.MISSING) { - show(alt); - set_label(label); - } else - hide(); + if (alt != last_alt) { + if (alt != AltosLib.MISSING) { + show(alt); + set_label(label); + } else + hide(); + last_alt = alt; + } } public PadAlt (GridBagLayout layout, int y) { super (layout, y, AltosConvert.height, "Pad Altitude"); diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java index 24a895eb..8ded1bea 100644 --- a/altosuilib/AltosInfoTable.java +++ b/altosuilib/AltosInfoTable.java @@ -18,16 +18,20 @@ package org.altusmetrum.altosuilib_2; import java.awt.*; +import java.awt.event.*; import javax.swing.*; import javax.swing.table.*; import org.altusmetrum.altoslib_4.*; -public class AltosInfoTable extends JTable implements AltosFlightDisplay { +public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener { private AltosFlightInfoTableModel model; static final int info_columns = 3; static final int info_rows = 17; + private AltosState last_state; + private AltosListenerState last_listener_state; + int desired_row_height() { FontMetrics infoValueMetrics = getFontMetrics(AltosUILib.table_value_font); return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; @@ -56,6 +60,7 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay { super(new AltosFlightInfoTableModel(info_rows, info_columns)); model = (AltosFlightInfoTableModel) getModel(); setFont(AltosUILib.table_value_font); + addHierarchyListener(this); setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); setShowGrid(true); set_layout(); @@ -71,6 +76,17 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay { public void units_changed(boolean imperial_units) { } + public void hierarchyChanged(HierarchyEvent e) { + if (last_state != null && isShowing()) { + AltosState state = last_state; + AltosListenerState listener_state = last_listener_state; + + last_state = null; + last_listener_state = null; + show(state, listener_state); + } + } + public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } @@ -108,6 +124,13 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay { } public void show(AltosState state, AltosListenerState listener_state) { + + if (!isShowing()) { + last_state = state; + last_listener_state = listener_state; + return; + } + reset(); if (state != null) { if (state.device_type != AltosLib.MISSING) diff --git a/altosuilib/AltosUIMapView.java b/altosuilib/AltosUIMapView.java index 70198682..efae3767 100644 --- a/altosuilib/AltosUIMapView.java +++ b/altosuilib/AltosUIMapView.java @@ -28,7 +28,7 @@ import java.util.*; import java.util.concurrent.*; import org.altusmetrum.altoslib_4.*; -public class AltosUIMapView extends Canvas implements MouseMotionListener, MouseListener, MouseWheelListener, ComponentListener, AltosUIMapTileListener, AltosUIMapStoreListener { +public class AltosUIMapView extends Component implements MouseMotionListener, MouseListener, MouseWheelListener, ComponentListener, AltosUIMapTileListener, AltosUIMapStoreListener { AltosUIMapPath path = new AltosUIMapPath(); @@ -422,7 +422,6 @@ public class AltosUIMapView extends Canvas implements MouseMotionListener, Mouse } public void paint(Graphics g) { - VolatileImage back_buffer = create_back_buffer(); do { GraphicsConfiguration gc = getGraphicsConfiguration(); diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java index 2765f5ab..15eb9b75 100644 --- a/telegps/TeleGPSInfo.java +++ b/telegps/TeleGPSInfo.java @@ -18,14 +18,18 @@ package org.altusmetrum.telegps; import java.awt.*; +import java.awt.event.*; import javax.swing.*; import org.altusmetrum.altoslib_4.*; import org.altusmetrum.altosuilib_2.*; -public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { +public class TeleGPSInfo extends JComponent implements AltosFlightDisplay, HierarchyListener { GridBagLayout layout; JLabel cur, max; + private AltosState last_state; + private AltosListenerState last_listener_state; + public abstract class Info implements AltosFontListener, AltosUnitsListener { JLabel label; JTextField value; @@ -280,6 +284,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { value1 = new JTextField(AltosUILib.text_width); value1.setFont(AltosUILib.value_font); value1.setHorizontalAlignment(SwingConstants.RIGHT); + value1.setEditable(false); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; @@ -290,6 +295,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { value2 = new JTextField(AltosUILib.text_width); value2.setFont(AltosUILib.value_font); value2.setHorizontalAlignment(SwingConstants.RIGHT); + value1.setEditable(false); c.gridx = 3; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; @@ -323,18 +329,16 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { } public void units_changed(boolean imperial_units) { - show(v); + show(v, max); } - void show(double v) { + void show(double v, double max) { this.v = v; - if (v == AltosLib.MISSING) { + this.max = max; + if (v == AltosLib.MISSING) value.setText("Missing"); - } else { + else value.setText(units.show(8, v)); - if (v > max || max == AltosLib.MISSING) - max = v; - } if (max == AltosLib.MISSING) max_value.setText("Missing"); else @@ -364,6 +368,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(AltosUILib.text_width); + value.setEditable(false); value.setFont(AltosUILib.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -374,6 +379,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { add(value); max_value = new JTextField(AltosUILib.text_width); + max_value.setEditable(false); max_value.setFont(AltosUILib.value_font); max_value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 3; c.gridy = y; @@ -388,7 +394,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { class Altitude extends ValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(state.altitude()); + show(state.altitude(), state.max_altitude()); } public Altitude (GridBagLayout layout, int y) { super (layout, y, AltosConvert.height, "Altitude"); @@ -399,7 +405,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { class AscentRate extends ValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(state.gps_ascent_rate()); + show(state.gps_ascent_rate(), state.max_gps_ascent_rate()); } public AscentRate (GridBagLayout layout, int y) { super (layout, y, AltosConvert.speed, "Ascent Rate"); @@ -410,7 +416,7 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { class GroundSpeed extends ValueHold { void show (AltosState state, AltosListenerState listener_state) { - show(state.gps_ground_speed()); + show(state.gps_ground_speed(), state.max_gps_ground_speed()); } public GroundSpeed (GridBagLayout layout, int y) { super (layout, y, AltosConvert.speed, "Ground Speed"); @@ -526,6 +532,12 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, AltosListenerState listener_state) { + if (!isShowing()) { + last_state = state; + last_listener_state = listener_state; + return; + } + if (state.gps != null && state.gps.connected) { lat.show(state, listener_state); lon.show(state, listener_state); @@ -562,6 +574,17 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { return "Info"; } + public void hierarchyChanged(HierarchyEvent e) { + if (last_state != null && isShowing()) { + AltosState state = last_state; + AltosListenerState listener_state = last_listener_state; + + last_state = null; + last_listener_state = null; + show(state, listener_state); + } + } + public TeleGPSInfo() { layout = new GridBagLayout(); @@ -582,5 +605,6 @@ public class TeleGPSInfo extends JComponent implements AltosFlightDisplay { lat = new Lat(layout, y++); lon = new Lon(layout, y++); gps_locked = new GPSLocked(layout, y++); + addHierarchyListener(this); } } diff --git a/telegps/TeleGPSStatus.java b/telegps/TeleGPSStatus.java index 37cfae37..e6bb1ea5 100644 --- a/telegps/TeleGPSStatus.java +++ b/telegps/TeleGPSStatus.java @@ -61,6 +61,7 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(""); + value.setEditable(false); value.setFont(AltosUILib.status_font); value.setHorizontalAlignment(SwingConstants.CENTER); c.gridx = x; c.gridy = 1; @@ -70,8 +71,13 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { } class Call extends Value { + String call; + void show(AltosState state, AltosListenerState listener_state) { - value.setText(state.callsign); + if (state.callsign != call) { + value.setText(state.callsign); + call = state.callsign; + } if (state.callsign == null) setVisible(false); else @@ -85,11 +91,15 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { Call call; class Serial extends Value { + int serial = -1; void show(AltosState state, AltosListenerState listener_state) { - if (state.serial == AltosLib.MISSING) - value.setText("none"); - else - value.setText(String.format("%d", state.serial)); + if (state.serial != serial) { + if (state.serial == AltosLib.MISSING) + value.setText("none"); + else + value.setText(String.format("%d", state.serial)); + serial = state.serial; + } } public Serial (GridBagLayout layout, int x) { super (layout, x, "Serial"); @@ -99,12 +109,19 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { Serial serial; class RSSI extends Value { + int rssi = 10000; + void show(AltosState state, AltosListenerState listener_state) { - value.setText(String.format("%d", state.rssi())); - if (state.rssi == AltosLib.MISSING) - setVisible(false); - else - setVisible(true); + int new_rssi = state.rssi(); + + if (new_rssi != rssi) { + value.setText(String.format("%d", new_rssi)); + if (state.rssi == AltosLib.MISSING) + setVisible(false); + else + setVisible(true); + rssi = new_rssi; + } } public RSSI (GridBagLayout layout, int x) { super (layout, x, "RSSI"); @@ -114,9 +131,16 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { RSSI rssi; class LastPacket extends Value { + + long last_secs = -1; + void show(AltosState state, AltosListenerState listener_state) { long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000; - value.setText(String.format("%d", secs)); + + if (secs != last_secs) { + value.setText(String.format("%d", secs)); + last_secs = secs; + } } public LastPacket(GridBagLayout layout, int x) { super (layout, x, "Age"); -- cgit v1.2.3 From 7ed63b6c3d5878a59f52f4114b5b01942735805f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Jun 2014 15:20:20 -0700 Subject: altosuilib: Build some common classes for displaying values in flight window Right now, all of the flight displays have piles of custom code for displaying values. These new widgets should be able to replace most of that. Signed-off-by: Keith Packard --- altosuilib/AltosUIIndicator.java | 159 ++++++++++++++++++++++++++++++++ altosuilib/AltosUIMap.java | 4 + altosuilib/AltosUIUnitsIndicator.java | 79 ++++++++++++++++ altosuilib/AltosUIVoltageIndicator.java | 42 +++++++++ altosuilib/Makefile.am | 5 +- 5 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 altosuilib/AltosUIIndicator.java create mode 100644 altosuilib/AltosUIUnitsIndicator.java create mode 100644 altosuilib/AltosUIVoltageIndicator.java (limited to 'altosuilib') diff --git a/altosuilib/AltosUIIndicator.java b/altosuilib/AltosUIIndicator.java new file mode 100644 index 00000000..59fe231b --- /dev/null +++ b/altosuilib/AltosUIIndicator.java @@ -0,0 +1,159 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener { + JLabel label; + JTextField[] values; + AltosLights lights; + int number_values; + boolean has_lights; + int value_width; + + abstract public void show(AltosState state, AltosListenerState listener_state); + + public void set_lights(boolean on) { + lights.set(on); + } + + public void setVisible(boolean visible) { + if (lights != null) + lights.setVisible(visible); + label.setVisible(visible); + for (int i = 0; i < values.length; i++) + values[i].setVisible(visible); + } + + public void reset() { + for (int i = 0; i < values.length; i++) + values[i].setText(""); + if (lights != null) + lights.set(false); + } + + public void show() { + if (lights != null) + lights.setVisible(true); + label.setVisible(true); + for (int i = 0; i < values.length; i++) + values[i].setVisible(true); + } + + public void show(String... s) { + int n = Math.min(s.length, values.length); + show(); + for (int i = 0; i < n; i++) + values[i].setText(s[i]); + } + + public void show(String format, double value) { + show(String.format(format, value)); + } + + public void show(String format, int value) { + show(String.format(format, value)); + } + + public void show(String format1, double value1, String format2, double value2) { + show(String.format(format1, value1), String.format(format2, value2)); + } + + public void show(String format1, int value1, String format2, int value2) { + show(String.format(format1, value1), String.format(format2, value2)); + } + + public void hide() { + if (lights != null) + lights.setVisible(false); + label.setVisible(false); + for (int i = 0; i < values.length; i++) + values[i].setVisible(false); + } + + public void font_size_changed(int font_size) { + label.setFont(AltosUILib.label_font); + for (int i = 0; i < values.length; i++) + values[i].setFont(AltosUILib.value_font); + } + + public void units_changed(boolean imperial_units) { + } + + public void set_label(String text) { + label.setText(text); + } + + public AltosUIIndicator (Container container, int y, String text, int number_values, boolean has_lights, int value_width) { + GridBagLayout layout = (GridBagLayout)(container.getLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + if (has_lights) { + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + container.add(lights); + } + + label = new JLabel(text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + container.add(label); + + values = new JTextField[number_values]; + for (int i = 0; i < values.length; i++) { + values[i] = new JTextField(AltosUILib.text_width); + values[i].setEditable(false); + values[i].setFont(AltosUILib.value_font); + values[i].setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2 + i; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.gridwidth = value_width; + layout.setConstraints(values[i], c); + container.add(values[i]); + } + } + + public AltosUIIndicator (Container container, int y, String text) { + this(container, y, text, 1, false, 1); + } + + public AltosUIIndicator (Container container, int y, String text, int number_values) { + this(container, y, text, number_values, false, 1); + } + + public AltosUIIndicator (Container container, int y, String text, int number_values, boolean has_lights) { + this(container, y, text, number_values, has_lights, 1); + } +} diff --git a/altosuilib/AltosUIMap.java b/altosuilib/AltosUIMap.java index 91087469..aaa68f23 100644 --- a/altosuilib/AltosUIMap.java +++ b/altosuilib/AltosUIMap.java @@ -139,6 +139,10 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosU public static void prefetch_maps(double lat, double lon) { } + public String getName() { + return "Map"; + } + public AltosUIMap() { view = new AltosUIMapView(); diff --git a/altosuilib/AltosUIUnitsIndicator.java b/altosuilib/AltosUIUnitsIndicator.java new file mode 100644 index 00000000..433cc0c2 --- /dev/null +++ b/altosuilib/AltosUIUnitsIndicator.java @@ -0,0 +1,79 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +public abstract class AltosUIUnitsIndicator extends AltosUIIndicator { + + AltosUnits units; + + abstract public double value(AltosState state, int i); + public boolean good(double value) { return false; } + + public double[] last_values; + + public void show(double... v) { + for (int i = 0; i < values.length; i++) { + if (v[i] != last_values[i]) { + String value_text; + boolean good = false; + + if (v[i] == AltosLib.MISSING) { + value_text = "Missing"; + } else { + value_text = units.show(8, v[i]); + if (i == 0) + good = good(v[i]); + } + last_values[i] = v[i]; + if (i == 0 && lights != null) + set_lights(good); + values[i].setText(value_text); + } + } + } + + public void units_changed(boolean imperial_units) { + show(last_values); + } + + public void show (AltosState state, AltosListenerState listener_state) { + + double[] v = new double[values.length]; + + for (int i = 0; i < values.length; i++) { + if (state != null) + v[i] = value(state, i); + else + v[i] = AltosLib.MISSING; + } + show(v); + + } + + public AltosUIUnitsIndicator (Container container, int y, AltosUnits units, String name, int number_values, boolean has_lights, int width) { + super(container, y, name, number_values, has_lights, width); + this.units = units; + last_values = new double[values.length]; + for (int i = 0; i < last_values.length; i++) + last_values[i] = AltosLib.MISSING - 1; + } +} diff --git a/altosuilib/AltosUIVoltageIndicator.java b/altosuilib/AltosUIVoltageIndicator.java new file mode 100644 index 00000000..36835663 --- /dev/null +++ b/altosuilib/AltosUIVoltageIndicator.java @@ -0,0 +1,42 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator { + + abstract public double voltage(AltosState state); + abstract public double good(); + + public double value(AltosState state, int i) { + return voltage(state); + } + + public boolean good(double value) { + return value >= good(); + } + + double last_voltage = -1; + + public AltosUIVoltageIndicator (Container container, int y, String name, int width) { + super(container, y, AltosConvert.voltage, name, 1, true, width); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 466cfd99..3904af3c 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -76,7 +76,10 @@ altosuilib_JAVA = \ AltosUIMapPreload.java \ AltosUIMapStore.java \ AltosUIMapStoreListener.java \ - AltosUILatLon.java + AltosUILatLon.java \ + AltosUIIndicator.java \ + AltosUIUnitsIndicator.java \ + AltosUIVoltageIndicator.java JAR=altosuilib_$(ALTOSUILIB_VERSION).jar -- cgit v1.2.3 From 9a6a3c34293eac6442f766e13ce148f595e891eb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Jun 2014 21:26:33 -0700 Subject: altosuilib: Make map-cache per-window instead of global This consumes more memory, but avoids cache conflicts between windows Signed-off-by: Keith Packard --- altosuilib/AltosUIMapCache.java | 22 ++++++++++++---------- altosuilib/AltosUIMapPreload.java | 3 +++ altosuilib/AltosUIMapTile.java | 4 +++- altosuilib/AltosUIMapTileListener.java | 2 ++ altosuilib/AltosUIMapView.java | 6 +++++- 5 files changed, 25 insertions(+), 12 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosUIMapCache.java b/altosuilib/AltosUIMapCache.java index e849da79..55311d8c 100644 --- a/altosuilib/AltosUIMapCache.java +++ b/altosuilib/AltosUIMapCache.java @@ -31,18 +31,19 @@ public class AltosUIMapCache { static final int bad_request = 3; static final int forbidden = 4; - static private Object fetch_lock = new Object(); + static final int min_cache_size = 9; + static final int max_cache_size = 24; - static final int min_cache_size = 9; - static final int max_cache_size = 24; + private Object fetch_lock = new Object(); + private Object cache_lock = new Object(); - static int cache_size = min_cache_size; + int cache_size = min_cache_size; - static AltosUIMapImage[] images = new AltosUIMapImage[cache_size]; + AltosUIMapImage[] images = new AltosUIMapImage[cache_size]; - static Object cache_lock = new Object(); + long used; - public static void set_cache_size(int new_size) { + public void set_cache_size(int new_size) { if (new_size < min_cache_size) new_size = min_cache_size; if (new_size > max_cache_size) @@ -64,9 +65,7 @@ public class AltosUIMapCache { } } - static long used; - - public static Image get(AltosUIMapTile tile, AltosUIMapStore store, int width, int height) { + public Image get(AltosUIMapTile tile, AltosUIMapStore store, int width, int height) { int oldest = -1; long age = used; @@ -109,4 +108,7 @@ public class AltosUIMapCache { } } } + + public AltosUIMapCache() { + } } diff --git a/altosuilib/AltosUIMapPreload.java b/altosuilib/AltosUIMapPreload.java index d702dddf..3bdba39e 100644 --- a/altosuilib/AltosUIMapPreload.java +++ b/altosuilib/AltosUIMapPreload.java @@ -209,6 +209,7 @@ class AltosUISites extends Thread { public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, ItemListener, AltosUIMapTileListener { AltosUIFrame owner; AltosUIMap map; + AltosUIMapCache cache = new AltosUIMapCache(); AltosUIMapPos lat; AltosUIMapPos lon; @@ -353,6 +354,8 @@ public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, I } } + public AltosUIMapCache cache() { return cache; } + public void set_sites() { int i = 1; for (AltosUISite site : sites.sites) { diff --git a/altosuilib/AltosUIMapTile.java b/altosuilib/AltosUIMapTile.java index 6fbcdb4b..7c823183 100644 --- a/altosuilib/AltosUIMapTile.java +++ b/altosuilib/AltosUIMapTile.java @@ -34,6 +34,7 @@ public class AltosUIMapTile { int zoom; int maptype; AltosUIMapStore store; + AltosUIMapCache cache; int status; private File map_file() { @@ -153,7 +154,7 @@ public class AltosUIMapTile { ++painting_serial; if (image == null && t.has_location()) - image = AltosUIMapCache.get(this, store, px_size, px_size); + image = cache.get(this, store, px_size, px_size); paint_graphics(g2d, t, painting_serial); } @@ -173,6 +174,7 @@ public class AltosUIMapTile { public AltosUIMapTile(AltosUIMapTileListener listener, AltosUILatLon upper_left, AltosUILatLon center, int zoom, int maptype, int px_size, Font font) { this.listener = listener; this.upper_left = upper_left; + cache = listener.cache(); while (center.lon < -180.0) center.lon += 360.0; diff --git a/altosuilib/AltosUIMapTileListener.java b/altosuilib/AltosUIMapTileListener.java index 4cc3ff2f..4ca13539 100644 --- a/altosuilib/AltosUIMapTileListener.java +++ b/altosuilib/AltosUIMapTileListener.java @@ -19,4 +19,6 @@ package org.altusmetrum.altosuilib_2; public interface AltosUIMapTileListener { abstract public void notify_tile(AltosUIMapTile tile, int status); + + abstract public AltosUIMapCache cache(); } diff --git a/altosuilib/AltosUIMapView.java b/altosuilib/AltosUIMapView.java index efae3767..4df178e2 100644 --- a/altosuilib/AltosUIMapView.java +++ b/altosuilib/AltosUIMapView.java @@ -34,6 +34,8 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo AltosUIMapLine line = new AltosUIMapLine(); + AltosUIMapCache cache = new AltosUIMapCache(); + LinkedList marks = new LinkedList(); LinkedList zoom_listeners = new LinkedList(); @@ -368,7 +370,7 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo for (Point point : to_remove) tiles.remove(point); - AltosUIMapCache.set_cache_size(((lower_right.y - upper_left.y) / px_size + 1) * ((lower_right.x - upper_left.x) / px_size + 1)); + cache.set_cache_size(((lower_right.y - upper_left.y) / px_size + 1) * ((lower_right.x - upper_left.x) / px_size + 1)); for (int y = upper_left.y; y <= lower_right.y; y += px_size) { for (int x = upper_left.x; x <= lower_right.x; x += px_size) { Point point = new Point(x, y); @@ -394,6 +396,8 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo } } + public AltosUIMapCache cache() { return cache; } + /* AltosUIMapStoreListener methods */ public void notify_store(AltosUIMapStore store, int status) { if (load_listener != null) { -- cgit v1.2.3 From bfbabfa60f3cedd994f693867bce56aad05be02a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Jun 2014 22:04:57 -0700 Subject: telegps: Allow TeleGPS preferences to have a custom title and label Don't just inherit the AltosUI ones Signed-off-by: Keith Packard --- altosuilib/AltosUIConfigure.java | 10 +++++++--- telegps/TeleGPSPreferences.java | 32 +------------------------------- 2 files changed, 8 insertions(+), 34 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java index ae7626de..920ed8e2 100644 --- a/altosuilib/AltosUIConfigure.java +++ b/altosuilib/AltosUIConfigure.java @@ -229,8 +229,8 @@ public class AltosUIConfigure public void add_frequencies() { } - public AltosUIConfigure(JFrame in_owner) { - super(in_owner, "Configure AltosUI", false); + public AltosUIConfigure(JFrame in_owner, String name, String label) { + super(in_owner, name, false); owner = in_owner; pane = getContentPane(); @@ -239,7 +239,7 @@ public class AltosUIConfigure row = 0; /* Nice label at the top */ - pane.add(new JLabel ("Configure AltOS UI"), + pane.add(new JLabel (label), constraints(0, 3)); row++; @@ -271,4 +271,8 @@ public class AltosUIConfigure setLocationRelativeTo(owner); setVisible(true); } + + public AltosUIConfigure(JFrame in_owner) { + this(in_owner, "Configure AltosUI", "Configure AltOS UI"); + } } diff --git a/telegps/TeleGPSPreferences.java b/telegps/TeleGPSPreferences.java index 534cf550..8bd371f4 100644 --- a/telegps/TeleGPSPreferences.java +++ b/telegps/TeleGPSPreferences.java @@ -112,38 +112,8 @@ public class TeleGPSPreferences row++; } - final static String[] position_names = { - "Top left", - "Top", - "Top right", - "Left", - "Center", - "Right", - "Bottom left", - "Bottom", - "Bottom right", - }; - - public void add_position() { - pane.add(new JLabel ("Menu position"), constraints(0, 1)); - - position_value = new JComboBox(position_names); - position_value.setMaximumRowCount(position_names.length); - int position = AltosUIPreferences.position(); - position_value.setSelectedIndex(position); - position_value.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int position = position_value.getSelectedIndex(); - AltosUIPreferences.set_position(position); - } - }); - pane.add(position_value, constraints(1, 2, GridBagConstraints.BOTH)); - position_value.setToolTipText("Position of main AltosUI window"); - row++; - } - public TeleGPSPreferences(JFrame owner, AltosVoice voice) { - super(owner); + super(owner, "TeleGPS Preferences", "Configure TeleGPS"); this.voice = voice; } -- cgit v1.2.3 From c7553c54765dcc9ac532fe52aae9594b2ad5e560 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 14:36:11 -0700 Subject: altosuilib: Require all flight display classes to provide a name Signed-off-by: Keith Packard --- altosuilib/AltosFlightDisplay.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'altosuilib') diff --git a/altosuilib/AltosFlightDisplay.java b/altosuilib/AltosFlightDisplay.java index 5fb0cab7..55b74034 100644 --- a/altosuilib/AltosFlightDisplay.java +++ b/altosuilib/AltosFlightDisplay.java @@ -23,4 +23,6 @@ public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListene void reset(); void show(AltosState state, AltosListenerState listener_state); + + String getName(); } -- cgit v1.2.3 From 242e968a6982f2ceaa79780cbeec8c4e21321b44 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 14:36:49 -0700 Subject: altosuilib: In graph, show zero sats in view as 0 instead of MISSING Signed-off-by: Keith Packard --- altosuilib/AltosGraphDataPoint.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosGraphDataPoint.java b/altosuilib/AltosGraphDataPoint.java index 446468d7..3aff1e82 100644 --- a/altosuilib/AltosGraphDataPoint.java +++ b/altosuilib/AltosGraphDataPoint.java @@ -101,8 +101,12 @@ public class AltosGraphDataPoint implements AltosUIDataPoint { 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; + if (state.gps != null) { + if (state.gps.cc_gps_sat != null) + y = state.gps.cc_gps_sat.length; + else + y = 0; + } break; case data_gps_altitude: y = state.gps_altitude(); -- cgit v1.2.3 From 2903f0911e79e381c6125022bb84096321c258eb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 14:37:35 -0700 Subject: altosuilib: provide getName() for AltosInfoTable Signed-off-by: Keith Packard --- altosuilib/AltosInfoTable.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'altosuilib') diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java index 8ded1bea..23ae4ae5 100644 --- a/altosuilib/AltosInfoTable.java +++ b/altosuilib/AltosInfoTable.java @@ -123,6 +123,8 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar model.clear(); } + public String getName() { return "Table"; } + public void show(AltosState state, AltosListenerState listener_state) { if (!isShowing()) { -- cgit v1.2.3 From 19273a4a341342ca6b5d65cfc490d92cbf23356f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 14:38:00 -0700 Subject: altosuilib: Make sure only one thread is closing serial device Multiple closers can cause a crash by freeing the libaltos device twice Signed-off-by: Keith Packard --- altosuilib/AltosSerial.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosSerial.java b/altosuilib/AltosSerial.java index 0632ca70..60e15bdb 100644 --- a/altosuilib/AltosSerial.java +++ b/altosuilib/AltosSerial.java @@ -117,7 +117,7 @@ public class AltosSerial extends AltosLink { SwingUtilities.invokeLater(r); } - private void close_serial() { + private synchronized void close_serial() { synchronized (devices_opened) { devices_opened.remove(device.getPath()); } -- cgit v1.2.3 From 8250777e6e869bcee9781691caa1f2a7cfb33b43 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 14:39:26 -0700 Subject: altosuilib: Add more options to AltosUIIndicator to suit AltosUI This makes AltosUIIndicator capable of displaying most stuff in AltosUI Signed-off-by: Keith Packard --- altosuilib/AltosUIIndicator.java | 40 ++++++++++++++++++------ altosuilib/AltosUIUnitsIndicator.java | 55 +++++++++++++++++++++++++++++---- altosuilib/AltosUIVoltageIndicator.java | 10 +++--- 3 files changed, 85 insertions(+), 20 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosUIIndicator.java b/altosuilib/AltosUIIndicator.java index 59fe231b..b1626cba 100644 --- a/altosuilib/AltosUIIndicator.java +++ b/altosuilib/AltosUIIndicator.java @@ -60,6 +60,7 @@ public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsL public void show(String... s) { int n = Math.min(s.length, values.length); + show(); for (int i = 0; i < n; i++) values[i].setText(s[i]); @@ -102,7 +103,15 @@ public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsL label.setText(text); } - public AltosUIIndicator (Container container, int y, String text, int number_values, boolean has_lights, int value_width) { + public void remove(Container container) { + if (lights != null) + container.remove(lights); + container.remove(label); + for (int i = 0; i < values.length; i++) + container.remove(values[i]); + } + + public AltosUIIndicator (Container container, int x, int y, int label_width, String text, int number_values, boolean has_lights, int value_width, int value_space) { GridBagLayout layout = (GridBagLayout)(container.getLayout()); GridBagConstraints c = new GridBagConstraints(); @@ -110,7 +119,7 @@ public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsL if (has_lights) { lights = new AltosLights(); - c.gridx = 0; c.gridy = y; + c.gridx = x; c.gridy = y; c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.VERTICAL; c.weightx = 0; @@ -121,7 +130,8 @@ public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsL label = new JLabel(text); label.setFont(AltosUILib.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 1; c.gridy = y; + c.gridx = x + 1; c.gridy = y; + c.gridwidth = label_width; c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; @@ -135,7 +145,7 @@ public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsL values[i].setEditable(false); values[i].setFont(AltosUILib.value_font); values[i].setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2 + i; c.gridy = y; + c.gridx = 1 + label_width + x + i * value_space; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -145,15 +155,27 @@ public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsL } } - public AltosUIIndicator (Container container, int y, String text) { - this(container, y, text, 1, false, 1); + public AltosUIIndicator (Container container, int x, int y, int label_width, String text, int number_values, boolean has_lights, int value_width) { + this(container, x, y, label_width, text, number_values, has_lights, value_width, 1); } - public AltosUIIndicator (Container container, int y, String text, int number_values) { - this(container, y, text, number_values, false, 1); + public AltosUIIndicator (Container container, int x, int y, String text, int number_values, boolean has_lights, int value_width) { + this(container, x, y, 1, text, number_values, has_lights, value_width); + } + + public AltosUIIndicator (Container container, int y, String text, int number_values, boolean has_lights, int value_width) { + this(container, 0, y, text, number_values, has_lights, value_width); } public AltosUIIndicator (Container container, int y, String text, int number_values, boolean has_lights) { - this(container, y, text, number_values, has_lights, 1); + this(container, 0, y, text, number_values, has_lights, 1); + } + + public AltosUIIndicator (Container container, int y, String text, int number_values) { + this(container, 0, y, text, number_values, false, 1); + } + + public AltosUIIndicator (Container container, int y, String text) { + this(container, 0, y, text, 1, false, 1); } } diff --git a/altosuilib/AltosUIUnitsIndicator.java b/altosuilib/AltosUIUnitsIndicator.java index 433cc0c2..2285b6fc 100644 --- a/altosuilib/AltosUIUnitsIndicator.java +++ b/altosuilib/AltosUIUnitsIndicator.java @@ -26,11 +26,24 @@ public abstract class AltosUIUnitsIndicator extends AltosUIIndicator { AltosUnits units; abstract public double value(AltosState state, int i); - public boolean good(double value) { return false; } + public double good() { return 0; } + public boolean good(double value) { return value != AltosLib.MISSING && value >= good(); } + public boolean hide(double value) { return false; } + + public boolean hide(AltosState state, int i) { + if (state == null) + return hide(AltosLib.MISSING); + return hide(value(state, i)); + } + + public double value (AltosState state, AltosListenerState listener_state, int i) { + return value(state, i); + } public double[] last_values; public void show(double... v) { + show(); for (int i = 0; i < values.length; i++) { if (v[i] != last_values[i]) { String value_text; @@ -56,24 +69,54 @@ public abstract class AltosUIUnitsIndicator extends AltosUIIndicator { } public void show (AltosState state, AltosListenerState listener_state) { - double[] v = new double[values.length]; + boolean hide = false; for (int i = 0; i < values.length; i++) { if (state != null) - v[i] = value(state, i); + v[i] = value(state, listener_state, i); else v[i] = AltosLib.MISSING; + if (hide(state, i)) + hide = true; } - show(v); + if (hide) + hide(); + else + show(v); } - public AltosUIUnitsIndicator (Container container, int y, AltosUnits units, String name, int number_values, boolean has_lights, int width) { - super(container, y, name, number_values, has_lights, width); + public void reset() { + for (int i = 0; i < last_values.length; i++) + last_values[i] = AltosLib.MISSING - 1; + } + + public AltosUIUnitsIndicator (Container container, int x, int y, int label_width, AltosUnits units, String name, int number_values, boolean has_lights, int width) { + super(container, x, y, label_width, name, number_values, has_lights, width); this.units = units; last_values = new double[values.length]; for (int i = 0; i < last_values.length; i++) last_values[i] = AltosLib.MISSING - 1; } + + public AltosUIUnitsIndicator (Container container, int x, int y, AltosUnits units, String name, int number_values, boolean has_lights, int width) { + this(container, x, y, 1, units, name, number_values, has_lights, width); + } + + public AltosUIUnitsIndicator (Container container, int y, AltosUnits units, String name, int number_values, boolean has_lights, int width) { + this(container, 0, y, units, name, number_values, has_lights, width); + } + + public AltosUIUnitsIndicator (Container container, int y, AltosUnits units, String name, int width) { + this(container, 0, y, units, name, 1, false, width); + } + + public AltosUIUnitsIndicator (Container container, int y, AltosUnits units, String name) { + this(container, 0, y, units, name, 1, false, 1); + } + + public AltosUIUnitsIndicator (Container container, int x,int y, AltosUnits units, String name) { + this(container, x, y, units, name, 1, false, 1); + } } diff --git a/altosuilib/AltosUIVoltageIndicator.java b/altosuilib/AltosUIVoltageIndicator.java index 36835663..3ff17213 100644 --- a/altosuilib/AltosUIVoltageIndicator.java +++ b/altosuilib/AltosUIVoltageIndicator.java @@ -30,13 +30,13 @@ public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator { return voltage(state); } - public boolean good(double value) { - return value >= good(); - } - double last_voltage = -1; + public AltosUIVoltageIndicator (Container container, int x, int y, String name, int width) { + super(container, x, y, AltosConvert.voltage, name, 1, true, width); + } + public AltosUIVoltageIndicator (Container container, int y, String name, int width) { - super(container, y, AltosConvert.voltage, name, 1, true, width); + this(container, 0, y, name, width); } } -- cgit v1.2.3 From f5887a3e7cf993e23dbb1e0f6b9ebece78c34413 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 14:40:24 -0700 Subject: altosuilib: Add AltosUIFlightTab class This covers most of the common functions for all flight status display tabs. Signed-off-by: Keith Packard --- altosuilib/AltosUIFlightTab.java | 88 ++++++++++++++++++++++++++++++++++++++++ altosuilib/Makefile.am | 1 + 2 files changed, 89 insertions(+) create mode 100644 altosuilib/AltosUIFlightTab.java (limited to 'altosuilib') diff --git a/altosuilib/AltosUIFlightTab.java b/altosuilib/AltosUIFlightTab.java new file mode 100644 index 00000000..039d83e0 --- /dev/null +++ b/altosuilib/AltosUIFlightTab.java @@ -0,0 +1,88 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_2; + +import java.util.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; + +public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener { + public GridBagLayout layout; + + AltosState last_state; + AltosListenerState last_listener_state; + + LinkedList indicators = new LinkedList(); + + public void add (AltosUIIndicator indicator) { + indicators.add(indicator); + } + + public void remove(AltosUIIndicator indicator) { + indicators.remove(indicator); + } + + public void reset() { + for (AltosUIIndicator i : indicators) + i.reset(); + } + + public void font_size_changed(int font_size) { + for (AltosUIIndicator i : indicators) + i.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + for (AltosUIIndicator i : indicators) + i.units_changed(imperial_units); + } + + public void show(AltosState state, AltosListenerState listener_state) { + if (!isShowing()) { + last_state = state; + last_listener_state = listener_state; + return; + } + + for (AltosUIIndicator i : indicators) + i.show(state, listener_state); + } + + public void hierarchyChanged(HierarchyEvent e) { + if (last_state != null && isShowing()) { + AltosState state = last_state; + AltosListenerState listener_state = last_listener_state; + + last_state = null; + last_listener_state = null; + show(state, listener_state); + } + } + + abstract public String getName(); + + public AltosUIFlightTab() { + layout = new GridBagLayout(); + + setLayout(layout); + + addHierarchyListener(this); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 3904af3c..e08fbe74 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -77,6 +77,7 @@ altosuilib_JAVA = \ AltosUIMapStore.java \ AltosUIMapStoreListener.java \ AltosUILatLon.java \ + AltosUIFlightTab.java \ AltosUIIndicator.java \ AltosUIUnitsIndicator.java \ AltosUIVoltageIndicator.java -- cgit v1.2.3 From 1fc3032d688cbb7c09c1dffde30cc815f3594e29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 15:20:07 -0700 Subject: alotsuilib: Remove old "mega" and "mini" file extensions from data chooser We never shipped AltosUI which stored mega/mini files in different extensions Signed-off-by: Keith Packard --- altosuilib/AltosDataChooser.java | 8 ++------ telegps/TeleGPSDisplayThread.java | 2 -- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosDataChooser.java b/altosuilib/AltosDataChooser.java index 14d28115..59891c4a 100644 --- a/altosuilib/AltosDataChooser.java +++ b/altosuilib/AltosDataChooser.java @@ -67,16 +67,12 @@ public class AltosDataChooser extends JFileChooser { public AltosDataChooser(JFrame in_frame) { frame = in_frame; setDialogTitle("Select Flight Record File"); - setFileFilter(new FileNameExtensionFilter("TeleMetrum eeprom file", + setFileFilter(new FileNameExtensionFilter("On-board Log file", "eeprom")); setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem")); - setFileFilter(new FileNameExtensionFilter("TeleMega eeprom file", - "mega")); - setFileFilter(new FileNameExtensionFilter("EasyMini eeprom file", - "mini")); setFileFilter(new FileNameExtensionFilter("Flight data file", - "telem", "eeprom", "mega", "mini")); + "telem", "eeprom")); setCurrentDirectory(AltosUIPreferences.logdir()); } } diff --git a/telegps/TeleGPSDisplayThread.java b/telegps/TeleGPSDisplayThread.java index 9de33098..a3d4ea07 100644 --- a/telegps/TeleGPSDisplayThread.java +++ b/telegps/TeleGPSDisplayThread.java @@ -90,8 +90,6 @@ public class TeleGPSDisplayThread extends Thread { voice.speak("Height %s.\n", AltosConvert.height.say(state.height())); } - } else { - voice.speak("Height is unknown.\n"); } } -- cgit v1.2.3 From 951fda701ed31f4d8390c130215597e8f63e837e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 16:26:22 -0700 Subject: altosuilib: Make graph enable buttons be CheckBoxes instead of RadioButtons aj noticed. Signed-off-by: Keith Packard --- altosuilib/AltosUIEnable.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java index 8d42c09b..da98797a 100644 --- a/altosuilib/AltosUIEnable.java +++ b/altosuilib/AltosUIEnable.java @@ -45,7 +45,7 @@ public class AltosUIEnable extends Container { class GraphElement implements ActionListener { AltosUIGrapher grapher; - JRadioButton enable; + JCheckBox enable; String name; public void actionPerformed(ActionEvent ae) { @@ -55,7 +55,7 @@ public class AltosUIEnable extends Container { GraphElement (String name, AltosUIGrapher grapher, boolean enabled) { this.name = name; this.grapher = grapher; - enable = new JRadioButton(name, enabled); + enable = new JCheckBox(name, enabled); grapher.set_enable(enabled); enable.addActionListener(this); } @@ -86,10 +86,10 @@ public class AltosUIEnable extends Container { /* Imperial units setting */ /* Add label */ - JRadioButton imperial_units = new JRadioButton("Imperial Units", AltosUIPreferences.imperial_units()); + JCheckBox imperial_units = new JCheckBox("Imperial Units", AltosUIPreferences.imperial_units()); imperial_units.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - JRadioButton item = (JRadioButton) e.getSource(); + JCheckBox item = (JCheckBox) e.getSource(); boolean enabled = item.isSelected(); AltosUIPreferences.set_imperial_units(enabled); } -- cgit v1.2.3 From 5392ee3c5328f8384ed30a2d147e4be96075e064 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 18:51:25 -0700 Subject: altosuilib: Serialize access to async tile notify function in preload This ensures that we see each tile getting downloaded and don't mis-count, which would result in wedging the process Signed-off-by: Keith Packard --- altosuilib/AltosUIMapPreload.java | 2 +- altosuilib/AltosUIMapView.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosUIMapPreload.java b/altosuilib/AltosUIMapPreload.java index 3bdba39e..c91b06b8 100644 --- a/altosuilib/AltosUIMapPreload.java +++ b/altosuilib/AltosUIMapPreload.java @@ -327,7 +327,7 @@ public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, I /* AltosUIMapTileListener methods */ - public void notify_tile(AltosUIMapTile tile, int status) { + public synchronized void notify_tile(AltosUIMapTile tile, int status) { if (status == AltosUIMapStore.loading) return; diff --git a/altosuilib/AltosUIMapView.java b/altosuilib/AltosUIMapView.java index 4df178e2..a14fde65 100644 --- a/altosuilib/AltosUIMapView.java +++ b/altosuilib/AltosUIMapView.java @@ -387,7 +387,7 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo } /* AltosUIMapTileListener methods */ - public void notify_tile(AltosUIMapTile tile, int status) { + public synchronized void notify_tile(AltosUIMapTile tile, int status) { for (Point point : tiles.keySet()) { if (tile == tiles.get(point)) { Point screen = transform.screen(point); @@ -399,7 +399,7 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo public AltosUIMapCache cache() { return cache; } /* AltosUIMapStoreListener methods */ - public void notify_store(AltosUIMapStore store, int status) { + public synchronized void notify_store(AltosUIMapStore store, int status) { if (load_listener != null) { for (AltosUIMapTile tile : tiles.values()) if (store.equals(tile.store)) -- cgit v1.2.3 From 823ef386f9dc5c5df197936f4254921f2e0282b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 20:08:40 -0700 Subject: altoslib: AltosFlightStatsTable: another editable text field that shouldn't be Signed-off-by: Keith Packard --- altosuilib/AltosFlightStatsTable.java | 1 + micropeak/MicroStatsTable.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java index b32e92a0..703dfb9d 100644 --- a/altosuilib/AltosFlightStatsTable.java +++ b/altosuilib/AltosFlightStatsTable.java @@ -55,6 +55,7 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen value = new JTextField[values.length]; for (int j = 0; j < values.length; j++) { value[j] = new JTextField(values[j]); + value[j].setEditable(false); value[j].setFont(AltosUILib.value_font); value[j].setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = j+1; c.gridy = y; diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java index 798d6535..3b17e731 100644 --- a/micropeak/MicroStatsTable.java +++ b/micropeak/MicroStatsTable.java @@ -59,9 +59,9 @@ public class MicroStatsTable extends JComponent implements AltosFontListener { texts = new JTextField[values.length]; for (int j = 0; j < values.length; j++) { JTextField value = new JTextField(values[j]); + value.setEditable(false); value.setFont(AltosUILib.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); - value.setEditable(false); texts[j] = value; c.gridx = j+1; c.gridy = y; c.anchor = GridBagConstraints.EAST; -- cgit v1.2.3 From 6cad0b783f654864f0d6d8726c74605f108db3e0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jun 2014 22:23:10 -0700 Subject: altosuilib: Remove some debugging printfs Signed-off-by: Keith Packard --- altosuilib/AltosUIMapPreload.java | 4 ---- 1 file changed, 4 deletions(-) (limited to 'altosuilib') diff --git a/altosuilib/AltosUIMapPreload.java b/altosuilib/AltosUIMapPreload.java index c91b06b8..56066d70 100644 --- a/altosuilib/AltosUIMapPreload.java +++ b/altosuilib/AltosUIMapPreload.java @@ -403,8 +403,6 @@ public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, I } public AltosUIMapPreload(AltosUIFrame in_owner) { - System.out.printf("start creating preload ui\n"); - owner = in_owner; Container pane = getContentPane(); @@ -605,7 +603,5 @@ public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, I pack(); setLocationRelativeTo(owner); setVisible(true); - - System.out.printf("done creating preload ui\n"); } } -- cgit v1.2.3