/*
 * Copyright (c) 1997, 2005, 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.sun.java.swing.plaf.motif;

import sun.swing.SwingUtilities2;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;

import java.io.Serializable;

/**
 * Factory object that can vend Icons appropriate for the basic L & F.
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases.  The current serialization support is appropriate
 * for short term storage or RMI between applications running the same
 * version of Swing.  A future release of Swing will provide support for
 * long term persistence.
 *
 * @author Amy Fowler
 */
public class MotifBorders {

    public static class BevelBorder extends AbstractBorder implements UIResource {
        private Color darkShadow = UIManager.getColor("controlShadow");
        private Color lightShadow = UIManager.getColor("controlLtHighlight");
        private boolean isRaised;

        public BevelBorder(boolean isRaised, Color darkShadow, Color lightShadow) {
            this.isRaised = isRaised;
            this.darkShadow = darkShadow;
            this.lightShadow = lightShadow;
        }

        public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
            g.setColor((isRaised) ? lightShadow : darkShadow);
            g.drawLine(x, y, x+w-1, y);           // top
            g.drawLine(x, y+h-1, x, y+1);         // left

            g.setColor((isRaised) ? darkShadow : lightShadow);
            g.drawLine(x+1, y+h-1, x+w-1, y+h-1); // bottom
            g.drawLine(x+w-1, y+h-1, x+w-1, y+1); // right
        }

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

