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

/** Represents an interactively drawable curve.
  * @version 1.0  24  July 1999
  * @author Larry Rodrigues
  ***/
public class Curve extends Shapes implements Drawable{
   /*** xp the x coordinates of the Box corners
     */
   protected int xp[] = new int[4];
   protected int prevxp[] = new int[4];

   /**
     * yp the y coordinates of the Box corners
    */
   protected int yp[] = new int[4];
   protected int prevyp[] = new int[4];

   boolean filled = false;

   Vector curveList = new Vector();
   int pointsCount =0;

   /**
    * 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;
      xp[0] = x; yp[0]= y;
      xp[1] = x; yp[1]= y;

      pointsCount =1;
      path = new GeneralPath();
      path.moveTo((float)x, (float)y);
   }

   /***
    * 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 setCurPoint(int x , int y){
      cur.x = x; cur.y = y;
   }

   /**
    * 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 ){
      if(pointsCount < 4) {
         xp[pointsCount] = cur.x;
         yp[pointsCount] = cur.y;
         if(pointsCount == 3) {
            basicStroke = g.getStroke();
            g.setColor(Color.black);
            g.setXORMode(drawingColor);
            //drawCurve(g, prevxp, prevyp);
           /* path.curveTo((float)xp[1], (float)yp[1],
                      (float)xp[2], (float)yp[2],
                      (float)xp[3], (float)yp[3]);*/

           prevxp[0] = xp[0];
           prevxp[1] = xp[1];
           prevxp[2] = xp[2];
           prevxp[3] = xp[3];
           prevyp[0] = yp[0];
           prevyp[1] = yp[1];
           prevyp[2] = yp[2];
           prevyp[3] = yp[3];

           drawCurve(g, xp,yp);
           xp[0] = xp[3];
           yp[0] = yp[3];
         }
      }else {
        pointsCount =0;
      }
      pointsCount++;
   }

   /**
    * Draws on a Graphics context g.
    * This API does not check whether the Box overflows
    * the borders of the component.
    * @param g the graphics object on which the shape is to  be drawn.
    **/
   public void  drawPermanent(Graphics2D g){
      g.setPaintMode();
      g.setColor(drawingColor);
      //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);

     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);
  }


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

     g.setColor(Color.black);
     g.setXORMode(drawingColor);
     for(Enumeration e= curveList.elements(); e.hasMoreElements();){
         CubicCurve2D.Float cc = (CubicCurve2D.Float)e.nextElement();
         g.draw(cc);
     }
     if(smallRectsOn) drawSmallRects(g);
    /* if(fillOn) {
        g.setXORMode(fillColor);
        fillPolygon(g, xp,yp);
     }*/
     curveList = new Vector();
     g.setStroke(savedStroke);
  }

  /**
    * Draws and returns itself.
    * shCnt is set by the caller.
    * Returns itself.
    * @param g the graphics object on which the shape is to be drawn.
    * @param shCnt the shape count.
    * @return Shape itself.
    **/
  /*
  public Shapes saveCurShape(Graphics2D g, int shCnt){
         g.setPaintMode();
         g.setColor(drawingColor);
         //setPolygonVertices();
         //drawPolygon(g, xp,yp);
         shapeCount = shCnt;
         return (Shapes)this;
  }
*/
  /**
    * 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) {
     for(Enumeration e= curveList.elements(); e.hasMoreElements();){
         CubicCurve2D.Float cc = (CubicCurve2D.Float)e.nextElement();
	  if(cc.contains((double)x, (double)y)) return true;
     }
     return false;
  }

  public void drawSmallRects(Graphics2D g) {
     smallRectsOn = !smallRectsOn;
     g.setColor(Color.black);
     g.setXORMode(drawingColor);
     g.drawRect(st.x, st.y, 5,5);
     g.drawRect(cur.x, cur.y, 5,5);
  }

  public void drawCurve(Graphics2D g, int x[], int y[]){
  /*    path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
      path.moveTo((float)x[0], (float)y[0]);
      for(int i=1; i<x.length;i++) {
          path.lineTo((float)x[i], (float)y[i]);
      }
      g.draw(path);*/
     CubicCurve2D.Float cc = new CubicCurve2D.Float((float)x[0], (float)y[0],
                                                   (float)x[1], (float)y[1],
                                                   (float)x[2], (float)y[2],
                                                   (float)x[3], (float)y[3]);
     g.draw(cc);
     curveList.addElement(cc);
  }
   public void fillPolygon(Graphics2D g, int x[], int y[]){
  }
}



