altosui: Make UI Look&Feel configurable
authorKeith Packard <keithp@keithp.com>
Sat, 12 Nov 2011 06:24:22 +0000 (22:24 -0800)
committerKeith Packard <keithp@keithp.com>
Sat, 12 Nov 2011 06:24:22 +0000 (22:24 -0800)
Saves the preferred style and uses that for all current and new windows.

Signed-off-by: Keith Packard <keithp@keithp.com>
23 files changed:
altosui/AltosBTManage.java
altosui/AltosCSVUI.java
altosui/AltosConfigFreqUI.java
altosui/AltosConfigUI.java
altosui/AltosConfigureUI.java
altosui/AltosDeviceDialog.java
altosui/AltosDialog.java [new file with mode: 0644]
altosui/AltosEepromMonitor.java
altosui/AltosEepromSelect.java
altosui/AltosFlashUI.java
altosui/AltosFlightUI.java
altosui/AltosFrame.java [new file with mode: 0644]
altosui/AltosGraphUI.java
altosui/AltosIdleMonitorUI.java
altosui/AltosIgniteUI.java
altosui/AltosLaunchUI.java
altosui/AltosPreferences.java
altosui/AltosRomconfigUI.java
altosui/AltosScanUI.java
altosui/AltosSiteMapPreload.java
altosui/AltosUI.java
altosui/AltosUIListener.java [new file with mode: 0644]
altosui/Makefile.am

index 10fdab3b211d839ff9019d1e75afc811b74468c3..6d46070196a7ee0340eb5b757be71924f91a2844 100644 (file)
@@ -32,7 +32,7 @@ import java.util.concurrent.*;
 
 import libaltosJNI.*;
 
