/*
 * 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
            List<String> sparts = split(temp);
            parts = new Part[sparts.size()];
            for (int i = 0; i < parts.length; i++) {
                parts[i] = new Part(sparts.get(i));
                if (parts[i].named) {
                    simple = false;
                }
            }
        }

        /**
         * Gets the style. Creates it if necessary.
         * @return the style
         */
        SynthStyle getStyle(JComponent c, Region r) {
            // if the component has overrides, it gets its own unique style
            // instead of the shared style.
            if (c.getClientProperty("Nimbus.Overrides") != null) {
                Map<Region, SynthStyle> map = overridesCache.get(c);
                SynthStyle s = null;
                if (map == null) {
                    map = new HashMap<Region, SynthStyle>();
                    overridesCache.put(c, map);
                } else {
                    s = map.get(r);
                }
                if (s == null) {
                    s = new NimbusStyle(prefix, c);
                    map.put(r, s);
                }
                return s;
            }
            
            // lazily create the style if necessary
            if (style == null)
                style = new NimbusStyle(prefix, null);
            
            // return the style
            return style;
        }

        /**
         * This LazyStyle is a match for the given component if, and only if,
         * for each part of the prefix the component hierarchy matches exactly.
         * That is, if given "a":something:"b", then:
         * c.getName() must equals "b"
         * c.getParent() can be anything
         * c.getParent().getParent().getName() must equal "a".
         */
        boolean matches(JComponent c) {
            return matches(c, parts.length - 1);
        }

        private boolean matches(Component c, int partIndex) {
            if (partIndex < 0) return true;
            if (c == null) return false;
            //only get here if partIndex > 0 and c == null

            String name = c.getName();
            if (parts[partIndex].named && parts[partIndex].s.equals(name)) {
                //so far so good, recurse
                return matches(c.getParent(), partIndex - 1);
            } else if (!parts[partIndex].named) {
                //if c is not named, and parts[partIndex] has an expected class
                //type registered, then check to make sure c is of the
                //right type;
                Class clazz = parts[partIndex].c;
                if (clazz != null && clazz.isAssignableFrom(c.getClass())) {
                    //so far so good, recurse
                    return matches(c.getParent(), partIndex - 1);
                } else if (clazz == null &&
                           registeredRegions.containsKey(parts[partIndex].s)) {
                    Region r = registeredRegions.get(parts[partIndex].s);
                    Component parent = r.isSubregion() ? c : c.getParent();
                    //special case the JInternalFrameTitlePane, because it
                    //doesn't fit the mold. very, very funky.
                    if (r == Region.INTERNAL_FRAME_TITLE_PANE && parent != null
                        && parent instanceof JInternalFrame.JDesktopIcon) {
                        JInternalFrame.JDesktopIcon icon =
                                (JInternalFrame.JDesktopIcon) parent;
                        parent = icon.getInternalFrame();
                    }
                    //it was the name of a region. So far, so good. Recurse.
                    return matches(parent, partIndex - 1);
                }
            }

            return false;
        }

        /**
         * Given some dot separated prefix, split on the colons that are
         * not within quotes, and not within brackets.
         *
         * @param prefix
         * @return
         */
        private List<String> split(String prefix) {
            List<String> parts = new ArrayList<String>();
            int bracketCount = 0;
            boolean inquotes = false;
            int lastIndex = 0;
            for (int i = 0; i < prefix.length(); i++) {
                char c = prefix.charAt(i);

                if (c == '[') {
                    bracketCount++;
                    continue;
                } else if (c == '"') {
                    inquotes = !inquotes;
                    continue;
                } else if (c == ']') {
                    bracketCount--;
                    if (bracketCount < 0) {
                        throw new RuntimeException(
                                "Malformed prefix: " + prefix);
                    }
                    continue;
                }

                if (c == ':' && !inquotes && bracketCount == 0) {
                    //found a character to split on.
                    parts.add(prefix.substring(lastIndex, i));
                    lastIndex = i + 1;
                }
            }
            if (lastIndex < prefix.length() - 1 && !inquotes
                    && bracketCount == 0) {
                parts.add(prefix.substring(lastIndex));
            }
            return parts;

        }

        private final class Part {
            private String s;
            //true if this part represents a component name
            private boolean named;
            private Class c;

            Part(String s) {
                named = s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"';
                if (named) {
                    this.s = s.substring(1, s.length() - 1);
                } else {
                    this.s = s;
                    //TODO use a map of known regions for Synth and Swing, and
                    //then use [classname] instead of org_class_name style
                    try {
                        c = Class.forName("javax.swing.J" + s);
                    } catch (Exception e) {
                    }
                    try {
                        c = Class.forName(s.replace("_", "."));
                    } catch (Exception e) {
                    }
                }
            }
        }
    }

    private void addColor(UIDefaults d, String uin, int r, int g, int b, int a) {
        Color color = new ColorUIResource(new Color(r, g, b, a));
        colorTree.addColor(uin, color);
        d.put(uin, color);
    }

    private void addColor(UIDefaults d, String uin, String parentUin,
            float hOffset, float sOffset, float bOffset, int aOffset) {
        addColor(d, uin, parentUin, hOffset, sOffset, bOffset, aOffset, true);
    }

    private void addColor(UIDefaults d, String uin, String parentUin,
            float hOffset, float sOffset, float bOffset,
            int aOffset, boolean uiResource) {
        Color color = getDerivedColor(uin, parentUin,
                hOffset, sOffset, bOffset, aOffset, uiResource);
        d.put(uin, color);
    }

    /**
     * Get a derived color, derived colors are shared instances and will be
     * updated when its parent UIDefault color changes.
     *
     * @param uiDefaultParentName The parent UIDefault key
     * @param hOffset The hue offset
     * @param sOffset The saturation offset
     * @param bOffset The brightness offset
     * @param aOffset The alpha offset
     * @param uiResource True if the derived color should be a UIResource,
     *        false if it should not be a UIResource
     * @return The stored derived color
     */
    public DerivedColor getDerivedColor(String parentUin,
                                        float hOffset, float sOffset,
                                        float bOffset, int aOffset,
                                        boolean uiResource){
        return getDerivedColor(null, parentUin,
                hOffset, sOffset, bOffset, aOffset, uiResource);
    }

    private DerivedColor getDerivedColor(String uin, String parentUin,
                                        float hOffset, float sOffset,
                                        float bOffset, int aOffset,
                                        boolean uiResource) {
        DerivedColor color;
        if (uiResource) {
            color = new DerivedColor.UIResource(parentUin,
                    hOffset, sOffset, bOffset, aOffset);
        } else {
            color = new DerivedColor(parentUin, hOffset, sOffset,
                bOffset, aOffset);
        }

        if (derivedColors.containsKey(color)) {
            return derivedColors.get(color);
        } else {
            derivedColors.put(color, color);
            color.rederiveColor(); /// move to ARP.decodeColor() ?
            colorTree.addColor(uin, color);
            return color;
        }
    }

    private Map<DerivedColor, DerivedColor> derivedColors =
            new HashMap<DerivedColor, DerivedColor>();

    private class ColorTree implements PropertyChangeListener {
        private Node root = new Node(null, null);
        private Map<String, Node> nodes = new HashMap<String, Node>();

        public Color getColor(String uin) {
            return nodes.get(uin).color;
        }

        public void addColor(String uin, Color color) {
            Node parent = getParentNode(color);
            Node node = new Node(color, parent);
            parent.children.add(node);
            if (uin != null) {
                nodes.put(uin, node);
            }
        }

        private Node getParentNode(Color color) {
            Node parent = root;
            if (color instanceof DerivedColor) {
                String parentUin = ((DerivedColor)color).getUiDefaultParentName();
                Node p = nodes.get(parentUin);
                if (p != null) {
                    parent = p;
                }
            }
            return parent;
        }

        public void update() {
            root.update();
        }

        @Override
        public void propertyChange(PropertyChangeEvent ev) {
            String name = ev.getPropertyName();
            Node node = nodes.get(name);
            if (node != null) {
                // this is a registered color
                node.parent.children.remove(node);
                Color color = (Color) ev.getNewValue();
                Node parent = getParentNode(color);
                node.set(color, parent);
                parent.children.add(node);
                node.update();
            }
        }

        class Node {
            Color color;
            Node parent;
            List<Node> children = new LinkedList<Node>();

            Node(Color color, Node parent) {
                set(color, parent);
            }

            public void set(Color color, Node parent) {
                this.color = color;
                this.parent = parent;
            }

            public void update() {
                if (color instanceof DerivedColor) {
                    ((DerivedColor)color).rederiveColor();
                }
                for (Node child: children) {
                    child.update();
                }
            }
        }
    }

    /**
     * Listener to update derived colors on UIManager Defaults changes
     */
    private class DefaultsListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if ("lookAndFeel".equals(evt.getPropertyName())) {
                // LAF has been installed, this is the first point at which we
                // can access our defaults table via UIManager so before now
                // all derived colors will be incorrect.
                // First we need to update
                colorTree.update();
            }
        }
    }

    private static final class PainterBorder implements Border, UIResource {
        private Insets insets;
        private Painter painter;
        private String painterKey;
        
        PainterBorder(String painterKey, Insets insets) {
            this.insets = insets;
            this.painterKey = painterKey;
        }
        
        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
            if (painter == null) {
                painter = (Painter)UIManager.get(painterKey);
                if (painter == null) return;
            }
            
            g.translate(x, y);
            if (g instanceof Graphics2D)
                painter.paint((Graphics2D)g, c, w, h);
            else {
                BufferedImage img = new BufferedImage(w, h, TYPE_INT_ARGB);
                Graphics2D gfx = img.createGraphics();
                painter.paint(gfx, c, w, h);
                gfx.dispose();
                g.drawImage(img, x, y, null);
                img = null;
            }
            g.translate(-x, -y);
        }

        @Override
        public Insets getBorderInsets(Component c) {
            return (Insets)insets.clone();
        }

        @Override
        public boolean isBorderOpaque() {
            return false;
        }
    }
}
