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.*;
26 import java.util.concurrent.*;
27 import org.altusmetrum.altoslib_3.*;
28 import org.altusmetrum.altosuilib_1.*;
30 public class AltosIgniteUI
32 implements ActionListener
39 javax.swing.Timer timer;
45 final static int timeout = 1 * 1000;
48 boolean timer_running;
50 LinkedBlockingQueue<String> command_queue;
52 LinkedBlockingQueue<String> reply_queue;
60 void set_status (int status) {
62 status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(status)));
65 Igniter(AltosIgniteUI ui, String label, String name, int y) {
66 Container pane = getContentPane();
67 GridBagConstraints c = new GridBagConstraints();
68 Insets i = new Insets(4,4,4,4);
71 this.status = AltosIgnite.Unknown;
76 c.anchor = GridBagConstraints.WEST;
77 button = new JRadioButton (label);
79 button.addActionListener(ui);
80 button.setActionCommand(name);
86 c.anchor = GridBagConstraints.WEST;
87 status_label = new JLabel("plenty of text");
88 pane.add(status_label, c);
90 status = AltosIgnite.Unknown;
96 void set_status(String _name, int _status) {
98 final String name = _name;
99 final int status = _status;
100 Runnable r = new Runnable() {
102 for (int p = 0; p < igniters.length; p++)
103 if (name.equals(igniters[p].name))
104 igniters[p].set_status(status);
107 SwingUtilities.invokeLater(r);
110 class IgniteHandler implements Runnable {
114 void send_exception(Exception e) {
115 final Exception f_e = e;
116 Runnable r = new Runnable() {
118 ignite_exception(f_e);
121 SwingUtilities.invokeLater(r);
126 AltosSerial serial = new AltosSerial(device);
127 serial.set_frame(owner);
128 ignite = new AltosIgnite(serial,
129 !device.matchProduct(Altos.product_altimeter));
131 } catch (Exception e) {
140 String command = command_queue.take();
143 if (command.equals("get_status")) {
144 HashMap<String,Integer> status_map = ignite.status();
146 for (int p = 0; p < igniters.length; p++) {
147 Integer i = status_map.get(igniters[p].name);
149 set_status(igniters[p].name, i);
152 } else if (command.equals("get_npyro")) {
153 put_reply(String.format("%d", ignite.npyro()));
155 } else if (command.equals("quit")) {
159 ignite.fire(command);
162 final String f_reply = reply;
165 ignite_reply(f_reply);
168 SwingUtilities.invokeLater(r);
169 } catch (Exception e) {
175 public IgniteHandler(JFrame in_owner) {
180 void ignite_exception(Exception e) {
181 if (e instanceof FileNotFoundException) {
182 JOptionPane.showMessageDialog(owner,
183 ((FileNotFoundException) e).getMessage(),
184 "Cannot open target device",
185 JOptionPane.ERROR_MESSAGE);
186 } else if (e instanceof AltosSerialInUseException) {
187 JOptionPane.showMessageDialog(owner,
188 String.format("Device \"%s\" already in use",
189 device.toShortString()),
191 JOptionPane.ERROR_MESSAGE);
192 } else if (e instanceof IOException) {
193 IOException ee = (IOException) e;
194 JOptionPane.showMessageDialog(owner,
195 device.toShortString(),
196 ee.getLocalizedMessage(),
197 JOptionPane.ERROR_MESSAGE);
199 JOptionPane.showMessageDialog(owner,
200 String.format("Connection to \"%s\" failed",
201 device.toShortString()),
203 JOptionPane.ERROR_MESSAGE);
208 void ignite_reply(String reply) {
209 if (reply.equals("status")) {
211 } else if (reply.equals("fired")) {
216 void set_arm_text() {
217 if (arm.isSelected())
218 arm.setText(String.format("%d", time_remaining));
226 timer_running = true;
231 fire.setEnabled(false);
232 timer_running = false;
233 arm.setSelected(false);
234 arm.setEnabled(false);
239 group.clearSelection();
240 fire.setEnabled(false);
244 void send_command(String command) {
246 command_queue.put(command);
247 } catch (Exception ex) {
248 ignite_exception(ex);
252 void put_reply(String reply) {
254 reply_queue.put(reply);
255 } catch (Exception ex) {
256 ignite_exception(ex);
263 reply = reply_queue.take();
264 } catch (Exception ex) {
265 ignite_exception(ex);
270 boolean getting_status = false;
272 boolean visible = false;
274 void set_ignite_status() {
275 getting_status = false;
282 void poll_ignite_status() {
283 if (!getting_status) {
284 getting_status = true;
285 send_command("get_status");
290 send_command("get_npyro");
291 String reply = get_reply();
292 return Integer.parseInt(reply);
295 boolean firing = false;
297 void start_fire(String which) {
310 send_command("quit");
319 if (time_remaining <= 0)
324 poll_ignite_status();
328 if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
329 String igniter = "none";
331 for (int p = 0; p < igniters.length; p++)
332 if (igniters[p].button.isSelected()) {
333 igniter = igniters[p].name;
336 send_command(igniter);
341 public void actionPerformed(ActionEvent e) {
342 String cmd = e.getActionCommand();
344 for (int p = 0; p < igniters.length; p++)
345 if (cmd.equals(igniters[p].name)) {
347 arm.setEnabled(true);
351 if (cmd.equals("arm")) {
352 if (arm.isSelected()) {
353 fire.setEnabled(true);
358 if (cmd.equals("fire"))
360 if (cmd.equals("tick"))
362 if (cmd.equals("close"))
366 /* A window listener to catch closing events and tell the config code */
367 class ConfigListener extends WindowAdapter {
370 public ConfigListener(AltosIgniteUI this_ui) {
374 public void windowClosing(WindowEvent e) {
375 ui.actionPerformed(new ActionEvent(e.getSource(),
376 ActionEvent.ACTION_PERFORMED,
381 private boolean open() {
382 command_queue = new LinkedBlockingQueue<String>();
383 reply_queue = new LinkedBlockingQueue<String>();
385 device = AltosDeviceUIDialog.show(owner, Altos.product_any);
386 if (device != null) {
387 IgniteHandler handler = new IgniteHandler(owner);
388 Thread t = new Thread(handler);
395 public AltosIgniteUI(JFrame in_owner) {
402 group = new ButtonGroup();
404 Container pane = getContentPane();
406 GridBagConstraints c = new GridBagConstraints();
407 Insets i = new Insets(4,4,4,4);
409 timer = new javax.swing.Timer(timeout, this);
410 timer.setActionCommand("tick");
411 timer_running = false;
416 pane.setLayout(new GridBagLayout());
418 c.fill = GridBagConstraints.NONE;
419 c.anchor = GridBagConstraints.CENTER;
429 c.anchor = GridBagConstraints.CENTER;
430 label = new JLabel ("Fire Igniter");
435 int npyro = get_npyro();
437 igniters = new Igniter[2 + npyro];
439 igniters[0] = new Igniter(this, "Apogee", AltosIgnite.Apogee, y++);
440 igniters[1] = new Igniter(this, "Main", AltosIgnite.Main, y++);
442 for (int p = 0; p < npyro; p++) {
443 String name = String.format("%d", p);
444 String label = String.format("%c", 'A' + p);
445 igniters[2+p] = new Igniter(this, label, name, y++);
451 c.anchor = GridBagConstraints.CENTER;
452 arm = new JToggleButton ("Arm");
454 arm.addActionListener(this);
455 arm.setActionCommand("arm");
456 arm.setEnabled(false);
461 c.anchor = GridBagConstraints.CENTER;
462 fire = new JButton ("Fire");
463 fire.setEnabled(false);
465 fire.addActionListener(this);
466 fire.setActionCommand("fire");
473 c.anchor = GridBagConstraints.CENTER;
474 close = new JButton ("Close");
476 close.addActionListener(this);
477 close.setActionCommand("close");
480 setLocationRelativeTo(owner);
482 addWindowListener(new ConfigListener(this));