-public class AltosBTManage extends JDialog implements ActionListener, Iterable<AltosBTDevice> {
+public class AltosBTManage extends AltosDialog implements ActionListener, Iterable<AltosBTDevice> {
        LinkedBlockingQueue<AltosBTDevice> found_devices;
        Frame frame;
        LinkedList<ActionListener> listeners;
index a212409ee83e3fc4f60aaa6d361a39cd87e15fc3..6d3e9065e15a6435fa27057ad1b5986430e67823 100644 (file)
@@ -29,7 +29,7 @@ import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
 
 public class AltosCSVUI
-       extends JDialog
+       extends AltosDialog
        implements ActionListener
 {
        JFileChooser            csv_chooser;
index 063d21b41eedde18fd1ee374e29382ea1faf930c..c6eabc536cbb17950d0374eaa40f29610c451e1e 100644 (file)
@@ -30,7 +30,7 @@ import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.*;
 
-class AltosEditFreqUI extends JDialog implements ActionListener {
+class AltosEditFreqUI extends AltosDialog implements ActionListener {
        Frame           frame;
        JTextField      frequency;
        JTextField      description;
@@ -165,7 +165,7 @@ class AltosEditFreqUI extends JDialog implements ActionListener {
        }
 }
 
-public class AltosConfigFreqUI extends JDialog implements ActionListener {
+public class AltosConfigFreqUI extends AltosDialog implements ActionListener {
 
        Frame frame;
        LinkedList<ActionListener> listeners;
index d20dd073ed7849d6eb18d2a852ddbfda33c2a457..9fef8e3bc47eb8ee97d4969e1532fd75313677f8 100644 (file)
@@ -32,7 +32,7 @@ import java.util.concurrent.LinkedBlockingQueue;
 import libaltosJNI.*;
 
 public class AltosConfigUI
-       extends JDialog
+       extends AltosDialog
        implements ActionListener, ItemListener, DocumentListener
 {
 
index 980068c0076fa4b867cb992269518f248fa48918..06b5745c7d493196fa170d6493dfd0db47f0bce3 100644 (file)
@@ -19,6 +19,7 @@ package altosui;
 
 import java.awt.*;
 import java.awt.event.*;
+import java.beans.*;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import javax.swing.table.*;
@@ -28,9 +29,51 @@ import java.util.*;
 import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
+import javax.swing.plaf.basic.*;
+
+class DelegatingRenderer implements ListCellRenderer {
+
+       // ...
+       public static void install(JComboBox comboBox) {
+               DelegatingRenderer renderer = new DelegatingRenderer(comboBox);
+               renderer.initialise();
+               comboBox.setRenderer(renderer);
+       }
+
+       // ...
+       private final JComboBox comboBox;
+
+       // ...
+       private ListCellRenderer delegate;
+
+       // ...
+       private DelegatingRenderer(JComboBox comboBox) {
+               this.comboBox = comboBox;
+       }
+
+       // ...
+       private void initialise() {
+               delegate = new JComboBox().getRenderer();
+               comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() {
+
+                               public void propertyChange(PropertyChangeEvent evt) {
+                                       delegate = new JComboBox().getRenderer();
+                               }
+                       });
+       }
+
+       // ...
+       public Component getListCellRendererComponent(JList list,
+                                                     Object value, int index, boolean isSelected, boolean cellHasFocus) {
+
+               return delegate.getListCellRendererComponent(list,
+                                                            ((UIManager.LookAndFeelInfo) value).getName(),
+                                                            index, isSelected, cellHasFocus);
+       }
+}
 
 public class AltosConfigureUI
-       extends JDialog
+       extends AltosDialog
        implements DocumentListener
 {
        JFrame          owner;
@@ -50,6 +93,9 @@ public class AltosConfigureUI
        JLabel          font_size_label;
        JComboBox       font_size_value;
 
+       JLabel          look_and_feel_label;
+       JComboBox       look_and_feel_value;
+
        JRadioButton    serial_debug;
 
        JButton         manage_bluetooth;
@@ -215,6 +261,60 @@ public class AltosConfigureUI
                pane.add(font_size_value, c);
                font_size_value.setToolTipText("Font size used in telemetry window");
 
+               /* Look & Feel setting */
+               c.gridx = 0;
+               c.gridy = row;
+               c.gridwidth = 1;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               pane.add(new JLabel("Look & feel"), c);
+
+               class LookAndFeelRenderer extends BasicComboBoxRenderer implements ListCellRenderer {
+
+                       public LookAndFeelRenderer() {
+                               super();
+                       }
+
+                       public Component getListCellRendererComponent(
+                               JList list,
+                               Object value,
+                               int index,
+                               boolean isSelected,
+                               boolean cellHasFocus)
+                       {
+                               super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+                               setText(((UIManager.LookAndFeelInfo) value).getName());
+                               return this;
+                       }
+               }
+
+               final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels();
+
+               System.out.printf("look_and_feels %d\n", look_and_feels.length);
+               look_and_feel_value = new JComboBox(look_and_feels);
+
+               DelegatingRenderer.install(look_and_feel_value);
+
+               String look_and_feel  = AltosPreferences.look_and_feel();
+               for (int i = 0; i < look_and_feels.length; i++)
+                       if (look_and_feel.equals(look_and_feels[i].getClassName()))
+                               look_and_feel_value.setSelectedIndex(i);
+
+               look_and_feel_value.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       int     id = look_and_feel_value.getSelectedIndex();
+
+                                       AltosPreferences.set_look_and_feel(look_and_feels[id].getClassName());
+                               }
+                       });
+               c.gridx = 1;
+               c.gridy = row++;
+               c.gridwidth = 2;
+               c.fill = GridBagConstraints.BOTH;
+               c.anchor = GridBagConstraints.WEST;
+               pane.add(look_and_feel_value, c);
+               look_and_feel_value.setToolTipText("Look&feel used for new windows");
+
                /* Serial debug setting */
                c.gridx = 0;
                c.gridy = row;
index 610bb73e76dfbae75fc6ab59c5b9f85755e7c477..e53e75c197bdd064988f2c18b375a7d5acbb2627 100644 (file)
@@ -24,7 +24,7 @@ import java.awt.*;
 import java.awt.event.*;
 import libaltosJNI.*;
 
-public class AltosDeviceDialog extends JDialog implements ActionListener {
+public class AltosDeviceDialog extends AltosDialog implements ActionListener {
 
        private AltosDevice     value;
        private JList           list;
diff --git a/altosui/AltosDialog.java b/altosui/AltosDialog.java
new file mode 100644 (file)
index 0000000..c30b575
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.*;
+
+import libaltosJNI.*;
+
+class AltosDialogListener extends WindowAdapter {
+       public void windowClosing (WindowEvent e) {
+               AltosPreferences.unregister_ui_listener((AltosDialog) e.getWindow());
+       }
+}
+
+public class AltosDialog extends JDialog implements AltosUIListener {
+
+       public void ui_changed(String look_and_feel) {
+               SwingUtilities.updateComponentTreeUI(this);
+               this.pack();
+       }
+
+       public AltosDialog() {
+               AltosPreferences.register_ui_listener(this);
+               addWindowListener(new AltosDialogListener());
+       }
+
+       public AltosDialog(Frame frame, String label, boolean modal) {
+               super(frame, label, modal);
+               AltosPreferences.register_ui_listener(this);
+               addWindowListener(new AltosDialogListener());
+       }
+
+       public AltosDialog(Frame frame, boolean modal) {
+               super(frame, modal);
+               AltosPreferences.register_ui_listener(this);
+               addWindowListener(new AltosDialogListener());
+       }
+}
index b9d913fa51a269483634f85305187ddf83eefd7c..34f5b891c02f8763396bdb27f371d6019d5eac67 100644 (file)
@@ -28,7 +28,7 @@ import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
 
-public class AltosEepromMonitor extends JDialog {
+public class AltosEepromMonitor extends AltosDialog {
 
        Container       pane;
        Box             box;
index 0a6eec173b3eeabcba9e736aec48c712920c9e27..ebafc4c87da3382f3f670035aea39a3bbc6f9f88 100644 (file)
@@ -62,7 +62,7 @@ class AltosEepromItem implements ActionListener {
        }
 }
 
-public class AltosEepromSelect extends JDialog implements ActionListener {
+public class AltosEepromSelect extends AltosDialog implements ActionListener {
        private JList                   list;
        private JFrame                  frame;
        JButton                         ok;
index 3956ff20a94789d99148df23fdda1455e9aa0beb..39151641e42bdbaa6bf1ef0bf93d269f8c1d9dfe 100644 (file)
@@ -29,7 +29,7 @@ import java.util.prefs.*;
 import java.util.concurrent.*;
 
 public class AltosFlashUI
-       extends JDialog
+       extends AltosDialog
        implements ActionListener
 {
        Container       pane;
index b44b9d43b84c4a7f3f511120a4c2e183c68f028d..d166c9aefbb30147d06118f0e11a55487903e2c5 100644 (file)
@@ -28,7 +28,7 @@ import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.*;
 
-public class AltosFlightUI extends JFrame implements AltosFlightDisplay, AltosFontListener {
+public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener {
        AltosVoice              voice;
        AltosFlightReader       reader;
        AltosDisplayThread      thread;
diff --git a/altosui/AltosFrame.java b/altosui/AltosFrame.java
new file mode 100644 (file)
index 0000000..f8cc4f5
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.*;
+
+import libaltosJNI.*;
+
+class AltosFrameListener extends WindowAdapter {
+       public void windowClosing (WindowEvent e) {
+               AltosPreferences.unregister_ui_listener((AltosFrame) e.getWindow());
+       }
+}
+
+public class AltosFrame extends JFrame implements AltosUIListener {
+
+       public void ui_changed(String look_and_feel) {
+               SwingUtilities.updateComponentTreeUI(this);
+               this.pack();
+       }
+
+       public AltosFrame() {
+               AltosPreferences.register_ui_listener(this);
+               addWindowListener(new AltosFrameListener());
+       }
+
+       public AltosFrame(String name) {
+               super(name);
+               AltosPreferences.register_ui_listener(this);
+               addWindowListener(new AltosFrameListener());
+       }
+}
index 59e92499e6a64439a32ce78b99f91a63122ffc6d..c30dc476048d55a2e1b661697c2b45b54b2141e8 100644 (file)
@@ -20,7 +20,7 @@ import org.jfree.chart.axis.AxisLocation;
 import org.jfree.ui.ApplicationFrame;
 import org.jfree.ui.RefineryUtilities;
 
-public class AltosGraphUI extends JFrame 
+public class AltosGraphUI extends AltosFrame 
 {
     JTabbedPane        pane;
 
index 988a797c963a85cdad456e530d16286983fd7fdc..a5f41e258891054732ee867a2ef9cb1ba468197a 100644 (file)
@@ -255,7 +255,7 @@ class AltosIdleMonitor extends Thread {
        }
 }
 
-public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay {
+public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener {
        AltosDevice             device;
        JTabbedPane             pane;
        AltosPad                pad;
@@ -289,6 +289,10 @@ public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay {
                flightInfo.set_font();
        }
 
+       public void font_size_changed(int font_size) {
+               set_font();
+       }
+
        public void show(AltosState state, int crc_errors) {
                try {
                        pad.show(state, crc_errors);
@@ -377,12 +381,16 @@ public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay {
                bag.add(pane, c);
 
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+
+               AltosPreferences.register_font_listener(this);
+
                addWindowListener(new WindowAdapter() {
                                @Override
                                public void windowClosing(WindowEvent e) {
                                        disconnect();
                                        setVisible(false);
                                        dispose();
+                                       AltosPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
                                }
                        });
 
index b215c22865604fd0631109e5b03b6ecd8000f6df..8623cbef3ace51a255f36899b68951727f867d45 100644 (file)
@@ -30,7 +30,7 @@ import java.util.prefs.*;
 import java.util.concurrent.*;
 
 public class AltosIgniteUI
-       extends JDialog
+       extends AltosDialog
        implements ActionListener
 {
        AltosDevice     device;
index 47365e03bd46a19bc933553d55beac501e3effd9..73fae16bf23ca3df1351cdacec507674c0048ba6 100644 (file)
@@ -50,7 +50,7 @@ class FireButton extends JButton {
 }
 
 public class AltosLaunchUI
-       extends JDialog
+       extends AltosDialog
        implements ActionListener
 {
        AltosDevice     device;
index 48aed44125c6c93d74d16d5493e7c4461e8f7b68..cc2b1a95acbe76ccacc095bd6987ebaeac0de7d3 100644 (file)
@@ -61,9 +61,12 @@ class AltosPreferences {
        /* Launcher serial preference name */
        final static String launcherSerialPreference = "LAUNCHER-SERIAL";
 
-       /* Launcher channel prefernce name */
+       /* Launcher channel preference name */
        final static String launcherChannelPreference = "LAUNCHER-CHANNEL";
        
+       /* Look&Feel preference name */
+       final static String lookAndFeelPreference = "LOOK-AND-FEEL";
+
        /* Default logdir is ~/TeleMetrum */
        final static String logdirName = "TeleMetrum";
 
@@ -101,6 +104,10 @@ class AltosPreferences {
 
        static int font_size = Altos.font_size_medium;
 
+       static LinkedList<AltosUIListener> ui_listeners;
+
+       static String look_and_feel = null;
+
        /* List of frequencies */
        final static String common_frequencies_node_name = "COMMON-FREQUENCIES";
        static AltosFrequency[] common_frequencies;
@@ -199,6 +206,10 @@ class AltosPreferences {
                AltosSerial.set_debug(serial_debug);
 
                common_frequencies = load_common_frequencies();
+
+               look_and_feel = preferences.get(lookAndFeelPreference, UIManager.getSystemLookAndFeelClassName());
+
+               ui_listeners = new LinkedList<AltosUIListener>();
        }
 
        static { init(); }
@@ -390,6 +401,35 @@ class AltosPreferences {
                }
        }
 
+       public static void set_look_and_feel(String new_look_and_feel) {
+               look_and_feel = new_look_and_feel;
+               try {
+                       UIManager.setLookAndFeel(look_and_feel);
+               } catch (Exception e) {
+               }
+               synchronized(preferences) {
+                       preferences.put(lookAndFeelPreference, look_and_feel);
+                       flush_preferences();
+                       for (AltosUIListener l : ui_listeners)
+                               l.ui_changed(look_and_feel);
+               }
+       }
+
+       public static String look_and_feel() {
+               return look_and_feel;
+       }
+
+       public static void register_ui_listener(AltosUIListener l) {
+               synchronized(preferences) {
+                       ui_listeners.add(l);
+               }
+       }
+
+       public static void unregister_ui_listener(AltosUIListener l) {
+               synchronized (preferences) {
+                       ui_listeners.remove(l);
+               }
+       }
        public static void set_serial_debug(boolean new_serial_debug) {
                serial_debug = new_serial_debug;
                AltosSerial.set_debug(serial_debug);
index 7e21735cd91ee152301ed70b3f22968127d63e19..e4e38c9c07015d9a648bdef62dfc05ed9530a028 100644 (file)
@@ -29,7 +29,7 @@ import java.text.*;
 import java.util.prefs.*;
 
 public class AltosRomconfigUI
-       extends JDialog
+       extends AltosDialog
        implements ActionListener
 {
        Container       pane;
index df5c51d4a2e3ab74d98dd9ad7b0a7bd7fe9bd1f8..e188834e64aa76a204d8026a42324273b800c29a 100644 (file)
@@ -102,7 +102,7 @@ class AltosScanResults extends LinkedList<AltosScanResult> implements ListModel
 }
 
 public class AltosScanUI
-       extends JDialog
+       extends AltosDialog
        implements ActionListener
 {
        AltosUI                         owner;
index aa07bebc03a0b205e370b3b001354ff72b8050d9..5de7a05edee77fde6c30cf7033117f76cae66dba 100644 (file)
@@ -212,7 +212,7 @@ class AltosSites extends Thread {
        }
 }
 
-public class AltosSiteMapPreload extends JDialog implements ActionListener, ItemListener {
+public class AltosSiteMapPreload extends AltosDialog implements ActionListener, ItemListener {
        AltosUI         owner;
        AltosSiteMap    map;
 
index 3e5bcf434fc5b8b8276fe2074873e528d8032d74..8799d560767a6d8f532bdc47914e6b228f498121 100644 (file)
@@ -30,7 +30,7 @@ import java.util.concurrent.*;
 
 import libaltosJNI.*;
 
-public class AltosUI extends JFrame {
+public class AltosUI extends AltosFrame {
        public AltosVoice voice = new AltosVoice();
 
        public static boolean load_library(Frame frame) {
@@ -519,7 +519,7 @@ public class AltosUI extends JFrame {
        
        public static void main(final String[] args) {
                try {
-                       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+                       UIManager.setLookAndFeel(AltosPreferences.look_and_feel());
                } catch (Exception e) {
                }
                /* Handle batch-mode */
diff --git a/altosui/AltosUIListener.java b/altosui/AltosUIListener.java
new file mode 100644 (file)
index 0000000..7ee62af
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+public interface AltosUIListener {
+       public void ui_changed(String look_and_feel);
+}
index c4d1e611ff41ce5f6d2d81f3389735d37b9fd6c1..7cd383ac2c74584b84078862f44f551898c4b283 100644 (file)
@@ -110,6 +110,9 @@ altosui_JAVA = \
        AltosTelemetry.java \
        AltosTelemetryIterable.java \
        AltosUI.java \
+       AltosUIListener.java \
+       AltosFrame.java \
+       AltosDialog.java \
        AltosWriter.java \
        AltosDataPointReader.java \
        AltosDataPoint.java \