/*
 * 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.Point;
import java.awt.Rectangle;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;

import jdraw.framework.Figure;
import jdraw.framework.FigureListener;
import jdraw.framework.FigureEvent;

/**
 * Abstract class implementing some basics of figures.
 * This class can be used as convenience class for concrete Figure
 * implementations.
 *
 * @author  Christoph Denzler
 * @version 1.0  12.4.03
 */
public abstract class AbstractFigure implements Figure {
	private transient List listeners = new ArrayList();

	/**
	 * 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) {
		Rectangle r = getBounds();
		return r.contains(x, y);
	}

	/**
	 * Returns the center of a figure. The center is usually the center
	 * of its bounds rectangle. More precise definitions have to be
	 * implemented in exdending classes
	 *
	 * @return center of the figure
	 */
	public Point getCenter() {
		Rectangle r = getBounds();
		return new Point(r.x + r.width/2, r.y + r.height/2);
	}

	/**
	 * Returns a list of handles. Note this abstract default implementation
	 * does not support handles and therefore always returns null.
	 *
	 * @return null, handles are not supported
	 * @see Handle
	 */
	public List getHandles() {
		return null;
	}

	/**
	 * Tests if the figure is empty. A figure is considered to be empty
	 * if its area is smaller than 4 square pixels.
	 *
	 * @return <tt>true</tt>, if figure is "empty"
	 *         <tt>false</tt> otherwise
	 * @see DrawTool
	 */
	public boolean isEmpty() {
		Rectangle r = getBounds();
		return r.width*r.height <= 4;
	}

	/**
	 * Adds the specified figure listener to receive figure events from
	 * this figure. If listener is null, no exception is thrown and no
	 * action is performed.
	 * @param listener the figure listener.
	 * @see FigureListener
	 */
	public void addFigureListener(FigureListener listener) {
		if (listener != null) {
			this.listeners.add(listener);
		}
	}

	/**
	 * Removes the specified figure listener so that it no longer receives
	 * figure events from this figure. This method performs no function,
	 * nor does it throw an exception, if the listener specified by the
	 * argument was not previously added to this figure.
	 * If listener is null, no exception is thrown and no action is performed.
	 * @param listener the figure listener.
	 * @see FigureListener
	 */
	public void removeFigureListener(FigureListener listener) {
		this.listeners.remove(listener);
	}

	/**
	 * Notify all FigureListeners of a FigureEvent.
	 */
	protected void notifyListeners(FigureEvent fe) {
		Iterator it = listeners.iterator();
		while (it.hasNext()) {
			((FigureListener)it.next()).figureChanged(fe);
		}
	}

	/**
	 * Copies the attributes filled and color.
	 *
	 * @see java.lang.Object#clone()
	 */
	public Object clone() {
		AbstractFigure f = null;
		try {
			f = (AbstractFigure)super.clone();
		} catch (CloneNotSupportedException cnse) {
			System.out.println("CloneNotSupportedException occured");
		}
		return f;
	}

}


/*
 * Created on Apr 21, 2003
 *
 * To change this generated comment go to
 * Window>Preferences>Java>Code Generation>Code Template
 */
package jdraw.figures;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;

import jdraw.framework.*;
import jdraw.std.StdHandle;

	/**
	 * Line implements straight lines
	 *
	 * @author  Christoph Denzler
	 * @version 1.0  21.4.03
	 */
public class Line extends AbstractFigure {

	public class LineHandle extends StdHandle {
		Point otherend;
		boolean isLineBeginHandle;

		/**
		 *
		 */
		public LineHandle(Line owner, boolean isLineBegin) {
			super(owner);
			isLineBeginHandle = isLineBegin;
		}

		protected Point getAnchor(java.awt.Rectangle r) {
			return isLineBeginHandle ?
							((Line)owner).getEnd():
						  ((Line)owner).getBegin();
		}

		/* (non-Javadoc)
		 * @see jdraw.framework.Handle#getBounds()
		 */
		public java.awt.Rectangle getBounds() {
			Point b = isLineBeginHandle ?((Line)owner).getBegin():((Line)owner).getEnd();
			return new java.awt.Rectangle(b.x-WIDTH/2, b.y-HEIGHT/2, WIDTH, HEIGHT);
		}

		/* (non-Javadoc)
		 * @see jdraw.framework.Handle#getCursor()
		 */
		public Cursor getCursor() {
			return Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
		}

