/* * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package ${PACKAGE}; import javax.swing.Painter;import java.awt.Graphics;import sun.font.FontUtilities;import sun.swing.plaf.synth.DefaultSynthStyle;import javax.swing.BorderFactory;import javax.swing.JComponent;import javax.swing.JInternalFrame;import javax.swing.UIDefaults;import javax.swing.UIManager;import javax.swing.plaf.BorderUIResource;import javax.swing.plaf.ColorUIResource;import javax.swing.plaf.DimensionUIResource;import javax.swing.plaf.FontUIResource;import javax.swing.plaf.InsetsUIResource;import javax.swing.plaf.synth.Region;import javax.swing.plaf.synth.SynthStyle;import java.awt.Color;import java.awt.Component;import java.awt.Dimension;import java.awt.Font;import java.awt.Graphics2D;import java.awt.Insets;import java.awt.image.BufferedImage;import static java.awt.image.BufferedImage.*;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.lang.ref.WeakReference;import java.lang.reflect.Constructor;import java.util.ArrayList;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Set;import java.util.WeakHashMap;import javax.swing.border.Border;import javax.swing.plaf.UIResource; /** * This class contains all the implementation details related to * ${LAF_NAME}. It contains all the code for initializing the UIDefaults table, * as well as for selecting * a SynthStyle based on a JComponent/Region pair. * * @author Richard Bair */final class ${LAF_NAME}Defaults { /** * The map of SynthStyles. This map is keyed by Region. Each Region maps * to a List of LazyStyles. Each LazyStyle has a reference to the prefix * that was registered with it. This reference can then be inspected to see * if it is the proper lazy style. * <p/> * There can be more than one LazyStyle for a single Region if there is more * than one prefix defined for a given region. For example, both Button and * "MyButton" might be prefixes assigned to the Region.Button region. */ private Map<Region, List<LazyStyle>> m; /** * A map of regions which have been registered. * This mapping is maintained so that the Region can be found based on * prefix in a very fast manner. This is used in the "matches" method of * LazyStyle. */ private Map<String, Region> registeredRegions = new HashMap<String, Region>(); private Map<JComponent, Map<Region, SynthStyle>> overridesCache = new WeakHashMap<JComponent, Map<Region, SynthStyle>>(); /** * Our fallback style to avoid NPEs if the proper style cannot be found in * this class. Not sure if relying on DefaultSynthStyle is the best choice. */ private DefaultSynthStyle defaultStyle; /** * The default font that will be used. I store this value so that it can be * set in the UIDefaults when requested. */ private FontUIResource defaultFont; private ColorTree colorTree = new ColorTree(); /** Listener for changes to user defaults table */ private DefaultsListener defaultsListener = new DefaultsListener(); /** Called by UIManager when this look and feel is installed. */ void initialize() { // add listener for derived colors UIManager.addPropertyChangeListener(defaultsListener); UIManager.getDefaults().addPropertyChangeListener(colorTree); } /** Called by UIManager when this look and feel is uninstalled. */ void uninitialize() { // remove listener for derived colors UIManager.removePropertyChangeListener(defaultsListener); UIManager.getDefaults().removePropertyChangeListener(colorTree); } /** * Create a new ${LAF_NAME}Defaults. This constructor is only called from * within ${LAF_NAME}LookAndFeel. */ ${LAF_NAME}Defaults() { m = new HashMap<Region, List<LazyStyle>>(); //Create the default font and default style. Also register all of the //regions and their states that this class will use for later lookup. //Additional regions can be registered later by 3rd party components. //These are simply the default registrations. defaultFont = FontUtilities.getFontConfigFUIR("sans", Font.PLAIN, 12); defaultStyle = new DefaultSynthStyle(); defaultStyle.setFont(defaultFont); //initialize the map of styles${STYLE_INIT} } //--------------- Methods called by ${LAF_NAME}LookAndFeel /** * Called from ${LAF_NAME}LookAndFeel to initialize the UIDefaults. * * @param d UIDefaults table to initialize. This will never be null. * If listeners are attached to <code>d</code>, then you will * only receive notification of LookAndFeel level defaults, not * all defaults on the UIManager. */ void initializeDefaults(UIDefaults d) {${UI_DEFAULT_INIT} } /** * <p>Registers the given region and prefix. The prefix, if it contains * quoted sections, refers to certain named components. If there are not * quoted sections, then the prefix refers to a generic component type.</p> * * <p>If the given region/prefix combo has already been registered, then * it will not be registered twice. The second registration attempt will * fail silently.</p> * * @param region The Synth Region that is being registered. Such as Button, * or ScrollBarThumb. * @param prefix The UIDefault prefix. For example, could be ComboBox, or if * a named components, "MyComboBox", or even something like * ToolBar:"MyComboBox":"ComboBox.arrowButton" */ void register(Region region, String prefix) { //validate the method arguments if (region == null || prefix == null) { throw new IllegalArgumentException( "Neither Region nor Prefix may be null"); } //Add a LazyStyle for this region/prefix to m. List<LazyStyle> styles = m.get(region); if (styles == null) { styles = new LinkedList<LazyStyle>(); styles.add(new LazyStyle(prefix)); m.put(region, styles); } else { //iterate over all the current styles and see if this prefix has //already been registered. If not, then register it. for (LazyStyle s : styles) { if (prefix.equals(s.prefix)) { return; } } styles.add(new LazyStyle(prefix)); } //add this region to the map of registered regions registeredRegions.put(region.getName(), region); } /** * <p>Locate the style associated with the given region, and component. * This is called from ${LAF_NAME}LookAndFeel in the SynthStyleFactory * implementation.</p> * * <p>Lookup occurs as follows:<br/> * Check the map of styles <code>m</code>. If the map contains no styles at * all, then simply return the defaultStyle. If the map contains styles, * then iterate over all of the styles for the Region <code>r</code> looking * for the best match, based on prefix. If a match was made, then return * that SynthStyle. Otherwise, return the defaultStyle.</p> * * @param comp The component associated with this region. For example, if * the Region is Region.Button then the component will be a JButton. * If the Region is a subregion, such as ScrollBarThumb, then the * associated component will be the component that subregion belongs * to, such as JScrollBar. The JComponent may be named. It may not be * null. * @param r The region we are looking for a style for. May not be null. */ SynthStyle getStyle(JComponent comp, Region r) { //validate method arguments if (comp == null || r == null) { throw new IllegalArgumentException( "Neither comp nor r may be null"); } //if there are no lazy styles registered for the region r, then return //the default style List<LazyStyle> styles = m.get(r); if (styles == null || styles.size() == 0) { return defaultStyle; } //Look for the best SynthStyle for this component/region pair. LazyStyle foundStyle = null; for (LazyStyle s : styles) { if (s.matches(comp)) { //replace the foundStyle if foundStyle is null, or //if the new style "s" is more specific (ie, its path was //longer), or if the foundStyle was "simple" and the new style //was not (ie: the foundStyle was for something like Button and //the new style was for something like "MyButton", hence, being //more specific.) In all cases, favor the most specific style //found. if (foundStyle == null || (foundStyle.parts.length < s.parts.length) || (foundStyle.parts.length == s.parts.length && foundStyle.simple && !s.simple)) { foundStyle = s; } } } //return the style, if found, or the default style if not found return foundStyle == null ? defaultStyle : foundStyle.getStyle(comp, r); } public void clearOverridesCache(JComponent c) { overridesCache.remove(c); } /* Various public helper classes. These may be used to register 3rd party values into UIDefaults */ /** * <p>Derives its font value based on a parent font and a set of offsets and * attributes. This class is an ActiveValue, meaning that it will recompute * its value each time it is requested from UIDefaults. It is therefore * recommended to read this value once and cache it in the UI delegate class * until asked to reinitialize.</p> * * <p>To use this class, create an instance with the key of the font in the * UI defaults table from which to derive this font, along with a size * offset (if any), and whether it is to be bold, italic, or left in its * default form.</p> */ static final class DerivedFont implements UIDefaults.ActiveValue { private float sizeOffset; private Boolean bold; private Boolean italic; private String parentKey; /** * Create a new DerivedFont. * * @param key The UIDefault key associated with this derived font's * parent or source. If this key leads to a null value, or a * value that is not a font, then null will be returned as * the derived font. The key must not be null. * @param sizeOffset The size offset, as a percentage, to use. For * example, if the source font was a 12pt font and the * sizeOffset were specified as .9, then the new font * will be 90% of what the source font was, or, 10.8 * pts which is rounded to 11pts. This fractional * based offset allows for proper font scaling in high * DPI or large system font scenarios. * @param bold Whether the new font should be bold. If null, then this * new font will inherit the bold setting of the source * font. * @param italic Whether the new font should be italicized. If null, * then this new font will inherit the italic setting of * the source font. */ public DerivedFont(String key, float sizeOffset, Boolean bold, Boolean italic) { //validate the constructor arguments if (key == null) { throw new IllegalArgumentException("You must specify a key"); } //set the values this.parentKey = key; this.sizeOffset = sizeOffset; this.bold = bold; this.italic = italic; } /** * @inheritDoc */ @Override public Object createValue(UIDefaults defaults) { Font f = defaults.getFont(parentKey); if (f != null) { // always round size for now so we have exact int font size // (or we may have lame looking fonts) float size = Math.round(f.getSize2D() * sizeOffset); int style = f.getStyle(); if (bold != null) { if (bold.booleanValue()) { style = style | Font.BOLD; } else { style = style & ~Font.BOLD; } } if (italic != null) { if (italic.booleanValue()) { style = style | Font.ITALIC; } else { style = style & ~Font.ITALIC; } } return f.deriveFont(style, size); } else { return null; } } } /** * This class is private because it relies on the constructor of the * auto-generated AbstractRegionPainter subclasses. Hence, it is not * generally useful, and is private. * <p/> * LazyPainter is a LazyValue class. It will create the * AbstractRegionPainter lazily, when asked. It uses reflection to load the * proper class and invoke its constructor. */ private static final class LazyPainter implements UIDefaults.LazyValue { private int which; private AbstractRegionPainter.PaintContext ctx; private String className; LazyPainter(String className, int which, Insets insets, Dimension canvasSize, boolean inverted) { if (className == null) { throw new IllegalArgumentException( "The className must be specified"); } this.className = className; this.which = which; this.ctx = new AbstractRegionPainter.PaintContext( insets, canvasSize, inverted); } LazyPainter(String className, int which, Insets insets, Dimension canvasSize, boolean inverted, AbstractRegionPainter.PaintContext.CacheMode cacheMode, double maxH, double maxV) { if (className == null) { throw new IllegalArgumentException( "The className must be specified"); } this.className = className; this.which = which; this.ctx = new AbstractRegionPainter.PaintContext( insets, canvasSize, inverted, cacheMode, maxH, maxV); } @Override public Object createValue(UIDefaults table) { try { Class c; Object cl; // See if we should use a separate ClassLoader if (table == null || !((cl = table.get("ClassLoader")) instanceof ClassLoader)) { cl = Thread.currentThread(). getContextClassLoader(); if (cl == null) { // Fallback to the system class loader. cl = ClassLoader.getSystemClassLoader(); } } c = Class.forName(className, true, (ClassLoader)cl); Constructor constructor = c.getConstructor( AbstractRegionPainter.PaintContext.class, int.class); if (constructor == null) { throw new NullPointerException( "Failed to find the constructor for the class: " + className); } return constructor.newInstance(ctx, which); } catch (Exception e) { e.printStackTrace(); return null; } } } /** * A class which creates the NimbusStyle associated with it lazily, but also * manages a lot more information about the style. It is less of a LazyValue * type of class, and more of an Entry or Item type of class, as it * represents an entry in the list of LazyStyles in the map m. * * The primary responsibilities of this class include: * <ul> * <li>Determining whether a given component/region pair matches this * style</li> * <li>Splitting the prefix specified in the constructor into its * constituent parts to facilitate quicker matching</li> * <li>Creating and vending a NimbusStyle lazily.</li> * </ul> */ private final class LazyStyle { /** * The prefix this LazyStyle was registered with. Something like * Button or ComboBox:"ComboBox.arrowButton" */ private String prefix; /** * Whether or not this LazyStyle represents an unnamed component */ private boolean simple = true; /** * The various parts, or sections, of the prefix. For example, * the prefix: * ComboBox:"ComboBox.arrowButton" * * will be broken into two parts, * ComboBox and "ComboBox.arrowButton" */ private Part[] parts; /** * Cached shared style. */ private NimbusStyle style; /** * Create a new LazyStyle. * * @param prefix The prefix associated with this style. Cannot be null. */ private LazyStyle(String prefix) { if (prefix == null) { throw new IllegalArgumentException( "The prefix must not be null"); } this.prefix = prefix; //there is one odd case that needs to be supported here: cell //renderers. A cell renderer is defined as a named internal //component, so for example: // List."List.cellRenderer" //The problem is that the component named List.cellRenderer is not a //child of a JList. Rather, it is treated more as a direct component //Thus, if the prefix ends with "cellRenderer", then remove all the //previous dotted parts of the prefix name so that it becomes, for //example: "List.cellRenderer" //Likewise, we have a hacked work around for cellRenderer, renderer, //and listRenderer. String temp = prefix; if (temp.endsWith("cellRenderer\"") || temp.endsWith("renderer\"") || temp.endsWith("listRenderer\"")) { temp = temp.substring(temp.lastIndexOf(":\"") + 1); } //otherwise, normal code pathLines 1–500 of 858. Load more
/* * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package ${PACKAGE}; import javax.swing.Painter; import java.awt.Graphics; import sun.font.FontUtilities; import sun.swing.plaf.synth.DefaultSynthStyle; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JInternalFrame; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.BorderUIResource; import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.DimensionUIResource; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.InsetsUIResource; import javax.swing.plaf.synth.Region; import javax.swing.plaf.synth.SynthStyle; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.image.BufferedImage; import static java.awt.image.BufferedImage.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import javax.swing.border.Border; import javax.swing.plaf.UIResource; /** * This class contains all the implementation details related to * ${LAF_NAME}. It contains all the code for initializing the UIDefaults table, * as well as for selecting * a SynthStyle based on a JComponent/Region pair. * * @author Richard Bair */ final class ${LAF_NAME}Defaults { /** * The map of SynthStyles. This map is keyed by Region. Each Region maps * to a List of LazyStyles. Each LazyStyle has a reference to the prefix * that was registered with it. This reference can then be inspected to see * if it is the proper lazy style. * <p/> * There can be more than one LazyStyle for a single Region if there is more * than one prefix defined for a given region. For example, both Button and * "MyButton" might be prefixes assigned to the Region.Button region. */ private Map<Region, List<LazyStyle>> m; /** * A map of regions which have been registered. * This mapping is maintained so that the Region can be found based on * prefix in a very fast manner. This is used in the "matches" method of * LazyStyle. */ private Map<String, Region> registeredRegions = new HashMap<String, Region>(); private Map<JComponent, Map<Region, SynthStyle>> overridesCache = new WeakHashMap<JComponent, Map<Region, SynthStyle>>(); /** * Our fallback style to avoid NPEs if the proper style cannot be found in * this class. Not sure if relying on DefaultSynthStyle is the best choice. */ private DefaultSynthStyle defaultStyle; /** * The default font that will be used. I store this value so that it can be * set in the UIDefaults when requested. */ private FontUIResource defaultFont; private ColorTree colorTree = new ColorTree(); /** Listener for changes to user defaults table */ private DefaultsListener defaultsListener = new DefaultsListener(); /** Called by UIManager when this look and feel is installed. */ void initialize() { // add listener for derived colors UIManager.addPropertyChangeListener(defaultsListener); UIManager.getDefaults().addPropertyChangeListener(colorTree); } /** Called by UIManager when this look and feel is uninstalled. */ void uninitialize() { // remove listener for derived colors UIManager.removePropertyChangeListener(defaultsListener); UIManager.getDefaults().removePropertyChangeListener(colorTree); } /** * Create a new ${LAF_NAME}Defaults. This constructor is only called from * within ${LAF_NAME}LookAndFeel. */ ${LAF_NAME}Defaults() { m = new HashMap<Region, List<LazyStyle>>(); //Create the default font and default style. Also register all of the //regions and their states that this class will use for later lookup. //Additional regions can be registered later by 3rd party components. //These are simply the default registrations. defaultFont = FontUtilities.getFontConfigFUIR("sans", Font.PLAIN, 12); defaultStyle = new DefaultSynthStyle(); defaultStyle.setFont(defaultFont); //initialize the map of styles ${STYLE_INIT} } //--------------- Methods called by ${LAF_NAME}LookAndFeel /** * Called from ${LAF_NAME}LookAndFeel to initialize the UIDefaults. * * @param d UIDefaults table to initialize. This will never be null. * If listeners are attached to <code>d</code>, then you will * only receive notification of LookAndFeel level defaults, not * all defaults on the UIManager. */ void initializeDefaults(UIDefaults d) { ${UI_DEFAULT_INIT} } /** * <p>Registers the given region and prefix. The prefix, if it contains * quoted sections, refers to certain named components. If there are not * quoted sections, then the prefix refers to a generic component type.</p> * * <p>If the given region/prefix combo has already been registered, then * it will not be registered twice. The second registration attempt will * fail silently.</p> * * @param region The Synth Region that is being registered. Such as Button, * or ScrollBarThumb. * @param prefix The UIDefault prefix. For example, could be ComboBox, or if * a named components, "MyComboBox", or even something like * ToolBar:"MyComboBox":"ComboBox.arrowButton" */ void register(Region region, String prefix) { //validate the method arguments if (region == null || prefix == null) { throw new IllegalArgumentException( "Neither Region nor Prefix may be null"); } //Add a LazyStyle for this region/prefix to m. List<LazyStyle> styles = m.get(region); if (styles == null) { styles = new LinkedList<LazyStyle>(); styles.add(new LazyStyle(prefix)); m.put(region, styles); } else { //iterate over all the current styles and see if this prefix has //already been registered. If not, then register it. for (LazyStyle s : styles) { if (prefix.equals(s.prefix)) { return; } } styles.add(new LazyStyle(prefix)); } //add this region to the map of registered regions registeredRegions.put(region.getName(), region); } /** * <p>Locate the style associated with the given region, and component. * This is called from ${LAF_NAME}LookAndFeel in the SynthStyleFactory * implementation.</p> * * <p>Lookup occurs as follows:<br/> * Check the map of styles <code>m</code>. If the map contains no styles at * all, then simply return the defaultStyle. If the map contains styles, * then iterate over all of the styles for the Region <code>r</code> looking * for the best match, based on prefix. If a match was made, then return * that SynthStyle. Otherwise, return the defaultStyle.</p> * * @param comp The component associated with this region. For example, if * the Region is Region.Button then the component will be a JButton. * If the Region is a subregion, such as ScrollBarThumb, then the * associated component will be the component that subregion belongs * to, such as JScrollBar. The JComponent may be named. It may not be * null. * @param r The region we are looking for a style for. May not be null. */ SynthStyle getStyle(JComponent comp, Region r) { //validate method arguments if (comp == null || r == null) { throw new IllegalArgumentException( "Neither comp nor r may be null"); } //if there are no lazy styles registered for the region r, then return //the default style List<LazyStyle> styles = m.get(r); if (styles == null || styles.size() == 0) { return defaultStyle; } //Look for the best SynthStyle for this component/region pair. LazyStyle foundStyle = null; for (LazyStyle s : styles) { if (s.matches(comp)) { //replace the foundStyle if foundStyle is null, or //if the new style "s" is more specific (ie, its path was //longer), or if the foundStyle was "simple" and the new style //was not (ie: the foundStyle was for something like Button and //the new style was for something like "MyButton", hence, being //more specific.) In all cases, favor the most specific style //found. if (foundStyle == null || (foundStyle.parts.length < s.parts.length) || (foundStyle.parts.length == s.parts.length && foundStyle.simple && !s.simple)) { foundStyle = s; } } } //return the style, if found, or the default style if not found return foundStyle == null ? defaultStyle : foundStyle.getStyle(comp, r); } public void clearOverridesCache(JComponent c) { overridesCache.remove(c); } /* Various public helper classes. These may be used to register 3rd party values into UIDefaults */ /** * <p>Derives its font value based on a parent font and a set of offsets and * attributes. This class is an ActiveValue, meaning that it will recompute * its value each time it is requested from UIDefaults. It is therefore * recommended to read this value once and cache it in the UI delegate class * until asked to reinitialize.</p> * * <p>To use this class, create an instance with the key of the font in the * UI defaults table from which to derive this font, along with a size * offset (if any), and whether it is to be bold, italic, or left in its * default form.</p> */ static final class DerivedFont implements UIDefaults.ActiveValue { private float sizeOffset; private Boolean bold; private Boolean italic; private String parentKey; /** * Create a new DerivedFont. * * @param key The UIDefault key associated with this derived font's * parent or source. If this key leads to a null value, or a * value that is not a font, then null will be returned as * the derived font. The key must not be null. * @param sizeOffset The size offset, as a percentage, to use. For * example, if the source font was a 12pt font and the * sizeOffset were specified as .9, then the new font * will be 90% of what the source font was, or, 10.8 * pts which is rounded to 11pts. This fractional * based offset allows for proper font scaling in high * DPI or large system font scenarios. * @param bold Whether the new font should be bold. If null, then this * new font will inherit the bold setting of the source * font. * @param italic Whether the new font should be italicized. If null, * then this new font will inherit the italic setting of * the source font. */ public DerivedFont(String key, float sizeOffset, Boolean bold, Boolean italic) { //validate the constructor arguments if (key == null) { throw new IllegalArgumentException("You must specify a key"); } //set the values this.parentKey = key; this.sizeOffset = sizeOffset; this.bold = bold; this.italic = italic; } /** * @inheritDoc */ @Override public Object createValue(UIDefaults defaults) { Font f = defaults.getFont(parentKey); if (f != null) { // always round size for now so we have exact int font size // (or we may have lame looking fonts) float size = Math.round(f.getSize2D() * sizeOffset); int style = f.getStyle(); if (bold != null) { if (bold.booleanValue()) { style = style | Font.BOLD; } else { style = style & ~Font.BOLD; } } if (italic != null) { if (italic.booleanValue()) { style = style | Font.ITALIC; } else { style = style & ~Font.ITALIC; } } return f.deriveFont(style, size); } else { return null; } } } /** * This class is private because it relies on the constructor of the * auto-generated AbstractRegionPainter subclasses. Hence, it is not * generally useful, and is private. * <p/> * LazyPainter is a LazyValue class. It will create the * AbstractRegionPainter lazily, when asked. It uses reflection to load the * proper class and invoke its constructor. */ private static final class LazyPainter implements UIDefaults.LazyValue { private int which; private AbstractRegionPainter.PaintContext ctx; private String className; LazyPainter(String className, int which, Insets insets, Dimension canvasSize, boolean inverted) { if (className == null) { throw new IllegalArgumentException( "The className must be specified"); } this.className = className; this.which = which; this.ctx = new AbstractRegionPainter.PaintContext( insets, canvasSize, inverted); } LazyPainter(String className, int which, Insets insets, Dimension canvasSize, boolean inverted, AbstractRegionPainter.PaintContext.CacheMode cacheMode, double maxH, double maxV) { if (className == null) { throw new IllegalArgumentException( "The className must be specified"); } this.className = className; this.which = which; this.ctx = new AbstractRegionPainter.PaintContext( insets, canvasSize, inverted, cacheMode, maxH, maxV); } @Override public Object createValue(UIDefaults table) { try { Class c; Object cl; // See if we should use a separate ClassLoader if (table == null || !((cl = table.get("ClassLoader")) instanceof ClassLoader)) { cl = Thread.currentThread(). getContextClassLoader(); if (cl == null) { // Fallback to the system class loader. cl = ClassLoader.getSystemClassLoader(); } } c = Class.forName(className, true, (ClassLoader)cl); Constructor constructor = c.getConstructor( AbstractRegionPainter.PaintContext.class, int.class); if (constructor == null) { throw new NullPointerException( "Failed to find the constructor for the class: " + className); } return constructor.newInstance(ctx, which); } catch (Exception e) { e.printStackTrace(); return null; } } } /** * A class which creates the NimbusStyle associated with it lazily, but also * manages a lot more information about the style. It is less of a LazyValue * type of class, and more of an Entry or Item type of class, as it * represents an entry in the list of LazyStyles in the map m. * * The primary responsibilities of this class include: * <ul> * <li>Determining whether a given component/region pair matches this * style</li> * <li>Splitting the prefix specified in the constructor into its * constituent parts to facilitate quicker matching</li> * <li>Creating and vending a NimbusStyle lazily.</li> * </ul> */ private final class LazyStyle { /** * The prefix this LazyStyle was registered with. Something like * Button or ComboBox:"ComboBox.arrowButton" */ private String prefix; /** * Whether or not this LazyStyle represents an unnamed component */ private boolean simple = true; /** * The various parts, or sections, of the prefix. For example, * the prefix: * ComboBox:"ComboBox.arrowButton" * * will be broken into two parts, * ComboBox and "ComboBox.arrowButton" */ private Part[] parts; /** * Cached shared style. */ private NimbusStyle style; /** * Create a new LazyStyle. * * @param prefix The prefix associated with this style. Cannot be null. */ private LazyStyle(String prefix) { if (prefix == null) { throw new IllegalArgumentException( "The prefix must not be null"); } this.prefix = prefix; //there is one odd case that needs to be supported here: cell //renderers. A cell renderer is defined as a named internal //component, so for example: // List."List.cellRenderer" //The problem is that the component named List.cellRenderer is not a //child of a JList. Rather, it is treated more as a direct component //Thus, if the prefix ends with "cellRenderer", then remove all the //previous dotted parts of the prefix name so that it becomes, for //example: "List.cellRenderer" //Likewise, we have a hacked work around for cellRenderer, renderer, //and listRenderer. String temp = prefix; if (temp.endsWith("cellRenderer\"") || temp.endsWith("renderer\"") || temp.endsWith("listRenderer\"")) { temp = temp.substring(temp.lastIndexOf(":\"") + 1); } //otherwise, normal code path