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_7.*;
28 import org.altusmetrum.altosuilib_7.*;
30 public class AltosIgniteUI
32 implements ActionListener
39 javax.swing.Timer timer;
46 final static int timeout = 1 * 1000;
49 boolean timer_running;
51 LinkedBlockingQueue<String> command_queue;
59 void set_status (int status) {
61 status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(status)));
64 Igniter(AltosIgniteUI ui, String label, String name, int y) {
65 Container pane = getContentPane();
66 GridBagConstraints c = new GridBagConstraints();
67 Insets i = new Insets(4,4,4,4);
70 this.status = AltosIgnite.Unknown;
75 c.anchor = GridBagConstraints.WEST;
76 button = new JRadioButton (label);
78 button.addActionListener(ui);
79 button.setActionCommand(name);
85 c.anchor = GridBagConstraints.WEST;
86 status_label = new JLabel("plenty of text");
87 pane.add(status_label, c);
89 status = AltosIgnite.Unknown;
95 void set_status(String _name, int _status) {
97 final String name = _name;
98 final int status = _status;
99 Runnable r = new Runnable() {
101 for (int p = 0; p < igniters.length; p++)
102 if (name.equals(igniters[p].name))
103 igniters[p].set_status(status);
106 SwingUtilities.invokeLater(r);
109 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 ignite = new AltosIgnite(link,
127 !device.matchProduct(Altos.product_altimeter));
129 } catch (Exception e) {
138 String command = command_queue.take();
141 if (command.equals("get_status")) {
142 HashMap<String,Integer> status_map = ignite.status();
144 for (int p = 0; p < igniters.length; p++) {
145 Integer i = status_map.get(igniters[p].name);
147 set_status(igniters[p].name, i);
150 } else if (command.equals("get_npyro")) {
151 reply = String.format("npyro %d", ignite.npyro());
152 } else if (command.equals("quit")) {
156 ignite.fire(command);
159 final String f_reply = reply;
162 ignite_reply(f_reply);
165 SwingUtilities.invokeLater(r);
166 } catch (Exception e) {
172 public IgniteHandler(JFrame in_owner, AltosLink in_link) {
178 void ignite_exception(Exception e) {
179 if (e instanceof FileNotFoundException) {
180 JOptionPane.showMessageDialog(owner,
181 ((FileNotFoundException) e).getMessage(),
182 "Cannot open target device",
183 JOptionPane.ERROR_MESSAGE);
184 } else if (e instanceof AltosSerialInUseException) {
185 JOptionPane.showMessageDialog(owner,
186 String.format("Device \"%s\" already in use",
187 device.toShortString()),
189 JOptionPane.ERROR_MESSAGE);
190 } else if (e instanceof IOException) {
191 IOException ee = (IOException) e;
192 JOptionPane.showMessageDialog(owner,
193 device.toShortString(),
194 ee.getLocalizedMessage(),
195 JOptionPane.ERROR_MESSAGE);
197 JOptionPane.showMessageDialog(owner,
198 String.format("Connection to \"%s\" failed",
199 device.toShortString()),
201 JOptionPane.ERROR_MESSAGE);
206 void ignite_reply(String reply) {
207 if (reply.equals("status")) {
209 } else if (reply.equals("fired")) {
211 } else if (reply.startsWith("npyro")) {
212 npyro = Integer.parseInt(reply.substring(6));
217 void set_arm_text() {
218 if (arm.isSelected())
219 arm.setText(String.format("%d", time_remaining));
227 timer_running = true;
232 fire.setEnabled(false);
233 timer_running = false;
234 arm.setSelected(false);
235 arm.setEnabled(false);
240 group.clearSelection();
241 fire.setEnabled(false);
245 void send_command(String command) {
247 command_queue.put(command);
248 } catch (Exception ex) {
249 ignite_exception(ex);
253 boolean getting_status = false;
255 boolean visible = false;
257 void set_ignite_status() {
258 getting_status = false;
265 void poll_ignite_status() {
266 if (!getting_status) {
267 getting_status = true;
268 send_command("get_status");
272 boolean firing = false;
274 void start_fire(String which) {
288 send_command("quit");
299 if (time_remaining <= 0)
304 poll_ignite_status();
308 if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
309 String igniter = "none";
311 for (int p = 0; p < igniters.length; p++)
312 if (igniters[p].button.isSelected()) {
313 igniter = igniters[p].name;
316 send_command(igniter);
321 public void actionPerformed(ActionEvent e) {
322 String cmd = e.getActionCommand();
324 for (int p = 0; p < igniters.length; p++)
325 if (cmd.equals(igniters[p].name)) {
327 arm.setEnabled(true);
331 if (cmd.equals("arm")) {
332 if (arm.isSelected()) {
333 fire.setEnabled(true);
338 if (cmd.equals("fire"))
340 if (cmd.equals("tick"))
342 if (cmd.equals("close"))
346 /* A window listener to catch closing events and tell the config code */
347 class ConfigListener extends WindowAdapter {
350 public ConfigListener(AltosIgniteUI this_ui) {
354 public void windowClosing(WindowEvent e) {
355 ui.actionPerformed(new ActionEvent(e.getSource(),
356 ActionEvent.ACTION_PERFORMED,
361 private boolean open() {
362 command_queue = new LinkedBlockingQueue<String>();
365 device = AltosDeviceUIDialog.show(owner, Altos.product_any);
366 if (device != null) {
368 AltosSerial serial = new AltosSerial(device);
369 serial.set_frame(owner);
370 IgniteHandler handler = new IgniteHandler(owner, serial);
371 Thread t = new Thread(handler);
375 } catch (Exception ex) {
376 ignite_exception(ex);
382 private void make_ui() {
383 group = new ButtonGroup();
385 Container pane = getContentPane();
387 GridBagConstraints c = new GridBagConstraints();
388 Insets i = new Insets(4,4,4,4);
390 timer = new javax.swing.Timer(timeout, this);
391 timer.setActionCommand("tick");
392 timer_running = false;
395 pane.setLayout(new GridBagLayout());
397 c.fill = GridBagConstraints.NONE;
398 c.anchor = GridBagConstraints.CENTER;
408 c.anchor = GridBagConstraints.CENTER;
409 label = new JLabel ("Fire Igniter");
414 igniters = new Igniter[2 + npyro];
416 igniters[0] = new Igniter(this, "Apogee", AltosIgnite.Apogee, y++);
417 igniters[1] = new Igniter(this, "Main", AltosIgnite.Main, y++);
419 for (int p = 0; p < npyro; p++) {
420 String name = String.format("%d", p);
421 String label = String.format("%c", 'A' + p);
422 igniters[2+p] = new Igniter(this, label, name, y++);
428 c.anchor = GridBagConstraints.CENTER;
429 arm = new JToggleButton ("Arm");
431 arm.addActionListener(this);
432 arm.setActionCommand("arm");
433 arm.setEnabled(false);
438 c.anchor = GridBagConstraints.CENTER;
439 fire = new JButton ("Fire");
440 fire.setEnabled(false);
442 fire.addActionListener(this);
443 fire.setActionCommand("fire");
450 c.anchor = GridBagConstraints.CENTER;
451 close = new JButton ("Close");
453 close.addActionListener(this);
454 close.setActionCommand("close");
457 setLocationRelativeTo(owner);
459 addWindowListener(new ConfigListener(this));
462 public AltosIgniteUI(JFrame in_owner) {
469 send_command("get_npyro");