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.*;
32 public class AltosIgniteUI
34 implements ActionListener
40 JLabel apogee_status_label;
42 JLabel main_status_label;
45 javax.swing.Timer timer;
50 final static int timeout = 1 * 1000;
53 boolean timer_running;
55 LinkedBlockingQueue<String> command_queue;
57 class IgniteHandler implements Runnable {
65 String command = command_queue.take();
68 if (command.equals("get_status")) {
69 apogee_status = ignite.status(AltosIgnite.Apogee);
70 main_status = ignite.status(AltosIgnite.Main);
72 } else if (command.equals("main")) {
73 ignite.fire(AltosIgnite.Main);
75 } else if (command.equals("apogee")) {
76 ignite.fire(AltosIgnite.Apogee);
78 } else if (command.equals("quit")) {
82 throw new ParseException(String.format("invalid command %s", command), 0);
84 final String f_reply = reply;
87 ignite_reply(f_reply);
90 } catch (Exception e) {
91 final Exception f_e = e;
94 ignite_exception(f_e);
98 SwingUtilities.invokeLater(r);
102 public IgniteHandler(AltosIgnite in_ignite) {
107 void ignite_exception(Exception e) {
111 void ignite_reply(String reply) {
112 if (reply.equals("status")) {
114 } else if (reply.equals("fired")) {
119 void set_arm_text() {
120 if (arm.isSelected())
121 arm.setText(String.format("%d", time_remaining));
129 timer_running = true;
134 arm.setSelected(false);
135 arm.setEnabled(false);
136 fire.setEnabled(false);
137 timer_running = false;
142 apogee.setSelected(false);
143 main.setSelected(false);
144 fire.setEnabled(false);
148 void send_command(String command) {
150 command_queue.put(command);
151 } catch (Exception ex) {
156 boolean getting_status = false;
158 boolean visible = false;
159 void set_ignite_status() {
160 getting_status = false;
161 apogee_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(apogee_status)));
162 main_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(main_status)));
169 void poll_ignite_status() {
170 if (!getting_status) {
171 getting_status = true;
172 send_command("get_status");
176 boolean firing = false;
178 void start_fire(String which) {
191 send_command("quit");
199 JOptionPane.showMessageDialog(owner,
200 String.format("Connection to \"%s\" failed",
201 device.toShortString()),
203 JOptionPane.ERROR_MESSAGE);
209 if (time_remaining <= 0)
214 poll_ignite_status();
218 if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
219 String igniter = "none";
220 if (apogee.isSelected() && !main.isSelected())
222 else if (main.isSelected() && !apogee.isSelected())
224 send_command(igniter);
229 public void actionPerformed(ActionEvent e) {
230 String cmd = e.getActionCommand();
231 if (cmd.equals("apogee") || cmd.equals("main")) {
235 if (cmd.equals("apogee") && apogee.isSelected()) {
236 main.setSelected(false);
237 arm.setEnabled(true);
239 if (cmd.equals("main") && main.isSelected()) {
240 apogee.setSelected(false);
241 arm.setEnabled(true);
244 if (cmd.equals("arm")) {
245 if (arm.isSelected()) {
246 fire.setEnabled(true);
251 if (cmd.equals("fire"))
253 if (cmd.equals("tick"))
255 if (cmd.equals("close")) {
260 /* A window listener to catch closing events and tell the config code */
261 class ConfigListener extends WindowAdapter {
264 public ConfigListener(AltosIgniteUI this_ui) {
268 public void windowClosing(WindowEvent e) {
269 ui.actionPerformed(new ActionEvent(e.getSource(),
270 ActionEvent.ACTION_PERFORMED,
275 private boolean open() {
276 command_queue = new LinkedBlockingQueue<String>();
278 device = AltosDeviceDialog.show(owner, AltosDevice.product_any);
279 if (device != null) {
281 AltosIgnite ignite = new AltosIgnite(device);
282 IgniteHandler handler = new IgniteHandler(ignite);
283 Thread t = new Thread(handler);
284 ignite.set_frame(owner);
287 } catch (FileNotFoundException ee) {
288 JOptionPane.showMessageDialog(owner,
289 String.format("Cannot open device \"%s\"",
290 device.toShortString()),
291 "Cannot open target device",
292 JOptionPane.ERROR_MESSAGE);
293 } catch (AltosSerialInUseException si) {
294 JOptionPane.showMessageDialog(owner,
295 String.format("Device \"%s\" already in use",
296 device.toShortString()),
298 JOptionPane.ERROR_MESSAGE);
299 } catch (IOException ee) {
300 JOptionPane.showMessageDialog(owner,
301 device.toShortString(),
302 ee.getLocalizedMessage(),
303 JOptionPane.ERROR_MESSAGE);
309 public AltosIgniteUI(JFrame in_owner) {
312 apogee_status = AltosIgnite.Unknown;
313 main_status = AltosIgnite.Unknown;
318 Container pane = getContentPane();
319 GridBagConstraints c = new GridBagConstraints();
320 Insets i = new Insets(4,4,4,4);
322 timer = new javax.swing.Timer(timeout, this);
323 timer.setActionCommand("tick");
324 timer_running = false;
329 pane.setLayout(new GridBagLayout());
331 c.fill = GridBagConstraints.NONE;
332 c.anchor = GridBagConstraints.CENTER;
340 c.anchor = GridBagConstraints.CENTER;
341 label = new JLabel ("Fire Igniter");
347 c.anchor = GridBagConstraints.WEST;
348 apogee = new JRadioButton ("Apogee");
350 apogee.addActionListener(this);
351 apogee.setActionCommand("apogee");
356 c.anchor = GridBagConstraints.WEST;
357 apogee_status_label = new JLabel();
358 pane.add(apogee_status_label, c);
363 c.anchor = GridBagConstraints.WEST;
364 main = new JRadioButton ("Main");
366 main.addActionListener(this);
367 main.setActionCommand("main");
372 c.anchor = GridBagConstraints.WEST;
373 main_status_label = new JLabel();
374 pane.add(main_status_label, c);
379 c.anchor = GridBagConstraints.CENTER;
380 arm = new JToggleButton ("Arm");
382 arm.addActionListener(this);
383 arm.setActionCommand("arm");
384 arm.setEnabled(false);
389 c.anchor = GridBagConstraints.CENTER;
390 fire = new JButton ("Fire");
391 fire.setEnabled(false);
393 fire.addActionListener(this);
394 fire.setActionCommand("fire");
397 setLocationRelativeTo(owner);
399 addWindowListener(new ConfigListener(this));