From 7ecde50fbebe68a2e2200a2f8d081fd37074f840 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 22:24:22 -0800 Subject: [PATCH] altosui: Make UI Look&Feel configurable Saves the preferred style and uses that for all current and new windows. Signed-off-by: Keith Packard --- altosui/AltosBTManage.java | 2 +- altosui/AltosCSVUI.java | 2 +- altosui/AltosConfigFreqUI.java | 4 +- altosui/AltosConfigUI.java | 2 +- altosui/AltosConfigureUI.java | 102 ++++++++++++++++++++++++++++++- altosui/AltosDeviceDialog.java | 2 +- altosui/AltosDialog.java | 62 +++++++++++++++++++ altosui/AltosEepromMonitor.java | 2 +- altosui/AltosEepromSelect.java | 2 +- altosui/AltosFlashUI.java | 2 +- altosui/AltosFlightUI.java | 2 +- altosui/AltosFrame.java | 56 +++++++++++++++++ altosui/AltosGraphUI.java | 2 +- altosui/AltosIdleMonitorUI.java | 10 ++- altosui/AltosIgniteUI.java | 2 +- altosui/AltosLaunchUI.java | 2 +- altosui/AltosPreferences.java | 42 ++++++++++++- altosui/AltosRomconfigUI.java | 2 +- altosui/AltosScanUI.java | 2 +- altosui/AltosSiteMapPreload.java | 2 +- altosui/AltosUI.java | 4 +- altosui/AltosUIListener.java | 22 +++++++ altosui/Makefile.am | 3 + 23 files changed, 312 insertions(+), 21 deletions(-) create mode 100644 altosui/AltosDialog.java create mode 100644 altosui/AltosFrame.java create mode 100644 altosui/AltosUIListener.java diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 10fdab3b..6d460701 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -32,7 +32,7 @@ import java.util.concurrent.*; import libaltosJNI.*; -public class AltosBTManage extends JDialog implements ActionListener, Iterable { +public class AltosBTManage extends AltosDialog implements ActionListener, Iterable { LinkedBlockingQueue found_devices; Frame frame; LinkedList listeners; diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index a212409e..6d3e9065 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -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; diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java index 063d21b4..c6eabc53 100644 --- a/altosui/AltosConfigFreqUI.java +++ b/altosui/AltosConfigFreqUI.java @@ -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 listeners; diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index d20dd073..9fef8e3b 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -32,7 +32,7 @@ import java.util.concurrent.LinkedBlockingQueue; import libaltosJNI.*; public class AltosConfigUI - extends JDialog + extends AltosDialog implements ActionListener, ItemListener, DocumentListener { diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 980068c0..06b5745c 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -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; diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index 610bb73e..e53e75c1 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -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 index 00000000..c30b5757 --- /dev/null +++ b/altosui/AltosDialog.java @@ -0,0 +1,62 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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()); + } +} diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java index b9d913fa..34f5b891 100644 --- a/altosui/AltosEepromMonitor.java +++ b/altosui/AltosEepromMonitor.java @@ -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; diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index 0a6eec17..ebafc4c8 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -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; diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 3956ff20..39151641 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -29,7 +29,7 @@ import java.util.prefs.*; import java.util.concurrent.*; public class AltosFlashUI - extends JDialog + extends AltosDialog implements ActionListener { Container pane; diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index b44b9d43..d166c9ae 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -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 index 00000000..f8cc4f52 --- /dev/null +++ b/altosui/AltosFrame.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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()); + } +} diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 59e92499..c30dc476 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -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; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 988a797c..a5f41e25 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -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); } }); diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index b215c228..8623cbef 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -30,7 +30,7 @@ import java.util.prefs.*; import java.util.concurrent.*; public class AltosIgniteUI - extends JDialog + extends AltosDialog implements ActionListener { AltosDevice device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 47365e03..73fae16b 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -50,7 +50,7 @@ class FireButton extends JButton { } public class AltosLaunchUI - extends JDialog + extends AltosDialog implements ActionListener { AltosDevice device; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 48aed441..cc2b1a95 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -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 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(); } 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); diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java index 7e21735c..e4e38c9c 100644 --- a/altosui/AltosRomconfigUI.java +++ b/altosui/AltosRomconfigUI.java @@ -29,7 +29,7 @@ import java.text.*; import java.util.prefs.*; public class AltosRomconfigUI - extends JDialog + extends AltosDialog implements ActionListener { Container pane; diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index df5c51d4..e188834e 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -102,7 +102,7 @@ class AltosScanResults extends LinkedList implements ListModel } public class AltosScanUI - extends JDialog + extends AltosDialog implements ActionListener { AltosUI owner; diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index aa07bebc..5de7a05e 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -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; diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 3e5bcf43..8799d560 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -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 index 00000000..7ee62afc --- /dev/null +++ b/altosui/AltosUIListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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); +} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index c4d1e611..7cd383ac 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -110,6 +110,9 @@ altosui_JAVA = \ AltosTelemetry.java \ AltosTelemetryIterable.java \ AltosUI.java \ + AltosUIListener.java \ + AltosFrame.java \ + AltosDialog.java \ AltosWriter.java \ AltosDataPointReader.java \ AltosDataPoint.java \ -- 2.30.2