/*
 * Rect.java      v1.0    Oct 18, 1996
 *
 * Copyright (c) 1996-7 H.J. Tsai, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for any purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. 
 *
 * H.J. Tsai MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 * PURPOSE, OR NON-INFRINGEMENT. H.J. Tsai SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * Version 1.0  Oct 18 1996
 *              Initial version
 */

import java.awt.*;
import ColorValue;

/**
 * A class to represent a rectangle which has thickness for its line
 * and knows how to paint itself properly when asked.
 */
public class Rect extends Rectangle {
    // A Rect object is defined by its upper left point, its size
    // and the thickness of the line used to draw the rectangle.
    // Because of the line has thickness, the <x,y> <width, height>
    // represent the outer-most boundary of the rectangle.
    public static final int RS_3DRAISED     = 1;
    public static final int RS_3DINSET      = 2;
    public static final int RS_ETCHEDIN     = 3;
    public static final int RS_ETCHEDOUT    = 4;
    public static final int RS_NORMAL       = 5;

    protected int thickness = 0;   // the thickness of the rectangle
    protected int style = RS_NORMAL;
    protected Color color = Color.lightGray;

    // Constructors
    public Rect() {
    }

    public Rect(Dimension d) {
        super(0, 0, d.width, d.height);
    }

    public Rect(Rectangle r) {
        super(r.x, r.y, r.width, r.height);
    }

        
    public Rect(Rectangle r, int thickness, int style, Color c) {
        super(r.x, r.y, r.width, r.height);
        this.thickness = thickness;
        this.style = style;
        this.color = c;
    }

    public Rect(Rect r, int thickness, int style, Color c) {
        super(r.x, r.y, r.width, r.height);
        this.thickness = thickness;
        this.style = style;
        this.color =c ;
    }

    public Rect(Rect rect) {
        super(rect.x, rect.y, rect.width, rect.height);
        this.style = rect.style;
        this.thickness = rect.thickness;
        this.color = rect.color;
    }
            
    /**
     * Shrinks the object by the specified width and height
     */    
    public Rect shrink(int w) {
        return doshrink(w, w, thickness);
    }
    
    public Rect shrink(int w, int h) {
        return doshrink(w, h, thickness);
    }
    
    /**
     * Shrinks the object size by the specified width, and height
     */
    private Rect doshrink(int w, int h, int thickness) {
        Rect r = new Rect();
        r.x = this.x + w;
        r.y = this.y + h;
        r.width =  this.width*2 - thickness * 2;
        r.height = this.height*2 - thickness * 2;
        r.thickness = thickness;
        return r;
    }
    
    /**
     * Returns the MyRect rectangle that is inside this rectangle
     */
    public Rect getInsideRect() {
        Rect inside = new Rect();
        inside.x = this.x + this.thickness;
        inside.y = this.y + this.thickness;
        inside.width = width - this.thickness * 2;
        inside.height = height - this.thickness * 2;
        return inside;
    }

    /**
     * Returns the Rectangle object of this object
     */
    public Rectangle getOutsideRect() {
        Rectangle r = new Rectangle();
        r.x = this.x;
        r.y = this.y;
        r.width = this.width;
        r.height = this.height;
        return r;
    }

    
    
    public void paint(Graphics g) {
        if (thickness == 0)
            return;

        Color highLight = ColorValue.getHighLightColor(color);
        Color shadow = ColorValue.getShadowColor(color);

        switch (style) {
    
        case RS_3DINSET:
                paint3dInset(g, highLight, shadow);
                break;
        case RS_3DRAISED:
                paint3dRaised(g, highLight, shadow);
                break;

        case RS_ETCHEDIN:
                paintEtchedIn(g, highLight, shadow);
                break;
        case RS_ETCHEDOUT:
                paintEtchedOut(g, highLight, shadow);
                break;

        case RS_NORMAL:
                paintNormal(g);
                break;
        }
    }

    /**
     * Paints the Rect object with the given color
     */    
    public void paintNormal(Graphics g) {
        g.setColor(color);
        for (int i = 0; i < thickness; i++)
            g.drawRect(x+i, y+i, width-(i*2)-1, height-(i*2)-1);
    }

    /**
     * Paints the Rect object with 'etched-in' style using the given colors
     */
    public void paintEtchedIn(Graphics g, Color highlight, Color shadow) {
        paintEtched(g, highlight, shadow);
    }
     
    /**
     * Paints the Rect with 'etched-out' style using the given colors
     */
    public void paintEtchedOut(Graphics g, Color highlight, Color shadow) {
        paintEtched(g, shadow, highlight);
    }

    /**
     * Paints the object -- etched by painting normally with color clr1
     * and with slight offset using color clr2
     */
    private void paintEtched(Graphics g, Color clr1, Color clr2) {
        int w = width - thickness;
        int h = height - thickness;
        int t = thickness / 2;
        
        // paint the regular box
        g.setColor(clr1);
        for (int i=0; i < t; i++) 
            g.drawRect(x+i, y+i, w-1, h-1);

        // paint the box with offset
        g.setColor(clr2);
        for (int i=0; i < t; i++) 
            g.drawRect(x+t+i, y+t+i, w-1, h-1);

    }

    /**
     * Paints the object with 3D Inset style
     */
    public void paint3dInset(Graphics g, Color highlight, Color shadow) {
        paint3dRect(g, shadow, highlight);
    }
    
    /**
     * Paints the object with 3D Raised style
     */
    public void paint3dRaised(Graphics g, Color hightlight, Color shadow) {
        paint3dRect(g, hightlight, shadow);
    }

    /**
     * Paints the object with a 3D style--
     * by painting the top and left sides of the object with the 'topleft' color
     * and the bottom and right of the object with the 'bottomright' color
     */
    private void paint3dRect(Graphics g, Color topleft, Color bottomright) {
        // paint top,left
        g.setColor(topleft);
        for (int i=0; i < thickness; i++) {
            g.drawLine(x+i, y+height-i-1, x+i, y+i+1);  // left: bottom to top
            g.drawLine(x+i, y+i, x+width-i-1, y+i);     // top: left to right
        }

        // paint bottom, right
        g.setColor(bottomright);
        for (int i = 0; i < thickness; i++) {
            // bottom: left->right
            g.drawLine(x+i+1, y+height-i, x+width-i, y+height-i); 

            // right: bot to top
            g.drawLine(x+width-i, y+height-i-1, x+width-i, y+i);  
        }
    }
   
    public String toString() {
        return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" 
               + width + ",height=" + height + ",thickness=" + thickness +"]";   
    }
    
   
}


