/*
 * Created on Apr 20, 2003
 *
 * To change this generated comment go to 
 * Window>Preferences>Java>Code Generation>Code Template
 */
package jdraw.figures;

import java.awt.*;
import java.awt.geom.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.ArrayList;

import jdraw.framework.*;
import jdraw.std.*;
/**
 * @author Christoph
 */
public class Ellipse extends AbstractFigure {
	
	private transient Ellipse2D ellipse;
	
	public Ellipse(int cx, int cy, int radius) {
		ellipse = new Ellipse2D.Float(cx-radius, cy-radius, 2*radius, 2*radius);
	}

	public Ellipse(Point p1, Point p2) {
		ellipse = new Ellipse2D.Float(Math.min(p1.x, p2.x),
																  Math.min(p1.y, p2.y),
																	Math.abs(p1.x - p2.x),
																	Math.abs(p1.y - p2.y));
	}
	
	/**
	 * Tests whether the mouse coordinates are contained in the ellipse.
	 * contains is called when the mouse is pressed in the grafic in
	 * order to decide which figure has to be selected.
	 * 
	 * @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) {
		boolean result;
		if (isFilled()) {
			result = ellipse.contains(x, y);
		} else {
			Ellipse2D inner = new Ellipse2D.Double(ellipse.getX()+gravity,
																						 ellipse.getY()+gravity,
																						 ellipse.getWidth()-2*gravity,
																						 ellipse.getHeight()-2*gravity);
			Ellipse2D outer = new Ellipse2D.Double(ellipse.getX()-gravity,
																						 ellipse.getY()-gravity,
																						 ellipse.getWidth()+2*gravity,
																						 ellipse.getHeight()+2*gravity);
			result = outer.contains(x, y) && !inner.contains(x, y);
		}
		return result;
	}

	/**
	 * Setting the bounding box of an ellipse also resizes the ellipse
	 * itself.
	 * @see jdraw.framework.Figure#setBounds(Point, Point)
	 */
	public void setBounds(Point origin, Point corner) {
		ellipse.setFrame(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 Ellipse
	 * @see jdraw.framework.Figure#draw(Graphics)
	 */
	public void draw(Graphics g) {
		Color tmp = g.getColor();
		g.setColor(getColor());
		if (isFilled())
			g.fillOval((int)ellipse.getX(), (int)ellipse.getY(),
								 (int)ellipse.getWidth(), (int)ellipse.getHeight());
		else
			g.drawOval((int)ellipse.getX(), (int)ellipse.getY(),
								 (int)ellipse.getWidth(), (int)ellipse.getHeight());
		g.setColor(tmp);
	}

	/* (non-Javadoc)
	 * @see jdraw.framework.Figure#move(int, int)
	 */
	public void move(int dx, int dy) {
		ellipse.setFrame(ellipse.getX()+dx,
										 ellipse.getY()+dy,
										 ellipse.getWidth(),
										 ellipse.getHeight());
		notifyListeners(new FigureEvent(this));
	}

	/* (non-Javadoc)
	 * @see jdraw.framework.Figure#getBounds()
	 */
	public java.awt.Rectangle getBounds() {
		return new java.awt.Rectangle((int)ellipse.getX(),
																	(int)ellipse.getY(),
																	(int)ellipse.getWidth(),
																	(int)ellipse.getHeight());
	}
	
	public int getWidth() {
		return (int)ellipse.getWidth();
	}

	public int getHeight() {
		return (int)ellipse.getHeight();
	}

	/**
	 * Returns a list of 8 handles for this Ellipse
	 * @see jdraw.framework.Figure#getHandles()
	 */	
	public List getHandles() {
		List handles = new ArrayList(8);
		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() {
		Ellipse copy = (Ellipse)super.clone();
		if (copy != null) {
			copy.ellipse = (Ellipse2D)ellipse.clone();
		}
		return copy;
	}

	private void writeObject(ObjectOutputStream oos) throws IOException {
		oos.defaultWriteObject();
		oos.writeFloat((float)ellipse.getX());
		oos.writeFloat((float)ellipse.getY());
		oos.writeFloat((float)ellipse.getWidth());
		oos.writeFloat((float)ellipse.getHeight());
	}
	
	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
		ois.defaultReadObject();
		float x = ois.readFloat();
		float y = ois.readFloat();
		float w = ois.readFloat();
		float h = ois.readFloat();
		ellipse = new Ellipse2D.Float(x, y, w, h);
	}
}
