// Copyright (c) 2006 - 2008, Markus Strauch. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. package net.sf.sdedit.ui.impl; import java.awt.Font; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.Map; import java.util.WeakHashMap; import javax.swing.JComponent; import javax.swing.RootPaneContainer; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.UIManager.LookAndFeelInfo; /** * For dynamically changing the look and feel of whole frames and dialogs. * * @author Markus Strauch */ public/* singleton */class LookAndFeelManager extends URLClassLoader { /* * These weak hash maps serve as sets */ private Map<JComponent, Object> rootComponents = new WeakHashMap<JComponent, Object>(); private Map<RootPaneContainer, Object> containers = new WeakHashMap<RootPaneContainer, Object>(); private Map<JComponent, Object> orphans = new WeakHashMap<JComponent, Object>(); /* * The dummy value for the weak hash maps */ private Object dummy = new Object(); private static LookAndFeelManager instance; private String currentLAF; private static UIManager.LookAndFeelInfo[] available; static { instance = new LookAndFeelManager(); available = new UIManager.LookAndFeelInfo[UIManager .getInstalledLookAndFeels().length]; int i = 0; for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { available[i] = info; i++; } } public void setFont(Font font) { UIManager.put("Button.font", font); UIManager.put("ToggleButton.font", font); UIManager.put("RadioButton.font", font); UIManager.put("CheckBox.font", font); UIManager.put("ColorChooser.font", font); UIManager.put("ComboBox.font", font); UIManager.put("Label.font", font); UIManager.put("List.font", font); UIManager.put("MenuBar.font", font); UIManager.put("MenuItem.font", font); UIManager.put("RadioButtonMenuItem.font", font); UIManager.put("CheckBoxMenuItem.font", font); UIManager.put("Menu.font", font); UIManager.put("PopupMenu.font", font); UIManager.put("OptionPane.font", font); UIManager.put("Panel.font", font); UIManager.put("ProgressBar.font", font); UIManager.put("ScrollPane.font", font); UIManager.put("Viewport.font", font); UIManager.put("TabbedPane.font", font); UIManager.put("Table.font", font); UIManager.put("TableHeader.font", font); UIManager.put("TextField.font", font); UIManager.put("PasswordField.font", font); UIManager.put("TextArea.font", font); UIManager.put("TextPane.font", font); UIManager.put("EditorPane.font", font); UIManager.put("TitledBorder.font", font); UIManager.put("ToolBar.font", font); UIManager.put("ToolTip.font", font); UIManager.put("Tree.font", font); } private LookAndFeelManager() { super(new URL[0], Thread.currentThread().getContextClassLoader()); } @SuppressWarnings("unchecked") public static UIManager.LookAndFeelInfo[] getAvailableLookAndFeels() { return available; } /** * Returns the singleton <tt>LookAndFeelManager</tt>. * * @return the singleton <tt>LookAndFeelManager</tt> */ public static LookAndFeelManager instance() { return instance; } public void useExternalLAF(File jarFile, String cls) throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException { addURL(jarFile.toURI().toURL()); Class<?> clazz = loadClass(cls, true); ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this); UIManager.installLookAndFeel(clazz.getSimpleName(), cls); UIManager.setLookAndFeel(cls); //Thread.currentThread().setContextClassLoader(contextCL); } /** * Registers a JDialog so its subcomponents will get another look and feel * when {@linkplain #updateUserInterface()} is called. * * @param dialog * a JDialog that is to be managed by this * <tt>LookAndFeelManager</tt>, so the JDialog's subcomponents * look and feel can be changed by it */ public void register(RootPaneContainer container) { containers.put(container, container); } private void collectFrom(RootPaneContainer container) { rootComponents.put((JComponent) container.getGlassPane(), dummy); rootComponents.put(container.getRootPane(), dummy); rootComponents.put(container.getLayeredPane(), dummy); rootComponents.put((JComponent) container.getContentPane(), dummy); rootComponents.put(container.getRootPane().getJMenuBar(), dummy); if (container.getRootPane().getJMenuBar() != null) { rootComponents.put(container.getRootPane().getJMenuBar(), dummy); } } /** * Call <tt>updateUI()</tt> on all components inside the registered frames * and dialogs. */ public void updateUserInterface() { rootComponents.clear(); for (RootPaneContainer container : containers.keySet()) { collectFrom(container); } for (JComponent comp : rootComponents.keySet()) { if (comp != null) { SwingUtilities.updateComponentTreeUI(comp); } } for (JComponent comp : orphans.keySet()) { SwingUtilities.updateComponentTreeUI(comp); } } public void registerOrphan(JComponent orphan) { orphans.put(orphan, dummy); } public boolean changeTo(String lookAndFeelName) { currentLAF = lookAndFeelName; for (LookAndFeelInfo info : available) { if (info.getName().equals(lookAndFeelName)) { try { UIManager.setLookAndFeel(info.getClassName()); updateUserInterface(); return true; } catch (RuntimeException re) { throw re; } catch (Throwable t) { t.printStackTrace(); return false; } } } return false; } public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("lookAndFeel")) { String newLAF = (String) evt.getNewValue(); if (currentLAF == null || !newLAF.equals(currentLAF)) { changeTo(newLAF); } } } }