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 ignite = new AltosIgnite(device);
76 } catch (Exception e) {
80 ignite.set_frame(owner);
86 String command = command_queue.take();
89 if (command.equals("get_status")) {
90 apogee_status = ignite.status(AltosIgnite.Apogee);
91 main_status = ignite.status(AltosIgnite.Main);
93 } else if (command.equals("main")) {
94 ignite.fire(AltosIgnite.Main);
96 } else if (command.equals("apogee")) {
97 ignite.fire(AltosIgnite.Apogee);
99 } else if (command.equals("quit")) {
103 throw new ParseException(String.format("invalid command %s", command), 0);
105 final String f_reply = reply;
108 ignite_reply(f_reply);
111 SwingUtilities.invokeLater(r);
112 } catch (Exception e) {
118 public IgniteHandler(JFrame in_owner) {
123 void ignite_exception(Exception e) {
124 if (e instanceof FileNotFoundException) {
125 JOptionPane.showMessageDialog(owner,
126 ((FileNotFoundException) e).getMessage(),
127 "Cannot open target device",
128 JOptionPane.ERROR_MESSAGE);
129 } else if (e instanceof AltosSerialInUseException) {
130 JOptionPane.showMessageDialog(owner,
131 String.format("Device \"%s\" already in use",
132 device.toShortString()),
134 JOptionPane.ERROR_MESSAGE);
135 } else if (e instanceof IOException) {
136 IOException ee = (IOException) e;
137 JOptionPane.showMessageDialog(owner,
138 device.toShortString(),
139 ee.getLocalizedMessage(),
140 JOptionPane.ERROR_MESSAGE);
142 JOptionPane.showMessageDialog(owner,
143 String.format("Connection to \"%s\" failed",
144 device.toShortString()),
146 JOptionPane.ERROR_MESSAGE);
151 void ignite_reply(String reply) {
152 if (reply.equals("status")) {
154 } else if (reply.equals("fired")) {
159 void set_arm_text() {
160 if (arm.isSelected())
161 arm.setText(String.format("%d", time_remaining));
169 timer_running = true;
174 arm.setSelected(false);
175 arm.setEnabled(false);
176 fire.setEnabled(false);
177 timer_running = false;
182 apogee.setSelected(false);
183 main.setSelected(false);
184 fire.setEnabled(false);
188 void send_command(String command) {
190 command_queue.put(command);
191 } catch (Exception ex) {
192 ignite_exception(ex);
196 boolean getting_status = false;
198 boolean visible = false;
199 void set_ignite_status() {
200 getting_status = false;
201 apogee_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(apogee_status)));
202 main_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(main_status)));
209 void poll_ignite_status() {
210 if (!getting_status) {
211 getting_status = true;
212 send_command("get_status");
216 boolean firing = false;
218 void start_fire(String which) {
231 send_command("quit");
240 if (time_remaining <= 0)
245 poll_ignite_status();
249 if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
250 String igniter = "none";
251 if (apogee.isSelected() && !main.isSelected())
253 else if (main.isSelected() && !apogee.isSelected())
255 send_command(igniter);
260 public void actionPerformed(ActionEvent e) {
261 String cmd = e.getActionCommand();
262 if (cmd.equals("apogee") || cmd.equals("main")) {
266 if (cmd.equals("apogee") && apogee.isSelected()) {
267 main.setSelected(false);
268 arm.setEnabled(true);
270 if (cmd.equals("main") && main.isSelected()) {
271 apogee.setSelected(false);
272 arm.setEnabled(true);
275 if (cmd.equals("arm")) {
276 if (arm.isSelected()) {
277 fire.setEnabled(true);
282 if (cmd.equals("fire"))
284 if (cmd.equals("tick"))
286 if (cmd.equals("close")) {
291 /* A window listener to catch closing events and tell the config code */
292 class ConfigListener extends WindowAdapter {
295 public ConfigListener(AltosIgniteUI this_ui) {
299 public void windowClosing(WindowEvent e) {
300 ui.actionPerformed(new ActionEvent(e.getSource(),
301 ActionEvent.ACTION_PERFORMED,
306 private boolean open() {
307 command_queue = new LinkedBlockingQueue<String>();
309 device = AltosDeviceDialog.show(owner, Altos.product_any);
310 if (device != null) {
311 IgniteHandler handler = new IgniteHandler(owner);
312 Thread t = new Thread(handler);
319 public AltosIgniteUI(JFrame in_owner) {
322 apogee_status = AltosIgnite.Unknown;
323 main_status = AltosIgnite.Unknown;
328 Container pane = getContentPane();
329 GridBagConstraints c = new GridBagConstraints();
330 Insets i = new Insets(4,4,4,4);
332 timer = new javax.swing.Timer(timeout, this);
333 timer.setActionCommand("tick");
334 timer_running = false;
339 pane.setLayout(new GridBagLayout());
341 c.fill = GridBagConstraints.NONE;
342 c.anchor = GridBagConstraints.CENTER;
350 c.anchor = GridBagConstraints.CENTER;
351 label = new JLabel ("Fire Igniter");
357 c.anchor = GridBagConstraints.WEST;
358 apogee = new JRadioButton ("Apogee");
360 apogee.addActionListener(this);
361 apogee.setActionCommand("apogee");
366 c.anchor = GridBagConstraints.WEST;
367 apogee_status_label = new JLabel();
368 pane.add(apogee_status_label, c);
373 c.anchor = GridBagConstraints.WEST;
374 main = new JRadioButton ("Main");
376 main.addActionListener(this);
377 main.setActionCommand("main");
382 c.anchor = GridBagConstraints.WEST;
383 main_status_label = new JLabel();
384 pane.add(main_status_label, c);
389 c.anchor = GridBagConstraints.CENTER;
390 arm = new JToggleButton ("Arm");
392 arm.addActionListener(this);
393 arm.setActionCommand("arm");
394 arm.setEnabled(false);
399 c.anchor = GridBagConstraints.CENTER;
400 fire = new JButton ("Fire");
401 fire.setEnabled(false);
403 fire.addActionListener(this);
404 fire.setActionCommand("fire");
409 c.anchor = GridBagConstraints.CENTER;
410 close = new JButton ("Close");
412 close.addActionListener(this);
413 close.setActionCommand("close");
416 setLocationRelativeTo(owner);
418 addWindowListener(new ConfigListener(this));