altoslib: Remove some debug printfs
[fw/altos] / altosui / AltosIgniteUI.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
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.
7  *
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.
12  *
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.
16  */
17
18 package altosui;
19
20 import java.awt.*;
21 import java.awt.event.*;
22 import javax.swing.*;
23 import java.io.*;
24 import java.text.*;
25 import java.util.*;
26 import java.util.concurrent.*;
27 import org.altusmetrum.altoslib_5.*;
28 import org.altusmetrum.altosuilib_3.*;
29
30 public class AltosIgniteUI
31         extends AltosUIDialog
32         implements ActionListener
33 {
34         AltosDevice     device;
35         JFrame          owner;
36         JLabel          label;
37         JToggleButton   arm;
38         JButton         fire;
39         javax.swing.Timer       timer;
40         JButton         close;
41         ButtonGroup     group;
42         Boolean         opened;
43
44         int             npyro;
45
46         final static int        timeout = 1 * 1000;
47
48         int             time_remaining;
49         boolean         timer_running;
50
51         LinkedBlockingQueue<String>     command_queue;
52
53         LinkedBlockingQueue<String>     reply_queue;
54
55         class Igniter {
56                 JRadioButton    button;
57                 JLabel          status_label;
58                 String          name;
59                 int             status;
60
61                 void set_status (int status) {
62                         this.status = status;
63                         status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(status)));
64                 }
65
66                 Igniter(AltosIgniteUI ui, String label, String name, int y) {
67                         Container               pane = getContentPane();
68                         GridBagConstraints      c = new GridBagConstraints();
69                         Insets                  i = new Insets(4,4,4,4);
70
71                         this.name = name;
72                         this.status = AltosIgnite.Unknown;
73
74                         c.gridx = 0;
75                         c.gridy = y;
76                         c.gridwidth = 1;
77                         c.anchor = GridBagConstraints.WEST;
78                         button = new JRadioButton (label);
79                         pane.add(button, c);
80                         button.addActionListener(ui);
81                         button.setActionCommand(name);
82                         group.add(button);
83
84                         c.gridx = 1;
85                         c.gridy = y;
86                         c.gridwidth = 1;
87                         c.anchor = GridBagConstraints.WEST;
88                         status_label = new JLabel("plenty of text");
89                         pane.add(status_label, c);
90
91                         status = AltosIgnite.Unknown;
92                 }
93         }
94
95         Igniter igniters[];
96
97         void set_status(String _name, int _status) {
98
99                 final String name = _name;
100                 final int status = _status;
101                 Runnable r = new Runnable() {
102                                 public void run() {
103                                         for (int p = 0; p < igniters.length; p++)
104                                                 if (name.equals(igniters[p].name))
105                                                         igniters[p].set_status(status);
106                                 }
107                         };
108                 SwingUtilities.invokeLater(r);
109         }
110
111         class IgniteHandler implements Runnable {
112                 AltosIgnite     ignite;
113                 JFrame          owner;
114                 AltosLink       link;
115
116                 void send_exception(Exception e) {
117                         final Exception f_e = e;
118                         Runnable r = new Runnable() {
119                                         public void run() {
120                                                 ignite_exception(f_e);
121                                         }
122                                 };
123                         SwingUtilities.invokeLater(r);
124                 }
125
126                 public void run () {
127                         try {
128                                 ignite = new AltosIgnite(link,
129                                                          !device.matchProduct(Altos.product_altimeter));
130
131                         } catch (Exception e) {
132                                 send_exception(e);
133                                 return;
134                         }
135
136                         for (;;) {
137                                 Runnable        r;
138
139                                 try {
140                                         String          command = command_queue.take();
141                                         String          reply = null;
142
143                                         if (command.equals("get_status")) {
144                                                 HashMap<String,Integer> status_map = ignite.status();
145
146                                                 for (int p = 0; p < igniters.length; p++) {
147                                                         Integer i = status_map.get(igniters[p].name);
148                                                         if (i != null)
149                                                                 set_status(igniters[p].name, i);
150                                                 }
151                                                 reply = "status";
152                                         } else if (command.equals("get_npyro")) {
153                                                 put_reply(String.format("%d", ignite.npyro()));
154                                                 continue;
155                                         } else if (command.equals("quit")) {
156                                                 ignite.close();
157                                                 break;
158                                         } else {
159                                                 ignite.fire(command);
160                                                 reply = "fired";
161                                         }
162                                         final String f_reply = reply;
163                                         r = new Runnable() {
164                                                         public void run() {
165                                                                 ignite_reply(f_reply);
166                                                         }
167                                                 };
168                                         SwingUtilities.invokeLater(r);
169                                 } catch (Exception e) {
170                                         send_exception(e);
171                                 }
172                         }
173                 }
174
175                 public IgniteHandler(JFrame in_owner, AltosLink in_link) {
176                         owner = in_owner;
177                         link = in_link;
178                 }
179         }
180
181         void ignite_exception(Exception e) {
182                 if (e instanceof FileNotFoundException) {
183                         JOptionPane.showMessageDialog(owner,
184                                                       ((FileNotFoundException) e).getMessage(),
185                                                       "Cannot open target device",
186                                                       JOptionPane.ERROR_MESSAGE);
187                 } else if (e instanceof AltosSerialInUseException) {
188                         JOptionPane.showMessageDialog(owner,
189                                                       String.format("Device \"%s\" already in use",
190                                                                     device.toShortString()),
191                                                       "Device in use",
192                                                       JOptionPane.ERROR_MESSAGE);
193                 } else if (e instanceof IOException) {
194                         IOException ee = (IOException) e;
195                         JOptionPane.showMessageDialog(owner,
196                                                       device.toShortString(),
197                                                       ee.getLocalizedMessage(),
198                                                       JOptionPane.ERROR_MESSAGE);
199                 } else {
200                         JOptionPane.showMessageDialog(owner,
201                                                       String.format("Connection to \"%s\" failed",
202                                                                     device.toShortString()),
203                                                       "Connection Failed",
204                                                       JOptionPane.ERROR_MESSAGE);
205                 }
206                 close();
207         }
208
209         void ignite_reply(String reply) {
210                 if (reply.equals("status")) {
211                         set_ignite_status();
212                 } else if (reply.equals("fired")) {
213                         fired();
214                 }
215         }
216
217         void set_arm_text() {
218                 if (arm.isSelected())
219                         arm.setText(String.format("%d", time_remaining));
220                 else
221                         arm.setText("Arm");
222         }
223
224         void start_timer() {
225                 time_remaining = 10;
226                 set_arm_text();
227                 timer_running = true;
228         }
229
230         void stop_timer() {
231                 time_remaining = 0;
232                 fire.setEnabled(false);
233                 timer_running = false;
234                 arm.setSelected(false);
235                 arm.setEnabled(false);
236                 set_arm_text();
237         }
238
239         void cancel () {
240                 group.clearSelection();
241                 fire.setEnabled(false);
242                 stop_timer();
243         }
244
245         void send_command(String command) {
246                 try {
247                         command_queue.put(command);
248                 } catch (Exception ex) {
249                         ignite_exception(ex);
250                 }
251         }
252
253         void put_reply(String reply) {
254                 try {
255                         reply_queue.put(reply);
256                 } catch (Exception ex) {
257                         ignite_exception(ex);
258                 }
259         }
260
261         String get_reply() {
262                 String reply = "";
263                 try {
264                         reply = reply_queue.take();
265                 } catch (Exception ex) {
266                         ignite_exception(ex);
267                 }
268                 return reply;
269         }
270
271         boolean getting_status = false;
272
273         boolean visible = false;
274
275         void set_ignite_status() {
276                 getting_status = false;
277                 if (!visible) {
278                         visible = true;
279                         setVisible(true);
280                 }
281         }
282
283         void poll_ignite_status() {
284                 if (!getting_status) {
285                         getting_status = true;
286                         send_command("get_status");
287                 }
288         }
289
290         int get_npyro() {
291                 send_command("get_npyro");
292                 String reply = get_reply();
293                 return Integer.parseInt(reply);
294         }
295
296         boolean firing = false;
297
298         void start_fire(String which) {
299                 if (!firing) {
300                         firing = true;
301                         send_command(which);
302                 }
303         }
304
305         void fired() {
306                 firing = false;
307                 cancel();
308         }
309
310         void close() {
311                 if (opened) {
312                         send_command("quit");
313                         timer.stop();
314                 }
315                 setVisible(false);
316                 dispose();
317         }
318
319         void tick_timer() {
320                 if (timer_running) {
321                         --time_remaining;
322                         if (time_remaining <= 0)
323                                 cancel();
324                         else
325                                 set_arm_text();
326                 }
327                 poll_ignite_status();
328         }
329
330         void fire() {
331                 if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
332                         String  igniter = "none";
333
334                         for (int p = 0; p < igniters.length; p++)
335                                 if (igniters[p].button.isSelected()) {
336                                         igniter = igniters[p].name;
337                                         break;
338                                 }
339                         send_command(igniter);
340                         cancel();
341                 }
342         }
343
344         public void actionPerformed(ActionEvent e) {
345                 String cmd = e.getActionCommand();
346
347                 for (int p = 0; p < igniters.length; p++)
348                         if (cmd.equals(igniters[p].name)) {
349                                 stop_timer();
350                                 arm.setEnabled(true);
351                                 break;
352                         }
353
354                 if (cmd.equals("arm")) {
355                         if (arm.isSelected()) {
356                                 fire.setEnabled(true);
357                                 start_timer();
358                         } else
359                                 cancel();
360                 }
361                 if (cmd.equals("fire"))
362                         fire();
363                 if (cmd.equals("tick"))
364                         tick_timer();
365                 if (cmd.equals("close"))
366                         close();
367         }
368
369         /* A window listener to catch closing events and tell the config code */
370         class ConfigListener extends WindowAdapter {
371                 AltosIgniteUI   ui;
372
373                 public ConfigListener(AltosIgniteUI this_ui) {
374                         ui = this_ui;
375                 }
376
377                 public void windowClosing(WindowEvent e) {
378                         ui.actionPerformed(new ActionEvent(e.getSource(),
379                                                            ActionEvent.ACTION_PERFORMED,
380                                                            "close"));
381                 }
382         }
383
384         private boolean open() {
385                 command_queue = new LinkedBlockingQueue<String>();
386                 reply_queue = new LinkedBlockingQueue<String>();
387
388                 opened = false;
389                 device = AltosDeviceUIDialog.show(owner, Altos.product_any);
390                 if (device != null) {
391                         try {
392                                 AltosSerial     serial = new AltosSerial(device);
393                                 serial.set_frame(owner);
394                                 IgniteHandler   handler = new IgniteHandler(owner, serial);
395                                 Thread          t = new Thread(handler);
396                                 t.start();
397                                 opened = true;
398                                 return true;
399                         } catch (Exception ex) {
400                                 ignite_exception(ex);
401                         }
402                 }
403                 return false;
404         }
405
406         public AltosIgniteUI(JFrame in_owner) {
407
408                 owner = in_owner;
409
410                 if (!open())
411                         return;
412
413                 group = new ButtonGroup();
414
415                 Container               pane = getContentPane();
416
417                 GridBagConstraints      c = new GridBagConstraints();
418                 Insets                  i = new Insets(4,4,4,4);
419
420                 timer = new javax.swing.Timer(timeout, this);
421                 timer.setActionCommand("tick");
422                 timer_running = false;
423                 timer.restart();
424
425                 owner = in_owner;
426
427                 pane.setLayout(new GridBagLayout());
428
429                 c.fill = GridBagConstraints.NONE;
430                 c.anchor = GridBagConstraints.CENTER;
431                 c.insets = i;
432                 c.weightx = 0;
433                 c.weighty = 0;
434
435                 int y = 0;
436
437                 c.gridx = 0;
438                 c.gridy = y;
439                 c.gridwidth = 2;
440                 c.anchor = GridBagConstraints.CENTER;
441                 label = new JLabel ("Fire Igniter");
442                 pane.add(label, c);
443
444                 y++;
445
446                 int npyro = get_npyro();
447
448                 igniters = new Igniter[2 + npyro];
449
450                 igniters[0] = new Igniter(this, "Apogee", AltosIgnite.Apogee, y++);
451                 igniters[1] = new Igniter(this, "Main", AltosIgnite.Main, y++);
452
453                 for (int p = 0; p < npyro; p++) {
454                         String  name = String.format("%d", p);
455                         String  label = String.format("%c", 'A' + p);
456                         igniters[2+p] = new Igniter(this, label, name, y++);
457                 }
458
459                 c.gridx = 0;
460                 c.gridy = y;
461                 c.gridwidth = 1;
462                 c.anchor = GridBagConstraints.CENTER;
463                 arm = new JToggleButton ("Arm");
464                 pane.add(arm, c);
465                 arm.addActionListener(this);
466                 arm.setActionCommand("arm");
467                 arm.setEnabled(false);
468
469                 c.gridx = 1;
470                 c.gridy = y;
471                 c.gridwidth = 1;
472                 c.anchor = GridBagConstraints.CENTER;
473                 fire = new JButton ("Fire");
474                 fire.setEnabled(false);
475                 pane.add(fire, c);
476                 fire.addActionListener(this);
477                 fire.setActionCommand("fire");
478
479                 y++;
480
481                 c.gridx = 0;
482                 c.gridy = y;
483                 c.gridwidth = 2;
484                 c.anchor = GridBagConstraints.CENTER;
485                 close = new JButton ("Close");
486                 pane.add(close, c);
487                 close.addActionListener(this);
488                 close.setActionCommand("close");
489
490                 pack();
491                 setLocationRelativeTo(owner);
492
493                 addWindowListener(new ConfigListener(this));
494         }
495 }