        public boolean isOpaque(Component c) {
            return true;
        }

    }


    public static class FocusBorder extends AbstractBorder implements UIResource {
        private Color focus;
        private Color control;

        public FocusBorder(Color control, Color focus) {
            this.control = control;
            this.focus = focus;
        }

        public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
            if (((JComponent)c).hasFocus()) {
                g.setColor(focus);
                g.drawRect(x, y, w-1, h-1);
            } else {
                g.setColor(control);
                g.drawRect(x, y, w-1, h-1);
            }
        }

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


    public static class ButtonBorder extends AbstractBorder implements UIResource {
        protected Color focus = UIManager.getColor("activeCaptionBorder");
        protected Color shadow = UIManager.getColor("Button.shadow");
        protected Color highlight = UIManager.getColor("Button.light");
        protected Color darkShadow;

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

        public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
            boolean isPressed = false;
            boolean hasFocus = false;
            boolean canBeDefault = false;
            boolean isDefault = false;

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

                isPressed = (model.isArmed() && model.isPressed());
                hasFocus = (model.isArmed() && isPressed) ||
                           (b.isFocusPainted() && b.hasFocus());
                if (b instanceof JButton) {
                    canBeDefault = ((JButton)b).isDefaultCapable();
                    isDefault = ((JButton)b).isDefaultButton();
                }
            }
            int bx1 = x+1;
            int by1 = y+1;
            int bx2 = x+w-2;
            int by2 = y+h-2;

            if (canBeDefault) {
                if (isDefault) {
                    g.setColor(shadow);
                    g.drawLine(x+3, y+3, x+3, y+h-4);
                    g.drawLine(x+3, y+3, x+w-4, y+3);

                    g.setColor(highlight);
                    g.drawLine(x+4, y+h-4, x+w-4, y+h-4);
                    g.drawLine(x+w-4, y+3, x+w-4, y+h-4);
                }
                bx1 +=6;
                by1 += 6;
                bx2 -= 6;
                by2 -= 6;
            }

            if (hasFocus) {
                g.setColor(focus);
                if (isDefault) {
                    g.drawRect(x, y, w-1, h-1);
                } else {
                    g.drawRect(bx1-1, by1-1, bx2-bx1+2, by2-by1+2);
                }
            }

            g.setColor(isPressed? shadow : highlight);
            g.drawLine(bx1, by1, bx2, by1);
            g.drawLine(bx1, by1, bx1, by2);

            g.setColor(isPressed? highlight : shadow);
            g.drawLine(bx2, by1+1, bx2, by2);
            g.drawLine(bx1+1, by2, bx2, by2);
        }

        public Insets getBorderInsets(Component c, Insets insets) {
            int thickness = (c instanceof JButton && ((JButton)c).isDefaultCapable())? 8 : 2;
            insets.set(thickness, thickness, thickness, thickness);
            return insets;
        }

    }

    public static class ToggleButtonBorder extends ButtonBorder {

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

        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()) {
                    drawBezel(g, x, y, width, height,
                              (model.isPressed() || model.isSelected()),
                              b.isFocusPainted() && b.hasFocus(), shadow, highlight, darkShadow, focus);
                } else {
                    drawBezel(g, x, y, width, height,
                              false, b.isFocusPainted() && b.hasFocus(),
                              shadow, highlight, darkShadow, focus);
                }
            } else {
                drawBezel(g, x, y, width, height, false, false,
                          shadow, highlight, darkShadow, focus);
            }
        }

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

    public static class MenuBarBorder extends ButtonBorder {

        public MenuBarBorder(Color shadow, Color highlight, Color darkShadow, Color focus) {
            super(shadow, highlight, darkShadow, focus);
        }

        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            JMenuBar menuBar = (JMenuBar)c;
            if (menuBar.isBorderPainted() == true) {
                // this draws the MenuBar border
                Dimension size = menuBar.getSize();
                drawBezel(g,x,y,size.width,size.height,false,false,
                          shadow, highlight, darkShadow, focus);
            }
        }

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

    public static class FrameBorder extends AbstractBorder implements UIResource {

        JComponent jcomp;
        Color frameHighlight;
        Color frameColor;
        Color frameShadow;

        // The width of the border
        public final static int BORDER_SIZE = 5;

        /** Constructs an FrameBorder for the JComponent <b>comp</b>.
        */
        public FrameBorder(JComponent comp) {
            jcomp = comp;
        }

        /** Sets the FrameBorder's JComponent.
      */
        public void setComponent(JComponent comp) {
            jcomp = comp;
        }

        /** Returns the FrameBorder's JComponent.
          * @see #setComponent
          */
        public JComponent component() {
            return jcomp;
        }

        protected Color getFrameHighlight() {
            return frameHighlight;
        }

        protected Color getFrameColor() {
            return frameColor;
        }

        protected Color getFrameShadow() {
            return frameShadow;
        }

        public Insets getBorderInsets(Component c, Insets newInsets) {
            newInsets.set(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE);
            return newInsets;
        }

       /** Draws the FrameBorder's top border.
         */
        protected boolean drawTopBorder(Component c, Graphics g,
                                    int x, int y, int width, int height) {
            Rectangle titleBarRect = new Rectangle(x, y, width, BORDER_SIZE);
            if (!g.getClipBounds().intersects(titleBarRect)) {
                return false;
            }

            int maxX = width - 1;
            int maxY = BORDER_SIZE - 1;

            // Draw frame
            g.setColor(frameColor);
            g.drawLine(x, y + 2, maxX - 2, y + 2);
            g.drawLine(x, y + 3, maxX - 2, y + 3);
            g.drawLine(x, y + 4, maxX - 2, y + 4);

            // Draw highlights
            g.setColor(frameHighlight);
            g.drawLine(x, y, maxX, y);
            g.drawLine(x, y + 1, maxX, y + 1);
            g.drawLine(x, y + 2, x, y + 4);
            g.drawLine(x + 1, y + 2, x + 1, y + 4);

            // Draw shadows
            g.setColor(frameShadow);
            g.drawLine(x + 4, y + 4, maxX - 4, y + 4);
            g.drawLine(maxX, y + 1, maxX, maxY);
            g.drawLine(maxX - 1, y + 2, maxX - 1, maxY);

            return true;
        }

        /** Draws the FrameBorder's left border.
          */
        protected boolean drawLeftBorder(Component c, Graphics g, int x, int y,
                               int width, int height) {
            Rectangle borderRect =
                new Rectangle(0, 0, getBorderInsets(c).left, height);
            if (!g.getClipBounds().intersects(borderRect)) {
                return false;
            }

            int startY = BORDER_SIZE;

            g.setColor(frameHighlight);
            g.drawLine(x, startY, x, height - 1);
            g.drawLine(x + 1, startY, x + 1, height - 2);

            g.setColor(frameColor);
            g.fillRect(x + 2, startY, x + 2, height - 3);

            g.setColor(frameShadow);
            g.drawLine(x + 4, startY, x + 4, height - 5);

            return true;
        }

        /** Draws the FrameBorder's right border.
          */
        protected boolean drawRightBorder(Component c, Graphics g, int x, int y,
                                int width, int height) {
            Rectangle borderRect = new Rectangle(
                width - getBorderInsets(c).right, 0,
                getBorderInsets(c).right, height);
            if (!g.getClipBounds().intersects(borderRect)) {
                return false;
            }

            int startX = width - getBorderInsets(c).right;
            int startY = BORDER_SIZE;

            g.setColor(frameColor);
            g.fillRect(startX + 1, startY, 2, height - 1);

            g.setColor(frameShadow);
            g.fillRect(startX + 3, startY, 2, height - 1);

            g.setColor(frameHighlight);
            g.drawLine(startX, startY, startX, height - 1);

            return true;
        }

        /** Draws the FrameBorder's bottom border.
          */
        protected boolean drawBottomBorder(Component c, Graphics g, int x, int y,
                                 int width, int height) {
            Rectangle    borderRect;
            int     marginHeight, startY;

            borderRect = new Rectangle(0, height - getBorderInsets(c).bottom,
                                  width, getBorderInsets(c).bottom);
            if (!g.getClipBounds().intersects(borderRect)) {
                return false;
            }

            startY = height - getBorderInsets(c).bottom;

            g.setColor(frameShadow);
            g.drawLine(x + 1, height - 1, width - 1, height - 1);
            g.drawLine(x + 2, height - 2, width - 2, height - 2);

            g.setColor(frameColor);
            g.fillRect(x + 2, startY + 1, width - 4, 2);

            g.setColor(frameHighlight);
            g.drawLine(x + 5, startY, width - 5, startY);

            return true;
        }

        // Returns true if the associated component has focus.
        protected boolean isActiveFrame() {
            return jcomp.hasFocus();
        }

        /** Draws the FrameBorder in the given Rect.  Calls
          * <b>drawTitleBar</b>, <b>drawLeftBorder</b>, <b>drawRightBorder</b> and
          * <b>drawBottomBorder</b>.
          */
        public void paintBorder(Component c, Graphics g,
                            int x, int y, int width, int height) {
            if (isActiveFrame()) {
                frameColor = UIManager.getColor("activeCaptionBorder");
            } else {
                frameColor = UIManager.getColor("inactiveCaptionBorder");
            }
            frameHighlight = frameColor.brighter();
            frameShadow = frameColor.darker().darker();

            drawTopBorder(c, g, x, y, width, height);
            drawLeftBorder(c, g, x, y, width, height);
            drawRightBorder(c, g, x, y, width, height);
            drawBottomBorder(c, g, x, y, width, height);
        }
    }

    public static class InternalFrameBorder extends FrameBorder {

        JInternalFrame frame;

        // The size of the bounding box for Motif frame corners.
        public final static int CORNER_SIZE = 24;

        /** Constructs an InternalFrameBorder for the InternalFrame
          * <b>aFrame</b>.
          */
        public InternalFrameBorder(JInternalFrame aFrame) {
            super(aFrame);
            frame = aFrame;
        }

        /** Sets the InternalFrameBorder's InternalFrame.
          */
        public void setFrame(JInternalFrame aFrame) {
            frame = aFrame;
        }

        /** Returns the InternalFrameBorder's InternalFrame.
          * @see #setFrame
          */
        public JInternalFrame frame() {
            return frame;
        }

        /** Returns the width of the InternalFrameBorder's resize controls,
          * appearing along the InternalFrameBorder's bottom border.  Clicking
          * and dragging within these controls lets the user change both the
          * InternalFrame's width and height, while dragging between the controls
          * constrains resizing to just the vertical dimension.  Override this
          * method if you implement your own bottom border painting and use a
          * resize control with a different size.
          */
        public int resizePartWidth() {
            if (!frame.isResizable()) {
                return 0;
            }
            return FrameBorder.BORDER_SIZE;
        }

        /** Draws the InternalFrameBorder's top border.
         */
        protected boolean drawTopBorder(Component c, Graphics g,
                                    int x, int y, int width, int height) {
            if (super.drawTopBorder(c, g, x, y, width, height) &&
                frame.isResizable()) {
                g.setColor(getFrameShadow());
                g.drawLine(CORNER_SIZE - 1, y + 1, CORNER_SIZE - 1, y + 4);
                g.drawLine(width - CORNER_SIZE - 1, y + 1,
                       width - CORNER_SIZE - 1, y + 4);

                g.setColor(getFrameHighlight());
                g.drawLine(CORNER_SIZE, y, CORNER_SIZE, y + 4);
                g.drawLine(width - CORNER_SIZE, y, width - CORNER_SIZE, y + 4);
                return true;
            }
            return false;
        }

        /** Draws the InternalFrameBorder's left border.
          */
        protected boolean drawLeftBorder(Component c, Graphics g, int x, int y,
                                     int width, int height) {
            if (super.drawLeftBorder(c, g, x, y, width, height) &&
                frame.isResizable()) {
                g.setColor(getFrameHighlight());
                int topY = y + CORNER_SIZE;
                g.drawLine(x, topY, x + 4, topY);
                int bottomY = height - CORNER_SIZE;
                g.drawLine(x + 1, bottomY, x + 5, bottomY);
                g.setColor(getFrameShadow());
                g.drawLine(x + 1, topY - 1, x + 5, topY - 1);
                g.drawLine(x + 1, bottomY - 1, x + 5, bottomY - 1);
                return true;
            }
            return false;
        }

        /** Draws the InternalFrameBorder's right border.
          */
        protected boolean drawRightBorder(Component c, Graphics g, int x, int y,
                                      int width, int height) {
            if (super.drawRightBorder(c, g, x, y, width, height) &&
                frame.isResizable()) {
                int startX = width - getBorderInsets(c).right;
                g.setColor(getFrameHighlight());
                int topY = y + CORNER_SIZE;
                g.drawLine(startX, topY, width - 2, topY);
                int bottomY = height - CORNER_SIZE;
                g.drawLine(startX + 1, bottomY, startX + 3, bottomY);
                g.setColor(getFrameShadow());
                g.drawLine(startX + 1, topY - 1, width - 2, topY - 1);
                g.drawLine(startX + 1, bottomY - 1, startX + 3, bottomY - 1);
                return true;
            }
            return false;
        }

        /** Draws the InternalFrameBorder's bottom border.
          */
        protected boolean drawBottomBorder(Component c, Graphics g, int x, int y,
                                       int width, int height) {
            if (super.drawBottomBorder(c, g, x, y, width, height) &&
                frame.isResizable()) {
                int startY = height - getBorderInsets(c).bottom;

                g.setColor(getFrameShadow());
                g.drawLine(CORNER_SIZE - 1, startY + 1,
                       CORNER_SIZE - 1, height - 1);
                g.drawLine(width - CORNER_SIZE, startY + 1,
                       width - CORNER_SIZE, height - 1);

                g.setColor(getFrameHighlight());
                g.drawLine(CORNER_SIZE, startY, CORNER_SIZE, height - 2);
                g.drawLine(width - CORNER_SIZE + 1, startY,
                       width - CORNER_SIZE + 1, height - 2);
                return true;
            }
            return false;
        }

        // Returns true if the associated internal frame has focus.
        protected boolean isActiveFrame() {
            return frame.isSelected();
        }
    }

    public static void drawBezel(Graphics g, int x, int y, int w, int h,
                               boolean isPressed, boolean hasFocus,
                               Color shadow, Color highlight,
                               Color darkShadow, Color focus)  {

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

        if (isPressed) {
            if (hasFocus){
                g.setColor(focus);
                g.drawRect(0, 0, w-1, h-1);
            }
            g.setColor(shadow);         // inner border
            g.drawRect(1, 1, w-3, h-3);

            g.setColor(highlight);    // inner 3D border
            g.drawLine(2, h-3, w-3, h-3);
            g.drawLine(w-3, 2, w-3, h-4);

        } else {
            if (hasFocus) {
                g.setColor(focus);
                g.drawRect(0, 0, w-1, h-1);

                g.setColor(highlight);   // inner 3D border
                g.drawLine(1, 1, 1, h-3);
                g.drawLine(2, 1, w-4, 1);

                g.setColor(shadow);
                g.drawLine(2, h-3, w-3, h-3);
                g.drawLine(w-3, 1, w-3, h-4);

                g.setColor(darkShadow);        // black drop shadow  __|
                g.drawLine(1, h-2, w-2, h-2);
                g.drawLine(w-2, h-2, w-2, 1);
            } else {
                g.setColor(highlight);    // inner 3D border
                g.drawLine(1,1,1,h-3);
                g.drawLine(2,1,w-4,1);
                g.setColor(shadow);
                g.drawLine(2,h-3,w-3,h-3);
                g.drawLine(w-3,1,w-3,h-4);

                g.setColor(darkShadow);         // black drop shadow  __|
                g.drawLine(1,h-2,w-2,h-2);
                g.drawLine(w-2,h-2,w-2,0);

            }
            g.translate(-x, -y);
        }
        g.setColor(oldColor);
    }

    public static class MotifPopupMenuBorder extends AbstractBorder implements UIResource {
        protected Font   font;
        protected Color  background;
        protected Color  foreground;
        protected Color  shadowColor;
        protected Color  highlightColor;

        // Space between the border and text
        static protected final int TEXT_SPACING = 2;

        // Space for the separator under the title
        static protected final int GROOVE_HEIGHT = 2;

        /**
         * Creates a MotifPopupMenuBorder instance
         *
         */
        public MotifPopupMenuBorder(
                                    Font titleFont,
                                    Color bgColor,
                                    Color fgColor,
                                    Color shadow,
                                    Color highlight)       {
            this.font = titleFont;
            this.background = bgColor;
            this.foreground = fgColor;
            this.shadowColor = shadow;
            this.highlightColor = highlight;
        }

        /**
         * Paints the border for the specified component with the
         * specified position and size.
         * @param c the component for which this border is being painted
         * @param g the paint graphics
         * @param x the x position of the painted border
         * @param y the y position of the painted border
         * @param width the width of the painted border
         * @param height the height of the painted border
         */
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {

            Font origFont = g.getFont();
            Color origColor = g.getColor();
            JPopupMenu popup = (JPopupMenu)c;

            String title = popup.getLabel();
            if (title == null) {
                return;
            }

            g.setFont(font);

            FontMetrics fm = SwingUtilities2.getFontMetrics(popup, g, font);
            int         fontHeight = fm.getHeight();
            int         descent = fm.getDescent();
            int         ascent = fm.getAscent();
            Point       textLoc = new Point();
            int         stringWidth = SwingUtilities2.stringWidth(popup, fm,
                                                                  title);

            textLoc.y = y + ascent + TEXT_SPACING;
            textLoc.x = x + ((width - stringWidth) / 2);

            g.setColor(background);
            g.fillRect(textLoc.x - TEXT_SPACING, textLoc.y - (fontHeight-descent),
                       stringWidth + (2 * TEXT_SPACING), fontHeight - descent);
            g.setColor(foreground);
            SwingUtilities2.drawString(popup, g, title, textLoc.x, textLoc.y);

            MotifGraphicsUtils.drawGroove(g, x, textLoc.y + TEXT_SPACING,
                                          width, GROOVE_HEIGHT,
                                          shadowColor, highlightColor);

            g.setFont(origFont);
            g.setColor(origColor);
        }

        /**
         * Reinitialize the insets parameter with this Border's current Insets.
         * @param c the component for which this border insets value applies
         * @param insets the object to be reinitialized
         */
        public Insets getBorderInsets(Component c, Insets insets) {
            FontMetrics fm;
            int         descent = 0;
            int         ascent = 16;

            String title = ((JPopupMenu)c).getLabel();
            if (title == null) {
                insets.left = insets.top = insets.right = insets.bottom = 0;
                return insets;
            }

            fm = c.getFontMetrics(font);

            if(fm != null) {
                descent = fm.getDescent();
                ascent = fm.getAscent();
            }

            insets.top += ascent + descent + TEXT_SPACING + GROOVE_HEIGHT;
            return insets;
        }

    }

}
