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.LinkedBlockingQueue;
34 public class AltosConfigUI
36 implements ActionListener, ItemListener, DocumentListener
44 JLabel main_deploy_label;
45 JLabel apogee_delay_label;
46 JLabel radio_channel_label;
47 JLabel radio_calibration_label;
48 JLabel flight_log_max_label;
49 JLabel ignite_mode_label;
50 JLabel pad_orientation_label;
51 JLabel callsign_label;
59 JComboBox main_deploy_value;
60 JComboBox apogee_delay_value;
61 JComboBox radio_channel_value;
62 JTextField radio_calibration_value;
63 JComboBox flight_log_max_value;
64 JComboBox ignite_mode_value;
65 JComboBox pad_orientation_value;
66 JTextField callsign_value;
73 ActionListener listener;
75 static String[] main_deploy_values = {
76 "100", "150", "200", "250", "300", "350",
80 static String[] apogee_delay_values = {
81 "0", "1", "2", "3", "4", "5"
84 static String[] flight_log_max_values = {
85 "64", "128", "192", "256", "320",
86 "384", "448", "512", "576", "640",
87 "704", "768", "832", "896", "960",
90 static String[] ignite_mode_values = {
96 static String[] pad_orientation_values = {
101 static String[] radio_channel_values = new String[10];
103 for (int i = 0; i <= 9; i++)
104 radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)",
105 i, 434.550 + i * 0.1);
108 /* A window listener to catch closing events and tell the config code */
109 class ConfigListener extends WindowAdapter {
112 public ConfigListener(AltosConfigUI this_ui) {
116 public void windowClosing(WindowEvent e) {
117 ui.actionPerformed(new ActionEvent(e.getSource(),
118 ActionEvent.ACTION_PERFORMED,
123 /* Build the UI using a grid bag */
124 public AltosConfigUI(JFrame in_owner, boolean remote) {
125 super (in_owner, "Configure TeleMetrum", false);
128 GridBagConstraints c;
130 Insets il = new Insets(4,4,4,4);
131 Insets ir = new Insets(4,4,4,4);
133 pane = getContentPane();
134 pane.setLayout(new GridBagLayout());
137 c = new GridBagConstraints();
138 c.gridx = 0; c.gridy = 0;
140 c.fill = GridBagConstraints.NONE;
141 c.anchor = GridBagConstraints.LINE_START;
143 product_label = new JLabel("Product:");
144 pane.add(product_label, c);
146 c = new GridBagConstraints();
147 c.gridx = 4; c.gridy = 0;
149 c.fill = GridBagConstraints.HORIZONTAL;
151 c.anchor = GridBagConstraints.LINE_START;
153 product_value = new JLabel("");
154 pane.add(product_value, c);
157 c = new GridBagConstraints();
158 c.gridx = 0; c.gridy = 1;
160 c.fill = GridBagConstraints.NONE;
161 c.anchor = GridBagConstraints.LINE_START;
164 version_label = new JLabel("Software version:");
165 pane.add(version_label, c);
167 c = new GridBagConstraints();
168 c.gridx = 4; c.gridy = 1;
170 c.fill = GridBagConstraints.HORIZONTAL;
172 c.anchor = GridBagConstraints.LINE_START;
175 version_value = new JLabel("");
176 pane.add(version_value, c);
179 c = new GridBagConstraints();
180 c.gridx = 0; c.gridy = 2;
182 c.fill = GridBagConstraints.NONE;
183 c.anchor = GridBagConstraints.LINE_START;
186 serial_label = new JLabel("Serial:");
187 pane.add(serial_label, c);
189 c = new GridBagConstraints();
190 c.gridx = 4; c.gridy = 2;
192 c.fill = GridBagConstraints.HORIZONTAL;
194 c.anchor = GridBagConstraints.LINE_START;
197 serial_value = new JLabel("");
198 pane.add(serial_value, c);
201 c = new GridBagConstraints();
202 c.gridx = 0; c.gridy = 3;
204 c.fill = GridBagConstraints.NONE;
205 c.anchor = GridBagConstraints.LINE_START;
208 main_deploy_label = new JLabel("Main Deploy Altitude(m):");
209 pane.add(main_deploy_label, c);
211 c = new GridBagConstraints();
212 c.gridx = 4; c.gridy = 3;
214 c.fill = GridBagConstraints.HORIZONTAL;
216 c.anchor = GridBagConstraints.LINE_START;
219 main_deploy_value = new JComboBox(main_deploy_values);
220 main_deploy_value.setEditable(true);
221 main_deploy_value.addItemListener(this);
222 pane.add(main_deploy_value, c);
225 c = new GridBagConstraints();
226 c.gridx = 0; c.gridy = 4;
228 c.fill = GridBagConstraints.NONE;
229 c.anchor = GridBagConstraints.LINE_START;
232 apogee_delay_label = new JLabel("Apogee Delay(s):");
233 pane.add(apogee_delay_label, c);
235 c = new GridBagConstraints();
236 c.gridx = 4; c.gridy = 4;
238 c.fill = GridBagConstraints.HORIZONTAL;
240 c.anchor = GridBagConstraints.LINE_START;
243 apogee_delay_value = new JComboBox(apogee_delay_values);
244 apogee_delay_value.setEditable(true);
245 apogee_delay_value.addItemListener(this);
246 pane.add(apogee_delay_value, c);
249 c = new GridBagConstraints();
250 c.gridx = 0; c.gridy = 5;
252 c.fill = GridBagConstraints.NONE;
253 c.anchor = GridBagConstraints.LINE_START;
256 radio_channel_label = new JLabel("Radio Channel:");
257 pane.add(radio_channel_label, c);
259 c = new GridBagConstraints();
260 c.gridx = 4; c.gridy = 5;
262 c.fill = GridBagConstraints.HORIZONTAL;
264 c.anchor = GridBagConstraints.LINE_START;
267 radio_channel_value = new JComboBox(radio_channel_values);
268 radio_channel_value.setEditable(false);
269 radio_channel_value.addItemListener(this);
270 pane.add(radio_channel_value, c);
272 /* Radio Calibration */
273 c = new GridBagConstraints();
274 c.gridx = 0; c.gridy = 6;
276 c.fill = GridBagConstraints.NONE;
277 c.anchor = GridBagConstraints.LINE_START;
280 radio_calibration_label = new JLabel("RF Calibration:");
281 pane.add(radio_calibration_label, c);
283 c = new GridBagConstraints();
284 c.gridx = 4; c.gridy = 6;
286 c.fill = GridBagConstraints.HORIZONTAL;
288 c.anchor = GridBagConstraints.LINE_START;
291 radio_calibration_value = new JTextField(String.format("%d", 1186611));
292 radio_calibration_value.getDocument().addDocumentListener(this);
294 radio_calibration_value.setEnabled(false);
295 pane.add(radio_calibration_value, c);
298 c = new GridBagConstraints();
299 c.gridx = 0; c.gridy = 7;
301 c.fill = GridBagConstraints.NONE;
302 c.anchor = GridBagConstraints.LINE_START;
305 callsign_label = new JLabel("Callsign:");
306 pane.add(callsign_label, c);
308 c = new GridBagConstraints();
309 c.gridx = 4; c.gridy = 7;
311 c.fill = GridBagConstraints.HORIZONTAL;
313 c.anchor = GridBagConstraints.LINE_START;
316 callsign_value = new JTextField(AltosPreferences.callsign());
317 callsign_value.getDocument().addDocumentListener(this);
318 pane.add(callsign_value, c);
321 c = new GridBagConstraints();
322 c.gridx = 0; c.gridy = 8;
324 c.fill = GridBagConstraints.NONE;
325 c.anchor = GridBagConstraints.LINE_START;
328 flight_log_max_label = new JLabel("Maximum Flight Log Size:");
329 pane.add(flight_log_max_label, c);
331 c = new GridBagConstraints();
332 c.gridx = 4; c.gridy = 8;
334 c.fill = GridBagConstraints.HORIZONTAL;
336 c.anchor = GridBagConstraints.LINE_START;
339 flight_log_max_value = new JComboBox(flight_log_max_values);
340 flight_log_max_value.setEditable(true);
341 flight_log_max_value.addItemListener(this);
342 pane.add(flight_log_max_value, c);
345 c = new GridBagConstraints();
346 c.gridx = 0; c.gridy = 9;
348 c.fill = GridBagConstraints.NONE;
349 c.anchor = GridBagConstraints.LINE_START;
352 ignite_mode_label = new JLabel("Igniter Firing Mode:");
353 pane.add(ignite_mode_label, c);
355 c = new GridBagConstraints();
356 c.gridx = 4; c.gridy = 9;
358 c.fill = GridBagConstraints.HORIZONTAL;
360 c.anchor = GridBagConstraints.LINE_START;
363 ignite_mode_value = new JComboBox(ignite_mode_values);
364 ignite_mode_value.setEditable(false);
365 ignite_mode_value.addItemListener(this);
366 pane.add(ignite_mode_value, c);
368 /* Pad orientation */
369 c = new GridBagConstraints();
370 c.gridx = 0; c.gridy = 10;
372 c.fill = GridBagConstraints.NONE;
373 c.anchor = GridBagConstraints.LINE_START;
376 pad_orientation_label = new JLabel("Pad Orientation:");
377 pane.add(pad_orientation_label, c);
379 c = new GridBagConstraints();
380 c.gridx = 4; c.gridy = 10;
382 c.fill = GridBagConstraints.HORIZONTAL;
384 c.anchor = GridBagConstraints.LINE_START;
387 pad_orientation_value = new JComboBox(pad_orientation_values);
388 pad_orientation_value.setEditable(false);
389 pad_orientation_value.addItemListener(this);
390 pane.add(pad_orientation_value, c);
393 c = new GridBagConstraints();
394 c.gridx = 0; c.gridy = 11;
396 c.fill = GridBagConstraints.NONE;
397 c.anchor = GridBagConstraints.LINE_START;
399 save = new JButton("Save");
401 save.addActionListener(this);
402 save.setActionCommand("Save");
404 c = new GridBagConstraints();
405 c.gridx = 2; c.gridy = 11;
407 c.fill = GridBagConstraints.NONE;
408 c.anchor = GridBagConstraints.CENTER;
410 reset = new JButton("Reset");
412 reset.addActionListener(this);
413 reset.setActionCommand("Reset");
415 c = new GridBagConstraints();
416 c.gridx = 4; c.gridy = 11;
418 c.fill = GridBagConstraints.NONE;
419 c.anchor = GridBagConstraints.CENTER;
421 reboot = new JButton("Reboot");
423 reboot.addActionListener(this);
424 reboot.setActionCommand("Reboot");
426 c = new GridBagConstraints();
427 c.gridx = 6; c.gridy = 11;
429 c.fill = GridBagConstraints.NONE;
430 c.anchor = GridBagConstraints.LINE_END;
432 close = new JButton("Close");
434 close.addActionListener(this);
435 close.setActionCommand("Close");
437 addWindowListener(new ConfigListener(this));
440 /* Once the initial values are set, the config code will show the dialog */
441 public void make_visible() {
443 setLocationRelativeTo(owner);
447 /* If any values have been changed, confirm before closing */
448 public boolean check_dirty(String operation) {
450 Object[] options = { String.format("%s anyway", operation), "Keep editing" };
452 i = JOptionPane.showOptionDialog(this,
453 String.format("Configuration modified. %s anyway?", operation),
454 "Configuration Modified",
455 JOptionPane.DEFAULT_OPTION,
456 JOptionPane.WARNING_MESSAGE,
457 null, options, options[1]);
464 /* Listen for events from our buttons */
465 public void actionPerformed(ActionEvent e) {
466 String cmd = e.getActionCommand();
468 if (cmd.equals("Close") || cmd.equals("Reboot"))
469 if (!check_dirty(cmd))
471 listener.actionPerformed(e);
472 if (cmd.equals("Close") || cmd.equals("Reboot")) {
479 /* ItemListener interface method */
480 public void itemStateChanged(ItemEvent e) {
484 /* DocumentListener interface methods */
485 public void changedUpdate(DocumentEvent e) {
489 public void insertUpdate(DocumentEvent e) {
493 public void removeUpdate(DocumentEvent e) {
497 /* Let the config code hook on a listener */
498 public void addActionListener(ActionListener l) {
502 /* set and get all of the dialog values */
503 public void set_product(String product) {
504 product_value.setText(product);
507 public void set_version(String version) {
508 version_value.setText(version);
511 public void set_serial(int serial) {
512 serial_value.setText(String.format("%d", serial));
515 public void set_main_deploy(int new_main_deploy) {
516 main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy));
519 public int main_deploy() {
520 return Integer.parseInt(main_deploy_value.getSelectedItem().toString());
523 public void set_apogee_delay(int new_apogee_delay) {
524 apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
527 public int apogee_delay() {
528 return Integer.parseInt(apogee_delay_value.getSelectedItem().toString());
531 public void set_radio_channel(int new_radio_channel) {
532 radio_channel_value.setSelectedIndex(new_radio_channel);
535 public int radio_channel() {
536 return radio_channel_value.getSelectedIndex();
539 public void set_radio_calibration(int new_radio_calibration) {
540 radio_calibration_value.setText(String.format("%d", new_radio_calibration));
543 public int radio_calibration() {
544 return Integer.parseInt(radio_calibration_value.getText());
547 public void set_callsign(String new_callsign) {
548 callsign_value.setText(new_callsign);
551 public String callsign() {
552 return callsign_value.getText();
555 public void set_flight_log_max(int new_flight_log_max) {
556 if (new_flight_log_max == 0)
557 flight_log_max_value.setEnabled(false);
558 flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max));
561 public int flight_log_max() {
562 return Integer.parseInt(flight_log_max_value.getSelectedItem().toString());
565 public void set_ignite_mode(int new_ignite_mode) {
566 if (new_ignite_mode < 0) {
567 ignite_mode_value.setEnabled(false);
570 ignite_mode_value.setEnabled(true);
572 ignite_mode_value.setSelectedIndex(new_ignite_mode);
575 public int ignite_mode() {
576 return ignite_mode_value.getSelectedIndex();
580 public void set_pad_orientation(int new_pad_orientation) {
581 if (new_pad_orientation < 0) {
582 pad_orientation_value.setEnabled(false);
583 new_pad_orientation = 0;
585 pad_orientation_value.setEnabled(true);
587 pad_orientation_value.setSelectedIndex(new_pad_orientation);
590 public int pad_orientation() {
591 return pad_orientation_value.getSelectedIndex();
594 public void set_clean() {