Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
[fw/altos] / altosui / AltosConfigureUI.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 java.beans.*;
23 import javax.swing.*;
24 import javax.swing.filechooser.FileNameExtensionFilter;
25 import javax.swing.table.*;
26 import javax.swing.event.*;
27 import java.io.*;
28 import java.util.*;
29 import java.text.*;
30 import java.util.prefs.*;
31 import java.util.concurrent.LinkedBlockingQueue;
32 import javax.swing.plaf.basic.*;
33 import org.altusmetrum.AltosLib.*;
34
35 class DelegatingRenderer implements ListCellRenderer {
36
37         // ...
38         public static void install(JComboBox comboBox) {
39                 DelegatingRenderer renderer = new DelegatingRenderer(comboBox);
40                 renderer.initialise();
41                 comboBox.setRenderer(renderer);
42         }
43
44         // ...
45         private final JComboBox comboBox;
46
47         // ...
48         private ListCellRenderer delegate;
49
50         // ...
51         private DelegatingRenderer(JComboBox comboBox) {
52                 this.comboBox = comboBox;
53         }
54
55         // ...
56         private void initialise() {
57                 delegate = new JComboBox().getRenderer();
58                 comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() {
59
60                                 public void propertyChange(PropertyChangeEvent evt) {
61                                         delegate = new JComboBox().getRenderer();
62                                 }
63                         });
64         }
65
66         // ...
67         public Component getListCellRendererComponent(JList list,
68                                                       Object value, int index, boolean isSelected, boolean cellHasFocus) {
69
70                 return delegate.getListCellRendererComponent(list,
71                                                              ((UIManager.LookAndFeelInfo) value).getName(),
72                                                              index, isSelected, cellHasFocus);
73         }
74 }
75
76 public class AltosConfigureUI
77         extends AltosDialog
78         implements DocumentListener
79 {
80         JFrame          owner;
81         AltosVoice      voice;
82         Container       pane;
83
84         JRadioButton    enable_voice;
85         JButton         test_voice;
86         JButton         close;
87
88         JButton         configure_log;
89         JTextField      log_directory;
90
91         JLabel          callsign_label;
92         JTextField      callsign_value;
93
94         JRadioButton    imperial_units;
95
96         JLabel          font_size_label;
97         JComboBox       font_size_value;
98
99         JLabel          look_and_feel_label;
100         JComboBox       look_and_feel_value;
101
102         JRadioButton    serial_debug;
103
104         JButton         manage_bluetooth;
105         JButton         manage_frequencies;
106
107         final static String[] font_size_names = { "Small", "Medium", "Large" };
108
109         /* DocumentListener interface methods */
110         public void changedUpdate(DocumentEvent e) {
111                 AltosUIPreferences.set_callsign(callsign_value.getText());
112         }
113
114         public void insertUpdate(DocumentEvent e) {
115                 changedUpdate(e);
116         }
117
118         public void removeUpdate(DocumentEvent e) {
119                 changedUpdate(e);
120         }
121
122         public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) {
123                 super(in_owner, "Configure AltosUI", false);
124
125                 GridBagConstraints      c;
126
127                 Insets insets = new Insets(4, 4, 4, 4);
128
129                 int row = 0;
130
131                 owner = in_owner;
132                 voice = in_voice;
133                 pane = getContentPane();
134                 pane.setLayout(new GridBagLayout());
135
136                 c = new GridBagConstraints();
137                 c.insets = insets;
138                 c.fill = GridBagConstraints.NONE;
139                 c.anchor = GridBagConstraints.WEST;
140
141                 /* Nice label at the top */
142                 c.gridx = 0;
143                 c.gridy = row++;
144                 c.gridwidth = 3;
145                 c.fill = GridBagConstraints.NONE;
146                 c.anchor = GridBagConstraints.CENTER;
147                 pane.add(new JLabel ("Configure AltOS UI"), c);
148
149                 c.gridx = 0;
150                 c.gridy = row++;
151                 c.gridwidth = 3;
152                 c.fill = GridBagConstraints.NONE;
153                 c.anchor = GridBagConstraints.CENTER;
154                 pane.add(new JLabel (String.format("AltOS version %s", AltosVersion.version)), c);
155
156                 /* Voice settings */
157                 c.gridx = 0;
158                 c.gridy = row;
159                 c.gridwidth = 1;
160                 c.fill = GridBagConstraints.NONE;
161                 c.anchor = GridBagConstraints.WEST;
162                 pane.add(new JLabel("Voice"), c);
163
164                 enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice());
165                 enable_voice.addActionListener(new ActionListener() {
166                                 public void actionPerformed(ActionEvent e) {
167                                         JRadioButton item = (JRadioButton) e.getSource();
168                                         boolean enabled = item.isSelected();
169                                         AltosUIPreferences.set_voice(enabled);
170                                         if (enabled)
171                                                 voice.speak_always("Enable voice.");
172                                         else
173                                                 voice.speak_always("Disable voice.");
174                                 }
175                         });
176                 c.gridx = 1;
177                 c.gridy = row;
178                 c.gridwidth = 1;
179                 c.weightx = 1;
180                 c.fill = GridBagConstraints.NONE;
181                 c.anchor = GridBagConstraints.WEST;
182                 pane.add(enable_voice, c);
183                 enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements");
184
185                 c.gridx = 2;
186                 c.gridy = row++;
187                 c.gridwidth = 1;
188                 c.weightx = 1;
189                 c.fill = GridBagConstraints.NONE;
190                 c.anchor = GridBagConstraints.EAST;
191                 test_voice = new JButton("Test Voice");
192                 test_voice.addActionListener(new ActionListener() {
193                                 public void actionPerformed(ActionEvent e) {
194                                         voice.speak("That's one small step for man; one giant leap for mankind.");
195                                 }
196                         });
197                 pane.add(test_voice, c);
198                 test_voice.setToolTipText("Play a stock audio clip to check volume");
199
200                 /* Log directory settings */
201                 c.gridx = 0;
202                 c.gridy = row;
203                 c.gridwidth = 1;
204                 c.fill = GridBagConstraints.NONE;
205                 c.anchor = GridBagConstraints.WEST;
206                 pane.add(new JLabel("Log Directory"), c);
207
208                 configure_log = new JButton(AltosUIPreferences.logdir().getPath());
209                 configure_log.addActionListener(new ActionListener() {
210                                 public void actionPerformed(ActionEvent e) {
211                                         AltosUIPreferences.ConfigureLog();
212                                         configure_log.setText(AltosUIPreferences.logdir().getPath());
213                                 }
214                         });
215                 c.gridx = 1;
216                 c.gridy = row++;
217                 c.gridwidth = 2;
218                 c.fill = GridBagConstraints.BOTH;
219                 c.anchor = GridBagConstraints.WEST;
220                 pane.add(configure_log, c);
221                 configure_log.setToolTipText("Which directory flight logs are stored in");
222
223                 /* Callsign setting */
224                 c.gridx = 0;
225                 c.gridy = row;
226                 c.gridwidth = 1;
227                 c.fill = GridBagConstraints.NONE;
228                 c.anchor = GridBagConstraints.WEST;
229                 pane.add(new JLabel("Callsign"), c);
230
231                 callsign_value = new JTextField(AltosUIPreferences.callsign());
232                 callsign_value.getDocument().addDocumentListener(this);
233                 c.gridx = 1;
234                 c.gridy = row++;
235                 c.gridwidth = 2;
236                 c.fill = GridBagConstraints.BOTH;
237                 c.anchor = GridBagConstraints.WEST;
238                 pane.add(callsign_value, c);
239                 callsign_value.setToolTipText("Callsign sent in packet mode");
240
241                 /* Imperial units setting */
242                 c.gridx = 0;
243                 c.gridy = row;
244                 c.gridwidth = 1;
245                 c.fill = GridBagConstraints.NONE;
246                 c.anchor = GridBagConstraints.WEST;
247                 pane.add(new JLabel("Imperial Units"), c);
248
249                 imperial_units = new JRadioButton("Enable", AltosUIPreferences.serial_debug());
250                 imperial_units.addActionListener(new ActionListener() {
251                                 public void actionPerformed(ActionEvent e) {
252                                         JRadioButton item = (JRadioButton) e.getSource();
253                                         boolean enabled = item.isSelected();
254                                         AltosUIPreferences.set_imperial_units(enabled);
255                                 }
256                         });
257                 imperial_units.setToolTipText("Use Imperial units instead of metric");
258
259                 c.gridx = 1;
260                 c.gridy = row++;
261                 c.gridwidth = 3;
262                 c.fill = GridBagConstraints.NONE;
263                 c.anchor = GridBagConstraints.WEST;
264                 pane.add(imperial_units, c);
265
266                 /* Font size setting */
267                 c.gridx = 0;
268                 c.gridy = row;
269                 c.gridwidth = 1;
270                 c.fill = GridBagConstraints.NONE;
271                 c.anchor = GridBagConstraints.WEST;
272                 pane.add(new JLabel("Font size"), c);
273
274                 font_size_value = new JComboBox(font_size_names);
275                 int font_size = AltosUIPreferences.font_size();
276                 font_size_value.setSelectedIndex(font_size - Altos.font_size_small);
277                 font_size_value.addActionListener(new ActionListener() {
278                                 public void actionPerformed(ActionEvent e) {
279                                         int     size = font_size_value.getSelectedIndex() + Altos.font_size_small;
280
281                                         AltosUIPreferences.set_font_size(size);
282                                 }
283                         });
284                 c.gridx = 1;
285                 c.gridy = row++;
286                 c.gridwidth = 2;
287                 c.fill = GridBagConstraints.BOTH;
288                 c.anchor = GridBagConstraints.WEST;
289                 pane.add(font_size_value, c);
290                 font_size_value.setToolTipText("Font size used in telemetry window");
291
292                 /* Look & Feel setting */
293                 c.gridx = 0;
294                 c.gridy = row;
295                 c.gridwidth = 1;
296                 c.fill = GridBagConstraints.NONE;
297                 c.anchor = GridBagConstraints.WEST;
298                 pane.add(new JLabel("Look & feel"), c);
299
300                 class LookAndFeelRenderer extends BasicComboBoxRenderer implements ListCellRenderer {
301
302                         public LookAndFeelRenderer() {
303                                 super();
304                         }
305
306                         public Component getListCellRendererComponent(
307                                 JList list,
308                                 Object value,
309                                 int index,
310                                 boolean isSelected,
311                                 boolean cellHasFocus)
312                         {
313                                 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
314                                 setText(((UIManager.LookAndFeelInfo) value).getName());
315                                 return this;
316                         }
317                 }
318
319                 final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels();
320
321                 look_and_feel_value = new JComboBox(look_and_feels);
322
323                 DelegatingRenderer.install(look_and_feel_value);
324
325                 String look_and_feel  = AltosUIPreferences.look_and_feel();
326                 for (int i = 0; i < look_and_feels.length; i++)
327                         if (look_and_feel.equals(look_and_feels[i].getClassName()))
328                                 look_and_feel_value.setSelectedIndex(i);
329
330                 look_and_feel_value.addActionListener(new ActionListener() {
331                                 public void actionPerformed(ActionEvent e) {
332                                         int     id = look_and_feel_value.getSelectedIndex();
333
334                                         AltosUIPreferences.set_look_and_feel(look_and_feels[id].getClassName());
335                                 }
336                         });
337                 c.gridx = 1;
338                 c.gridy = row++;
339                 c.gridwidth = 2;
340                 c.fill = GridBagConstraints.BOTH;
341                 c.anchor = GridBagConstraints.WEST;
342                 pane.add(look_and_feel_value, c);
343                 look_and_feel_value.setToolTipText("Look&feel used for new windows");
344
345                 /* Serial debug setting */
346                 c.gridx = 0;
347                 c.gridy = row;
348                 c.gridwidth = 1;
349                 c.fill = GridBagConstraints.NONE;
350                 c.anchor = GridBagConstraints.WEST;
351                 pane.add(new JLabel("Serial Debug"), c);
352
353                 serial_debug = new JRadioButton("Enable", AltosUIPreferences.serial_debug());
354                 serial_debug.addActionListener(new ActionListener() {
355                                 public void actionPerformed(ActionEvent e) {
356                                         JRadioButton item = (JRadioButton) e.getSource();
357                                         boolean enabled = item.isSelected();
358                                         AltosUIPreferences.set_serial_debug(enabled);
359                                 }
360                         });
361                 serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console");
362
363                 c.gridx = 1;
364                 c.gridy = row++;
365                 c.gridwidth = 3;
366                 c.fill = GridBagConstraints.NONE;
367                 c.anchor = GridBagConstraints.WEST;
368                 pane.add(serial_debug, c);
369
370                 manage_bluetooth = new JButton("Manage Bluetooth");
371                 manage_bluetooth.addActionListener(new ActionListener() {
372                                 public void actionPerformed(ActionEvent e) {
373                                         AltosBTManage.show(owner, AltosBTKnown.bt_known());
374                                 }
375                         });
376                 c.gridx = 0;
377                 c.gridy = row;
378                 c.gridwidth = 2;
379                 c.fill = GridBagConstraints.NONE;
380                 c.anchor = GridBagConstraints.WEST;
381                 pane.add(manage_bluetooth, c);
382
383                 manage_frequencies = new JButton("Manage Frequencies");
384                 manage_frequencies.addActionListener(new ActionListener() {
385                                 public void actionPerformed(ActionEvent e) {
386                                         AltosConfigFreqUI.show(owner);
387                                 }
388                         });
389                 manage_frequencies.setToolTipText("Configure which values are shown in frequency menus");
390                 c.gridx = 2;
391                 c.gridx = 2;
392                 c.gridy = row++;
393                 c.gridwidth = 2;
394                 c.fill = GridBagConstraints.NONE;
395                 c.anchor = GridBagConstraints.WEST;
396                 pane.add(manage_frequencies, c);
397
398                 /* And a close button at the bottom */
399                 close = new JButton("Close");
400                 close.addActionListener(new ActionListener() {
401                                 public void actionPerformed(ActionEvent e) {
402                                         setVisible(false);
403                                 }
404                         });
405                 c.gridx = 0;
406                 c.gridy = row++;
407                 c.gridwidth = 3;
408                 c.fill = GridBagConstraints.NONE;
409                 c.anchor = GridBagConstraints.CENTER;
410                 pane.add(close, c);
411
412                 pack();
413                 setLocationRelativeTo(owner);
414                 setVisible(true);
415         }
416 }