/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.toolbox.rebop;

import java.awt.Color;
import java.awt.Graphics;

/**
 * Used to draw 3D boxes and edges around components.
 * Can be used to draw solid flat rectangles, buttons,
 * and edges around other controls. Implements the
 * GenericDrawable interface so it can be used as a
 * drawable for any GenericComponent.
 *
 * @author Gavin Doughtie
 */
public class BevelBox extends AbstractDrawable implements GenericDrawable {
    public static final String versionId = "$Id: //core-platform/dev/src/com/arsdigita/toolbox/rebop/BevelBox.java#7 $ by $Author: dennis $, $DateTime: 2004/04/07 16:07:11 $";
    public static final int STANDARD_BEVEL = 2;
    private Color m_fillColor = Color.gray;
    private Color m_lightEdge = Color.lightGray;
    private Color m_darkEdge = Color.darkGray;
    private int m_bevelWidth = STANDARD_BEVEL;
    private boolean m_in = false;

    /**
     * Construct a new BevelBox. Will draw as a
     * standard-looking gray button.
     */
    public BevelBox() {
    }

    /**
     * Construct a new BevelBox with the specified
     * fillColor and the "raised button" appearance.
     * @param fillColor box will be drawn with this as its fill color.
     * fillColor shouldn't be null, because then there's nothing to draw!
     */
    public BevelBox(Color fillColor) {
        this(fillColor, STANDARD_BEVEL, false);
    }

    /**
     * Construct a new BevelBox with the specified
     * appearance.
     * @param fillColor box will be drawn with this as its fill color.
     * fillColor shouldn't be null, because then there's nothing to draw!
     * @param bevelWidth number of pixels to use for bevelled edges
     * @param in if true, then the lightEdge will be the lower-right
     * edges of the box, otherwise the lightEdge will be the upper-left edges.
     */
    public BevelBox
        (
         Color fillColor,
         int bevelWidth,
         boolean in
         ) {
        Color dark = null;
        Color light = null;
        if (null != fillColor) {
            light = fillColor.brighter().brighter();
            dark = fillColor.darker().darker();
        }

        init(fillColor,
             light,
             dark,
             bevelWidth,
             in);
    }

    /**
     * Construct a new BevelBox with the specified
     * appearance.
     * @param fillColor box will be drawn with this as its fill color.
     * if null, then no center will be drawn.
     * @param lightEdge color to draw the light edge in.  If null, no
     * light edge will be drawn.
     * @param darkEdge color to draw the light edge in. If null, no
     * dark edge will be drawn.
     * @param bevelWidth number of pixels to use for bevelled edges
     * @param in if true, then the lightEdge will be the lower-right
     * edges of the box, otherwise the lightEdge will be the upper-left edges.
     */
    public BevelBox
        (
         Color fillColor,
         Color lightEdge,
         Color darkEdge,
         int bevelWidth,
         boolean in
         ) {
        init(fillColor,
             lightEdge,
             darkEdge,
             bevelWidth,
             in);
    }

    /**
     * Ultimately called by all constructors. See BevelBox()
     */
    private void init(
                      Color fillColor,
                      Color lightEdge,
                      Color darkEdge,
                      int bevelWidth,
                      boolean in
                      ) {
        m_fillColor = fillColor;
        m_lightEdge = lightEdge;
        m_darkEdge = darkEdge;
        m_bevelWidth = bevelWidth;
        m_in = in;
    }

    public void setIn(boolean in) {
        m_in = in;
    }

    public void toggleIn() {
        m_in = !m_in;
    }

    public boolean getIn() {
        return m_in;
    }

    /**
     * Implementation of the GenericDrawable interface
     */
    public void draw(Graphics g, int x, int y, int width, int height) {
        if (null != m_fillColor) {
            g.setColor(m_fillColor);
            g.fillRect(x, y, width, height);
        }

        Color tlEdgeColor = m_lightEdge;
        Color brEdgeColor = m_darkEdge;

        if (m_in) {
            tlEdgeColor = m_darkEdge;
            brEdgeColor = m_lightEdge;
        }

        int currentX = x;
        int currentY = y;
        int currentLineWidth = width - 1;
        if (null != tlEdgeColor) {
            g.setColor(tlEdgeColor);
            for (int i = 0; i < m_bevelWidth; i++) {
                g.drawLine(
                           currentX,
                           currentY,
                           currentX + currentLineWidth,
                           currentY);
                currentX++;
                currentY++;
                currentLineWidth -= 2;
            }

            currentX = x;
            currentY = y;
            currentLineWidth = height - 1;

            for (int i = 0; i < m_bevelWidth; i++) {
                g.drawLine(
                           currentX,
                           currentY,
                           currentX,
                           currentY + currentLineWidth);
                currentX++;
                currentY++;
                currentLineWidth -= 2;
            }
        } // end of if ()

        if (null != brEdgeColor) {
            g.setColor(brEdgeColor);

            // bottom
            currentX = x;
            currentY = height - 1;
            currentLineWidth = width - 1;
            for (int i = 0; i < m_bevelWidth; i++) {
                g.drawLine(
                           currentX,
                           currentY,
                           currentX + currentLineWidth,
                           currentY);
                currentX++;
                currentY--;
                currentLineWidth -= 2;
            }

            // right
            currentX = width - 1;
            currentY = y;
            currentLineWidth = height - 1;

            for (int i = 0; i < m_bevelWidth; i++) {
                g.drawLine(
                           currentX,
                           currentY,
                           currentX,
                           currentY + currentLineWidth);
                currentX--;
                currentY++;
                currentLineWidth -= 2;
            }
        }
    }
}// BevelBox