		/* (non-Javadoc)
		 * @see jdraw.framework.Handle#startInteraction(int, int, java.awt.event.MouseEvent, jdraw.framework.DrawView)
		 */
		public void startInteraction(int x, int y, MouseEvent e, DrawView v) {
			otherend = isLineBeginHandle ?
									((Line)owner).getEnd():
									((Line)owner).getBegin();
		}

		/* (non-Javadoc)
		 * @see jdraw.framework.Handle#dragInteraction(int, int, java.awt.event.MouseEvent, jdraw.framework.DrawView)
		 */
		public void dragInteraction(int x, int y, MouseEvent e, DrawView v) {
			owner.setBounds(otherend, e.getPoint());
		}

		/* (non-Javadoc)
		 * @see jdraw.framework.Handle#stopInteraction(int, int, java.awt.event.MouseEvent, jdraw.framework.DrawView)
		 */
		public void stopInteraction(int x, int y, MouseEvent e, DrawView v) {
			owner.setBounds(otherend, e.getPoint());
		}

	}


	private Line2D line;

	/**
	 * Create a new Line from begin to end.
	 * @param begin
	 * @param end
	 */
	public Line(Point begin, Point end) {
		line = new Line2D.Float(begin, end);
	}

	/**
	 * Create a new Line of length 0 starting
	 * at Point begin.
	 * @param begin
	 */
	public Line(Point begin) {
		line = new Line2D.Float(begin, begin);
	}

	/**
	 * Sets the bounding box. Note that the diagonal of the
	 * bounding box is the line defined by the two arguments
	 * @see jdraw.framework.Figure#setBounds(Point, Point)
	 */
	public void setBounds(Point origin, Point corner) {
		line.setLine(origin, corner);
		notifyListeners(new FigureEvent(this));
	}

	/**
	 * Draws the line
	 * @see jdraw.framework.Figure#draw(Graphics)
	 */
	public void draw(Graphics g) {
		Color tmp = g.getColor();
		g.drawLine((int)line.getX1(), (int)line.getY1(),
							 (int)line.getX2(), (int)line.getY2());
		g.setColor(tmp);
	}

	/**
	 * Tests whether the mouse coordinates are on the Line
	 *
	 * @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) {
		return line.ptLineDistSq(x, y) <= 5;
	}

	/* (non-Javadoc)
	 * @see jdraw.framework.Figure#move(int, int)
	 */
	public void move(int dx, int dy) {
		line.setLine(line.getX1()+dx, line.getY1()+dy, line.getX2()+dx, line.getY2()+dy);
		notifyListeners(new FigureEvent(this));
	}

	/* (non-Javadoc)
	 * @see jdraw.framework.Figure#getBounds()
	 */
	public java.awt.Rectangle getBounds() {
		return line.getBounds();
	}

	public Point getBegin() {
		return new Point((int)line.getX1(), (int)line.getY1());
	}

	public Point getEnd() {
		return new Point((int)line.getX2(), (int)line.getY2());
	}

	public int getLength () {
		return (int)line.getP1().distance(line.getP2());
	}
	/**
	 * Returns a list of 8 handles for this Rectangle
	 * @see jdraw.framework.Figure#getHandles()
	 */
	public List getHandles() {
		List handles = new ArrayList(2);
		handles.add(new LineHandle(this, true));
		handles.add(new LineHandle(this, false));
		return handles;
	}

	/**
	 * Copies the internals of Rectangle.
	 *
	 * @see java.lang.Object#clone()
	 */
	public Object clone() {
		return null;
	}

}


/*
 * Created on 01.06.2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package jdraw.figures;

import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;

import jdraw.framework.FigureEvent;
import jdraw.std.StdHandle;

public class Rectangle extends AbstractFigure {
	java.awt.Rectangle boundingBox;

	public Rectangle(int x, int y, int w, int h) {
		boundingBox = new java.awt.Rectangle(x, y, w, h);
	}

	/**
	 * 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) {
		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);
	}

	/**
	 * 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(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));
		return handles;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	public Object clone() {
		return null;
	}

}



/*
 * Created on Apr 28, 2003
 *
 * To change this generated comment go to
 * Window>Preferences>Java>Code Generation>Code Template
 */
package jdraw.figures;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Iterator;

import jdraw.framework.*;
import jdraw.std.StdMoveHandle;

/**
 * @author Christoph Denzler
 */
public class GroupFigure extends AbstractFigure {
	private static final int NW = 0;
	private static final int SW = 1;
	private static final int SE = 2;
	private static final int NE = 3;

	private Set figures;

