/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.swing.plaf.basic;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.text.JTextComponent;

import java.awt.Component;
import java.awt.Insets;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Color;
import java.awt.Graphics;
import java.io.Serializable;


/**
 * Factory object that can vend Borders appropriate for the basic L & F.
 * @author Georges Saab
 * @author Amy Fowler
 */

public class BasicBorders {

    public static Border getButtonBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border buttonBorder = new BorderUIResource.CompoundBorderUIResource(
                           new BasicBorders.ButtonBorder(
                                           table.getColor("Button.shadow"),
                                           table.getColor("Button.darkShadow"),
                                           table.getColor("Button.light"),
                                           table.getColor("Button.highlight")),
                                     new MarginBorder());
        return buttonBorder;
    }

    public static Border getRadioButtonBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border radioButtonBorder = new BorderUIResource.CompoundBorderUIResource(
                           new BasicBorders.RadioButtonBorder(
                                           table.getColor("RadioButton.shadow"),
                                           table.getColor("RadioButton.darkShadow"),
                                           table.getColor("RadioButton.light"),
                                           table.getColor("RadioButton.highlight")),
                                     new MarginBorder());
        return radioButtonBorder;
    }

    public static Border getToggleButtonBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
                                     new BasicBorders.ToggleButtonBorder(
                                           table.getColor("ToggleButton.shadow"),
                                           table.getColor("ToggleButton.darkShadow"),
                                           table.getColor("ToggleButton.light"),
                                           table.getColor("ToggleButton.highlight")),
                                     new MarginBorder());
        return toggleButtonBorder;
    }

    public static Border getMenuBarBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border menuBarBorder = new BasicBorders.MenuBarBorder(
                                        table.getColor("MenuBar.shadow"),
                                        table.getColor("MenuBar.highlight")
                                   );
        return menuBarBorder;
    }

    public static Border getSplitPaneBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border splitPaneBorder = new BasicBorders.SplitPaneBorder(
                                     table.getColor("SplitPane.highlight"),
                                     table.getColor("SplitPane.darkShadow"));
        return splitPaneBorder;
    }

    /**
     * Returns a border instance for a JSplitPane divider
     * @since 1.3
     */
    public static Border getSplitPaneDividerBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border splitPaneBorder = new BasicBorders.SplitPaneDividerBorder(
                                     table.getColor("SplitPane.highlight"),
                                     table.getColor("SplitPane.darkShadow"));
        return splitPaneBorder;
    }

    public static Border getTextFieldBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border textFieldBorder = new BasicBorders.FieldBorder(
                                           table.getColor("TextField.shadow"),
                                           table.getColor("TextField.darkShadow"),
                                           table.getColor("TextField.light"),
                                           table.getColor("TextField.highlight"));
        return textFieldBorder;
    }

    public static Border getProgressBarBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border progressBarBorder = new BorderUIResource.LineBorderUIResource(Color.green, 2);
        return progressBarBorder;
    }

    public static Border getInternalFrameBorder() {
        UIDefaults table = UIManager.getLookAndFeelDefaults();
        Border internalFrameBorder = new BorderUIResource.CompoundBorderUIResource(
                                new BevelBorder(BevelBorder.RAISED,
                                        table.getColor("InternalFrame.borderLight"),
                                        table.getColor("InternalFrame.borderHighlight"),
                                        table.getColor("InternalFrame.borderDarkShadow"),
                                        table.getColor("InternalFrame.borderShadow")),
                                BorderFactory.createLineBorder(
                                        table.getColor("InternalFrame.borderColor"), 1));

        return internalFrameBorder;
    }

    /**
     * Special thin border for rollover toolbar buttons.
     * @since 1.4
     */
    public static class RolloverButtonBorder extends ButtonBorder {

        public RolloverButtonBorder(Color shadow, Color darkShadow,
                                  Color highlight, Color lightHighlight) {
            super(shadow, darkShadow, highlight, lightHighlight);
        }

        public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) {
            AbstractButton b = (AbstractButton) c;
            ButtonModel model = b.getModel();

            Color shade = shadow;
            Component p = b.getParent();
            if (p != null && p.getBackground().equals(shadow)) {
                shade = darkShadow;
            }

            if ((model.isRollover() && !(model.isPressed() && !model.isArmed())) ||
                model.isSelected()) {

                Color oldColor = g.getColor();
                g.translate(x, y);

                if (model.isPressed() && model.isArmed() || model.isSelected()) {
                    // Draw the pressd button
                    g.setColor(shade);
                    g.drawRect(0, 0, w-1, h-1);
                    g.setColor(lightHighlight);
                    g.drawLine(w-1, 0, w-1, h-1);
                    g.drawLine(0, h-1, w-1, h-1);
                } else {
                    // Draw a rollover button
                    g.setColor(lightHighlight);
                    g.drawRect(0, 0, w-1, h-1);
                    g.setColor(shade);
                    g.drawLine(w-1, 0, w-1, h-1);
                    g.drawLine(0, h-1, w-1, h-1);
                }
                g.translate(-x, -y);
                g.setColor(oldColor);
            }
        }
    }


    /**
     * A border which is like a Margin border but it will only honor the margin
     * if the margin has been explicitly set by the developer.
     *
     * Note: This is identical to the package private class
     * MetalBorders.RolloverMarginBorder and should probably be consolidated.
     */
    static class RolloverMarginBorder extends EmptyBorder {

        public RolloverMarginBorder() {
            super(3,3,3,3); // hardcoded margin for JLF requirements.
        }

        public Insets getBorderInsets(Component c, Insets insets) {
            Insets margin = null;

            if (c instanceof AbstractButton) {
                margin = ((AbstractButton)c).getMargin();
            }
            if (margin == null || margin instanceof UIResource) {
                // default margin so replace
                insets.left = left;
                insets.top = top;
                insets.right = right;
                insets.bottom = bottom;
            } else {
                // Margin which has been explicitly set by the user.
                insets.left = margin.left;
                insets.top = margin.top;
                insets.right = margin.right;
                insets.bottom = margin.bottom;
            }
            return insets;
        }
    }

   public static class ButtonBorder extends AbstractBorder implements UIResource {
        protected Color shadow;
        protected Color darkShadow;
        protected Color highlight;
        protected Color lightHighlight;

        public ButtonBorder(Color shadow, Color darkShadow,
                            Color highlight, Color lightHighlight) {
            this.shadow = shadow;
            this.darkShadow = darkShadow;
            this.highlight = highlight;
            this.lightHighlight = lightHighlight;
        }

        public void paintBorder(Component c, Graphics g, int x, int y,
                            int width, int height) {
            boolean isPressed = false;
            boolean isDefault = false;

            if (c instanceof AbstractButton) {
                AbstractButton b = (AbstractButton)c;
                ButtonModel model = b.getModel();

                isPressed = model.isPressed() && model.isArmed();

                if (c instanceof JButton) {
                    isDefault = ((JButton)c).isDefaultButton();
                }
            }
            BasicGraphicsUtils.drawBezel(g, x, y, width, height,
                                   isPressed, isDefault, shadow,
                                   darkShadow, highlight, lightHighlight);
        }

        public Insets getBorderInsets(Component c, Insets insets)       {
            // leave room for default visual
            insets.set(2, 3, 3, 3);
            return insets;
        }

    }

    public static class ToggleButtonBorder extends ButtonBorder {

        public ToggleButtonBorder(Color shadow, Color darkShadow,
                                  Color highlight, Color lightHighlight) {
            super(shadow, darkShadow, highlight, lightHighlight);
        }

        public void paintBorder(Component c, Graphics g, int x, int y,
                                int width, int height) {
                BasicGraphicsUtils.drawBezel(g, x, y, width, height,
                                             false, false,
                                             shadow, darkShadow,
                                             highlight, lightHighlight);
        }

        public Insets getBorderInsets(Component c, Insets insets)       {
            insets.set(2, 2, 2, 2);
            return insets;
        }
    }

    public static class RadioButtonBorder extends ButtonBorder {

        public RadioButtonBorder(Color shadow, Color darkShadow,
                                 Color highlight, Color lightHighlight) {
            super(shadow, darkShadow, highlight, lightHighlight);
        }


        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {

            if (c instanceof AbstractButton) {
                AbstractButton b = (AbstractButton)c;
                ButtonModel model = b.getModel();

                if (model.isArmed() && model.isPressed() || model.isSelected()) {
                    BasicGraphicsUtils.drawLoweredBezel(g, x, y, width, height,
                                                        shadow, darkShadow,
                                                        highlight, lightHighlight);
                } else {
                    BasicGraphicsUtils.drawBezel(g, x, y, width, height,
                                               false, b.isFocusPainted() && b.hasFocus(),
                                                 shadow, darkShadow,
                                                 highlight, lightHighlight);
                }
            } else {
                BasicGraphicsUtils.drawBezel(g, x, y, width, height, false, false,
                                             shadow, darkShadow, highlight, lightHighlight);
            }
        }

        public Insets getBorderInsets(Component c, Insets insets)       {
            insets.set(2, 2, 2, 2);
            return insets;
        }
    }

    public static class MenuBarBorder extends AbstractBorder implements UIResource {
        private Color shadow;
        private Color highlight;

        public MenuBarBorder(Color shadow, Color highlight) {
            this.shadow = shadow;
            this.highlight = highlight;
        }

        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            Color oldColor = g.getColor();
            g.translate(x, y);
            g.setColor(shadow);
            g.drawLine(0, height-2, width, height-2);
            g.setColor(highlight);
            g.drawLine(0, height-1, width, height-1);
            g.translate(-x,-y);
            g.setColor(oldColor);
        }

        public Insets getBorderInsets(Component c, Insets insets)       {
            insets.set(0, 0, 2, 0);
            return insets;
        }
    }

    public static class MarginBorder extends AbstractBorder implements UIResource {
        public Insets getBorderInsets(Component c, Insets insets)       {
            Insets margin = null;
            //
            // Ideally we'd have an interface defined for classes which
            // support margins (to avoid this hackery), but we've
            // decided against it for simplicity
            //
           if (c instanceof AbstractButton) {
               AbstractButton b = (AbstractButton)c;
               margin = b.getMargin();
           } else if (c instanceof JToolBar) {
               JToolBar t = (JToolBar)c;
               margin = t.getMargin();
           } else if (c instanceof JTextComponent) {
               JTextComponent t = (JTextComponent)c;
               margin = t.getMargin();
           }
           insets.top = margin != null? margin.top : 0;
           insets.left = margin != null? margin.left : 0;
           insets.bottom = margin != null? margin.bottom : 0;
           insets.right = margin != null? margin.right : 0;

           return insets;
        }
    }

    public static class FieldBorder extends AbstractBorder implements UIResource {
        protected Color shadow;
        protected Color darkShadow;
        protected Color highlight;
        protected Color lightHighlight;

        public FieldBorder(Color shadow, Color darkShadow,
                           Color highlight, Color lightHighlight) {
            this.shadow = shadow;
            this.highlight = highlight;
            this.darkShadow = darkShadow;
            this.lightHighlight = lightHighlight;
        }

        public void paintBorder(Component c, Graphics g, int x, int y,
                            int width, int height) {
            BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height,
                                              shadow, darkShadow,
                                              highlight, lightHighlight);
        }

        public Insets getBorderInsets(Component c, Insets insets) {
            Insets margin = null;
            if (c instanceof JTextComponent) {
                margin = ((JTextComponent)c).getMargin();
            }
            insets.top = margin != null? 2+margin.top : 2;
            insets.left = margin != null? 2+margin.left : 2;
            insets.bottom = margin != null? 2+margin.bottom : 2;
            insets.right = margin != null? 2+margin.right : 2;

            return insets;
        }
    }


    /**
     * Draws the border around the divider in a splitpane
     * (when BasicSplitPaneUI is used). To get the appropriate effect, this
     * needs to be used with a SplitPaneBorder.
     */
    static class SplitPaneDividerBorder implements Border, UIResource {
        Color highlight;
        Color shadow;

        SplitPaneDividerBorder(Color highlight, Color shadow) {
            this.highlight = highlight;
            this.shadow = shadow;
        }

        public void paintBorder(Component c, Graphics g, int x, int y,
                                int width, int height) {
            Component          child;
            Rectangle          cBounds;
            JSplitPane         splitPane = ((BasicSplitPaneDivider)c).
                                         getBasicSplitPaneUI().getSplitPane();
            Dimension          size = c.getSize();

            child = splitPane.getLeftComponent();
            // This is needed for the space between the divider and end of
            // splitpane.
            g.setColor(c.getBackground());
            g.drawRect(x, y, width - 1, height - 1);
            if(splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
                if(child != null) {
                    g.setColor(highlight);
                    g.drawLine(0, 0, 0, size.height);
                }
                child = splitPane.getRightComponent();
                if(child != null) {
                    g.setColor(shadow);
                    g.drawLine(size.width - 1, 0, size.width - 1, size.height);
                }
            } else {
                if(child != null) {
                    g.setColor(highlight);
                    g.drawLine(0, 0, size.width, 0);
                }
                child = splitPane.getRightComponent();
                if(child != null) {
                    g.setColor(shadow);
                    g.drawLine(0, size.height - 1, size.width,
                               size.height - 1);
                }
            }
        }
        public Insets getBorderInsets(Component c) {
            Insets insets = new Insets(0,0,0,0);
            if (c instanceof BasicSplitPaneDivider) {
                BasicSplitPaneUI bspui = ((BasicSplitPaneDivider)c).
                                         getBasicSplitPaneUI();

                if (bspui != null) {
                    JSplitPane splitPane = bspui.getSplitPane();

                    if (splitPane != null) {
                        if (splitPane.getOrientation() ==
                            JSplitPane.HORIZONTAL_SPLIT) {
                            insets.top = insets.bottom = 0;
                            insets.left = insets.right = 1;
                            return insets;
                        }
                        // VERTICAL_SPLIT
                        insets.top = insets.bottom = 1;
                        insets.left = insets.right = 0;
                        return insets;
                    }
                }
            }
            insets.top = insets.bottom = insets.left = insets.right = 1;
            return insets;
        }
        public boolean isBorderOpaque() { return true; }
    }


    /**
     * Draws the border around the splitpane. To work correctly you shoudl
     * also install a border on the divider (property SplitPaneDivider.border).
     */
    public static class SplitPaneBorder implements Border, UIResource {
        protected Color highlight;
        protected Color shadow;

        public SplitPaneBorder(Color highlight, Color shadow) {
            this.highlight = highlight;
            this.shadow = shadow;
        }

        public void paintBorder(Component c, Graphics g, int x, int y,
                                int width, int height) {
            // The only tricky part with this border is that the divider is
            // not positioned at the top (for horizontal) or left (for vert),
            // so this border draws to where the divider is:
            // -----------------
            // |xxxxxxx xxxxxxx|
            // |x     ---     x|
            // |x     | |     x|
            // |x     |D|     x|
            // |x     | |     x|
            // |x     ---     x|
            // |xxxxxxx xxxxxxx|
            // -----------------
            // The above shows (rather excessively) what this looks like for
            // a horizontal orientation. This border then draws the x's, with
            // the SplitPaneDividerBorder drawing its own border.

            Component          child;
            Rectangle          cBounds;

            JSplitPane splitPane = (JSplitPane)c;

            child = splitPane.getLeftComponent();
            // This is needed for the space between the divider and end of
            // splitpane.
            g.setColor(c.getBackground());
            g.drawRect(x, y, width - 1, height - 1);
            if(splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
                if(child != null) {
                    cBounds = child.getBounds();
                    g.setColor(shadow);
                    g.drawLine(0, 0, cBounds.width + 1, 0);
                    g.drawLine(0, 1, 0, cBounds.height + 1);

                    g.setColor(highlight);
                    g.drawLine(0, cBounds.height + 1, cBounds.width + 1,
                               cBounds.height + 1);
                }
                child = splitPane.getRightComponent();
                if(child != null) {
                    cBounds = child.getBounds();

                    int             maxX = cBounds.x + cBounds.width;
                    int             maxY = cBounds.y + cBounds.height;

                    g.setColor(shadow);
                    g.drawLine(cBounds.x - 1, 0, maxX, 0);
                    g.setColor(highlight);
                    g.drawLine(cBounds.x - 1, maxY, maxX, maxY);
                    g.drawLine(maxX, 0, maxX, maxY + 1);
                }
            } else {
                if(child != null) {
                    cBounds = child.getBounds();
                    g.setColor(shadow);
                    g.drawLine(0, 0, cBounds.width + 1, 0);
                    g.drawLine(0, 1, 0, cBounds.height);
                    g.setColor(highlight);
                    g.drawLine(1 + cBounds.width, 0, 1 + cBounds.width,
                               cBounds.height + 1);
                    g.drawLine(0, cBounds.height + 1, 0, cBounds.height + 1);
                }
                child = splitPane.getRightComponent();
                if(child != null) {
                    cBounds = child.getBounds();

                    int             maxX = cBounds.x + cBounds.width;
                    int             maxY = cBounds.y + cBounds.height;

                    g.setColor(shadow);
                    g.drawLine(0, cBounds.y - 1, 0, maxY);
                    g.drawLine(maxX, cBounds.y - 1, maxX, cBounds.y - 1);
                    g.setColor(highlight);
                    g.drawLine(0, maxY, cBounds.width + 1, maxY);
                    g.drawLine(maxX, cBounds.y, maxX, maxY);
                }
            }
        }
        public Insets getBorderInsets(Component c) {
            return new Insets(1, 1, 1, 1);
        }
        public boolean isBorderOpaque() { return true; }
    }

}
