/*
 * Copyright (c) 2011, 2015, 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 com.apple.laf;

import java.awt.*;
import java.awt.event.*;
import java.beans.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.MouseInputAdapter;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicInternalFrameUI;

import apple.laf.*;
import apple.laf.JRSUIConstants.*;

import com.apple.laf.AquaUtils.*;
import com.apple.laf.AquaUtils.Painter;

import sun.lwawt.macosx.CPlatformWindow;

/**
 * From AquaInternalFrameUI
 *
 * InternalFrame implementation for Aqua LAF
 *
 * We want to inherit most of the inner classes, but not the base class,
 * so be very careful about subclassing so you know you get what you want
 *
 */
public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingConstants {
    protected static final String IS_PALETTE_PROPERTY = "JInternalFrame.isPalette";
    private static final String FRAME_TYPE = "JInternalFrame.frameType";
    private static final String NORMAL_FRAME = "normal";
    private static final String PALETTE_FRAME = "palette";
    private static final String OPTION_DIALOG = "optionDialog";

    // Instance variables
    PropertyChangeListener fPropertyListener;

    protected Color fSelectedTextColor;
    protected Color fNotSelectedTextColor;

    AquaInternalFrameBorder fAquaBorder;
    private ResizeBox resizeBox;

    // for button tracking
    boolean fMouseOverPressedButton;
    int fWhichButtonPressed = -1;
    boolean fRollover = false;
    boolean fDocumentEdited = false; // to indicate whether we should use the dirty document red dot.
    boolean fIsPallet;

    public int getWhichButtonPressed() {
        return fWhichButtonPressed;
    }

    public boolean getMouseOverPressedButton() {
        return fMouseOverPressedButton;
    }

    public boolean getRollover() {
        return fRollover;
    }

    // ComponentUI Interface Implementation methods
    public static ComponentUI createUI(final JComponent b) {
        return new AquaInternalFrameUI((JInternalFrame)b);
    }

    public AquaInternalFrameUI(final JInternalFrame b) {
        super(b);
    }

    /// Inherit  (but be careful to check everything they call):
    @Override
    public void installUI(final JComponent c) {
//        super.installUI(c);  // Swing 1.1.1 has a bug in installUI - it doesn't check for null northPane
        frame = (JInternalFrame)c;
        frame.add(frame.getRootPane(), "Center");

        installDefaults();
        installListeners();
        installComponents();
        installKeyboardActions();

        Object paletteProp = c.getClientProperty(IS_PALETTE_PROPERTY);
        if (paletteProp != null) {
            setPalette(((Boolean)paletteProp).booleanValue());
        } else {
            paletteProp = c.getClientProperty(FRAME_TYPE);
            if (paletteProp != null) {
                setFrameType((String)paletteProp);
            } else {
                setFrameType(NORMAL_FRAME);
            }
        }

        // We only have a southPane, for grow box room, created in setFrameType
        frame.setMinimumSize(new Dimension(fIsPallet ? 120 : 150, fIsPallet ? 39 : 65));
        frame.setOpaque(false);

        c.setBorder(new CompoundUIBorder(fIsPallet ? paletteWindowShadow.get() : documentWindowShadow.get(), c.getBorder()));
    }

    @Override
    protected void installDefaults() {
        super.installDefaults();
        fSelectedTextColor = UIManager.getColor("InternalFrame.activeTitleForeground");
        fNotSelectedTextColor = UIManager.getColor("InternalFrame.inactiveTitleForeground");
    }

    @Override
    public void setSouthPane(final JComponent c) {
        if (southPane != null) {
            frame.remove(southPane);
            deinstallMouseHandlers(southPane);
        }
        if (c != null) {
            frame.add(c);
            installMouseHandlers(c);
        }
        southPane = c;
    }

    private static final RecyclableSingleton<Icon> closeIcon = new RecyclableSingleton<Icon>() {
        @Override
        protected Icon getInstance() {
            return new AquaInternalFrameButtonIcon(Widget.TITLE_BAR_CLOSE_BOX);
        }
    };
    public static Icon exportCloseIcon() {
        return closeIcon.get();
    }

    private static final RecyclableSingleton<Icon> minimizeIcon = new RecyclableSingleton<Icon>() {
        @Override
        protected Icon getInstance() {
            return new AquaInternalFrameButtonIcon(Widget.TITLE_BAR_COLLAPSE_BOX);
        }
    };
    public static Icon exportMinimizeIcon() {
        return minimizeIcon.get();
    }

    private static final RecyclableSingleton<Icon> zoomIcon = new RecyclableSingleton<Icon>() {
        @Override
        protected Icon getInstance() {
            return new AquaInternalFrameButtonIcon(Widget.TITLE_BAR_ZOOM_BOX);
        }
    };
    public static Icon exportZoomIcon() {
        return zoomIcon.get();
    }

    static class AquaInternalFrameButtonIcon extends AquaIcon.JRSUIIcon {
        public AquaInternalFrameButtonIcon(final Widget widget) {
            painter.state.set(widget);
        }

        @Override
        public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
            painter.state.set(getStateFor(c));
            super.paintIcon(c, g, x, y);
        }

        State getStateFor(final Component c) {
            return State.ROLLOVER;
        }

        @Override
        public int getIconWidth() {
            return 19;
        }

        @Override
        public int getIconHeight() {
            return 19;
        }
    }

    @Override
    protected void installKeyboardActions() {
    } //$ Not Mac-ish - should we support?

    @Override
    protected void installComponents() {
        final JLayeredPane layeredPane = frame.getLayeredPane();
        resizeBox = new ResizeBox(layeredPane);
        resizeBox.repositionResizeBox();

        layeredPane.add(resizeBox);
        layeredPane.setLayer(resizeBox, JLayeredPane.DRAG_LAYER);
        layeredPane.addComponentListener(resizeBox);

        resizeBox.addListeners();
        resizeBox.setVisible(frame.isResizable());
    }

    /// Inherit all the listeners - that's the main reason we subclass Basic!
    @Override
    protected void installListeners() {
        fPropertyListener = new PropertyListener();
        frame.addPropertyChangeListener(fPropertyListener);
        super.installListeners();
    }

    // uninstallDefaults

    @Override
    protected void uninstallComponents() {
        super.uninstallComponents();
        final JLayeredPane layeredPane = frame.getLayeredPane();
        resizeBox.removeListeners();
        layeredPane.removeComponentListener(resizeBox);
        layeredPane.remove(resizeBox);
        resizeBox = null;
    }

    @Override
    protected void uninstallListeners() {
        super.uninstallListeners();
        frame.removePropertyChangeListener(fPropertyListener);
    }

    @Override
    protected void uninstallKeyboardActions() {
    }

    // Called when a DesktopIcon replaces an InternalFrame & vice versa
    //protected void replacePane(JComponent currentPane, JComponent newPane) {}
    @Override
    protected void installMouseHandlers(final JComponent c) {
        c.addMouseListener(borderListener);
        c.addMouseMotionListener(borderListener);
    }

    @Override
    protected void deinstallMouseHandlers(final JComponent c) {
        c.removeMouseListener(borderListener);
        c.removeMouseMotionListener(borderListener);
    }

    ActionMap createActionMap() {
        final ActionMap map = new ActionMapUIResource();
        // add action for the system menu
        // Set the ActionMap's parent to the Auditory Feedback Action Map
        final AquaLookAndFeel lf = (AquaLookAndFeel)UIManager.getLookAndFeel();
        final ActionMap audioMap = lf.getAudioActionMap();
        map.setParent(audioMap);
        return map;
    }

    @Override
    public Dimension getPreferredSize(JComponent x) {
        Dimension preferredSize = super.getPreferredSize(x);
        Dimension minimumSize = frame.getMinimumSize();
        if (preferredSize.width < minimumSize.width) {
            preferredSize.width = minimumSize.width;
        }
        if (preferredSize.height < minimumSize.height) {
            preferredSize.height = minimumSize.height;
        }
        return preferredSize;
    }

    @Override
    public void setNorthPane(final JComponent c) {
        replacePane(northPane, c);
        northPane = c;
    }

    /**
     * Installs necessary mouse handlers on {@code newPane}
     * and adds it to the frame.
     * Reverse process for the {@code currentPane}.
     */
    @Override
    protected void replacePane(final JComponent currentPane, final JComponent newPane) {
        if (currentPane != null) {
            deinstallMouseHandlers(currentPane);
            frame.remove(currentPane);
        }
        if (newPane != null) {
            frame.add(newPane);
            installMouseHandlers(newPane);
        }
    }

    // Our "Border" listener is shared by the AquaDesktopIcon
    @Override
    protected MouseInputAdapter createBorderListener(final JInternalFrame w) {
        return new AquaBorderListener();
    }

    /**
     * Mac-specific stuff begins here
     */
    void setFrameType(final String frameType) {
        // Basic sets the background of the contentPane to null so it can inherit JInternalFrame.setBackground
        // but if *that's* null, we get the JDesktop, which makes ours look invisible!
        // So JInternalFrame has to have a background color
        // See Sun bugs 4268949 & 4320889
        final Color bg = frame.getBackground();
        final boolean replaceColor = (bg == null || bg instanceof UIResource);

        final Font font = frame.getFont();
        final boolean replaceFont = (font == null || font instanceof UIResource);

        boolean isPalette = false;
        if (frameType.equals(OPTION_DIALOG)) {
            fAquaBorder = AquaInternalFrameBorder.dialog();
            if (replaceColor) frame.setBackground(UIManager.getColor("InternalFrame.optionDialogBackground"));
            if (replaceFont) frame.setFont(UIManager.getFont("InternalFrame.optionDialogTitleFont"));
        } else if (frameType.equals(PALETTE_FRAME)) {
            fAquaBorder = AquaInternalFrameBorder.utility();
            if (replaceColor) frame.setBackground(UIManager.getColor("InternalFrame.paletteBackground"));
            if (replaceFont) frame.setFont(UIManager.getFont("InternalFrame.paletteTitleFont"));
            isPalette = true;
        } else {
            fAquaBorder = AquaInternalFrameBorder.window();
            if (replaceColor) frame.setBackground(UIManager.getColor("InternalFrame.background"));
            if (replaceFont) frame.setFont(UIManager.getFont("InternalFrame.titleFont"));
        }
        // We don't get the borders from UIManager, in case someone changes them - this class will not work with
        // different borders.  If they want different ones, they have to make their own InternalFrameUI class

        fAquaBorder.setColors(fSelectedTextColor, fNotSelectedTextColor);
        frame.setBorder(fAquaBorder);

        fIsPallet = isPalette;
    }

    public void setPalette(final boolean isPalette) {
        setFrameType(isPalette ? PALETTE_FRAME : NORMAL_FRAME);
    }

    public boolean isDocumentEdited() {
        return fDocumentEdited;
    }

    public void setDocumentEdited(final boolean flag) {
        fDocumentEdited = flag;
    }

/*
    // helpful debug drawing, shows component and content bounds
    public void paint(final Graphics g, final JComponent c) {
        super.paint(g, c);

        g.setColor(Color.green);
        g.drawRect(0, 0, frame.getWidth() - 1, frame.getHeight() - 1);

        final Insets insets = frame.getInsets();
        g.setColor(Color.orange);
        g.drawRect(insets.left - 2, insets.top - 2, frame.getWidth() - insets.left - insets.right + 4, frame.getHeight() - insets.top - insets.bottom + 4);
    }
*/

    // Border Listener Class
    /**
     * Listens for border adjustments.
     */
    protected class AquaBorderListener extends MouseInputAdapter {
        // _x & _y are the mousePressed location in absolute coordinate system
        int _x, _y;
        // __x & __y are the mousePressed location in source view's coordinate system
        int __x, __y;
        Rectangle startingBounds;
        boolean fDraggingFrame;
        int resizeDir;

        protected final int RESIZE_NONE = 0;
        private boolean discardRelease = false;

        @Override
        public void mouseClicked(final MouseEvent e) {
            if (didForwardEvent(e)) return;

            if (e.getClickCount() <= 1 || e.getSource() != getNorthPane()) return;

            if (frame.isIconifiable() && frame.isIcon()) {
                try {
                    frame.setIcon(false);
                } catch(final PropertyVetoException e2) {}
            } else if (frame.isMaximizable()) {
                if (!frame.isMaximum()) try {
                    frame.setMaximum(true);
                } catch(final PropertyVetoException e2) {}
                else try {
                    frame.setMaximum(false);
                } catch(final PropertyVetoException e3) {}
            }
        }

        public void updateRollover(final MouseEvent e) {
            final boolean oldRollover = fRollover;
            final Insets i = frame.getInsets();
            fRollover = (isTitleBarDraggableArea(e) && fAquaBorder.getWithinRolloverArea(i, e.getX(), e.getY()));
            if (fRollover != oldRollover) {
                repaintButtons();
            }
        }

        public void repaintButtons() {
            fAquaBorder.repaintButtonArea(frame);
        }

        @Override
        @SuppressWarnings("deprecation")
        public void mouseReleased(final MouseEvent e) {
            if (didForwardEvent(e)) return;

            fDraggingFrame = false;

            if (fWhichButtonPressed != -1) {
                final int newButton = fAquaBorder.getWhichButtonHit(frame, e.getX(), e.getY());

                final int buttonPresed = fWhichButtonPressed;
                fWhichButtonPressed = -1;
                fMouseOverPressedButton = false;

                if (buttonPresed == newButton) {
                    fMouseOverPressedButton = false;
                    fRollover = false; // not sure if this is needed?

                    fAquaBorder.doButtonAction(frame, buttonPresed);
                }

                updateRollover(e);
                repaintButtons();
                return;
            }

            if (discardRelease) {
                discardRelease = false;
                return;
            }
            if (resizeDir == RESIZE_NONE) getDesktopManager().endDraggingFrame(frame);
            else {
                final Container c = frame.getTopLevelAncestor();
                if (c instanceof JFrame) {
                    ((JFrame)frame.getTopLevelAncestor()).getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

                    ((JFrame)frame.getTopLevelAncestor()).getGlassPane().setVisible(false);
                } else if (c instanceof JApplet) {
                    ((JApplet)c).getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    ((JApplet)c).getGlassPane().setVisible(false);
                } else if (c instanceof JWindow) {
                    ((JWindow)c).getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    ((JWindow)c).getGlassPane().setVisible(false);
                } else if (c instanceof JDialog) {
                    ((JDialog)c).getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    ((JDialog)c).getGlassPane().setVisible(false);
                }
                getDesktopManager().endResizingFrame(frame);
            }
            _x = 0;
            _y = 0;
            __x = 0;
            __y = 0;
            startingBounds = null;
            resizeDir = RESIZE_NONE;
        }

        @Override
        public void mousePressed(final MouseEvent e) {
            if (didForwardEvent(e)) return;

            final Point p = SwingUtilities.convertPoint((Component)e.getSource(), e.getX(), e.getY(), null);
            __x = e.getX();
            __y = e.getY();
            _x = p.x;
            _y = p.y;
            startingBounds = frame.getBounds();
            resizeDir = RESIZE_NONE;

            if (updatePressed(e)) { return; }

            if (!frame.isSelected()) {
                try {
                    frame.setSelected(true);
                } catch(final PropertyVetoException e1) {}
            }

            if (isTitleBarDraggableArea(e)) {
                getDesktopManager().beginDraggingFrame(frame);
                fDraggingFrame = true;
                return;
            }

            if (e.getSource() == getNorthPane()) {
                getDesktopManager().beginDraggingFrame(frame);
                return;
            }

            if (!frame.isResizable()) { return; }

            if (e.getSource() == frame) {
                discardRelease = true;
                return;
            }
        }

        // returns true if we have handled the pressed
        public boolean updatePressed(final MouseEvent e) {
            // get the component.
            fWhichButtonPressed = getButtonHit(e);
            fMouseOverPressedButton = true;
            repaintButtons();
            return (fWhichButtonPressed >= 0);
            // e.getX(), e.getY()
        }

        public int getButtonHit(final MouseEvent e) {
            return fAquaBorder.getWhichButtonHit(frame, e.getX(), e.getY());
        }

        public boolean isTitleBarDraggableArea(final MouseEvent e) {
            if (e.getSource() != frame) return false;

            final Point point = e.getPoint();
            final Insets insets = frame.getInsets();

            if (point.y < insets.top - fAquaBorder.getTitleHeight()) return false;
            if (point.y > insets.top) return false;
            if (point.x < insets.left) return false;
            if (point.x > frame.getWidth() - insets.left - insets.right) return false;

            return true;
        }

        @Override
        @SuppressWarnings("deprecation")
        public void mouseDragged(final MouseEvent e) {
// do not forward drags
//            if (didForwardEvent(e)) return;

            if (startingBounds == null) {
                // (STEVE) Yucky work around for bug ID 4106552
                return;
            }

            if (fWhichButtonPressed != -1) {
                // track the button we started on.
                final int newButton = getButtonHit(e);
                fMouseOverPressedButton = (fWhichButtonPressed == newButton);
                repaintButtons();
                return;
            }

            final Point p = SwingUtilities.convertPoint((Component)e.getSource(), e.getX(), e.getY(), null);
            final int deltaX = _x - p.x;
            final int deltaY = _y - p.y;
            int newX, newY;

            // Handle a MOVE
            if (!fDraggingFrame && e.getSource() != getNorthPane()) return;

            if (frame.isMaximum() || ((e.getModifiers() & InputEvent.BUTTON1_MASK) != InputEvent.BUTTON1_MASK)) {
                // don't allow moving of frames if maximixed or left mouse
                // button was not used.
                return;
            }

            final Dimension s = frame.getParent().getSize();
            final int pWidth = s.width;
            final int pHeight = s.height;

            final Insets i = frame.getInsets();
            newX = startingBounds.x - deltaX;
            newY = startingBounds.y - deltaY;

            // Make sure we stay in-bounds
            if (newX + i.left <= -__x) newX = -__x - i.left;
            if (newY + i.top <= -__y) newY = -__y - i.top;
            if (newX + __x + i.right > pWidth) newX = pWidth - __x - i.right;
            if (newY + __y + i.bottom > pHeight) newY = pHeight - __y - i.bottom;

            getDesktopManager().dragFrame(frame, newX, newY);
            return;
        }

        @Override
        public void mouseMoved(final MouseEvent e) {
            if (didForwardEvent(e)) return;
            updateRollover(e);
        }

        // guards against accidental infinite recursion
        boolean isTryingToForwardEvent = false;
        boolean didForwardEvent(final MouseEvent e) {
            if (isTryingToForwardEvent) return true; // we didn't actually...but we wound up back where we started.

            isTryingToForwardEvent = true;
            final boolean didForwardEvent = didForwardEventInternal(e);
            isTryingToForwardEvent = false;

            return didForwardEvent;
        }
        @SuppressWarnings("deprecation")
        boolean didForwardEventInternal(final MouseEvent e) {
            if (fDraggingFrame) return false;

            final Point originalPoint = e.getPoint();
            if (!isEventInWindowShadow(originalPoint)) return false;

            final Container parent = frame.getParent();
            if (!(parent instanceof JDesktopPane)) return false;
            final JDesktopPane pane = (JDesktopPane)parent;
            final Point parentPoint = SwingUtilities.convertPoint(frame, originalPoint, parent);

        /*     // debug drawing
            Graphics g = parent.getGraphics();
            g.setColor(Color.red);
            g.drawLine(parentPoint.x, parentPoint.y, parentPoint.x, parentPoint.y);
        */

            final Component hitComponent = findComponentToHitBehindMe(pane, parentPoint);
            if (hitComponent == null || hitComponent == frame) return false;

            final Point hitComponentPoint = SwingUtilities.convertPoint(pane, parentPoint, hitComponent);
            hitComponent.dispatchEvent(
                    new MouseEvent(hitComponent, e.getID(), e.getWhen(),
                                   e.getModifiers(), hitComponentPoint.x,
                                   hitComponentPoint.y, e.getClickCount(),
                                   e.isPopupTrigger(), e.getButton()));
            return true;
        }

        Component findComponentToHitBehindMe(final JDesktopPane pane, final Point parentPoint) {
            final JInternalFrame[] allFrames = pane.getAllFrames();

            boolean foundSelf = false;
            for (final JInternalFrame f : allFrames) {
                if (f == frame) { foundSelf = true; continue; }
                if (!foundSelf) continue;

                final Rectangle bounds = f.getBounds();
                if (bounds.contains(parentPoint)) return f;
            }

            return pane;
        }

        boolean isEventInWindowShadow(final Point point) {
            final Rectangle bounds = frame.getBounds();
            final Insets insets = frame.getInsets();
            insets.top -= fAquaBorder.getTitleHeight();

            if (point.x < insets.left) return true;
            if (point.x > bounds.width - insets.right) return true;
            if (point.y < insets.top) return true;
            if (point.y > bounds.height - insets.bottom) return true;

            return false;
        }
    }

    static void updateComponentTreeUIActivation(final Component c, final Object active) {
        if (c instanceof javax.swing.JComponent) {
            ((javax.swing.JComponent)c).putClientProperty(AquaFocusHandler.FRAME_ACTIVE_PROPERTY, active);
        }

        Component[] children = null;

        if (c instanceof javax.swing.JMenu) {
            children = ((javax.swing.JMenu)c).getMenuComponents();
        } else if (c instanceof Container) {
            children = ((Container)c).getComponents();
        }

        if (children != null) {
            for (final Component element : children) {
                updateComponentTreeUIActivation(element, active);
            }
        }
    }

    class PropertyListener implements PropertyChangeListener {
        @Override
        public void propertyChange(final PropertyChangeEvent e) {
            final String name = e.getPropertyName();
            if (FRAME_TYPE.equals(name)) {
                if (e.getNewValue() instanceof String) {
                    setFrameType((String)e.getNewValue());
                }
            } else if (IS_PALETTE_PROPERTY.equals(name)) {
                if (e.getNewValue() != null) {
                    setPalette(((Boolean)e.getNewValue()).booleanValue());
                } else {
                    setPalette(false);
                }
                // TODO: CPlatformWindow?
            } else if ("windowModified".equals(name) || CPlatformWindow.WINDOW_DOCUMENT_MODIFIED.equals(name)) {
                // repaint title bar
                setDocumentEdited(((Boolean)e.getNewValue()).booleanValue());
                frame.repaint(0, 0, frame.getWidth(), frame.getBorder().getBorderInsets(frame).top);
            } else if ("resizable".equals(name) || "state".equals(name) || "iconable".equals(name) || "maximizable".equals(name) || "closable".equals(name)) {
                if ("resizable".equals(name)) {
                    frame.revalidate();
                }
                frame.repaint();
            } else if ("title".equals(name)) {
                frame.repaint();
            } else if ("componentOrientation".equals(name)) {
                frame.revalidate();
                frame.repaint();
            } else if (JInternalFrame.IS_SELECTED_PROPERTY.equals(name)) {
                final Component source = (Component)(e.getSource());
                updateComponentTreeUIActivation(source, frame.isSelected() ? Boolean.TRUE : Boolean.FALSE);
            }

        }
    } // end class PaletteListener

    private static final InternalFrameShadow documentWindowShadow = new InternalFrameShadow() {
        @Override
        Border getForegroundShadowBorder() {
            return new AquaUtils.SlicedShadowBorder(new Painter() {
                @Override
                public void paint(final Graphics g, final int x, final int y, final int w, final int h) {
                    g.setColor(new Color(0, 0, 0, 196));
                    g.fillRoundRect(x, y, w, h, 16, 16);
                    g.fillRect(x, y + h - 16, w, 16);
                }
            }, new Painter() {
                @Override
                public void paint(final Graphics g, int x, int y, int w, int h) {
                    g.setColor(new Color(0, 0, 0, 64));
                    g.drawLine(x + 2, y - 8, x + w - 2, y - 8);
                }
            },
            0, 7, 1.1f, 1.0f, 24, 51, 51, 25, 25, 25, 25);
        }

        @Override
        Border getBackgroundShadowBorder() {
            return new AquaUtils.SlicedShadowBorder(new Painter() {
                @Override
                public void paint(final Graphics g, final int x, final int y, final int w, final int h) {
                    g.setColor(new Color(0, 0, 0, 128));
                    g.fillRoundRect(x - 3, y - 8, w + 6, h, 16, 16);
                    g.fillRect(x - 3, y + h - 20, w + 6, 19);
                }
            }, new Painter() {
                @Override
                public void paint(final Graphics g, int x, int y, int w, int h) {
                    g.setColor(new Color(0, 0, 0, 32));
                    g.drawLine(x, y - 11, x + w - 1, y - 11);
                }
            },
            0, 0, 3.0f, 1.0f, 10, 51, 51, 25, 25, 25, 25);
        }
    };

    private static final InternalFrameShadow paletteWindowShadow = new InternalFrameShadow() {
        @Override
        Border getForegroundShadowBorder() {
            return new AquaUtils.SlicedShadowBorder(new Painter() {
                @Override
                public void paint(final Graphics g, final int x, final int y, final int w, final int h) {
                    g.setColor(new Color(0, 0, 0, 128));
                    g.fillRect(x, y + 3, w, h - 3);
                }
            }, null,
            0, 3, 1.0f, 1.0f, 10, 25, 25, 12, 12, 12, 12);
        }

        @Override
        Border getBackgroundShadowBorder() {
            return getForegroundShadowBorder();
        }
    };

    @SuppressWarnings("serial") // Superclass is not serializable across versions
    static class CompoundUIBorder extends CompoundBorder implements UIResource {
        public CompoundUIBorder(final Border inside, final Border outside) { super(inside, outside); }
    }

    abstract static class InternalFrameShadow extends RecyclableSingleton<Border> {
        abstract Border getForegroundShadowBorder();
        abstract Border getBackgroundShadowBorder();

        @Override
        protected Border getInstance() {
            final Border fgShadow = getForegroundShadowBorder();
            final Border bgShadow = getBackgroundShadowBorder();

            return new Border() {
                @Override
                public Insets getBorderInsets(final Component c) {
                    return fgShadow.getBorderInsets(c);
                }

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

                @Override
                public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) {
                    if (((JInternalFrame)c).isSelected()) {
                        fgShadow.paintBorder(c, g, x, y, w, h);
                    } else {
                        bgShadow.paintBorder(c, g, x, y, w, h);
                    }
                }
            };
        }
    }

    private static final RecyclableSingleton<Icon> RESIZE_ICON = new RecyclableSingleton<Icon>() {
        @Override
        protected Icon getInstance() {
            return new AquaIcon.ScalingJRSUIIcon(11, 11) {
                @Override
                public void initIconPainter(final AquaPainter<JRSUIState> iconState) {
                    iconState.state.set(Widget.GROW_BOX_TEXTURED);
                    iconState.state.set(WindowType.UTILITY);
                }
            };
        }
    };

    @SuppressWarnings("serial") // Superclass is not serializable across versions
    private final class ResizeBox extends JLabel
            implements MouseListener, MouseMotionListener, MouseWheelListener,
            ComponentListener, PropertyChangeListener, UIResource {

        private final JLayeredPane layeredPane;
        private Dimension originalSize;
        private Point originalLocation;

        ResizeBox(final JLayeredPane layeredPane) {
            super(RESIZE_ICON.get());
            setSize(11, 11);
            this.layeredPane = layeredPane;

            addMouseListener(this);
            addMouseMotionListener(this);
            addMouseWheelListener(this);
        }

        void addListeners() {
            frame.addPropertyChangeListener("resizable", this);
        }

        void removeListeners() {
            frame.removePropertyChangeListener("resizable", this);
        }

        void repositionResizeBox() {
            if (frame == null) { setSize(0, 0); } else { setSize(11, 11); }
            setLocation(layeredPane.getWidth() - 12, layeredPane.getHeight() - 12);
        }

        void resizeInternalFrame(final Point pt) {
            if (originalLocation == null || frame == null) return;

            final Container parent = frame.getParent();
            if (!(parent instanceof JDesktopPane)) return;

            final Point newPoint = SwingUtilities.convertPoint(this, pt, frame);
            int deltaX = originalLocation.x - newPoint.x;
            int deltaY = originalLocation.y - newPoint.y;
            final Dimension min = frame.getMinimumSize();
            final Dimension max = frame.getMaximumSize();

            final int newX = frame.getX();
            final int newY = frame.getY();
            int newW = frame.getWidth();
            int newH = frame.getHeight();

            final Rectangle parentBounds = parent.getBounds();

            if (originalSize.width - deltaX < min.width) {
                deltaX = originalSize.width - min.width;
            }  else if (originalSize.width - deltaX > max.width) {
                deltaX = -(max.width - originalSize.width);
            }

            if (newX + originalSize.width - deltaX > parentBounds.width) {
                deltaX = newX + originalSize.width - parentBounds.width;
            }

            if (originalSize.height - deltaY < min.height) {
                deltaY = originalSize.height - min.height;
            }  else if (originalSize.height - deltaY > max.height) {
                deltaY = -(max.height - originalSize.height);
            }

            if (newY + originalSize.height - deltaY > parentBounds.height) {
                deltaY = newY + originalSize.height - parentBounds.height;
            }

            newW = originalSize.width - deltaX;
            newH = originalSize.height - deltaY;

            getDesktopManager().resizeFrame(frame, newX, newY, newW, newH);
        }

        boolean testGrowboxPoint(final int x, final int y, final int w, final int h) {
            return (w - x) + (h - y) < 12;
        }

        @SuppressWarnings("deprecation")
        void forwardEventToFrame(final MouseEvent e) {
            final Point pt = new Point();
            final Component c = getComponentToForwardTo(e, pt);
            if (c == null) return;
            c.dispatchEvent(
                    new MouseEvent(c, e.getID(), e.getWhen(), e.getModifiers(),
                                   pt.x, pt.y, e.getClickCount(),
                                   e.isPopupTrigger(), e.getButton()));
        }

        Component getComponentToForwardTo(final MouseEvent e, final Point dst) {
            if (frame == null) return null;
            final Container contentPane = frame.getContentPane();
            if (contentPane == null) return null;
            Point pt = SwingUtilities.convertPoint(this, e.getPoint(), contentPane);
            final Component c = SwingUtilities.getDeepestComponentAt(contentPane, pt.x, pt.y);
            if (c == null) return null;
            pt = SwingUtilities.convertPoint(contentPane, pt, c);
            if (dst != null) dst.setLocation(pt);
            return c;
        }

        @Override
        public void mouseClicked(final MouseEvent e) {
            forwardEventToFrame(e);
        }

        @Override
        public void mouseEntered(final MouseEvent e) { }

        @Override
        public void mouseExited(final MouseEvent e) { }

        @Override
        public void mousePressed(final MouseEvent e) {
            if (frame == null) return;

            if (frame.isResizable() && !frame.isMaximum() && testGrowboxPoint(e.getX(), e.getY(), getWidth(), getHeight())) {
                originalLocation = SwingUtilities.convertPoint(this, e.getPoint(), frame);
                originalSize = frame.getSize();
                getDesktopManager().beginResizingFrame(frame, SwingConstants.SOUTH_EAST);
                return;
            }

            forwardEventToFrame(e);
        }

        @Override
        public void mouseReleased(final MouseEvent e) {
            if (originalLocation != null) {
                resizeInternalFrame(e.getPoint());
                originalLocation = null;
                getDesktopManager().endResizingFrame(frame);
                return;
            }

            forwardEventToFrame(e);
        }

        @Override
        public void mouseDragged(final MouseEvent e) {
            resizeInternalFrame(e.getPoint());
            repositionResizeBox();
        }

        @Override
        public void mouseMoved(final MouseEvent e) { }

        @Override
        @SuppressWarnings("deprecation")
        public void mouseWheelMoved(final MouseWheelEvent e) {
            final Point pt = new Point();
            final Component c = getComponentToForwardTo(e, pt);
            if (c == null) return;
            c.dispatchEvent(new MouseWheelEvent(c, e.getID(), e.getWhen(),
                    e.getModifiers(), pt.x, pt.y, e.getXOnScreen(), e.getYOnScreen(),
                    e.getClickCount(), e.isPopupTrigger(), e.getScrollType(),
                    e.getScrollAmount(), e.getWheelRotation(),
                    e.getPreciseWheelRotation()));
        }

        @Override
        public void componentResized(final ComponentEvent e) {
            repositionResizeBox();
        }

        @Override
        public void componentShown(final ComponentEvent e) {
            repositionResizeBox();
        }

        @Override
        public void componentMoved(final ComponentEvent e) {
            repositionResizeBox();
        }

        @Override
        public void componentHidden(final ComponentEvent e) { }

        @Override
        public void propertyChange(final PropertyChangeEvent evt) {
            if (!"resizable".equals(evt.getPropertyName())) return;
            setVisible(Boolean.TRUE.equals(evt.getNewValue()));
        }
    }
}
