2 * Copyright © 2010 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 import java.awt.event.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.*;
25 import javax.swing.event.*;
29 import java.util.prefs.*;
30 import java.util.concurrent.*;
31 import org.altusmetrum.AltosLib.*;
33 public class AltosIgniteUI
35 implements ActionListener
41 JLabel apogee_status_label;
43 JLabel main_status_label;
46 javax.swing.Timer timer;
52 final static int timeout = 1 * 1000;
55 boolean timer_running;
57 LinkedBlockingQueue<String> command_queue;
59 class IgniteHandler implements Runnable {
63 void send_exception(Exception e) {
64 final Exception f_e = e;
65 Runnable r = new Runnable() {
67 ignite_exception(f_e);
70 SwingUtilities.invokeLater(r);
75 AltosSerial serial = new AltosSerial(device);
76 serial.set_frame(owner);
77 ignite = new AltosIgnite(serial,
78 !device.matchProduct(Altos.product_altimeter));
80 } catch (Exception e) {
89 String command = command_queue.take();
92 if (command.equals("get_status")) {
93 apogee_status = ignite.status(AltosIgnite.Apogee);
94 main_status = ignite.status(AltosIgnite.Main);
96 } else if (command.equals("main")) {
97 ignite.fire(AltosIgnite.Main);
99 } else if (command.equals("apogee")) {
100 ignite.fire(AltosIgnite.Apogee);
102 } else if (command.equals("quit")) {
106 throw new ParseException(String.format("invalid command %s", command), 0);
108 final String f_reply = reply;
111 ignite_reply(f_reply);
114 SwingUtilities.invokeLater(r);
115 } catch (Exception e) {
121 public IgniteHandler(JFrame in_owner) {
126 void ignite_exception(Exception e) {
127 if (e instanceof FileNotFoundException) {
128 JOptionPane.showMessageDialog(owner,
129 ((FileNotFoundException) e).getMessage(),
130 "Cannot open target device",
131 JOptionPane.ERROR_MESSAGE);
132 } else if (e instanceof AltosSerialInUseException) {
133 JOptionPane.showMessageDialog(owner,
134 String.format("Device \"%s\" already in use",
135 device.toShortString()),
137 JOptionPane.ERROR_MESSAGE);
138 } else if (e instanceof IOException) {
139 IOException ee = (IOException) e;
140 JOptionPane.showMessageDialog(owner,
141 device.toShortString(),
142 ee.getLocalizedMessage(),
143 JOptionPane.ERROR_MESSAGE);
145 JOptionPane.showMessageDialog(owner,
146 String.format("Connection to \"%s\" failed",
147 device.toShortString()),
149 JOptionPane.ERROR_MESSAGE);
154 void ignite_reply(String reply) {
155 if (reply.equals("status")) {
157 } else if (reply.equals("fired")) {
162 void set_arm_text() {
163 if (arm.isSelected())
164 arm.setText(String.format("%d", time_remaining));
172 timer_running = true;
177 arm.setSelected(false);
178 arm.setEnabled(false);
179 fire.setEnabled(false);
180 timer_running = false;
185 apogee.setSelected(false);
186 main.setSelected(false);
187 fire.setEnabled(false);
191 void send_command(String command) {
193 command_queue.put(command);
194 } catch (Exception ex) {
195 ignite_exception(ex);
199 boolean getting_status = false;
201 boolean visible = false;
202 void set_ignite_status() {
203 getting_status = false;
204 apogee_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(apogee_status)));
205 main_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(main_status)));
212 void poll_ignite_status() {
213 if (!getting_status) {
214 getting_status = true;
215 send_command("get_status");
219 boolean firing = false;
221 void start_fire(String which) {
234 send_command("quit");
243 if (time_remaining <= 0)
248 poll_ignite_status();
252 if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
253 String igniter = "none";
254 if (apogee.isSelected() && !main.isSelected())
256 else if (main.isSelected() && !apogee.isSelected())
258 send_command(igniter);
263 public void actionPerformed(ActionEvent e) {
264 String cmd = e.getActionCommand();
265 if (cmd.equals("apogee") || cmd.equals("main")) {
269 if (cmd.equals("apogee") && apogee.isSelected()) {
270 main.setSelected(false);
271 arm.setEnabled(true);
273 if (cmd.equals("main") && main.isSelected()) {
274 apogee.setSelected(false);
275 arm.setEnabled(true);
278 if (cmd.equals("arm")) {
279 if (arm.isSelected()) {
280 fire.setEnabled(true);
285 if (cmd.equals("fire"))
287 if (cmd.equals("tick"))
289 if (cmd.equals("close")) {
294 /* A window listener to catch closing events and tell the config code */
295 class ConfigListener extends WindowAdapter {
298 public ConfigListener(AltosIgniteUI this_ui) {
302 public void windowClosing(WindowEvent e) {
303 ui.actionPerformed(new ActionEvent(e.getSource(),
304 ActionEvent.ACTION_PERFORMED,
309 private boolean open() {
310 command_queue = new LinkedBlockingQueue<String>();
312 device = AltosDeviceDialog.show(owner, Altos.product_any);
313 if (device != null) {
314 IgniteHandler handler = new IgniteHandler(owner);
315 Thread t = new Thread(handler);
322 public AltosIgniteUI(JFrame in_owner) {
325 apogee_status = AltosIgnite.Unknown;
326 main_status = AltosIgnite.Unknown;
331 Container pane = getContentPane();
332 GridBagConstraints c = new GridBagConstraints();
333 Insets i = new Insets(4,4,4,4);
335 timer = new javax.swing.Timer(timeout, this);
336 timer.setActionCommand("tick");
337 timer_running = false;
342 pane.setLayout(new GridBagLayout());
344 c.fill = GridBagConstraints.NONE;
345 c.anchor = GridBagConstraints.CENTER;
353 c.anchor = GridBagConstraints.CENTER;
354 label = new JLabel ("Fire Igniter");
360 c.anchor = GridBagConstraints.WEST;
361 apogee = new JRadioButton ("Apogee");
363 apogee.addActionListener(this);
364 apogee.setActionCommand("apogee");
369 c.anchor = GridBagConstraints.WEST;
370 apogee_status_label = new JLabel();
371 pane.add(apogee_status_label, c);
376 c.anchor = GridBagConstraints.WEST;
377 main = new JRadioButton ("Main");
379 main.addActionListener(this);
380 main.setActionCommand("main");
385 c.anchor = GridBagConstraints.WEST;
386 main_status_label = new JLabel();
387 pane.add(main_status_label, c);
392 c.anchor = GridBagConstraints.CENTER;
393 arm = new JToggleButton ("Arm");
395 arm.addActionListener(this);
396 arm.setActionCommand("arm");
397 arm.setEnabled(false);
402 c.anchor = GridBagConstraints.CENTER;
403 fire = new JButton ("Fire");
404 fire.setEnabled(false);
406 fire.addActionListener(this);
407 fire.setActionCommand("fire");
412 c.anchor = GridBagConstraints.CENTER;
413 close = new JButton ("Close");
415 close.addActionListener(this);
416 close.setActionCommand("close");
419 setLocationRelativeTo(owner);
421 addWindowListener(new ConfigListener(this));