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 callsign_label;
58 JComboBox main_deploy_value;
59 JComboBox apogee_delay_value;
60 JComboBox radio_channel_value;
61 JTextField radio_calibration_value;
62 JComboBox flight_log_max_value;
63 JComboBox ignite_mode_value;
64 JTextField callsign_value;
71 ActionListener listener;
73 static String[] main_deploy_values = {
74 "100", "150", "200", "250", "300", "350",
78 static String[] apogee_delay_values = {
79 "0", "1", "2", "3", "4", "5"
82 static String[] flight_log_max_values = {
83 "64", "128", "192", "256", "320",
84 "384", "448", "512", "576", "640",
85 "704", "768", "832", "896", "960",
88 static String[] ignite_mode_values = {
94 static String[] radio_channel_values = new String[10];
96 for (int i = 0; i <= 9; i++)
97 radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)",
98 i, 434.550 + i * 0.1);
101 /* A window listener to catch closing events and tell the config code */
102 class ConfigListener extends WindowAdapter {
105 public ConfigListener(AltosConfigUI this_ui) {
109 public void windowClosing(WindowEvent e) {
110 ui.actionPerformed(new ActionEvent(e.getSource(),
111 ActionEvent.ACTION_PERFORMED,
116 /* Build the UI using a grid bag */
117 public AltosConfigUI(JFrame in_owner, boolean remote) {
118 super (in_owner, "Configure TeleMetrum", false);
121 GridBagConstraints c;
123 Insets il = new Insets(4,4,4,4);
124 Insets ir = new Insets(4,4,4,4);
126 pane = getContentPane();
127 pane.setLayout(new GridBagLayout());
130 c = new GridBagConstraints();
131 c.gridx = 0; c.gridy = 0;
133 c.fill = GridBagConstraints.NONE;
134 c.anchor = GridBagConstraints.LINE_START;
136 product_label = new JLabel("Product:");
137 pane.add(product_label, c);
139 c = new GridBagConstraints();
140 c.gridx = 4; c.gridy = 0;
142 c.fill = GridBagConstraints.HORIZONTAL;
144 c.anchor = GridBagConstraints.LINE_START;
146 product_value = new JLabel("");
147 pane.add(product_value, c);
150 c = new GridBagConstraints();
151 c.gridx = 0; c.gridy = 1;
153 c.fill = GridBagConstraints.NONE;
154 c.anchor = GridBagConstraints.LINE_START;
157 version_label = new JLabel("Software version:");
158 pane.add(version_label, c);
160 c = new GridBagConstraints();
161 c.gridx = 4; c.gridy = 1;
163 c.fill = GridBagConstraints.HORIZONTAL;
165 c.anchor = GridBagConstraints.LINE_START;
168 version_value = new JLabel("");
169 pane.add(version_value, c);
172 c = new GridBagConstraints();
173 c.gridx = 0; c.gridy = 2;
175 c.fill = GridBagConstraints.NONE;
176 c.anchor = GridBagConstraints.LINE_START;
179 serial_label = new JLabel("Serial:");
180 pane.add(serial_label, c);
182 c = new GridBagConstraints();
183 c.gridx = 4; c.gridy = 2;
185 c.fill = GridBagConstraints.HORIZONTAL;
187 c.anchor = GridBagConstraints.LINE_START;
190 serial_value = new JLabel("");
191 pane.add(serial_value, c);
194 c = new GridBagConstraints();
195 c.gridx = 0; c.gridy = 3;
197 c.fill = GridBagConstraints.NONE;
198 c.anchor = GridBagConstraints.LINE_START;
201 main_deploy_label = new JLabel("Main Deploy Altitude(m):");
202 pane.add(main_deploy_label, c);
204 c = new GridBagConstraints();
205 c.gridx = 4; c.gridy = 3;
207 c.fill = GridBagConstraints.HORIZONTAL;
209 c.anchor = GridBagConstraints.LINE_START;
212 main_deploy_value = new JComboBox(main_deploy_values);
213 main_deploy_value.setEditable(true);
214 main_deploy_value.addItemListener(this);
215 pane.add(main_deploy_value, c);
218 c = new GridBagConstraints();
219 c.gridx = 0; c.gridy = 4;
221 c.fill = GridBagConstraints.NONE;
222 c.anchor = GridBagConstraints.LINE_START;
225 apogee_delay_label = new JLabel("Apogee Delay(s):");
226 pane.add(apogee_delay_label, c);
228 c = new GridBagConstraints();
229 c.gridx = 4; c.gridy = 4;
231 c.fill = GridBagConstraints.HORIZONTAL;
233 c.anchor = GridBagConstraints.LINE_START;
236 apogee_delay_value = new JComboBox(apogee_delay_values);
237 apogee_delay_value.setEditable(true);
238 apogee_delay_value.addItemListener(this);
239 pane.add(apogee_delay_value, c);
242 c = new GridBagConstraints();
243 c.gridx = 0; c.gridy = 5;
245 c.fill = GridBagConstraints.NONE;
246 c.anchor = GridBagConstraints.LINE_START;
249 radio_channel_label = new JLabel("Radio Channel:");
250 pane.add(radio_channel_label, c);
252 c = new GridBagConstraints();
253 c.gridx = 4; c.gridy = 5;
255 c.fill = GridBagConstraints.HORIZONTAL;
257 c.anchor = GridBagConstraints.LINE_START;
260 radio_channel_value = new JComboBox(radio_channel_values);
261 radio_channel_value.setEditable(false);
262 radio_channel_value.addItemListener(this);
263 pane.add(radio_channel_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);
362 c = new GridBagConstraints();
363 c.gridx = 0; c.gridy = 10;
365 c.fill = GridBagConstraints.NONE;
366 c.anchor = GridBagConstraints.LINE_START;
368 save = new JButton("Save");
370 save.addActionListener(this);
371 save.setActionCommand("Save");
373 c = new GridBagConstraints();
374 c.gridx = 2; c.gridy = 10;
376 c.fill = GridBagConstraints.NONE;
377 c.anchor = GridBagConstraints.CENTER;
379 reset = new JButton("Reset");
381 reset.addActionListener(this);
382 reset.setActionCommand("Reset");
384 c = new GridBagConstraints();
385 c.gridx = 4; c.gridy = 10;
387 c.fill = GridBagConstraints.NONE;
388 c.anchor = GridBagConstraints.CENTER;
390 reboot = new JButton("Reboot");
392 reboot.addActionListener(this);
393 reboot.setActionCommand("Reboot");
395 c = new GridBagConstraints();
396 c.gridx = 6; c.gridy = 10;
398 c.fill = GridBagConstraints.NONE;
399 c.anchor = GridBagConstraints.LINE_END;
401 close = new JButton("Close");
403 close.addActionListener(this);
404 close.setActionCommand("Close");
406 addWindowListener(new ConfigListener(this));
409 /* Once the initial values are set, the config code will show the dialog */
410 public void make_visible() {
412 setLocationRelativeTo(owner);
416 /* If any values have been changed, confirm before closing */
417 public boolean check_dirty(String operation) {
419 Object[] options = { String.format("%s anyway", operation), "Keep editing" };
421 i = JOptionPane.showOptionDialog(this,
422 String.format("Configuration modified. %s anyway?", operation),
423 "Configuration Modified",
424 JOptionPane.DEFAULT_OPTION,
425 JOptionPane.WARNING_MESSAGE,
426 null, options, options[1]);
433 /* Listen for events from our buttons */
434 public void actionPerformed(ActionEvent e) {
435 String cmd = e.getActionCommand();
437 if (cmd.equals("Close") || cmd.equals("Reboot"))
438 if (!check_dirty(cmd))
440 listener.actionPerformed(e);
441 if (cmd.equals("Close") || cmd.equals("Reboot")) {
448 /* ItemListener interface method */
449 public void itemStateChanged(ItemEvent e) {
453 /* DocumentListener interface methods */
454 public void changedUpdate(DocumentEvent e) {
458 public void insertUpdate(DocumentEvent e) {
462 public void removeUpdate(DocumentEvent e) {
466 /* Let the config code hook on a listener */
467 public void addActionListener(ActionListener l) {
471 /* set and get all of the dialog values */
472 public void set_product(String product) {
473 product_value.setText(product);
476 public void set_version(String version) {
477 version_value.setText(version);
480 public void set_serial(int serial) {
481 serial_value.setText(String.format("%d", serial));
484 public void set_main_deploy(int new_main_deploy) {
485 main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy));
488 public int main_deploy() {
489 return Integer.parseInt(main_deploy_value.getSelectedItem().toString());
492 public void set_apogee_delay(int new_apogee_delay) {
493 apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
496 public int apogee_delay() {
497 return Integer.parseInt(apogee_delay_value.getSelectedItem().toString());
500 public void set_radio_channel(int new_radio_channel) {
501 radio_channel_value.setSelectedIndex(new_radio_channel);
504 public int radio_channel() {
505 return radio_channel_value.getSelectedIndex();
508 public void set_radio_calibration(int new_radio_calibration) {
509 radio_calibration_value.setText(String.format("%d", new_radio_calibration));
512 public int radio_calibration() {
513 return Integer.parseInt(radio_calibration_value.getText());
516 public void set_callsign(String new_callsign) {
517 callsign_value.setText(new_callsign);
520 public String callsign() {
521 return callsign_value.getText();
524 public void set_flight_log_max(int new_flight_log_max) {
525 if (new_flight_log_max == 0)
526 flight_log_max_value.setEnabled(false);
527 flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max));
530 public int flight_log_max() {
531 return Integer.parseInt(flight_log_max_value.getSelectedItem().toString());
534 public void set_ignite_mode(int new_ignite_mode) {
535 if (new_ignite_mode < 0) {
536 ignite_mode_value.setEnabled(false);
539 ignite_mode_value.setEnabled(true);
541 ignite_mode_value.setSelectedItem(Integer.toString(new_ignite_mode));
544 public int ignite_mode() {
545 return ignite_mode_value.getSelectedIndex();
548 public void set_clean() {