/*
 * Course:       CSCI 215
 * Title:        Lab 1
 * Description:  DrawPad
 * Author:       Yu Chong
 * Copyright (c)2001 Yu Chong.  All Rights Reserved.
 */

import java.awt.Graphics;
import java.awt.Color;
import java.util.Vector;
/**
 * CLASS:    DrawableShape<BR>
 * PURPOSE:  Serve as a super class for other shape, force the subclass to have method
 *           for drawing and editing.<BR>
 * IMPORT:   java.awt.Graphics, java.awt.Color, java.util.Vector, Point<BR>
 * EXPORT:   None, This is an abstract class with partial implementation.  User
 *           should not instantiate this class.  Some basic functions have already
 *           been implemented:  addPoint, getColor, move, movePointBox,
 *           removeLastPoint, setColor, setEndPoint, setFill, setSelected,
 *           setStartPoint<BR>
 */
public abstract class DrawableShape
{
  //Protected Attributes
  /** Reference Point object for resize change(X component) */
  protected Point xPointChange=null;
  /** Reference Point object for resize change(Y component) */
  protected Point yPointChange=null;
  /** Vector to keep track of the shapes point(s)*/
  protected Vector pointList = new Vector();
  /** Color for the shape*/
  protected Color color = Color.black;
  /** Flag to indicate the shape is to be filled or not */
  protected boolean bFill=false;
  /** Flag to indicate if the shape has been selected */
  protected boolean bSelected=false;

  /** <BR>
   *  PRE:  None<BR>
   *  POST: A new DrawableShape object is copy from the current instance and returned<BR>
   */
  abstract public DrawableShape copyClone();

  /** <BR>
   *  PRE:  A valid Graphics object to paint on<BR>
   *  POST: Current object will be draw using the Graphics object<BR>
   */
  abstract public void paint(Graphics g);

  /** <BR>
   *  PRE:  A valid Point Object<BR>
   *  POST: Check to see if the point hit the shape<BR>
   */
  abstract public boolean hitTest(Point p);

  /** <BR>
   *  PRE:  A valid Point object<BR>
   *  POST: Return true if the point hit the Point Box<BR>
   */
  abstract public boolean hitTestPointBox(Point p);

  /** <BR>
   *  PRE:  A valid Point Object<BR>
   *  POST: Set the startPoint of the shape from the input<BR>
   */
  public void setStartPoint(Point p)
  {
    if(pointList.size() > 0)
    {
      Point tmp = (Point)pointList.firstElement();
      tmp.x=p.x;
      tmp.y=p.y;
    }
  }

  /** <BR>
   *  PRE:  A valid Point Object<BR>
   *  POST: Set the endPoint of the shape from the input<BR>
   */
  public void setEndPoint(Point p)
  {
    Point sp;
    if(pointList.size() > 0)
    {
      Point tmp = (Point)pointList.lastElement();
      tmp.x=p.x;
      tmp.y=p.y;
    }
  }

  /** <BR>
   *  PRE:  A valid Color Object<BR>
   *  POST: Set the color of the shape from the input<BR>
   */
  public void setColor(Color color)
  {
    this.color = color;
  }

  /** <BR>
   *  PRE:  None<BR>
   *  POST: Set the private variable bFill as the input<BR>
   */
  public void setFill(boolean b)
  {
    bFill = b;
  }

  /** <BR>
   *  PRE:  None<BR>
   *  POST: Set the shape flag to indicate whether it has been selected or not<BR>
   */
  public void setSelected(boolean b)
  {
    bSelected = b;
  }

  /** <BR>
   *  PRE:  None<BR>
   *  POST: Move the shape offset by the input x and y<BR>
   */
  public void move(int deltaX, int deltaY)
  {
    for(int i = 0; i < pointList.size(); i++)
    {
      Point tmp = (Point)pointList.elementAt(i);
      tmp.x+=deltaX;
      tmp.y+=deltaY;
    }
  }

  /** <BR>
   *  PRE:  A valid Point object<BR>
   *  POST: Add a new point to the point list.  Will create a new instance of
   *        the point<BR>
   */
  public void addPoint(Point pt)
  {
    pointList.addElement(pt.copyClone());
  }

  /** <BR>
   *  PRE:  None<BR>
   *  POST: Resize the shape by offset the reference point(s) by the input x
   *        and y<BR>
   */
  public void movePointBox(int deltaX, int deltaY)
  {
    if(xPointChange!=null)
    {
      xPointChange.x+=deltaX;
    }
    if(yPointChange!=null)
    {
      yPointChange.y+=deltaY;
    }
  }

  /** <BR>
   *  PRE:  None<BR>
   *  POST: Remove the last point from the point list (if any)<BR>
   */
  public void removeLastPoint()
  {
    if(pointList.size()>0)
    {
      pointList.removeElementAt(pointList.size()-1);
    }
  }

  /** <BR>
   *  PRE:  None<BR>
   *  POST: Return the color of the shape<BR>
   */
  public Color getColor()
  {
    return color;
  }

  /** <BR>
   *  PRE:  None<BR>
   *  POST: Return the least value for x in the point list<BR>
   */
  public int getLeastX()
  {
    int leastX=0;
   Point currentPt;
    if(pointList.size()>0)
    {
      currentPt = (Point)pointList.elementAt(0);
      leastX = currentPt.x;
    }
    for(int i = 1; i < pointList.size(); i++)
    {
      currentPt = (Point)pointList.elementAt(i);
      if(currentPt.x < leastX)
      {
        leastX = currentPt.x;
      }
    }
    return leastX;
  }

  /** <BR>
   *  PRE:  None<BR>
   *  POST: Return the least value for y in the point list<BR>
   */
  public int getLeastY()
  {
    int leastY=0;
    Point currentPt;
    if(pointList.size()>0)
    {
      currentPt = (Point)pointList.elementAt(0);
      leastY = currentPt.y;
    }
    for(int i = 1; i < pointList.size(); i++)
    {
      currentPt = (Point)pointList.elementAt(i);
      if(currentPt.y < leastY)
      {
        leastY = currentPt.y;
      }
    }
    return leastY;
  }
}
