/* @(#) Box.java 1.0 99/07/30 Larry Rodrigues
 **/
package com.vistech.shapes;
import java.awt.*;
import java.lang.Math;
import java.awt.geom.*;

/** Represents an interactively drawable rectangle.
  * Although the Box shape is a rectangle, it is drawn as a polygon
  * in this implementation. The drawing of a rectangle requires the
  * upper left hand corner coordinates as the starting position.
  * So the drawRect will draw the rectangle from
  * top to bottom and left to right. If the current position
  * moves up or right with respect to the starting  position,
  * the rectangle will not be drawn because the width and height
  * values are negative. So there are two options.
  * 1. Switch the starting and current positions
  *    whenever the rectangle is drawn from bottom to top or  right to left.
  * 2. Use the drawPolygon method.
  * We chose the second option because it involved less programming.
  * @version 1.0  30  July 1999
  * @author Larry Rodrigues
  ***/
public class Box extends Shapes implements Fillable{
    /** xp the x coordinates of the Box corners */
    protected int xp[] = new int[5];
    /** yp the y coordinates of the Box corners */
    protected int yp[] = new int[5];
    boolean filled = false;

    /** Initializes the Box parameters.
      * The arguments provide the starting point  of the box
      * which may be the upper left hand corner(ULHC) or bottom righthand
      * corner coordinates(BRHC) of the Box.
      * @param  x  the x coordinate of the starting position.
      * @param  y  the y coordinate of the starting poistion.
      **/
    public void init(int x , int y){
       st.x = x; st.y = y;
       cur.x =x; cur.y =y;
       setPolygonVertices();
    }

    /** Sets the current position.
      * @param  x  the x coordinate of the current position.
      * @param  y  the y coordinate of the current poistion.
      **/
    public synchronized void setCurrentPosition(Point cp){
       cur = cp;
    }

    /** Draws interactively on a Graphics context g.
      * This API does not check whether the Box overflows
      * the borders of the component.
      * This  method uses the XOR paint mode. It erases the
      * previously drawn shape and draws a new shape in its
      * place.
      * @param g the graphics object on which the shape is to  be drawn.
      **/
    public void drawInteractive(Graphics2D g ){
       basicStroke = g.getStroke();
       g.setColor(Color.black);
       g.setXORMode(drawingColor);
       drawPolygon(g, xp,yp);
       setPolygonVertices();
       drawPolygon(g, xp,yp);
    }

    public void  draw(Graphics2D g){
       Stroke savedStroke = g.getStroke();
       if(basicStroke != null) g.setStroke(basicStroke);

       g.setColor(Color.black);
       g.setXORMode(drawingColor);
       setPolygonVertices();
       drawPolygon(g, xp,yp);
       if(fillOn) {
          g.setXORMode(fillColor);
          fillPolygon(g, xp,yp);
       }
       g.setStroke(savedStroke);
    }

    public void move(Graphics2D g, int diffx, int diffy){
       Stroke savedStroke = g.getStroke();
       if(basicStroke != null) g.setStroke(basicStroke);
       g.setColor(Color.black);
       g.setXORMode(drawingColor);
       drawPolygon(g, xp,yp);
       if(smallRectsOn) drawSmallRects(g);
       if(fillOn) {
          g.setXORMode(fillColor);
          fillPolygon(g, xp,yp);
       }
       st.x += diffx; st.y += diffy;
       cur.x += diffx; cur.y += diffy;
       setPolygonVertices();
       g.setXORMode(drawingColor);
       drawPolygon(g, xp,yp);
       drawSmallRects(g);
       if(fillOn) {
          g.setXORMode(fillColor);
          fillPolygon(g, xp,yp);
       }
       g.setStroke(savedStroke);
    }

    /** Erases the box
      * @param g the graphics object on which the shape is drawn.
      **/
    public void erase(Graphics2D g){
       Stroke savedStroke = g.getStroke();
       if(basicStroke != null) g.setStroke(basicStroke);

       g.setColor(Color.black);
       g.setXORMode(drawingColor);
       setPolygonVertices();
       drawPolygon(g, xp,yp);
       if(smallRectsOn) drawSmallRects(g);
       if(fillOn) {
          g.setXORMode(fillColor);
          fillPolygon(g, xp,yp);
       }
       g.setStroke(savedStroke);
    }

    /** Fills with a given color.
      * @param g the graphics object on which the shape is to  be drawn.
      * @param color the filling color.
      **/
    public void fill(Graphics2D g, Color color){
       if(filled) return;
       filled = true;
       fillOn = true;
       fillColor = color;
       g.setXORMode(color);
       fillPolygon(g, xp,yp);
    }

    /**  Sets the box points. There are five points. This is because,
      *  in order to make a closed polygon of n vertices, n+1 points are
      *  needed. The last one is same as the first one.
      **/
    private final void setPolygonVertices(){
       xp[0] = st.x; yp[0] = st.y;
       xp[1] = st.x; yp[1] = cur.y;
       xp[2] = cur.x; yp[2] = cur.y;
       xp[3] = cur.x; yp[3] = st.y;
       xp[4] = st.x; yp[4] = st.y;
    }

    public boolean contains(Graphics2D g, int x, int y) {
       if(!path.contains((double)x, (double)y)) return false;
       drawSmallRects(g);
       return true;
    }

    public void drawSmallRects(Graphics2D g) {
       Stroke savedStroke = g.getStroke();
       if(basicStroke != null) g.setStroke(basicStroke);

       smallRectsOn = !smallRectsOn;
       g.setColor(Color.black);
       g.setXORMode(drawingColor);
       for (int i=0; i< xp.length-1;i++) {
            int x, y;
            if(xp[i] > xp[(i+2)%4]) x = xp[i]+1;
            else x = xp[i]-6;
            if(yp[i] > yp[(i+2)%4]) y = yp[i]+1;
            else y = yp[i]-6;
            g.drawRect(x, y, 5,5);
       }
       g.setStroke(savedStroke);
    }

    /** Draws the box with the specified vertices.
      * @param g the graphics object on which the shape is to  be drawn.
      * @param x an array of x coordinates.
      * @param y an array of y coordinates.
      **/
    public void drawPolygon(Graphics2D g, int x[], int y[]){
        if((x == null) || (y==null))return;
        int num = x.length;
        path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
        path.moveTo((float)x[0], (float)y[0]);
        for(int i=1; i<num;i++) {
            path.lineTo((float)x[i], (float)y[i]);
        }
        g.draw(path);
    }
    /** Fills the box.
      * @param g the graphics object on which the shape is to  be drawn.
      * @param x an array of x coordinates.
      * @param y an array of y coordinates.
      **/
    public void fillPolygon(Graphics2D g, int x[], int y[]){
        if((x == null) || (y==null))return;
        int num = x.length;
        path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
        path.moveTo((float)x[0], (float)y[0]);
        for(int i=1; i<num;i++) {
            path.lineTo((float)x[i], (float)y[i]);
        }
        g.fill(path);
    }
}



