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.event.*;
25 import org.altusmetrum.altoslib_9.*;
26 import org.altusmetrum.altosuilib_9.*;
28 public class AltosConfigUI
30 implements ActionListener, ItemListener, DocumentListener, AltosConfigValues, AltosUnitsListener
37 JLabel main_deploy_label;
38 JLabel apogee_delay_label;
39 JLabel apogee_lockout_label;
40 JLabel frequency_label;
41 JLabel radio_calibration_label;
42 JLabel radio_frequency_label;
43 JLabel radio_enable_label;
45 JLabel aprs_interval_label;
46 JLabel aprs_ssid_label;
47 JLabel aprs_format_label;
48 JLabel flight_log_max_label;
49 JLabel ignite_mode_label;
50 JLabel pad_orientation_label;
51 JLabel callsign_label;
53 JLabel tracker_motion_label;
54 JLabel tracker_interval_label;
62 JComboBox<String> main_deploy_value;
63 JComboBox<String> apogee_delay_value;
64 JComboBox<String> apogee_lockout_value;
65 AltosUIFreqList radio_frequency_value;
66 JTextField radio_calibration_value;
67 JRadioButton radio_enable_value;
68 AltosUIRateList rate_value;
69 JComboBox<String> aprs_interval_value;
70 JComboBox<Integer> aprs_ssid_value;
71 JComboBox<String> aprs_format_value;
72 JComboBox<String> flight_log_max_value;
73 JComboBox<String> ignite_mode_value;
74 JComboBox<String> pad_orientation_value;
75 JTextField callsign_value;
76 JComboBox<String> beep_value;
77 JComboBox<String> tracker_motion_value;
78 JComboBox<String> tracker_interval_value;
88 double pyro_firing_time;
90 ActionListener listener;
92 static String[] main_deploy_values_m = {
93 "100", "150", "200", "250", "300", "350",
97 static String[] main_deploy_values_ft = {
98 "250", "500", "750", "1000", "1250", "1500",
102 static String[] apogee_delay_values = {
103 "0", "1", "2", "3", "4", "5"
106 static String[] apogee_lockout_values = {
107 "0", "5", "10", "15", "20"
110 static String[] ignite_mode_values = {
116 static String[] aprs_interval_values = {
123 static Integer[] aprs_ssid_values = {
124 0, 1, 2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
127 static String[] beep_values = {
133 static String[] pad_orientation_values = {
138 static String[] tracker_motion_values_m = {
145 static String[] tracker_motion_values_ft = {
152 static String[] tracker_interval_values = {
159 /* A window listener to catch closing events and tell the config code */
160 class ConfigListener extends WindowAdapter {
163 public ConfigListener(AltosConfigUI this_ui) {
167 public void windowClosing(WindowEvent e) {
168 ui.actionPerformed(new ActionEvent(e.getSource(),
169 ActionEvent.ACTION_PERFORMED,
174 boolean is_telemini_v1() {
175 String product = product_value.getText();
176 return product != null && product.startsWith("TeleMini-v1");
179 boolean is_telemini() {
180 String product = product_value.getText();
181 return product != null && product.startsWith("TeleMini");
184 boolean is_easymini() {
185 String product = product_value.getText();
186 return product != null && product.startsWith("EasyMini");
189 boolean is_telemetrum() {
190 String product = product_value.getText();
191 return product != null && product.startsWith("TeleMetrum");
194 void set_radio_calibration_tool_tip() {
195 if (radio_calibration_value.isEnabled())
196 radio_calibration_value.setToolTipText("Tune radio output to match desired frequency");
198 radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode");
201 void set_radio_enable_tool_tip() {
202 if (radio_enable_value.isEnabled())
203 radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
205 radio_enable_value.setToolTipText("Firmware version does not support disabling radio");
208 void set_rate_tool_tip() {
209 if (rate_value.isEnabled())
210 rate_value.setToolTipText("Select telemetry baud rate");
212 rate_value.setToolTipText("Firmware version does not support variable telemetry rates");
215 void set_aprs_interval_tool_tip() {
216 if (aprs_interval_value.isEnabled())
217 aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");
219 aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
222 void set_aprs_ssid_tool_tip() {
223 if (aprs_ssid_value.isEnabled())
224 aprs_ssid_value.setToolTipText("Set the APRS SSID (secondary station identifier)");
225 else if (aprs_ssid_value.isEnabled())
226 aprs_ssid_value.setToolTipText("Software version doesn't support setting the APRS SSID");
228 aprs_ssid_value.setToolTipText("Hardware doesn't support APRS");
231 void set_aprs_format_tool_tip() {
232 if (aprs_format_value.isEnabled())
233 aprs_format_value.setToolTipText("Set the APRS format (compressed/uncompressed)");
234 else if (aprs_format_value.isEnabled())
235 aprs_format_value.setToolTipText("Software version doesn't support setting the APRS format");
237 aprs_format_value.setToolTipText("Hardware doesn't support APRS");
240 void set_flight_log_max_tool_tip() {
241 if (flight_log_max_value.isEnabled())
242 flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
244 if (is_telemini_v1())
245 flight_log_max_value.setToolTipText("TeleMini-v1 stores only one flight");
247 flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory");
251 void set_ignite_mode_tool_tip() {
252 if (ignite_mode_value.isEnabled())
253 ignite_mode_value.setToolTipText("Select when igniters will be fired");
255 ignite_mode_value.setToolTipText("Older firmware could not select ignite mode");
258 void set_pad_orientation_tool_tip() {
259 if (pad_orientation_value.isEnabled())
260 pad_orientation_value.setToolTipText("How will the computer be mounted in the airframe");
263 pad_orientation_value.setToolTipText("Older TeleMetrum firmware must fly antenna forward");
264 else if (is_telemini() || is_easymini())
265 pad_orientation_value.setToolTipText("TeleMini and EasyMini don't care how they are mounted");
267 pad_orientation_value.setToolTipText("Can't select orientation");
271 void set_beep_tool_tip() {
272 if (beep_value.isEnabled())
273 beep_value.setToolTipText("What frequency the beeper will sound at");
275 beep_value.setToolTipText("Older firmware could not select beeper frequency");
278 /* Build the UI using a grid bag */
279 public AltosConfigUI(JFrame in_owner, boolean remote) {
280 super (in_owner, "Configure Flight Computer", false);
283 GridBagConstraints c;
286 Insets il = new Insets(4,4,4,4);
287 Insets ir = new Insets(4,4,4,4);
289 pane = getContentPane();
290 pane.setLayout(new GridBagLayout());
293 c = new GridBagConstraints();
294 c.gridx = 0; c.gridy = row;
296 c.fill = GridBagConstraints.NONE;
297 c.anchor = GridBagConstraints.LINE_START;
299 product_label = new JLabel("Product:");
300 pane.add(product_label, c);
302 c = new GridBagConstraints();
303 c.gridx = 4; c.gridy = row;
305 c.fill = GridBagConstraints.HORIZONTAL;
307 c.anchor = GridBagConstraints.LINE_START;
309 product_value = new JLabel("");
310 pane.add(product_value, c);
314 c = new GridBagConstraints();
315 c.gridx = 0; c.gridy = row;
317 c.fill = GridBagConstraints.NONE;
318 c.anchor = GridBagConstraints.LINE_START;
321 version_label = new JLabel("Software version:");
322 pane.add(version_label, c);
324 c = new GridBagConstraints();
325 c.gridx = 4; c.gridy = row;
327 c.fill = GridBagConstraints.HORIZONTAL;
329 c.anchor = GridBagConstraints.LINE_START;
332 version_value = new JLabel("");
333 pane.add(version_value, c);
337 c = new GridBagConstraints();
338 c.gridx = 0; c.gridy = row;
340 c.fill = GridBagConstraints.NONE;
341 c.anchor = GridBagConstraints.LINE_START;
344 serial_label = new JLabel("Serial:");
345 pane.add(serial_label, c);
347 c = new GridBagConstraints();
348 c.gridx = 4; c.gridy = row;
350 c.fill = GridBagConstraints.HORIZONTAL;
352 c.anchor = GridBagConstraints.LINE_START;
355 serial_value = new JLabel("");
356 pane.add(serial_value, c);
360 c = new GridBagConstraints();
361 c.gridx = 0; c.gridy = row;
363 c.fill = GridBagConstraints.NONE;
364 c.anchor = GridBagConstraints.LINE_START;
367 main_deploy_label = new JLabel(get_main_deploy_label());
368 pane.add(main_deploy_label, c);
370 c = new GridBagConstraints();
371 c.gridx = 4; c.gridy = row;
373 c.fill = GridBagConstraints.HORIZONTAL;
375 c.anchor = GridBagConstraints.LINE_START;
378 main_deploy_value = new JComboBox<String>(main_deploy_values());
379 main_deploy_value.setEditable(true);
380 main_deploy_value.addItemListener(this);
381 pane.add(main_deploy_value, c);
382 main_deploy_value.setToolTipText("Height above pad altitude to fire main charge");
386 c = new GridBagConstraints();
387 c.gridx = 0; c.gridy = row;
389 c.fill = GridBagConstraints.NONE;
390 c.anchor = GridBagConstraints.LINE_START;
393 apogee_delay_label = new JLabel("Apogee Delay(s):");
394 pane.add(apogee_delay_label, c);
396 c = new GridBagConstraints();
397 c.gridx = 4; c.gridy = row;
399 c.fill = GridBagConstraints.HORIZONTAL;
401 c.anchor = GridBagConstraints.LINE_START;
404 apogee_delay_value = new JComboBox<String>(apogee_delay_values);
405 apogee_delay_value.setEditable(true);
406 apogee_delay_value.addItemListener(this);
407 pane.add(apogee_delay_value, c);
408 apogee_delay_value.setToolTipText("Delay after apogee before charge fires");
412 c = new GridBagConstraints();
413 c.gridx = 0; c.gridy = row;
415 c.fill = GridBagConstraints.NONE;
416 c.anchor = GridBagConstraints.LINE_START;
419 apogee_lockout_label = new JLabel("Apogee Lockout(s):");
420 pane.add(apogee_lockout_label, c);
422 c = new GridBagConstraints();
423 c.gridx = 4; c.gridy = row;
425 c.fill = GridBagConstraints.HORIZONTAL;
427 c.anchor = GridBagConstraints.LINE_START;
430 apogee_lockout_value = new JComboBox<String>(apogee_lockout_values);
431 apogee_lockout_value.setEditable(true);
432 apogee_lockout_value.addItemListener(this);
433 pane.add(apogee_lockout_value, c);
434 apogee_lockout_value.setToolTipText("Time after boost while apogee detection is locked out");
438 c = new GridBagConstraints();
439 c.gridx = 0; c.gridy = row;
441 c.fill = GridBagConstraints.NONE;
442 c.anchor = GridBagConstraints.LINE_START;
445 radio_frequency_label = new JLabel("Frequency:");
446 pane.add(radio_frequency_label, c);
448 c = new GridBagConstraints();
449 c.gridx = 4; c.gridy = row;
451 c.fill = GridBagConstraints.HORIZONTAL;
453 c.anchor = GridBagConstraints.LINE_START;
456 radio_frequency_value = new AltosUIFreqList();
457 radio_frequency_value.addItemListener(this);
458 pane.add(radio_frequency_value, c);
459 radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
462 /* Radio Calibration */
463 c = new GridBagConstraints();
464 c.gridx = 0; c.gridy = row;
466 c.fill = GridBagConstraints.NONE;
467 c.anchor = GridBagConstraints.LINE_START;
470 radio_calibration_label = new JLabel("RF Calibration:");
471 pane.add(radio_calibration_label, c);
473 c = new GridBagConstraints();
474 c.gridx = 4; c.gridy = row;
476 c.fill = GridBagConstraints.HORIZONTAL;
478 c.anchor = GridBagConstraints.LINE_START;
481 radio_calibration_value = new JTextField(String.format("%d", 1186611));
482 radio_calibration_value.getDocument().addDocumentListener(this);
484 radio_calibration_value.setEnabled(false);
485 pane.add(radio_calibration_value, c);
486 set_radio_calibration_tool_tip();
490 c = new GridBagConstraints();
491 c.gridx = 0; c.gridy = row;
493 c.fill = GridBagConstraints.NONE;
494 c.anchor = GridBagConstraints.LINE_START;
497 radio_enable_label = new JLabel("Telemetry/RDF/APRS Enable:");
498 pane.add(radio_enable_label, c);
500 c = new GridBagConstraints();
501 c.gridx = 4; c.gridy = row;
503 c.fill = GridBagConstraints.HORIZONTAL;
505 c.anchor = GridBagConstraints.LINE_START;
508 radio_enable_value = new JRadioButton("Enabled");
509 radio_enable_value.addItemListener(this);
510 pane.add(radio_enable_value, c);
511 set_radio_enable_tool_tip();
515 c = new GridBagConstraints();
516 c.gridx = 0; c.gridy = row;
518 c.fill = GridBagConstraints.NONE;
519 c.anchor = GridBagConstraints.LINE_START;
522 rate_label = new JLabel("Telemetry baud rate:");
523 pane.add(rate_label, c);
525 c = new GridBagConstraints();
526 c.gridx = 4; c.gridy = row;
528 c.fill = GridBagConstraints.HORIZONTAL;
530 c.anchor = GridBagConstraints.LINE_START;
533 rate_value = new AltosUIRateList();
534 rate_value.addItemListener(this);
535 pane.add(rate_value, c);
540 c = new GridBagConstraints();
541 c.gridx = 0; c.gridy = row;
543 c.fill = GridBagConstraints.NONE;
544 c.anchor = GridBagConstraints.LINE_START;
547 aprs_interval_label = new JLabel("APRS Interval(s):");
548 pane.add(aprs_interval_label, c);
550 c = new GridBagConstraints();
551 c.gridx = 4; c.gridy = row;
553 c.fill = GridBagConstraints.HORIZONTAL;
555 c.anchor = GridBagConstraints.LINE_START;
558 aprs_interval_value = new JComboBox<String>(aprs_interval_values);
559 aprs_interval_value.setEditable(true);
560 aprs_interval_value.addItemListener(this);
561 pane.add(aprs_interval_value, c);
562 set_aprs_interval_tool_tip();
566 c = new GridBagConstraints();
567 c.gridx = 0; c.gridy = row;
569 c.fill = GridBagConstraints.NONE;
570 c.anchor = GridBagConstraints.LINE_START;
573 aprs_ssid_label = new JLabel("APRS SSID:");
574 pane.add(aprs_ssid_label, c);
576 c = new GridBagConstraints();
577 c.gridx = 4; c.gridy = row;
579 c.fill = GridBagConstraints.HORIZONTAL;
581 c.anchor = GridBagConstraints.LINE_START;
584 aprs_ssid_value = new JComboBox<Integer>(aprs_ssid_values);
585 aprs_ssid_value.setEditable(false);
586 aprs_ssid_value.addItemListener(this);
587 aprs_ssid_value.setMaximumRowCount(aprs_ssid_values.length);
588 pane.add(aprs_ssid_value, c);
589 set_aprs_ssid_tool_tip();
593 c = new GridBagConstraints();
594 c.gridx = 0; c.gridy = row;
596 c.fill = GridBagConstraints.NONE;
597 c.anchor = GridBagConstraints.LINE_START;
600 aprs_format_label = new JLabel("APRS format:");
601 pane.add(aprs_format_label, c);
603 c = new GridBagConstraints();
604 c.gridx = 4; c.gridy = row;
606 c.fill = GridBagConstraints.HORIZONTAL;
608 c.anchor = GridBagConstraints.LINE_START;
611 aprs_format_value = new JComboBox<String>(AltosLib.ao_aprs_format_name);
612 aprs_format_value.setEditable(false);
613 aprs_format_value.addItemListener(this);
614 aprs_format_value.setMaximumRowCount(AltosLib.ao_aprs_format_name.length);
615 pane.add(aprs_format_value, c);
616 set_aprs_format_tool_tip();
620 c = new GridBagConstraints();
621 c.gridx = 0; c.gridy = row;
623 c.fill = GridBagConstraints.NONE;
624 c.anchor = GridBagConstraints.LINE_START;
627 callsign_label = new JLabel("Callsign:");
628 pane.add(callsign_label, c);
630 c = new GridBagConstraints();
631 c.gridx = 4; c.gridy = row;
633 c.fill = GridBagConstraints.HORIZONTAL;
635 c.anchor = GridBagConstraints.LINE_START;
638 callsign_value = new JTextField(AltosUIPreferences.callsign());
639 callsign_value.getDocument().addDocumentListener(this);
640 pane.add(callsign_value, c);
641 callsign_value.setToolTipText("Callsign reported in telemetry data");
645 c = new GridBagConstraints();
646 c.gridx = 0; c.gridy = row;
648 c.fill = GridBagConstraints.NONE;
649 c.anchor = GridBagConstraints.LINE_START;
652 flight_log_max_label = new JLabel("Maximum Flight Log Size (kB):");
653 pane.add(flight_log_max_label, c);
655 c = new GridBagConstraints();
656 c.gridx = 4; c.gridy = row;
658 c.fill = GridBagConstraints.HORIZONTAL;
660 c.anchor = GridBagConstraints.LINE_START;
663 flight_log_max_value = new JComboBox<String>();
664 flight_log_max_value.setEditable(true);
665 flight_log_max_value.addItemListener(this);
666 pane.add(flight_log_max_value, c);
667 set_flight_log_max_tool_tip();
671 c = new GridBagConstraints();
672 c.gridx = 0; c.gridy = row;
674 c.fill = GridBagConstraints.NONE;
675 c.anchor = GridBagConstraints.LINE_START;
678 ignite_mode_label = new JLabel("Igniter Firing Mode:");
679 pane.add(ignite_mode_label, c);
681 c = new GridBagConstraints();
682 c.gridx = 4; c.gridy = row;
684 c.fill = GridBagConstraints.HORIZONTAL;
686 c.anchor = GridBagConstraints.LINE_START;
689 ignite_mode_value = new JComboBox<String>(ignite_mode_values);
690 ignite_mode_value.setEditable(false);
691 ignite_mode_value.addItemListener(this);
692 pane.add(ignite_mode_value, c);
693 set_ignite_mode_tool_tip();
696 /* Pad orientation */
697 c = new GridBagConstraints();
698 c.gridx = 0; c.gridy = row;
700 c.fill = GridBagConstraints.NONE;
701 c.anchor = GridBagConstraints.LINE_START;
704 pad_orientation_label = new JLabel("Pad Orientation:");
705 pane.add(pad_orientation_label, c);
707 c = new GridBagConstraints();
708 c.gridx = 4; c.gridy = row;
710 c.fill = GridBagConstraints.HORIZONTAL;
712 c.anchor = GridBagConstraints.LINE_START;
715 pad_orientation_value = new JComboBox<String>(pad_orientation_values);
716 pad_orientation_value.setEditable(false);
717 pad_orientation_value.addItemListener(this);
718 pane.add(pad_orientation_value, c);
719 set_pad_orientation_tool_tip();
723 c = new GridBagConstraints();
724 c.gridx = 0; c.gridy = row;
726 c.fill = GridBagConstraints.NONE;
727 c.anchor = GridBagConstraints.LINE_START;
730 beep_label = new JLabel("Beeper Frequency:");
731 pane.add(beep_label, c);
733 c = new GridBagConstraints();
734 c.gridx = 4; c.gridy = row;
736 c.fill = GridBagConstraints.HORIZONTAL;
738 c.anchor = GridBagConstraints.LINE_START;
741 beep_value = new JComboBox<String>(beep_values);
742 beep_value.setEditable(true);
743 beep_value.addItemListener(this);
744 pane.add(beep_value, c);
748 /* Tracker triger horiz distances */
749 c = new GridBagConstraints();
750 c.gridx = 0; c.gridy = row;
752 c.fill = GridBagConstraints.NONE;
753 c.anchor = GridBagConstraints.LINE_START;
756 tracker_motion_label = new JLabel(get_tracker_motion_label());
757 pane.add(tracker_motion_label, c);
759 c = new GridBagConstraints();
760 c.gridx = 4; c.gridy = row;
762 c.fill = GridBagConstraints.HORIZONTAL;
764 c.anchor = GridBagConstraints.LINE_START;
767 tracker_motion_value = new JComboBox<String>(tracker_motion_values());
768 tracker_motion_value.setEditable(true);
769 tracker_motion_value.addItemListener(this);
770 pane.add(tracker_motion_value, c);
773 /* Tracker triger vert distances */
774 c = new GridBagConstraints();
775 c.gridx = 0; c.gridy = row;
777 c.fill = GridBagConstraints.NONE;
778 c.anchor = GridBagConstraints.LINE_START;
781 tracker_interval_label = new JLabel("Position Reporting Interval(s):");
782 pane.add(tracker_interval_label, c);
784 c = new GridBagConstraints();
785 c.gridx = 4; c.gridy = row;
787 c.fill = GridBagConstraints.HORIZONTAL;
789 c.anchor = GridBagConstraints.LINE_START;
792 tracker_interval_value = new JComboBox<String>(tracker_interval_values);
793 tracker_interval_value.setEditable(true);
794 tracker_interval_value.addItemListener(this);
795 pane.add(tracker_interval_value, c);
796 set_tracker_tool_tip();
800 c = new GridBagConstraints();
801 c.gridx = 4; c.gridy = row;
803 c.fill = GridBagConstraints.HORIZONTAL;
804 c.anchor = GridBagConstraints.LINE_START;
807 pyro = new JButton("Configure Pyro Channels");
809 pyro.addActionListener(this);
810 pyro.setActionCommand("Pyro");
814 c = new GridBagConstraints();
815 c.gridx = 0; c.gridy = row;
817 c.fill = GridBagConstraints.NONE;
818 c.anchor = GridBagConstraints.LINE_START;
820 save = new JButton("Save");
822 save.addActionListener(this);
823 save.setActionCommand("Save");
825 c = new GridBagConstraints();
826 c.gridx = 2; c.gridy = row;
828 c.fill = GridBagConstraints.NONE;
829 c.anchor = GridBagConstraints.CENTER;
831 reset = new JButton("Reset");
833 reset.addActionListener(this);
834 reset.setActionCommand("Reset");
836 c = new GridBagConstraints();
837 c.gridx = 4; c.gridy = row;
839 c.fill = GridBagConstraints.NONE;
840 c.anchor = GridBagConstraints.CENTER;
842 reboot = new JButton("Reboot");
844 reboot.addActionListener(this);
845 reboot.setActionCommand("Reboot");
847 c = new GridBagConstraints();
848 c.gridx = 6; c.gridy = row;
850 c.fill = GridBagConstraints.NONE;
851 c.anchor = GridBagConstraints.LINE_END;
853 close = new JButton("Close");
855 close.addActionListener(this);
856 close.setActionCommand("Close");
858 addWindowListener(new ConfigListener(this));
859 AltosPreferences.register_units_listener(this);
862 /* Once the initial values are set, the config code will show the dialog */
863 public void make_visible() {
865 setLocationRelativeTo(owner);
869 /* If any values have been changed, confirm before closing */
870 public boolean check_dirty(String operation) {
872 Object[] options = { String.format("%s anyway", operation), "Keep editing" };
874 i = JOptionPane.showOptionDialog(this,
875 String.format("Configuration modified. %s anyway?", operation),
876 "Configuration Modified",
877 JOptionPane.DEFAULT_OPTION,
878 JOptionPane.WARNING_MESSAGE,
879 null, options, options[1]);
888 save.setEnabled(true);
891 public void set_clean() {
893 save.setEnabled(false);
896 AltosConfigPyroUI pyro_ui;
898 public void dispose() {
901 AltosPreferences.unregister_units_listener(this);
905 /* Listen for events from our buttons */
906 public void actionPerformed(ActionEvent e) {
907 String cmd = e.getActionCommand();
909 if (cmd.equals("Pyro")) {
910 if (pyro_ui == null && pyros != null)
911 pyro_ui = new AltosConfigPyroUI(this, pyros, pyro_firing_time);
913 pyro_ui.make_visible();
917 if (cmd.equals("Close") || cmd.equals("Reboot"))
918 if (!check_dirty(cmd))
920 listener.actionPerformed(e);
921 if (cmd.equals("Close") || cmd.equals("Reboot")) {
928 /* ItemListener interface method */
929 public void itemStateChanged(ItemEvent e) {
933 /* DocumentListener interface methods */
934 public void changedUpdate(DocumentEvent e) {
938 public void insertUpdate(DocumentEvent e) {
942 public void removeUpdate(DocumentEvent e) {
946 /* Let the config code hook on a listener */
947 public void addActionListener(ActionListener l) {
951 /* set and get all of the dialog values */
952 public void set_product(String product) {
953 radio_frequency_value.set_product(product);
954 product_value.setText(product);
955 set_pad_orientation_tool_tip();
956 set_flight_log_max_tool_tip();
959 public void set_version(String version) {
960 version_value.setText(version);
963 public void set_serial(int serial) {
964 radio_frequency_value.set_serial(serial);
965 serial_value.setText(String.format("%d", serial));
968 public void set_altitude_32(int altitude_32) {
971 public void set_main_deploy(int new_main_deploy) {
972 main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy));
973 main_deploy_value.setEnabled(new_main_deploy >= 0);
975 main_deploy_value.setVisible(new_main_deploy >= 0);
976 main_deploy_label.setVisible(new_main_deploy >= 0);
980 public int main_deploy() throws AltosConfigDataException {
981 String str = main_deploy_value.getSelectedItem().toString();
983 return (int) (AltosConvert.height.parse_locale(str) + 0.5);
984 } catch (ParseException pe) {
985 throw new AltosConfigDataException("invalid main deploy height %s", str);
989 String get_main_deploy_label() {
990 return String.format("Main Deploy Altitude(%s):", AltosConvert.height.show_units());
993 String[] main_deploy_values() {
994 if (AltosConvert.imperial_units)
995 return main_deploy_values_ft;
997 return main_deploy_values_m;
1000 void set_main_deploy_values() {
1001 String[] v = main_deploy_values();
1002 while (main_deploy_value.getItemCount() > 0)
1003 main_deploy_value.removeItemAt(0);
1004 for (int i = 0; i < v.length; i++)
1005 main_deploy_value.addItem(v[i]);
1006 main_deploy_value.setMaximumRowCount(v.length);
1009 public void units_changed(boolean imperial_units) {
1010 boolean was_dirty = dirty;
1012 String v = main_deploy_value.getSelectedItem().toString();
1013 main_deploy_label.setText(get_main_deploy_label());
1014 set_main_deploy_values();
1016 int m = (int) (AltosConvert.height.parse_locale(v, !imperial_units) + 0.5);
1018 } catch (ParseException pe) {
1021 if (tracker_motion_value.isEnabled()) {
1022 String motion = tracker_motion_value.getSelectedItem().toString();
1023 tracker_motion_label.setText(get_tracker_motion_label());
1024 set_tracker_motion_values();
1026 int m = (int) (AltosConvert.height.parse_locale(motion, !imperial_units) + 0.5);
1027 set_tracker_motion(m);
1028 } catch (ParseException pe) {
1036 public void set_apogee_delay(int new_apogee_delay) {
1037 apogee_delay_value.setVisible(new_apogee_delay >= 0);
1038 apogee_delay_label.setVisible(new_apogee_delay >= 0);
1040 apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
1041 apogee_delay_value.setEnabled(new_apogee_delay >= 0);
1044 private int parse_int(String name, String s, boolean split) throws AltosConfigDataException {
1047 v = s.split("\\s+")[0];
1049 return Integer.parseInt(v);
1050 } catch (NumberFormatException ne) {
1051 throw new AltosConfigDataException("Invalid %s \"%s\"", name, s);
1055 public int apogee_delay() throws AltosConfigDataException {
1056 return parse_int("apogee delay", apogee_delay_value.getSelectedItem().toString(), false);
1059 public void set_apogee_lockout(int new_apogee_lockout) {
1060 apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout));
1061 apogee_lockout_value.setEnabled(new_apogee_lockout >= 0);
1063 apogee_lockout_value.setVisible(new_apogee_lockout >= 0);
1064 apogee_lockout_label.setVisible(new_apogee_lockout >= 0);
1067 public int apogee_lockout() throws AltosConfigDataException {
1068 return parse_int("apogee lockout", apogee_lockout_value.getSelectedItem().toString(), false);
1071 public void set_radio_frequency(double new_radio_frequency) {
1072 radio_frequency_label.setVisible(new_radio_frequency >= 0);
1073 radio_frequency_value.set_frequency(new_radio_frequency);
1076 public double radio_frequency() {
1077 return radio_frequency_value.frequency();
1080 public void set_radio_calibration(int new_radio_calibration) {
1081 radio_calibration_value.setVisible(new_radio_calibration >= 0);
1082 radio_calibration_label.setVisible(new_radio_calibration >= 0);
1084 if (new_radio_calibration < 0)
1085 radio_calibration_value.setText("Disabled");
1087 radio_calibration_value.setText(String.format("%d", new_radio_calibration));
1090 public int radio_calibration() throws AltosConfigDataException {
1091 return parse_int("radio calibration", radio_calibration_value.getText(), false);
1094 public void set_radio_enable(int new_radio_enable) {
1095 radio_enable_label.setVisible(new_radio_enable >= 0);
1096 radio_enable_value.setVisible(new_radio_enable >= 0);
1098 if (new_radio_enable >= 0) {
1099 radio_enable_value.setSelected(new_radio_enable > 0);
1100 radio_enable_value.setEnabled(true);
1102 radio_enable_value.setSelected(true);
1103 radio_enable_value.setEnabled(false);
1105 set_radio_enable_tool_tip();
1108 public int radio_enable() {
1109 if (radio_enable_value.isEnabled())
1110 return radio_enable_value.isSelected() ? 1 : 0;
1115 public void set_telemetry_rate(int new_rate) {
1116 rate_label.setVisible(new_rate >= 0);
1118 rate_value.set_rate(new_rate);
1121 public int telemetry_rate() {
1122 return rate_value.rate();
1125 public void set_callsign(String new_callsign) {
1126 callsign_value.setVisible(new_callsign != null);
1127 callsign_label.setVisible(new_callsign != null);
1129 callsign_value.setText(new_callsign);
1132 public String callsign() {
1133 return callsign_value.getText();
1136 int flight_log_max_limit;
1139 public String flight_log_max_label(int flight_log_max) {
1140 if (flight_log_max_limit != 0) {
1141 int nflight = flight_log_max_limit / flight_log_max;
1142 String plural = nflight > 1 ? "s" : "";
1144 return String.format("%d (%d flight%s)", flight_log_max, nflight, plural);
1146 return String.format("%d", flight_log_max);
1149 public void set_flight_log_max(int new_flight_log_max) {
1150 flight_log_max_value.setVisible(new_flight_log_max >= 0);
1151 flight_log_max_label.setVisible(new_flight_log_max >= 0);
1153 flight_log_max_value.setSelectedItem(flight_log_max_label(new_flight_log_max));
1154 flight_log_max = new_flight_log_max;
1155 set_flight_log_max_tool_tip();
1158 public void set_flight_log_max_enabled(boolean enable) {
1159 flight_log_max_value.setEnabled(enable);
1160 set_flight_log_max_tool_tip();
1163 public int flight_log_max() throws AltosConfigDataException {
1164 return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true);
1167 public void set_flight_log_max_limit(int new_flight_log_max_limit) {
1168 flight_log_max_limit = new_flight_log_max_limit;
1169 flight_log_max_value.removeAllItems();
1170 for (int i = 8; i >= 1; i--) {
1171 int size = flight_log_max_limit / i;
1172 flight_log_max_value.addItem(String.format("%d (%d flights)", size, i));
1174 if (flight_log_max != 0)
1175 set_flight_log_max(flight_log_max);
1178 public void set_ignite_mode(int new_ignite_mode) {
1179 ignite_mode_value.setVisible(new_ignite_mode >= 0);
1180 ignite_mode_label.setVisible(new_ignite_mode >= 0);
1182 if (new_ignite_mode >= ignite_mode_values.length)
1183 new_ignite_mode = 0;
1184 if (new_ignite_mode < 0) {
1185 ignite_mode_value.setEnabled(false);
1186 new_ignite_mode = 0;
1188 ignite_mode_value.setEnabled(true);
1190 ignite_mode_value.setSelectedIndex(new_ignite_mode);
1191 set_ignite_mode_tool_tip();
1194 public int ignite_mode() {
1195 if (ignite_mode_value.isEnabled())
1196 return ignite_mode_value.getSelectedIndex();
1202 public void set_pad_orientation(int new_pad_orientation) {
1203 pad_orientation_value.setVisible(new_pad_orientation >= 0);
1204 pad_orientation_label.setVisible(new_pad_orientation >= 0);
1206 if (new_pad_orientation >= pad_orientation_values.length)
1207 new_pad_orientation = 0;
1208 if (new_pad_orientation < 0)
1209 new_pad_orientation = 0;
1210 pad_orientation_value.setSelectedIndex(new_pad_orientation);
1211 set_pad_orientation_tool_tip();
1214 public int pad_orientation() {
1215 if (pad_orientation_value.isEnabled())
1216 return pad_orientation_value.getSelectedIndex();
1221 public void set_beep(int new_beep) {
1222 beep_value.setVisible(new_beep >= 0);
1223 beep_label.setVisible(new_beep >= 0);
1225 int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5);
1226 for (int i = 0; i < beep_values.length; i++)
1227 if (new_beep == AltosConvert.beep_freq_to_value(Integer.parseInt(beep_values[i]))) {
1228 beep_value.setSelectedIndex(i);
1229 set_beep_tool_tip();
1232 beep_value.setSelectedItem(String.format("%d", new_freq));
1233 beep_value.setEnabled(new_beep >= 0);
1234 set_beep_tool_tip();
1238 if (beep_value.isEnabled())
1239 return AltosConvert.beep_freq_to_value(Integer.parseInt(beep_value.getSelectedItem().toString()));
1244 String[] tracker_motion_values() {
1245 if (AltosConvert.imperial_units)
1246 return tracker_motion_values_ft;
1248 return tracker_motion_values_m;
1251 void set_tracker_motion_values() {
1252 String[] v = tracker_motion_values();
1253 while (tracker_motion_value.getItemCount() > 0)
1254 tracker_motion_value.removeItemAt(0);
1255 for (int i = 0; i < v.length; i++)
1256 tracker_motion_value.addItem(v[i]);
1257 tracker_motion_value.setMaximumRowCount(v.length);
1260 String get_tracker_motion_label() {
1261 return String.format("Logging Trigger Motion (%s):", AltosConvert.height.show_units());
1264 void set_tracker_tool_tip() {
1265 if (tracker_motion_value.isEnabled())
1266 tracker_motion_value.setToolTipText("How far the device must move before logging");
1268 tracker_motion_value.setToolTipText("This device doesn't disable logging when stationary");
1269 if (tracker_interval_value.isEnabled())
1270 tracker_interval_value.setToolTipText("How often to report GPS position");
1272 tracker_interval_value.setToolTipText("This device can't configure interval");
1275 public void set_tracker_motion(int tracker_motion) {
1276 tracker_motion_label.setVisible(tracker_motion >= 0);
1277 tracker_motion_value.setVisible(tracker_motion >= 0);
1279 if (tracker_motion < 0) {
1280 tracker_motion_value.setEnabled(false);
1282 tracker_motion_value.setEnabled(true);
1283 tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
1287 public int tracker_motion() throws AltosConfigDataException {
1288 String str = tracker_motion_value.getSelectedItem().toString();
1290 return (int) (AltosConvert.height.parse_locale(str) + 0.5);
1291 } catch (ParseException pe) {
1292 throw new AltosConfigDataException("invalid tracker motion %s", str);
1296 public void set_tracker_interval(int tracker_interval) {
1297 tracker_interval_label.setVisible(tracker_interval >= 0);
1298 tracker_interval_value.setVisible(tracker_interval >= 0);
1300 if (tracker_interval< 0) {
1301 tracker_interval_value.setEnabled(false);
1303 tracker_interval_value.setEnabled(true);
1304 tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
1308 public int tracker_interval() throws AltosConfigDataException {
1309 return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false);
1312 public void set_pyros(AltosPyro[] new_pyros) {
1314 pyro.setVisible(pyros != null);
1315 if (pyros != null && pyro_ui != null)
1316 pyro_ui.set_pyros(pyros);
1319 public AltosPyro[] pyros() throws AltosConfigDataException {
1320 if (pyro_ui != null)
1321 pyros = pyro_ui.get_pyros();
1325 public void set_pyro_firing_time(double new_pyro_firing_time) {
1326 pyro_firing_time = new_pyro_firing_time;
1327 pyro.setVisible(pyro_firing_time >= 0);
1328 if (pyro_firing_time >= 0 && pyro_ui != null)
1329 pyro_ui.set_pyro_firing_time(pyro_firing_time);
1332 public double pyro_firing_time() throws AltosConfigDataException {
1333 if (pyro_ui != null)
1334 pyro_firing_time = pyro_ui.get_pyro_firing_time();
1335 return pyro_firing_time;
1338 public void set_aprs_interval(int new_aprs_interval) {
1339 aprs_interval_value.setVisible(new_aprs_interval >= 0);
1340 aprs_interval_label.setVisible(new_aprs_interval >= 0);
1344 if (new_aprs_interval <= 0)
1347 s = Integer.toString(new_aprs_interval);
1348 aprs_interval_value.setSelectedItem(s);
1349 set_aprs_interval_tool_tip();
1352 public int aprs_interval() throws AltosConfigDataException {
1353 String s = aprs_interval_value.getSelectedItem().toString();
1355 if (s.equals("Disabled"))
1357 return parse_int("aprs interval", s, false);
1360 public void set_aprs_ssid(int new_aprs_ssid) {
1361 aprs_ssid_value.setVisible(new_aprs_ssid >= 0);
1362 aprs_ssid_label.setVisible(new_aprs_ssid >= 0);
1364 aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid));
1365 set_aprs_ssid_tool_tip();
1368 public int aprs_ssid() throws AltosConfigDataException {
1369 Integer i = (Integer) aprs_ssid_value.getSelectedItem();
1373 public void set_aprs_format(int new_aprs_format) {
1374 aprs_format_value.setVisible(new_aprs_format >= 0);
1375 aprs_format_label.setVisible(new_aprs_format >= 0);
1377 aprs_format_value.setSelectedIndex(Math.max(0,new_aprs_format));
1378 set_aprs_format_tool_tip();
1381 public int aprs_format() throws AltosConfigDataException {
1382 return aprs_format_value.getSelectedIndex();