[ Team LiB ] Previous Section Next Section

11.14 Look-and-Feel Preferences

A number of the examples in this chapter have used the utility class LookAndFeelPrefs to install the user's preferred look-and-feel and create a JMenu listing available look-and-feel choices. LookAndFeelPrefs is shown in Example 11-29. It demonstrates the use of the javax.swing.UIManager class for querying and setting look-and-feels, and also demonstrates the use of the java.util.prefs package (new in Java 1.4) for retrieving and storing persistent user preferences.

LookAndFeelPrefs relies on the list of installed look-and-feel implementations returned by UIManager.getInstalledLookAndFeels( ). By default (in Java 1.4.2, at least) this method returns three look-and-feels: the Java "Metal" look-and-feel, the Motif (CDE) look-and-feel, and the Windows look-and-feel. This is true even on non-Windows platforms for which the Windows look-and-feel is unsupported. Java 1.4.2 also ships with a GTK look-and-feel, which mimics the Linux GTK look-and-feel, but getInstalledLookAndFeels( ) does not know about it. To make this new look-and-feel available to the LookAndFeelPrefs example, you'll need to create a swing.properties file and place it in the jre/lib/ directory of your Java SDK. The contents of the file should look like this:

# Add the Mac look-and-feel if your SDK comes with it.
# Delete the Windows look-and-feel if it is not supported on your platform.
swing.installedlafs = gtk,metal,motif,win
swing.installedlaf.gtk.name = GTK Look and Feel,
swing.installedlaf.gtk.class = com.sun.java.swing.plaf.gtk.GTKLookAndFeel
swing.installedlaf.metal.name = Java Look and Feel
swing.installedlaf.metal.class = javax.swing.plaf.metal.MetalLookAndFeel
swing.installedlaf.motif.name = Motif/CDE Look and Feel
swing.installedlaf.motif.class = com.sun.java.swing.plaf.motif.MotifLookAndFeel
swing.installedlaf.win.name = Windows Look and Feel
swing.installedlaf.win.class = com.sun.java.swing.plaf.windows.WindowsLookAndFeel
Example 11-29. LookAndFeelPrefs.java
package je3.gui;
import javax.swing.*;
import java.awt.event.*;
import java.util.prefs.Preferences;

public class LookAndFeelPrefs {
    public static final String PREF_NAME = "preferredLookAndFeelClassName";

    /**
     * Get the desired look-and-feel from a per-user preference.  If
     * the preference doesn't exist or is unavailable, use the
     * default look-and-feel.  The preference is shared by all classes
     * in the same package as prefsClass.
     **/
    public static void setPreferredLookAndFeel(Class prefsClass) {
        Preferences prefs=Preferences.userNodeForPackage(prefsClass);
        String defaultLAF = UIManager.getSystemLookAndFeelClassName( );
        String laf = prefs.get(PREF_NAME, defaultLAF);
        try { UIManager.setLookAndFeel(laf); }
        catch (Exception e) { // ClassNotFound or InstantiationException
            // An exception here is probably caused by a bogus preference.
            // Ignore it silently; the user will make do with the default LAF.
        }
    }

    /**
     * Create a menu of radio buttons listing the available Look and Feels.
     * When the user selects one, change the component hierarchy under frame
     * to the new LAF, and store the new selection as the current preference
     * for the package containing class c.
     **/
    public static JMenu createLookAndFeelMenu(final Class prefsClass,
                                              final ActionListener listener)
    {
        // Create the menu
        final JMenu plafmenu = new JMenu("Look and Feel");

        // Create an object used for radio button mutual exclusion
        ButtonGroup radiogroup = new ButtonGroup( );  

        // Look up the available look-and-feels
        UIManager.LookAndFeelInfo[  ] plafs=UIManager.getInstalledLookAndFeels( );

        // Find out which one is currently used
        String currentLAFName=UIManager.getLookAndFeel( ).getClass( ).getName( );

        // Loop through the plafs, and add a menu item for each one
        for(int i = 0; i < plafs.length; i++) {
            String plafName = plafs[i].getName( );
            final String plafClassName = plafs[i].getClassName( );

            // Create the menu item
            final JMenuItem item =
                plafmenu.add(new JRadioButtonMenuItem(plafName));
            item.setSelected(plafClassName.equals(currentLAFName));
            
            // Tell the menu item what to do when it is selected
            item.addActionListener(new ActionListener( ) {
                public void actionPerformed(ActionEvent event) {
                    // Set the new look-and-feel
                    try { UIManager.setLookAndFeel(plafClassName); }
                    catch(UnsupportedLookAndFeelException e) {
                        // Sometimes a Look-and-Feel is installed but not
                        // supported, as in the Windows LaF on Linux platforms.
                        JOptionPane.showMessageDialog(plafmenu,
                              "The selected Look-and-Feel is " +
                              "not supported on this platform.",
                              "Unsupported Look And Feel",
                              JOptionPane.ERROR_MESSAGE);
                        item.setEnabled(false);
                    }
                    catch (Exception e) { // ClassNotFound or Instantiation
                        item.setEnabled(false);  // shouldn't happen
                    }

                    // Make the selection persistent by storing it in prefs.
                    Preferences p = Preferences.userNodeForPackage(prefsClass);
                    p.put(PREF_NAME, plafClassName);

                    // Invoke the supplied action listener so the calling
                    // application can update its components to the new LAF
                    // Reuse the event that was passed here.
                    listener.actionPerformed(event);
                }
            });

            // Only allow one menu item to be selected at once
            radiogroup.add(item);  
        }

        return plafmenu;
    }
}
    [ Team LiB ] Previous Section Next Section