altos: Check for full log and complain
[fw/altos] / altosui / AltosConfigUI.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
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.
7  *
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.
12  *
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.
16  */
17
18 package altosui;
19
20 import java.awt.*;
21 import java.awt.event.*;
22 import javax.swing.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.*;
25 import javax.swing.event.*;
26 import java.io.*;
27 import java.util.*;
28 import java.text.*;
29 import java.util.prefs.*;
30 import java.util.concurrent.LinkedBlockingQueue;
31
32 import libaltosJNI.*;
33
34 public class AltosConfigUI
35         extends JDialog
36         implements ActionListener, ItemListener, DocumentListener
37 {
38
39         Container       pane;
40         Box             box;
41         JLabel          product_label;
42         JLabel          version_label;
43         JLabel          serial_label;
44         JLabel          main_deploy_label;
45         JLabel          apogee_delay_label;
46         JLabel          radio_channel_label;
47         JLabel          radio_calibration_label;
48         JLabel          callsign_label;
49
50         public boolean          dirty;
51
52         JFrame          owner;
53         JLabel          product_value;
54         JLabel          version_value;
55         JLabel          serial_value;
56         JComboBox       main_deploy_value;
57         JComboBox       apogee_delay_value;
58         JComboBox       radio_channel_value;
59         JTextField      radio_calibration_value;
60         JTextField      callsign_value;
61
62         JButton         save;
63         JButton         reset;
64         JButton         reboot;
65         JButton         close;
66
67         ActionListener  listener;
68
69         static String[] main_deploy_values = {
70                 "100", "150", "200", "250", "300", "350",
71                 "400", "450", "500"
72         };
73
74         static String[] apogee_delay_values = {
75                 "0", "1", "2", "3", "4", "5"
76         };
77
78         static String[] radio_channel_values = new String[10];
79                 {
80                         for (int i = 0; i <= 9; i++)
81                                 radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)",
82                                                                         i, 434.550 + i * 0.1);
83                 }
84
85         /* A window listener to catch closing events and tell the config code */
86         class ConfigListener extends WindowAdapter {
87                 AltosConfigUI   ui;
88
89                 public ConfigListener(AltosConfigUI this_ui) {
90                         ui = this_ui;
91                 }
92
93                 public void windowClosing(WindowEvent e) {
94                         ui.actionPerformed(new ActionEvent(e.getSource(),
95                                                            ActionEvent.ACTION_PERFORMED,
96                                                            "Close"));
97                 }
98         }
99
100         /* Build the UI using a grid bag */
101         public AltosConfigUI(JFrame in_owner, boolean remote) {
102                 super (in_owner, "Configure TeleMetrum", false);
103
104                 owner = in_owner;
105                 GridBagConstraints c;
106
107                 Insets il = new Insets(4,4,4,4);
108                 Insets ir = new Insets(4,4,4,4);
109
110                 pane = getContentPane();
111                 pane.setLayout(new GridBagLayout());
112
113                 /* Product */
114                 c = new GridBagConstraints();
115                 c.gridx = 0; c.gridy = 0;
116                 c.gridwidth = 4;
117                 c.fill = GridBagConstraints.NONE;
118                 c.anchor = GridBagConstraints.LINE_START;
119                 c.insets = il;
120                 product_label = new JLabel("Product:");
121                 pane.add(product_label, c);
122
123                 c = new GridBagConstraints();
124                 c.gridx = 4; c.gridy = 0;
125                 c.gridwidth = 4;
126                 c.fill = GridBagConstraints.HORIZONTAL;
127                 c.weightx = 1;
128                 c.anchor = GridBagConstraints.LINE_START;
129                 c.insets = ir;
130                 product_value = new JLabel("");
131                 pane.add(product_value, c);
132
133                 /* Version */
134                 c = new GridBagConstraints();
135                 c.gridx = 0; c.gridy = 1;
136                 c.gridwidth = 4;
137                 c.fill = GridBagConstraints.NONE;
138                 c.anchor = GridBagConstraints.LINE_START;
139                 c.insets = il;
140                 c.ipady = 5;
141                 version_label = new JLabel("Software version:");
142                 pane.add(version_label, c);
143
144                 c = new GridBagConstraints();
145                 c.gridx = 4; c.gridy = 1;
146                 c.gridwidth = 4;
147                 c.fill = GridBagConstraints.HORIZONTAL;
148                 c.weightx = 1;
149                 c.anchor = GridBagConstraints.LINE_START;
150                 c.insets = ir;
151                 c.ipady = 5;
152                 version_value = new JLabel("");
153                 pane.add(version_value, c);
154
155                 /* Serial */
156                 c = new GridBagConstraints();
157                 c.gridx = 0; c.gridy = 2;
158                 c.gridwidth = 4;
159                 c.fill = GridBagConstraints.NONE;
160                 c.anchor = GridBagConstraints.LINE_START;
161                 c.insets = il;
162                 c.ipady = 5;
163                 serial_label = new JLabel("Serial:");
164                 pane.add(serial_label, c);
165
166                 c = new GridBagConstraints();
167                 c.gridx = 4; c.gridy = 2;
168                 c.gridwidth = 4;
169                 c.fill = GridBagConstraints.HORIZONTAL;
170                 c.weightx = 1;
171                 c.anchor = GridBagConstraints.LINE_START;
172                 c.insets = ir;
173                 c.ipady = 5;
174                 serial_value = new JLabel("");
175                 pane.add(serial_value, c);
176
177                 /* Main deploy */
178                 c = new GridBagConstraints();
179                 c.gridx = 0; c.gridy = 3;
180                 c.gridwidth = 4;
181                 c.fill = GridBagConstraints.NONE;
182                 c.anchor = GridBagConstraints.LINE_START;
183                 c.insets = il;
184                 c.ipady = 5;
185                 main_deploy_label = new JLabel("Main Deploy Altitude(m):");
186                 pane.add(main_deploy_label, c);
187
188                 c = new GridBagConstraints();
189                 c.gridx = 4; c.gridy = 3;
190                 c.gridwidth = 4;
191                 c.fill = GridBagConstraints.HORIZONTAL;
192                 c.weightx = 1;
193                 c.anchor = GridBagConstraints.LINE_START;
194                 c.insets = ir;
195                 c.ipady = 5;
196                 main_deploy_value = new JComboBox(main_deploy_values);
197                 main_deploy_value.setEditable(true);
198                 main_deploy_value.addItemListener(this);
199                 pane.add(main_deploy_value, c);
200
201                 /* Apogee delay */
202                 c = new GridBagConstraints();
203                 c.gridx = 0; c.gridy = 4;
204                 c.gridwidth = 4;
205                 c.fill = GridBagConstraints.NONE;
206                 c.anchor = GridBagConstraints.LINE_START;
207                 c.insets = il;
208                 c.ipady = 5;
209                 apogee_delay_label = new JLabel("Apogee Delay(s):");
210                 pane.add(apogee_delay_label, c);
211
212                 c = new GridBagConstraints();
213                 c.gridx = 4; c.gridy = 4;
214                 c.gridwidth = 4;
215                 c.fill = GridBagConstraints.HORIZONTAL;
216                 c.weightx = 1;
217                 c.anchor = GridBagConstraints.LINE_START;
218                 c.insets = ir;
219                 c.ipady = 5;
220                 apogee_delay_value = new JComboBox(apogee_delay_values);
221                 apogee_delay_value.setEditable(true);
222                 apogee_delay_value.addItemListener(this);
223                 pane.add(apogee_delay_value, c);
224
225                 /* Radio channel */
226                 c = new GridBagConstraints();
227                 c.gridx = 0; c.gridy = 5;
228                 c.gridwidth = 4;
229                 c.fill = GridBagConstraints.NONE;
230                 c.anchor = GridBagConstraints.LINE_START;
231                 c.insets = il;
232                 c.ipady = 5;
233                 radio_channel_label = new JLabel("Radio Channel:");
234                 pane.add(radio_channel_label, c);
235
236                 c = new GridBagConstraints();
237                 c.gridx = 4; c.gridy = 5;
238                 c.gridwidth = 4;
239                 c.fill = GridBagConstraints.HORIZONTAL;
240                 c.weightx = 1;
241                 c.anchor = GridBagConstraints.LINE_START;
242                 c.insets = ir;
243                 c.ipady = 5;
244                 radio_channel_value = new JComboBox(radio_channel_values);
245                 radio_channel_value.setEditable(false);
246                 radio_channel_value.addItemListener(this);
247                 if (remote)
248                         radio_channel_value.setEnabled(false);
249                 pane.add(radio_channel_value, c);
250
251                 /* Radio Calibration */
252                 c = new GridBagConstraints();
253                 c.gridx = 0; c.gridy = 6;
254                 c.gridwidth = 4;
255                 c.fill = GridBagConstraints.NONE;
256                 c.anchor = GridBagConstraints.LINE_START;
257                 c.insets = il;
258                 c.ipady = 5;
259                 radio_calibration_label = new JLabel("RF Calibration:");
260                 pane.add(radio_calibration_label, c);
261
262                 c = new GridBagConstraints();
263                 c.gridx = 4; c.gridy = 6;
264                 c.gridwidth = 4;
265                 c.fill = GridBagConstraints.HORIZONTAL;
266                 c.weightx = 1;
267                 c.anchor = GridBagConstraints.LINE_START;
268                 c.insets = ir;
269                 c.ipady = 5;
270                 radio_calibration_value = new JTextField(String.format("%d", 1186611));
271                 radio_calibration_value.getDocument().addDocumentListener(this);
272                 if (remote)
273                         radio_calibration_value.setEnabled(false);
274                 pane.add(radio_calibration_value, c);
275
276                 /* Callsign */
277                 c = new GridBagConstraints();
278                 c.gridx = 0; c.gridy = 7;
279                 c.gridwidth = 4;
280                 c.fill = GridBagConstraints.NONE;
281                 c.anchor = GridBagConstraints.LINE_START;
282                 c.insets = il;
283                 c.ipady = 5;
284                 callsign_label = new JLabel("Callsign:");
285                 pane.add(callsign_label, c);
286
287                 c = new GridBagConstraints();
288                 c.gridx = 4; c.gridy = 7;
289                 c.gridwidth = 4;
290                 c.fill = GridBagConstraints.HORIZONTAL;
291                 c.weightx = 1;
292                 c.anchor = GridBagConstraints.LINE_START;
293                 c.insets = ir;
294                 c.ipady = 5;
295                 callsign_value = new JTextField(AltosPreferences.callsign());
296                 callsign_value.getDocument().addDocumentListener(this);
297                 pane.add(callsign_value, c);
298
299                 /* Buttons */
300                 c = new GridBagConstraints();
301                 c.gridx = 0; c.gridy = 8;
302                 c.gridwidth = 2;
303                 c.fill = GridBagConstraints.NONE;
304                 c.anchor = GridBagConstraints.LINE_START;
305                 c.insets = il;
306                 save = new JButton("Save");
307                 pane.add(save, c);
308                 save.addActionListener(this);
309                 save.setActionCommand("Save");
310
311                 c = new GridBagConstraints();
312                 c.gridx = 2; c.gridy = 8;
313                 c.gridwidth = 2;
314                 c.fill = GridBagConstraints.NONE;
315                 c.anchor = GridBagConstraints.CENTER;
316                 c.insets = il;
317                 reset = new JButton("Reset");
318                 pane.add(reset, c);
319                 reset.addActionListener(this);
320                 reset.setActionCommand("Reset");
321
322                 c = new GridBagConstraints();
323                 c.gridx = 4; c.gridy = 8;
324                 c.gridwidth = 2;
325                 c.fill = GridBagConstraints.NONE;
326                 c.anchor = GridBagConstraints.CENTER;
327                 c.insets = il;
328                 reboot = new JButton("Reboot");
329                 pane.add(reboot, c);
330                 reboot.addActionListener(this);
331                 reboot.setActionCommand("Reboot");
332
333                 c = new GridBagConstraints();
334                 c.gridx = 6; c.gridy = 8;
335                 c.gridwidth = 2;
336                 c.fill = GridBagConstraints.NONE;
337                 c.anchor = GridBagConstraints.LINE_END;
338                 c.insets = il;
339                 close = new JButton("Close");
340                 pane.add(close, c);
341                 close.addActionListener(this);
342                 close.setActionCommand("Close");
343
344                 addWindowListener(new ConfigListener(this));
345         }
346
347         /* Once the initial values are set, the config code will show the dialog */
348         public void make_visible() {
349                 pack();
350                 setLocationRelativeTo(owner);
351                 setVisible(true);
352         }
353
354         /* If any values have been changed, confirm before closing */
355         public boolean check_dirty(String operation) {
356                 if (dirty) {
357                         Object[] options = { String.format("%s anyway", operation), "Keep editing" };
358                         int i;
359                         i = JOptionPane.showOptionDialog(this,
360                                                          String.format("Configuration modified. %s anyway?", operation),
361                                                          "Configuration Modified",
362                                                          JOptionPane.DEFAULT_OPTION,
363                                                          JOptionPane.WARNING_MESSAGE,
364                                                          null, options, options[1]);
365                         if (i != 0)
366                                 return false;
367                 }
368                 return true;
369         }
370
371         /* Listen for events from our buttons */
372         public void actionPerformed(ActionEvent e) {
373                 String  cmd = e.getActionCommand();
374
375                 if (cmd.equals("Close") || cmd.equals("Reboot"))
376                         if (!check_dirty(cmd))
377                                 return;
378                 listener.actionPerformed(e);
379                 if (cmd.equals("Close") || cmd.equals("Reboot")) {
380                         setVisible(false);
381                         dispose();
382                 }
383                 dirty = false;
384         }
385
386         /* ItemListener interface method */
387         public void itemStateChanged(ItemEvent e) {
388                 dirty = true;
389         }
390
391         /* DocumentListener interface methods */
392         public void changedUpdate(DocumentEvent e) {
393                 dirty = true;
394         }
395
396         public void insertUpdate(DocumentEvent e) {
397                 dirty = true;
398         }
399
400         public void removeUpdate(DocumentEvent e) {
401                 dirty = true;
402         }
403
404         /* Let the config code hook on a listener */
405         public void addActionListener(ActionListener l) {
406                 listener = l;
407         }
408
409         /* set and get all of the dialog values */
410         public void set_product(String product) {
411                 product_value.setText(product);
412         }
413
414         public void set_version(String version) {
415                 version_value.setText(version);
416         }
417
418         public void set_serial(int serial) {
419                 serial_value.setText(String.format("%d", serial));
420         }
421
422         public void set_main_deploy(int new_main_deploy) {
423                 main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy));
424         }
425
426         public int main_deploy() {
427                 return Integer.parseInt(main_deploy_value.getSelectedItem().toString());
428         }
429
430         public void set_apogee_delay(int new_apogee_delay) {
431                 apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
432         }
433
434         public int apogee_delay() {
435                 return Integer.parseInt(apogee_delay_value.getSelectedItem().toString());
436         }
437
438         public void set_radio_channel(int new_radio_channel) {
439                 radio_channel_value.setSelectedIndex(new_radio_channel);
440         }
441
442         public int radio_channel() {
443                 return radio_channel_value.getSelectedIndex();
444         }
445
446         public void set_radio_calibration(int new_radio_calibration) {
447                 radio_calibration_value.setText(String.format("%d", new_radio_calibration));
448         }
449
450         public int radio_calibration() {
451                 return Integer.parseInt(radio_calibration_value.getText());
452         }
453
454         public void set_callsign(String new_callsign) {
455                 callsign_value.setText(new_callsign);
456         }
457
458         public String callsign() {
459                 return callsign_value.getText();
460         }
461
462         public void set_clean() {
463                 dirty = false;
464         }
465
466  }