	public GroupFigure(Set elements) {
		if (elements == null) elements = new HashSet();
		figures = elements;
	}

	public void setBounds(Point origin, Point corner) {
	}

	public void draw(Graphics g) {
		Iterator it = figures.iterator();
		while(it.hasNext()) {
			((Figure)it.next()).draw(g);
		}
		notifyListeners(new FigureEvent(this));
	}

	public void move(int dx, int dy) {
		Iterator it = figures.iterator();
		while(it.hasNext()) {
			((Figure)it.next()).move(dx, dy);
		}
	}

	public boolean contains(int x, int y) {
		boolean contains = false;
		Iterator it = figures.iterator();
		while(it.hasNext()) {
			contains |= ((Figure)it.next()).contains(x, y);
		}
		return contains;
	}

	public Rectangle getBounds() {
		Rectangle r = null;
		Iterator it = figures.iterator();
		if (it.hasNext()) r = ((Figure)it.next()).getBounds();
		while(it.hasNext()) {
			r.add(((Figure)it.next()).getBounds());
		}
		return r;
	}

	public List getHandles() {
		List handles = new ArrayList(4);
		handles.add(new StdMoveHandle(NW, this));
		handles.add(new StdMoveHandle(SW, this));
		handles.add(new StdMoveHandle(SE, this));
		handles.add(new StdMoveHandle(NE, this));
		return handles;
	}

	public Set unGroup() {
		Set s = figures;
		figures = null;
		return s;
	}

	/**
	 * Copies the internals of Rectangle.
	 *
	 * @see java.lang.Object#clone()
	 */
	public Object clone() {
		return null;
	}

}


/*
 * 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.Cursor;

import jdraw.framework.*;

/**
 * The AbstractTool supports:
 * - Color
 * - filled or outline mode
 * - xy constraints, i.e. the Figure can only be created with
 *   the same width and height.
 * @author Christoph
 */
public abstract class AbstractTool implements DrawTool {

	private final DrawEditor editor;
	private final DrawView view;

	public AbstractTool(DrawEditor editor) {
		this.editor = editor;
		this.view = editor.getView();
	}

	protected DrawView getView() {
		return view;
	}

	protected DrawEditor getEditor() {
		return editor;
	}

	public void deactivate() {
		getView().setCursor(Cursor.getDefaultCursor());
		getEditor().showStatus("");
	}
}


/*
 * 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.event.*;
import java.awt.*;

import jdraw.framework.*;

/**
 * This tool defines a mode for drawing rectangles.
 *
 * @see Figure
 *
 * @author  Christoph Denzler
 * @version 1.0, 12.4.03
 */
public class RectangleTool extends AbstractTool {

	private Point anchor = null;
	private jdraw.figures.Rectangle rubberband = null;

	public RectangleTool(DrawEditor e ) {
		super(e);
	}

	/**
	 * Activates the Rectangle Mode. There will be a
	 * specific menu added to the menu bar that provides settings for
	 * Rectangle attributes
	 */
	public void activate() {
		getView().setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
		getEditor().showStatus("Rectangle Mode");
	}

	/**
	 * Initializes a new Rectangle object by setting an anchor
	 * point where the mouse was pressed. A new Rectangle is then
	 * added to the model.
	 *
	 * @see jdraw.framework.DrawTool#mouseDown(int, int, MouseEvent)
	 */
	public void mouseDown(int x, int y, MouseEvent e) {
		anchor = new Point(x, y);
		rubberband = new jdraw.figures.Rectangle(x, y, 0, 0);
		getView().getModel().addFigure(rubberband);
	}

	/**
	 * During a mouse drag, the Rectangle will be resized according to
	 * the mouse position. The status bar shows the current size.
	 *
	 * @see jdraw.framework.DrawTool#mouseDrag(int, int, MouseEvent)
	 */
	public void mouseDrag(int x, int y, MouseEvent e) {
		rubberband.setBounds(anchor, new Point(x, y));
		java.awt.Rectangle r = rubberband.getBounds();
		getEditor().showStatus("w: "+ r.width + ", h: " + r.height);
	}

	/**
	 * When the user releases the mouse, the Rectangle object is
	 * updated according to the color and fill status settings.
	 *
	 * @see jdraw.framework.DrawTool#mouseUp(int, int, MouseEvent)
	 */
	public void mouseUp(int x, int y, MouseEvent e) {
		rubberband.setBounds(anchor, new Point(x, y));
		rubberband = null;
		getEditor().showStatus("");
	}

}




