X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosui%2FAltosIgniteUI.java;h=debbf763481136e781ff274d165da27c2d0abb54;hp=d542729cd0de5003d2272b5ad902a0d2450472e5;hb=0d691170a96545a9e57aad454de87541cea8c292;hpb=f01096c4b42f9a4720ed0414826c2a283a992545 diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index d542729c..debbf763 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -3,7 +3,8 @@ * * 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. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,39 +21,204 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import javax.swing.filechooser.FileNameExtensionFilter; -import javax.swing.table.*; -import javax.swing.event.*; import java.io.*; -import java.util.*; import java.text.*; -import java.util.prefs.*; +import java.util.*; import java.util.concurrent.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosIgniteUI - extends JDialog + extends AltosUIDialog implements ActionListener { AltosDevice device; - AltosIgnite ignite; JFrame owner; JLabel label; - JRadioButton apogee; - JLabel apogee_status_label; - JRadioButton main; - JLabel main_status_label; JToggleButton arm; JButton fire; javax.swing.Timer timer; + JButton close; + ButtonGroup group; + Boolean opened; - int apogee_status; - int main_status; + int npyro; final static int timeout = 1 * 1000; int time_remaining; boolean timer_running; + int poll_remaining; + + LinkedBlockingQueue command_queue; + + class Igniter { + JRadioButton button; + JLabel status_label; + String name; + int status; + + void set_status (int status) { + this.status = status; + status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(status))); + } + + Igniter(AltosIgniteUI ui, String label, String name, int y) { + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + this.name = name; + this.status = AltosIgnite.Unknown; + + c.gridx = 0; + c.gridy = y; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + button = new JRadioButton (label); + pane.add(button, c); + button.addActionListener(ui); + button.setActionCommand(name); + group.add(button); + + c.gridx = 1; + c.gridy = y; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + status_label = new JLabel("plenty of text"); + pane.add(status_label, c); + + status = AltosIgnite.Unknown; + } + } + + Igniter igniters[]; + + void set_status(String _name, int _status) { + + final String name = _name; + final int status = _status; + Runnable r = new Runnable() { + public void run() { + for (int p = 0; p < igniters.length; p++) + if (name.equals(igniters[p].name)) + igniters[p].set_status(status); + } + }; + SwingUtilities.invokeLater(r); + } + + class IgniteHandler implements Runnable { + AltosIgnite ignite; + JFrame owner; + AltosLink link; + + void send_exception(Exception e) { + final Exception f_e = e; + Runnable r = new Runnable() { + public void run() { + ignite_exception(f_e); + } + }; + SwingUtilities.invokeLater(r); + } + + public void run () { + try { + ignite = new AltosIgnite(link, + !device.matchProduct(Altos.product_altimeter)); + + } catch (Exception e) { + send_exception(e); + return; + } + + for (;;) { + Runnable r; + + try { + String command = command_queue.take(); + String reply = null; + + if (command.equals("get_status")) { + HashMap status_map = ignite.status(); + + for (int p = 0; p < igniters.length; p++) { + Integer i = status_map.get(igniters[p].name); + if (i != null) + set_status(igniters[p].name, i); + } + reply = "status"; + } else if (command.equals("get_npyro")) { + reply = String.format("npyro %d", ignite.npyro()); + } else if (command.equals("quit")) { + ignite.close(); + break; + } else { + ignite.fire(command); + reply = "fired"; + } + final String f_reply = reply; + r = new Runnable() { + public void run() { + ignite_reply(f_reply); + } + }; + SwingUtilities.invokeLater(r); + } catch (Exception e) { + send_exception(e); + } + } + } + + public IgniteHandler(JFrame in_owner, AltosLink in_link) { + owner = in_owner; + link = in_link; + } + } + + void ignite_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(); + } + + void ignite_reply(String reply) { + if (reply.equals("status")) { + set_ignite_status(); + } else if (reply.equals("fired")) { + fired(); + } else if (reply.startsWith("npyro")) { + npyro = Integer.parseInt(reply.substring(6)); + if (npyro == AltosLib.MISSING) + npyro = 0; + make_ui(); + } + } + void set_arm_text() { if (arm.isSelected()) arm.setText(String.format("%d", time_remaining)); @@ -68,44 +234,69 @@ public class AltosIgniteUI void stop_timer() { time_remaining = 0; - arm.setSelected(false); - arm.setEnabled(false); fire.setEnabled(false); timer_running = false; + arm.setSelected(false); + arm.setEnabled(false); set_arm_text(); } void cancel () { - apogee.setSelected(false); - main.setSelected(false); + group.clearSelection(); fire.setEnabled(false); stop_timer(); } - void get_ignite_status() throws InterruptedException, TimeoutException { - apogee_status = ignite.status(AltosIgnite.Apogee); - main_status = ignite.status(AltosIgnite.Main); + void send_command(String command) { + try { + command_queue.put(command); + } catch (Exception ex) { + ignite_exception(ex); + } } - void set_ignite_status() throws InterruptedException, TimeoutException { - get_ignite_status(); - apogee_status_label.setText(String.format("\"%s\"", ignite.status_string(apogee_status))); - main_status_label.setText(String.format("\"%s\"", ignite.status_string(main_status))); + boolean getting_status = false; + + void set_ignite_status() { + getting_status = false; + poll_remaining = 2; + if (!isVisible()) + setVisible(true); } - void close() { - timer.stop(); - setVisible(false); - ignite.close(); + void poll_ignite_status() { + if (poll_remaining > 0) { + --poll_remaining; + return; + } + if (!getting_status) { + getting_status = true; + send_command("get_status"); + } } - void abort() { - close(); - JOptionPane.showMessageDialog(owner, - String.format("Connection to \"%s\" failed", - device.toShortString()), - "Connection Failed", - JOptionPane.ERROR_MESSAGE); + boolean firing = false; + + void start_fire(String which) { + if (!firing) { + firing = true; + send_command(which); + } + } + + void fired() { + firing = false; + cancel(); + } + + void close() { + if (opened) { + send_command("quit"); + } + if (timer != null) + timer.stop(); + setVisible(false); + dispose(); } void tick_timer() { @@ -116,41 +307,32 @@ public class AltosIgniteUI else set_arm_text(); } - try { - set_ignite_status(); - } catch (InterruptedException ie) { - abort(); - } catch (TimeoutException te) { - abort(); - } + poll_ignite_status(); } void fire() { if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) { - int igniter = AltosIgnite.None; - if (apogee.isSelected() && !main.isSelected()) - igniter = AltosIgnite.Apogee; - else if (main.isSelected() && !apogee.isSelected()) - igniter = AltosIgnite.Main; - ignite.fire(igniter); + String igniter = "none"; + + for (int p = 0; p < igniters.length; p++) + if (igniters[p].button.isSelected()) { + igniter = igniters[p].name; + break; + } + send_command(igniter); cancel(); } } public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("apogee") || cmd.equals("main")) { - stop_timer(); - } - if (cmd.equals("apogee") && apogee.isSelected()) { - main.setSelected(false); - arm.setEnabled(true); - } - if (cmd.equals("main") && main.isSelected()) { - apogee.setSelected(false); - arm.setEnabled(true); - } + for (int p = 0; p < igniters.length; p++) + if (cmd.equals(igniters[p].name)) { + stop_timer(); + arm.setEnabled(true); + break; + } if (cmd.equals("arm")) { if (arm.isSelected()) { @@ -163,9 +345,8 @@ public class AltosIgniteUI fire(); if (cmd.equals("tick")) tick_timer(); - if (cmd.equals("close")) { + if (cmd.equals("close")) close(); - } } /* A window listener to catch closing events and tell the config code */ @@ -184,43 +365,31 @@ public class AltosIgniteUI } private boolean open() { - device = AltosDeviceDialog.show(owner, AltosDevice.product_any); + command_queue = new LinkedBlockingQueue(); + + opened = false; + device = AltosDeviceUIDialog.show(owner, Altos.product_any); if (device != null) { try { - ignite = new AltosIgnite(device); + AltosSerial serial = new AltosSerial(device); + serial.set_frame(owner); + IgniteHandler handler = new IgniteHandler(owner, serial); + Thread t = new Thread(handler); + t.start(); + opened = true; return true; - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), - "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(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); + } catch (Exception ex) { + ignite_exception(ex); } } return false; } - public AltosIgniteUI(JFrame in_owner) { - - owner = in_owner; - apogee_status = AltosIgnite.Unknown; - main_status = AltosIgnite.Unknown; - - if (!open()) - return; + private void make_ui() { + group = new ButtonGroup(); Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); @@ -229,67 +398,38 @@ public class AltosIgniteUI timer_running = false; timer.restart(); - owner = in_owner; - pane.setLayout(new GridBagLayout()); c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; c.insets = i; - c.weightx = 1; - c.weighty = 1; + c.weightx = 0; + c.weighty = 0; + + int y = 0; c.gridx = 0; - c.gridy = 0; + c.gridy = y; c.gridwidth = 2; c.anchor = GridBagConstraints.CENTER; label = new JLabel ("Fire Igniter"); pane.add(label, c); - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - apogee = new JRadioButton ("Apogee"); - pane.add(apogee, c); - apogee.addActionListener(this); - apogee.setActionCommand("apogee"); + y++; - c.gridx = 1; - c.gridy = 1; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - apogee_status_label = new JLabel(); - pane.add(apogee_status_label, c); + igniters = new Igniter[2 + npyro]; - c.gridx = 0; - c.gridy = 2; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - main = new JRadioButton ("Main"); - pane.add(main, c); - main.addActionListener(this); - main.setActionCommand("main"); - - c.gridx = 1; - c.gridy = 2; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - main_status_label = new JLabel(); - pane.add(main_status_label, c); + igniters[0] = new Igniter(this, "Apogee", AltosIgnite.Apogee, y++); + igniters[1] = new Igniter(this, "Main", AltosIgnite.Main, y++); - try { - set_ignite_status(); - } catch (InterruptedException ie) { - abort(); - return; - } catch (TimeoutException te) { - abort(); - return; + for (int p = 0; p < npyro; p++) { + String name = String.format("%d", p); + String label = String.format("%c", 'A' + p); + igniters[2+p] = new Igniter(this, label, name, y++); } c.gridx = 0; - c.gridy = 3; + c.gridy = y; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; arm = new JToggleButton ("Arm"); @@ -299,7 +439,7 @@ public class AltosIgniteUI arm.setEnabled(false); c.gridx = 1; - c.gridy = 3; + c.gridy = y; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; fire = new JButton ("Fire"); @@ -308,10 +448,30 @@ public class AltosIgniteUI fire.addActionListener(this); fire.setActionCommand("fire"); + y++; + + c.gridx = 0; + c.gridy = y; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + close = new JButton ("Close"); + pane.add(close, c); + close.addActionListener(this); + close.setActionCommand("close"); + pack(); setLocationRelativeTo(owner); - setVisible(true); addWindowListener(new ConfigListener(this)); } -} \ No newline at end of file + + public AltosIgniteUI(JFrame in_owner) { + + owner = in_owner; + + if (!open()) + return; + + send_command("get_npyro"); + } +}