All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jidesoft.plaf.CachedLookAndFeel Maven / Gradle / Ivy

There is a newer version: 3.6.18
Show newest version
package com.jidesoft.plaf;

import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * When UIManager.getUI(JComponent target) is called to retrieve a ComponentUI object for a target, we want to make sure
 * that ComponentUI is from the same classloader as the target classloader.
 * 

* The CacheCleanerLookAndFeel will install itself as a hook to intercept UIManager().getUI(). It will clean up the * UIManager cache if needed and also update the UIManager L&F defaults table if needed. This is very useful if you have * to use multiple class loader and each class loader has its own version of JIDE jars. *

*

 * CachedLookAndFeel.install();
 * CachedLookAndFeel.installJideExtension(LookAndFeelFactory.class.getClassLoader(), true);
 * 
*/ class CachedLookAndFeel extends LookAndFeel { static ClassLoader currentLoader; // active classloader UIDefaults customDefaults = new CustomUIDefaults(); /** * Install itself as UIManager.getLAFState().multiLookAndFeel to that calls to getUI() can be trapped */ public static void install() { try { // lafState = UIManager.getLAFState() method Method method = UIManager.class.getDeclaredMethod("getLAFState", new Class[]{null}); method.setAccessible(true); // turn off checking for private method Object lafState = method.invoke(null, new Object[]{null}); // lafState.multiLookAndFeel = new CacheCleanerLookAndFeel() Field field = lafState.getClass().getDeclaredField("multiLookAndFeel"); field.setAccessible(true); // turn off security checking CachedLookAndFeel laf = new CachedLookAndFeel(); field.set(lafState, laf); } catch (Exception e) { e.printStackTrace(); } } public CachedLookAndFeel() { customDefaults = new CustomUIDefaults(); } @Override public String getName() { return "CachedLookAndFeel"; } @Override public String getID() { return "CachedLookAndFeel"; } @Override public String getDescription() { return "Provide customized behaviour for getUI() method"; } @Override public boolean isNativeLookAndFeel() { return false; } @Override public boolean isSupportedLookAndFeel() { return true; } @Override public UIDefaults getDefaults() { return customDefaults; } /** * Call the LookAndFeelFactory.installJideExtension using a specific class loader. This is used for GUI context * switch when going between two class loaders. * * @param newLoader ClassLoader */ public static void installJideExtension(ClassLoader newLoader) { installJideExtension(newLoader, false); } /** * Call the LookAndFeelFactory.installJideExtension using a specific class loader. This is used for GUI context * switch when going between two class loaders. * * @param newLoader ClassLoader * @param force if true, we will install the extension even when the current loader and new class loader are the * same. */ public static void installJideExtension(ClassLoader newLoader, boolean force) { if (currentLoader == newLoader && !force) { return; } try { Class lafFactory = newLoader.loadClass("com.jidesoft.plaf.LookAndFeelFactory"); Method installJideExtension = lafFactory.getDeclaredMethod("installJideExtension", new Class[]{int.class}); int style = LookAndFeelFactory.getDefaultStyle(); UIManager.put(LookAndFeelFactory.JIDE_EXTENSION_INSTALLED, null); // force population installJideExtension.invoke(null, style); } catch (Exception e) { // ignore } currentLoader = newLoader; UIManager.put("ClassLoader", newLoader); } public static void reinstallJideExtension() { installJideExtension(currentLoader, true); } private static void removeCachedClass(UIDefaults defaults, Class componentUIClass) { if (componentUIClass != null) { // remove className <--> class definition defaults.remove(componentUIClass.getName()); // remove class definition <--> method definition defaults.remove(componentUIClass); } } static class CustomUIDefaults extends UIDefaults { private static final long serialVersionUID = -6034471887061473005L; @Override public ComponentUI getUI(JComponent target) { UIDefaults defaults = UIManager.getDefaults(); // to increase the performance, UIManager is caching the // className <--> class definition object // It does not differentiate between classNames from different class loaders // This means that the cached class definition may not match the current // classloader and will cause ClassCastException later on. // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4675772 String className = (String) defaults.get(target.getUIClassID()); Class componentUIClass = className != null ? (Class) defaults.get(className) : null; ClassLoader componentUIClassLoader = componentUIClass != null ? componentUIClass.getClassLoader() : null; ClassLoader targetClassLoader = target.getClass().getClassLoader(); ClassLoader uiClassLoader = (ClassLoader) UIManager.get("ClassLoader"); if (targetClassLoader == null) { // for JMenuItem and JPopupMenu.Separator if (componentUIClassLoader != null && componentUIClassLoader != uiClassLoader) { removeCachedClass(defaults, componentUIClass); } return null; } if (targetClassLoader != componentUIClassLoader || targetClassLoader != uiClassLoader) { if (componentUIClassLoader != null) { removeCachedClass(defaults, componentUIClass); } installJideExtension(targetClassLoader); } return null; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy