/*
 * 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;
    }

    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();
    }

    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();
    }

    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
        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;
        }

        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

    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);
        }
    };

    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);
                    }
                }
            };
        }
    }

    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;
        }

        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
        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()));
        }
    }
}
