package com.mindprod.common17;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JRootPane;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.security.AccessControlException;
import java.util.prefs.Preferences;
import static java.lang.System.*;
/**
* Methods for selecting Look and Feel.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.0 2010-03-22 initial version
* @since 2010-03-22
*/
public final class Laf
{
/**
* build JMenu to allow user to choose a L&F. It must be installed in a JMenuBar.
* USE REQUIRES APPLET TO BE SIGNED. We set system property and persist the chosen LAF.
*
* @return the JMenu containing all the supported Look and Feels
*/
public static JMenu buildLookAndFeelMenu()
{
try
{
System.setProperty( "swing.aatext", "true" );
final JMenu menuLAF = new JMenu( "Look & Feel" );
ActionListener changeLAFListener = new ActionListener()
{
public void actionPerformed( final ActionEvent e )
{
final JRadioButtonMenuItem rbmi = ( JRadioButtonMenuItem ) e.getSource();
setLookAndFeel( rbmi.getActionCommand() );
propagateLookAndFeelChange();
persistLookAndFeel( new UIManager.LookAndFeelInfo( rbmi.getText(), rbmi.getActionCommand() ) );
}
};
UIManager.LookAndFeelInfo laf = Laf.getPersistedLookAndFeel();
if ( laf == null )
{
laf = Laf.getPreferredLookAndFeel();
if ( laf == null )
{
laf = Laf.getCurrentLookAndFeel();
}
}
setLookAndFeel( laf.getClassName() );
final ButtonGroup bg = new ButtonGroup();
final UIManager.LookAndFeelInfo[] installed = UIManager.getInstalledLookAndFeels();
for ( UIManager.LookAndFeelInfo info : installed )
{
final JRadioButtonMenuItem rbmi = new JRadioButtonMenuItem( info.getName(),
isSameLookAndFeel( info, laf ) );
menuLAF.add( rbmi );
bg.add( rbmi );
rbmi.setActionCommand( info.getClassName() );
rbmi.addActionListener( changeLAFListener );
}
return menuLAF;
}
catch ( AccessControlException e )
{
err.println( "Look and Feel changes are not available because you refused permission." );
return null;
}
}
/**
* get current L&F
*
* @return L&F currently in effect
*/
private static UIManager.LookAndFeelInfo getCurrentLookAndFeel()
{
final LookAndFeel current = UIManager.getLookAndFeel();
final String currentLAFName = current.getName();
final String currentLAFClassName = current.getClass().getName();
if ( currentLAFName.length() > 0 )
{
return new UIManager.LookAndFeelInfo( currentLAFName, currentLAFClassName );
}
else
{
return null;
}
}
/**
* fetch the persisted L&F the user has selected previously
*
* @return L&F user chose last time, null if none.
*/
private static UIManager.LookAndFeelInfo getPersistedLookAndFeel()
{
final Preferences lafPref = Preferences.userRoot().node( "/com/mindprod/common17/laf" );
final String persistedLAFName = lafPref.get( "lafName", "" );
final String persistedLAFClassName = lafPref.get( "lafClassName", "" );
if ( persistedLAFName.length() > 0 )
{
final UIManager.LookAndFeelInfo laf = new UIManager.LookAndFeelInfo( persistedLAFName,
persistedLAFClassName );
if ( isLookAndFeelSupported( laf ) )
{
return laf;
}
else
{
return null;
}
}
else
{
return null;
}
}
/**
* Get the preferred LookAndFeel, default before the user has expressed a preference.
*
* @return look and feel, null if none of desirable ones are supported.
*/
private static UIManager.LookAndFeelInfo getPreferredLookAndFeel()
{
final String preferredClassNames[] = {
"ch.randelshofer.quaqua.QuaquaLookAndFeel",
"com.sun.java.swing.plaf.mac.MacLookAndFeel",
"com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel",
"javax.swing.plaf.metal.MetalLookAndFeel",
UIManager.getSystemLookAndFeelClassName() };
final UIManager.LookAndFeelInfo[] installed = UIManager.getInstalledLookAndFeels();
for ( final String preferredClassName : preferredClassNames )
{
for ( UIManager.LookAndFeelInfo anInstalled : installed )
{
if ( preferredClassName.equals( anInstalled.getClassName() ) )
{
return new UIManager.LookAndFeelInfo( anInstalled.getName(), preferredClassName );
}
}
}
return null;
}
/**
* is this L&F supported
*
* @param laf to check if is supported
*
* @return true laf is supported.
*/
private static boolean isLookAndFeelSupported( UIManager.LookAndFeelInfo laf )
{
final UIManager.LookAndFeelInfo[] installed = UIManager.getInstalledLookAndFeels();
for ( UIManager.LookAndFeelInfo info : installed )
{
if ( isSameLookAndFeel( info, laf ) )
{
return true;
}
}
return false;
}
/**
* do two L&Fs match ?
*
* @param a first L&F
* @param b second L&F
*
* @return true if both the name and className match
*/
private static boolean isSameLookAndFeel( UIManager.LookAndFeelInfo a, UIManager.LookAndFeelInfo b )
{
return a == b || a != null && b != null && a.getName().equals( b.getName() ) && a.getClassName().equals( b
.getClassName() );
}
/**
* save L&F using the persistence mechanism
*
* @param laf L&F to persist
*/
private static void persistLookAndFeel( UIManager.LookAndFeelInfo laf )
{
Preferences lafPref = Preferences.userRoot().node( "/com/mindprod/common17/laf" );
lafPref.put( "lafName", laf.getName() );
lafPref.put( "lafClassName", laf.getClassName() );
}
/**
* make sure all Frames and Windows are repainted with the new Look and Feel.
*/
private static void propagateLookAndFeelChange()
{
final Frame frames[] = Frame.getFrames();
if ( frames.length == 0 )
{
return;
}
for ( Frame frame : frames )
{
SwingUtilities.updateComponentTreeUI( frame );
Window windows[] = frame.getOwnedWindows();
for ( Window window : windows )
{
SwingUtilities.updateComponentTreeUI( window );
}
}
try
{
final JFrame outerFrame = ( JFrame ) frames[ 0 ];
outerFrame.setVisible( false );
outerFrame.dispose();
outerFrame.setUndecorated( false );
outerFrame.getRootPane().setWindowDecorationStyle( JRootPane.NONE );
outerFrame.setVisible( true );
}
catch ( ClassCastException e )
{
}
}
/**
* change the current look and feel.
* If the class is invalid, the command is ignored.
*
* @param lookAndFeelClassName name of Look and Feel class
*/
private static void setLookAndFeel( String lookAndFeelClassName )
{
if ( UIManager.getLookAndFeel().getClass().getName().equals( lookAndFeelClassName ) )
{
return;
}
try
{
UIManager.setLookAndFeel( lookAndFeelClassName );
}
catch ( Exception exception )
{
err.println( "Setting Look and Feel failed" );
err.println( exception.getMessage() );
}
}
/**
* test harness
*
* @param args not used
*
* @noinspection EmptyMethod
*/
public static void main( String[] args )
{
}
}