/*
 * Created on Apr 12, 2003
 *
 * To change this generated comment go to 
 * Window>Preferences>Java>Code Generation>Code Template
 */
package jdraw.figures;

import java.awt.*;
import java.util.*;

import jdraw.framework.FigureEvent;
import jdraw.std.*;

/**
 * Rectangle implements Figures that are rectangles.
 *
 * @author  Christoph Denzler
 * @version 1.0  12.4.03
 */
public class Rectangle extends AbstractFigure {

	private java.awt.Rectangle boundingBox;
	
	public Rectangle(int x, int y, int w, int h) {
		boundingBox = new java.awt.Rectangle(x, y, w, h);
	}
	
	public Rectangle(Point origin, Point corner) {
		this(Math.min(origin.x, corner.x),
		     Math.min(origin.y, corner.y),
		     Math.abs(origin.x - corner.x),
		     Math.abs(origin.y - corner.y));
	}
	
	public Rectangle(java.awt.Rectangle r) {
		this(r.x, r.y, r.width, r.height);
	}

	/**
	 * Changes the bounds of the figure. The figure has to adjust its size
	 * and position when this method is called, and registered figure listeners
	 * have to be notified.
	 * @param origin the new origin
	 * @param corner the new corner
	 * @see #addFigureListener
	 */
	public void setBounds(Point origin, Point corner) {
		boundingBox.setBounds(Math.min(origin.x, corner.x),
													Math.min(origin.y, corner.y),
													Math.abs(origin.x - corner.x),
													Math.abs(origin.y - corner.y));
		notifyListeners(new FigureEvent(this));
	}

	/**
	 * draw is called when the figure has to be drawn.
	 * @param g Graphics object on which figure has to be drawn.
	 * @see java.awt.Graphics
	 */
	public void draw(Graphics g) {
		Color tmp = g.getColor();
		g.setColor(getColor());
		if (isFilled()) {
			g.fillRect(boundingBox.x, boundingBox.y, 
								 boundingBox.width, boundingBox.height);
		} else {
			g.drawRect(boundingBox.x, boundingBox.y, 
								 boundingBox.width, boundingBox.height);
		}
	}

	/**
	 * Moves the figure. The figure has to adjust its coordinates 
	 * when this method is called, and registered figure listeners
	 * have to be notified.
	 * @param dx move distance in x direction (argument in pixels)
	 * @param dy move distance in y direction (argument in pixels)
	 * @see #addFigureListener
	 */
	public void move(int dx, int dy) {
		boundingBox.setLocation(boundingBox.x + dx,
														boundingBox.y + dy);
		notifyListeners(new FigureEvent(this));
	}

	/**
	 * Returns the bounds of a figure. The bounds of a figure  is
	 * a rectangle which contains the figure.
	 * @return bounds of the figure
	 */
	public java.awt.Rectangle getBounds() {
		return new java.awt.Rectangle(boundingBox);
	}

	/**
	 * Tests whether the mouse coordinates are contained in the figure.
	 * contains is called when the mouse is pressed in the grafic in
	 * order to decide which figure has to be selected.
	 * Note: this default implementation may be to insensitive, as it
	 * returns true as soon as the given coordinates are contained in
	 * the bounding box. Finer grained definitions have to be
	 * implemented in extending classes.
	 * 
	 * @param x x-coordinate of mouse position
	 * @param y y-coordinate of mouse position
	 * @return <tt>true</tt>, if coordinates are contained in the figure, 
	 *         <tt>false</tt> otherwise
	 */
	public boolean contains(int x, int y) {
		java.awt.Rectangle r = boundingBox;
		
		if (isFilled()) return r.contains(x,y);
		else {
			x -= r.x;
			y -= r.y;
			
			return ((Math.abs(x) <= gravity || Math.abs(x-r.width) <= gravity) &&
							-gravity < y && y < r.height + gravity) ||
						 ((Math.abs(y) <= gravity || Math.abs(y-r.height) <= gravity) &&
						 	-gravity < x && x < r.width + gravity);
		}
	}

	/**
	 * Returns a list of 8 handles for this Rectangle
	 * @see jdraw.framework.Figure#getHandles()
	 */	
	public java.util.List getHandles() {
		java.util.List handles = new ArrayList(9);
		handles.add(new StdHandle.North(this));
		handles.add(new StdHandle.NorthWest(this));
		handles.add(new StdHandle.West(this));
		handles.add(new StdHandle.SouthWest(this));
		handles.add(new StdHandle.South(this));
		handles.add(new StdHandle.SouthEast(this));
		handles.add(new StdHandle.East(this));
		handles.add(new StdHandle.NorthEast(this));
		handles.add(new CenterMarker(this));
		return handles;
	}
	
	/**
	 * Copies the internals of Rectangle.
	 * 
	 * @see java.lang.Object#clone()
	 */
	public Object clone() {
		Rectangle copy = (Rectangle)super.clone();
		if (copy != null) {
			copy.boundingBox = new java.awt.Rectangle(boundingBox);
		}
		return copy;
	}

}
