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 frequency_label;
47 JLabel radio_calibration_label;
48 JLabel radio_frequency_label;
49 JLabel flight_log_max_label;
50 JLabel ignite_mode_label;
51 JLabel pad_orientation_label;
52 JLabel callsign_label;
60 JComboBox main_deploy_value;
61 JComboBox apogee_delay_value;
62 AltosFreqList radio_frequency_value;
63 JTextField radio_calibration_value;
64 JComboBox flight_log_max_value;
65 JComboBox ignite_mode_value;
66 JComboBox pad_orientation_value;
67 JTextField callsign_value;
74 ActionListener listener;
76 static String[] main_deploy_values = {
77 "100", "150", "200", "250", "300", "350",
81 static String[] apogee_delay_values = {
82 "0", "1", "2", "3", "4", "5"
85 static String[] flight_log_max_values = {
86 "64", "128", "192", "256", "320",
87 "384", "448", "512", "576", "640",
88 "704", "768", "832", "896", "960",
91 static String[] ignite_mode_values = {
97 static String[] pad_orientation_values = {
102 /* A window listener to catch closing events and tell the config code */
103 class ConfigListener extends WindowAdapter {
106 public ConfigListener(AltosConfigUI this_ui) {
110 public void windowClosing(WindowEvent e) {
111 ui.actionPerformed(new ActionEvent(e.getSource(),
112 ActionEvent.ACTION_PERFORMED,
117 /* Build the UI using a grid bag */
118 public AltosConfigUI(JFrame in_owner, boolean remote) {
119 super (in_owner, "Configure TeleMetrum", false);
122 GridBagConstraints c;
124 Insets il = new Insets(4,4,4,4);
125 Insets ir = new Insets(4,4,4,4);
127 pane = getContentPane();
128 pane.setLayout(new GridBagLayout());
131 c = new GridBagConstraints();
132 c.gridx = 0; c.gridy = 0;
134 c.fill = GridBagConstraints.NONE;
135 c.anchor = GridBagConstraints.LINE_START;
137 product_label = new JLabel("Product:");
138 pane.add(product_label, c);
140 c = new GridBagConstraints();
141 c.gridx = 4; c.gridy = 0;
143 c.fill = GridBagConstraints.HORIZONTAL;
145 c.anchor = GridBagConstraints.LINE_START;
147 product_value = new JLabel("");
148 pane.add(product_value, c);
151 c = new GridBagConstraints();
152 c.gridx = 0; c.gridy = 1;
154 c.fill = GridBagConstraints.NONE;
155 c.anchor = GridBagConstraints.LINE_START;
158 version_label = new JLabel("Software version:");
159 pane.add(version_label, c);
161 c = new GridBagConstraints();
162 c.gridx = 4; c.gridy = 1;
164 c.fill = GridBagConstraints.HORIZONTAL;
166 c.anchor = GridBagConstraints.LINE_START;
169 version_value = new JLabel("");
170 pane.add(version_value, c);
173 c = new GridBagConstraints();
174 c.gridx = 0; c.gridy = 2;
176 c.fill = GridBagConstraints.NONE;
177 c.anchor = GridBagConstraints.LINE_START;
180 serial_label = new JLabel("Serial:");
181 pane.add(serial_label, c);
183 c = new GridBagConstraints();
184 c.gridx = 4; c.gridy = 2;
186 c.fill = GridBagConstraints.HORIZONTAL;
188 c.anchor = GridBagConstraints.LINE_START;
191 serial_value = new JLabel("");
192 pane.add(serial_value, c);
195 c = new GridBagConstraints();
196 c.gridx = 0; c.gridy = 3;
198 c.fill = GridBagConstraints.NONE;
199 c.anchor = GridBagConstraints.LINE_START;
202 main_deploy_label = new JLabel("Main Deploy Altitude(m):");
203 pane.add(main_deploy_label, c);
205 c = new GridBagConstraints();
206 c.gridx = 4; c.gridy = 3;
208 c.fill = GridBagConstraints.HORIZONTAL;
210 c.anchor = GridBagConstraints.LINE_START;
213 main_deploy_value = new JComboBox(main_deploy_values);
214 main_deploy_value.setEditable(true);
215 main_deploy_value.addItemListener(this);
216 pane.add(main_deploy_value, c);
219 c = new GridBagConstraints();
220 c.gridx = 0; c.gridy = 4;
222 c.fill = GridBagConstraints.NONE;
223 c.anchor = GridBagConstraints.LINE_START;
226 apogee_delay_label = new JLabel("Apogee Delay(s):");
227 pane.add(apogee_delay_label, c);
229 c = new GridBagConstraints();
230 c.gridx = 4; c.gridy = 4;
232 c.fill = GridBagConstraints.HORIZONTAL;
234 c.anchor = GridBagConstraints.LINE_START;
237 apogee_delay_value = new JComboBox(apogee_delay_values);
238 apogee_delay_value.setEditable(true);
239 apogee_delay_value.addItemListener(this);
240 pane.add(apogee_delay_value, c);
243 c = new GridBagConstraints();
244 c.gridx = 0; c.gridy = 5;
246 c.fill = GridBagConstraints.NONE;
247 c.anchor = GridBagConstraints.LINE_START;
250 radio_frequency_label = new JLabel("Frequency:");
251 pane.add(radio_frequency_label, c);
253 c = new GridBagConstraints();
254 c.gridx = 4; c.gridy = 5;
256 c.fill = GridBagConstraints.HORIZONTAL;
258 c.anchor = GridBagConstraints.LINE_START;
261 radio_frequency_value = new AltosFreqList();
262 radio_frequency_value.addItemListener(this);
263 pane.add(radio_frequency_value, c);
265 /* Radio Calibration */
266 c = new GridBagConstraints();
267 c.gridx = 0; c.gridy = 6;
269 c.fill = GridBagConstraints.NONE;
270 c.anchor = GridBagConstraints.LINE_START;
273 radio_calibration_label = new JLabel("RF Calibration:");
274 pane.add(radio_calibration_label, c);
276 c = new GridBagConstraints();
277 c.gridx = 4; c.gridy = 6;
279 c.fill = GridBagConstraints.HORIZONTAL;
281 c.anchor = GridBagConstraints.LINE_START;
284 radio_calibration_value = new JTextField(String.format("%d", 1186611));
285 radio_calibration_value.getDocument().addDocumentListener(this);
287 radio_calibration_value.setEnabled(false);
288 pane.add(radio_calibration_value, c);
291 c = new GridBagConstraints();
292 c.gridx = 0; c.gridy = 7;
294 c.fill = GridBagConstraints.NONE;
295 c.anchor = GridBagConstraints.LINE_START;
298 callsign_label = new JLabel("Callsign:");
299 pane.add(callsign_label, c);
301 c = new GridBagConstraints();
302 c.gridx = 4; c.gridy = 7;
304 c.fill = GridBagConstraints.HORIZONTAL;
306 c.anchor = GridBagConstraints.LINE_START;
309 callsign_value = new JTextField(AltosPreferences.callsign());
310 callsign_value.getDocument().addDocumentListener(this);
311 pane.add(callsign_value, c);
314 c = new GridBagConstraints();
315 c.gridx = 0; c.gridy = 8;
317 c.fill = GridBagConstraints.NONE;
318 c.anchor = GridBagConstraints.LINE_START;
321 flight_log_max_label = new JLabel("Maximum Flight Log Size:");
322 pane.add(flight_log_max_label, c);
324 c = new GridBagConstraints();
325 c.gridx = 4; c.gridy = 8;
327 c.fill = GridBagConstraints.HORIZONTAL;
329 c.anchor = GridBagConstraints.LINE_START;
332 flight_log_max_value = new JComboBox(flight_log_max_values);
333 flight_log_max_value.setEditable(true);
334 flight_log_max_value.addItemListener(this);
335 pane.add(flight_log_max_value, c);
338 c = new GridBagConstraints();
339 c.gridx = 0; c.gridy = 9;
341 c.fill = GridBagConstraints.NONE;
342 c.anchor = GridBagConstraints.LINE_START;
345 ignite_mode_label = new JLabel("Igniter Firing Mode:");
346 pane.add(ignite_mode_label, c);
348 c = new GridBagConstraints();
349 c.gridx = 4; c.gridy = 9;
351 c.fill = GridBagConstraints.HORIZONTAL;
353 c.anchor = GridBagConstraints.LINE_START;
356 ignite_mode_value = new JComboBox(ignite_mode_values);
357 ignite_mode_value.setEditable(false);
358 ignite_mode_value.addItemListener(this);
359 pane.add(ignite_mode_value, c);
361 /* Pad orientation */
362 c = new GridBagConstraints();
363 c.gridx = 0; c.gridy = 10;
365 c.fill = GridBagConstraints.NONE;
366 c.anchor = GridBagConstraints.LINE_START;
369 pad_orientation_label = new JLabel("Pad Orientation:");
370 pane.add(pad_orientation_label, c);
372 c = new GridBagConstraints();
373 c.gridx = 4; c.gridy = 10;
375 c.fill = GridBagConstraints.HORIZONTAL;
377 c.anchor = GridBagConstraints.LINE_START;
380 pad_orientation_value = new JComboBox(pad_orientation_values);
381 pad_orientation_value.setEditable(false);
382 pad_orientation_value.addItemListener(this);
383 pane.add(pad_orientation_value, c);
386 c = new GridBagConstraints();
387 c.gridx = 0; c.gridy = 11;
389 c.fill = GridBagConstraints.NONE;
390 c.anchor = GridBagConstraints.LINE_START;
392 save = new JButton("Save");
394 save.addActionListener(this);
395 save.setActionCommand("Save");
397 c = new GridBagConstraints();
398 c.gridx = 2; c.gridy = 11;
400 c.fill = GridBagConstraints.NONE;
401 c.anchor = GridBagConstraints.CENTER;
403 reset = new JButton("Reset");
405 reset.addActionListener(this);
406 reset.setActionCommand("Reset");
408 c = new GridBagConstraints();
409 c.gridx = 4; c.gridy = 11;
411 c.fill = GridBagConstraints.NONE;
412 c.anchor = GridBagConstraints.CENTER;
414 reboot = new JButton("Reboot");
416 reboot.addActionListener(this);
417 reboot.setActionCommand("Reboot");
419 c = new GridBagConstraints();
420 c.gridx = 6; c.gridy = 11;
422 c.fill = GridBagConstraints.NONE;
423 c.anchor = GridBagConstraints.LINE_END;
425 close = new JButton("Close");
427 close.addActionListener(this);
428 close.setActionCommand("Close");
430 addWindowListener(new ConfigListener(this));
433 /* Once the initial values are set, the config code will show the dialog */
434 public void make_visible() {
436 setLocationRelativeTo(owner);
440 /* If any values have been changed, confirm before closing */
441 public boolean check_dirty(String operation) {
443 Object[] options = { String.format("%s anyway", operation), "Keep editing" };
445 i = JOptionPane.showOptionDialog(this,
446 String.format("Configuration modified. %s anyway?", operation),
447 "Configuration Modified",
448 JOptionPane.DEFAULT_OPTION,
449 JOptionPane.WARNING_MESSAGE,
450 null, options, options[1]);
457 /* Listen for events from our buttons */
458 public void actionPerformed(ActionEvent e) {
459 String cmd = e.getActionCommand();
461 if (cmd.equals("Close") || cmd.equals("Reboot"))
462 if (!check_dirty(cmd))
464 listener.actionPerformed(e);
465 if (cmd.equals("Close") || cmd.equals("Reboot")) {
472 /* ItemListener interface method */
473 public void itemStateChanged(ItemEvent e) {
477 /* DocumentListener interface methods */
478 public void changedUpdate(DocumentEvent e) {
482 public void insertUpdate(DocumentEvent e) {
486 public void removeUpdate(DocumentEvent e) {
490 /* Let the config code hook on a listener */
491 public void addActionListener(ActionListener l) {
495 /* set and get all of the dialog values */
496 public void set_product(String product) {
497 radio_frequency_value.set_product(product);
498 product_value.setText(product);
501 public void set_version(String version) {
502 version_value.setText(version);
505 public void set_serial(int serial) {
506 radio_frequency_value.set_serial(serial);
507 serial_value.setText(String.format("%d", serial));
510 public void set_main_deploy(int new_main_deploy) {
511 main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy));
514 public int main_deploy() {
515 return Integer.parseInt(main_deploy_value.getSelectedItem().toString());
518 public void set_apogee_delay(int new_apogee_delay) {
519 apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
522 public int apogee_delay() {
523 return Integer.parseInt(apogee_delay_value.getSelectedItem().toString());
526 public void set_radio_frequency(double new_radio_frequency) {
528 for (i = 0; i < radio_frequency_value.getItemCount(); i++) {
529 AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i);
531 if (f.close(new_radio_frequency)) {
532 radio_frequency_value.setSelectedIndex(i);
536 for (i = 0; i < radio_frequency_value.getItemCount(); i++) {
537 AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i);
539 if (new_radio_frequency < f.frequency)
542 String description = String.format("%s serial %s",
543 product_value.getText(),
544 serial_value.getText());
545 AltosFrequency new_frequency = new AltosFrequency(new_radio_frequency, description);
546 AltosPreferences.add_common_frequency(new_frequency);
547 radio_frequency_value.insertItemAt(new_frequency, i);
550 public double radio_frequency() {
551 return radio_frequency_value.frequency();
554 public void set_radio_calibration(int new_radio_calibration) {
555 radio_calibration_value.setText(String.format("%d", new_radio_calibration));
558 public int radio_calibration() {
559 return Integer.parseInt(radio_calibration_value.getText());
562 public void set_callsign(String new_callsign) {
563 callsign_value.setText(new_callsign);
566 public String callsign() {
567 return callsign_value.getText();
570 public void set_flight_log_max(int new_flight_log_max) {
571 if (new_flight_log_max == 0)
572 flight_log_max_value.setEnabled(false);
573 flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max));
576 public int flight_log_max() {
577 return Integer.parseInt(flight_log_max_value.getSelectedItem().toString());
580 public void set_ignite_mode(int new_ignite_mode) {
581 if (new_ignite_mode < 0) {
582 ignite_mode_value.setEnabled(false);
585 ignite_mode_value.setEnabled(true);
587 ignite_mode_value.setSelectedIndex(new_ignite_mode);
590 public int ignite_mode() {
591 return ignite_mode_value.getSelectedIndex();
595 public void set_pad_orientation(int new_pad_orientation) {
596 if (new_pad_orientation < 0) {
597 pad_orientation_value.setEnabled(false);
598 new_pad_orientation = 0;
600 pad_orientation_value.setEnabled(true);
602 pad_orientation_value.setSelectedIndex(new_pad_orientation);
605 public int pad_orientation() {
606 return pad_orientation_value.getSelectedIndex();
609 public void set_clean() {