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 callsign_label;
57 JComboBox main_deploy_value;
58 JComboBox apogee_delay_value;
59 JComboBox radio_channel_value;
60 JTextField radio_calibration_value;
61 JComboBox flight_log_max_value;
62 JTextField callsign_value;
69 ActionListener listener;
71 static String[] main_deploy_values = {
72 "100", "150", "200", "250", "300", "350",
76 static String[] apogee_delay_values = {
77 "0", "1", "2", "3", "4", "5"
80 static String[] flight_log_max_values = {
81 "64", "128", "192", "256", "320",
82 "384", "448", "512", "576", "640",
83 "704", "768", "832", "896", "960",
86 static String[] radio_channel_values = new String[10];
88 for (int i = 0; i <= 9; i++)
89 radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)",
90 i, 434.550 + i * 0.1);
93 /* A window listener to catch closing events and tell the config code */
94 class ConfigListener extends WindowAdapter {
97 public ConfigListener(AltosConfigUI this_ui) {
101 public void windowClosing(WindowEvent e) {
102 ui.actionPerformed(new ActionEvent(e.getSource(),
103 ActionEvent.ACTION_PERFORMED,
108 /* Build the UI using a grid bag */
109 public AltosConfigUI(JFrame in_owner, boolean remote) {
110 super (in_owner, "Configure TeleMetrum", false);
113 GridBagConstraints c;
115 Insets il = new Insets(4,4,4,4);
116 Insets ir = new Insets(4,4,4,4);
118 pane = getContentPane();
119 pane.setLayout(new GridBagLayout());
122 c = new GridBagConstraints();
123 c.gridx = 0; c.gridy = 0;
125 c.fill = GridBagConstraints.NONE;
126 c.anchor = GridBagConstraints.LINE_START;
128 product_label = new JLabel("Product:");
129 pane.add(product_label, c);
131 c = new GridBagConstraints();
132 c.gridx = 4; c.gridy = 0;
134 c.fill = GridBagConstraints.HORIZONTAL;
136 c.anchor = GridBagConstraints.LINE_START;
138 product_value = new JLabel("");
139 pane.add(product_value, c);
142 c = new GridBagConstraints();
143 c.gridx = 0; c.gridy = 1;
145 c.fill = GridBagConstraints.NONE;
146 c.anchor = GridBagConstraints.LINE_START;
149 version_label = new JLabel("Software version:");
150 pane.add(version_label, c);
152 c = new GridBagConstraints();
153 c.gridx = 4; c.gridy = 1;
155 c.fill = GridBagConstraints.HORIZONTAL;
157 c.anchor = GridBagConstraints.LINE_START;
160 version_value = new JLabel("");
161 pane.add(version_value, c);
164 c = new GridBagConstraints();
165 c.gridx = 0; c.gridy = 2;
167 c.fill = GridBagConstraints.NONE;
168 c.anchor = GridBagConstraints.LINE_START;
171 serial_label = new JLabel("Serial:");
172 pane.add(serial_label, c);
174 c = new GridBagConstraints();
175 c.gridx = 4; c.gridy = 2;
177 c.fill = GridBagConstraints.HORIZONTAL;
179 c.anchor = GridBagConstraints.LINE_START;
182 serial_value = new JLabel("");
183 pane.add(serial_value, c);
186 c = new GridBagConstraints();
187 c.gridx = 0; c.gridy = 3;
189 c.fill = GridBagConstraints.NONE;
190 c.anchor = GridBagConstraints.LINE_START;
193 main_deploy_label = new JLabel("Main Deploy Altitude(m):");
194 pane.add(main_deploy_label, c);
196 c = new GridBagConstraints();
197 c.gridx = 4; c.gridy = 3;
199 c.fill = GridBagConstraints.HORIZONTAL;
201 c.anchor = GridBagConstraints.LINE_START;
204 main_deploy_value = new JComboBox(main_deploy_values);
205 main_deploy_value.setEditable(true);
206 main_deploy_value.addItemListener(this);
207 pane.add(main_deploy_value, c);
210 c = new GridBagConstraints();
211 c.gridx = 0; c.gridy = 4;
213 c.fill = GridBagConstraints.NONE;
214 c.anchor = GridBagConstraints.LINE_START;
217 apogee_delay_label = new JLabel("Apogee Delay(s):");
218 pane.add(apogee_delay_label, c);
220 c = new GridBagConstraints();
221 c.gridx = 4; c.gridy = 4;
223 c.fill = GridBagConstraints.HORIZONTAL;
225 c.anchor = GridBagConstraints.LINE_START;
228 apogee_delay_value = new JComboBox(apogee_delay_values);
229 apogee_delay_value.setEditable(true);
230 apogee_delay_value.addItemListener(this);
231 pane.add(apogee_delay_value, c);
234 c = new GridBagConstraints();
235 c.gridx = 0; c.gridy = 5;
237 c.fill = GridBagConstraints.NONE;
238 c.anchor = GridBagConstraints.LINE_START;
241 radio_channel_label = new JLabel("Radio Channel:");
242 pane.add(radio_channel_label, c);
244 c = new GridBagConstraints();
245 c.gridx = 4; c.gridy = 5;
247 c.fill = GridBagConstraints.HORIZONTAL;
249 c.anchor = GridBagConstraints.LINE_START;
252 radio_channel_value = new JComboBox(radio_channel_values);
253 radio_channel_value.setEditable(false);
254 radio_channel_value.addItemListener(this);
256 radio_channel_value.setEnabled(false);
257 pane.add(radio_channel_value, c);
259 /* Radio Calibration */
260 c = new GridBagConstraints();
261 c.gridx = 0; c.gridy = 6;
263 c.fill = GridBagConstraints.NONE;
264 c.anchor = GridBagConstraints.LINE_START;
267 radio_calibration_label = new JLabel("RF Calibration:");
268 pane.add(radio_calibration_label, c);
270 c = new GridBagConstraints();
271 c.gridx = 4; c.gridy = 6;
273 c.fill = GridBagConstraints.HORIZONTAL;
275 c.anchor = GridBagConstraints.LINE_START;
278 radio_calibration_value = new JTextField(String.format("%d", 1186611));
279 radio_calibration_value.getDocument().addDocumentListener(this);
281 radio_calibration_value.setEnabled(false);
282 pane.add(radio_calibration_value, c);
285 c = new GridBagConstraints();
286 c.gridx = 0; c.gridy = 7;
288 c.fill = GridBagConstraints.NONE;
289 c.anchor = GridBagConstraints.LINE_START;
292 callsign_label = new JLabel("Callsign:");
293 pane.add(callsign_label, c);
295 c = new GridBagConstraints();
296 c.gridx = 4; c.gridy = 7;
298 c.fill = GridBagConstraints.HORIZONTAL;
300 c.anchor = GridBagConstraints.LINE_START;
303 callsign_value = new JTextField(AltosPreferences.callsign());
304 callsign_value.getDocument().addDocumentListener(this);
305 pane.add(callsign_value, c);
308 c = new GridBagConstraints();
309 c.gridx = 0; c.gridy = 8;
311 c.fill = GridBagConstraints.NONE;
312 c.anchor = GridBagConstraints.LINE_START;
315 flight_log_max_label = new JLabel("Maximum Flight Log Size:");
316 pane.add(flight_log_max_label, c);
318 c = new GridBagConstraints();
319 c.gridx = 4; c.gridy = 8;
321 c.fill = GridBagConstraints.HORIZONTAL;
323 c.anchor = GridBagConstraints.LINE_START;
326 flight_log_max_value = new JComboBox(flight_log_max_values);
327 flight_log_max_value.setEditable(true);
328 flight_log_max_value.addItemListener(this);
329 pane.add(flight_log_max_value, c);
332 c = new GridBagConstraints();
333 c.gridx = 0; c.gridy = 9;
335 c.fill = GridBagConstraints.NONE;
336 c.anchor = GridBagConstraints.LINE_START;
338 save = new JButton("Save");
340 save.addActionListener(this);
341 save.setActionCommand("Save");
343 c = new GridBagConstraints();
344 c.gridx = 2; c.gridy = 9;
346 c.fill = GridBagConstraints.NONE;
347 c.anchor = GridBagConstraints.CENTER;
349 reset = new JButton("Reset");
351 reset.addActionListener(this);
352 reset.setActionCommand("Reset");
354 c = new GridBagConstraints();
355 c.gridx = 4; c.gridy = 9;
357 c.fill = GridBagConstraints.NONE;
358 c.anchor = GridBagConstraints.CENTER;
360 reboot = new JButton("Reboot");
362 reboot.addActionListener(this);
363 reboot.setActionCommand("Reboot");
365 c = new GridBagConstraints();
366 c.gridx = 6; c.gridy = 9;
368 c.fill = GridBagConstraints.NONE;
369 c.anchor = GridBagConstraints.LINE_END;
371 close = new JButton("Close");
373 close.addActionListener(this);
374 close.setActionCommand("Close");
376 addWindowListener(new ConfigListener(this));
379 /* Once the initial values are set, the config code will show the dialog */
380 public void make_visible() {
382 setLocationRelativeTo(owner);
386 /* If any values have been changed, confirm before closing */
387 public boolean check_dirty(String operation) {
389 Object[] options = { String.format("%s anyway", operation), "Keep editing" };
391 i = JOptionPane.showOptionDialog(this,
392 String.format("Configuration modified. %s anyway?", operation),
393 "Configuration Modified",
394 JOptionPane.DEFAULT_OPTION,
395 JOptionPane.WARNING_MESSAGE,
396 null, options, options[1]);
403 /* Listen for events from our buttons */
404 public void actionPerformed(ActionEvent e) {
405 String cmd = e.getActionCommand();
407 if (cmd.equals("Close") || cmd.equals("Reboot"))
408 if (!check_dirty(cmd))
410 listener.actionPerformed(e);
411 if (cmd.equals("Close") || cmd.equals("Reboot")) {
418 /* ItemListener interface method */
419 public void itemStateChanged(ItemEvent e) {
423 /* DocumentListener interface methods */
424 public void changedUpdate(DocumentEvent e) {
428 public void insertUpdate(DocumentEvent e) {
432 public void removeUpdate(DocumentEvent e) {
436 /* Let the config code hook on a listener */
437 public void addActionListener(ActionListener l) {
441 /* set and get all of the dialog values */
442 public void set_product(String product) {
443 product_value.setText(product);
446 public void set_version(String version) {
447 version_value.setText(version);
450 public void set_serial(int serial) {
451 serial_value.setText(String.format("%d", serial));
454 public void set_main_deploy(int new_main_deploy) {
455 main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy));
458 public int main_deploy() {
459 return Integer.parseInt(main_deploy_value.getSelectedItem().toString());
462 public void set_apogee_delay(int new_apogee_delay) {
463 apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
466 public int apogee_delay() {
467 return Integer.parseInt(apogee_delay_value.getSelectedItem().toString());
470 public void set_radio_channel(int new_radio_channel) {
471 radio_channel_value.setSelectedIndex(new_radio_channel);
474 public int radio_channel() {
475 return radio_channel_value.getSelectedIndex();
478 public void set_radio_calibration(int new_radio_calibration) {
479 radio_calibration_value.setText(String.format("%d", new_radio_calibration));
482 public int radio_calibration() {
483 return Integer.parseInt(radio_calibration_value.getText());
486 public void set_callsign(String new_callsign) {
487 callsign_value.setText(new_callsign);
490 public String callsign() {
491 return callsign_value.getText();
494 public void set_flight_log_max(int new_flight_log_max) {
495 if (new_flight_log_max == 0)
496 flight_log_max_value.setEnabled(false);
497 flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max));
500 public int flight_log_max() {
501 return Integer.parseInt(flight_log_max_value.getSelectedItem().toString());
504 public void set_clean() {