/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.draw2d;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Display;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Translatable;
import org.eclipse.swt.SWT;

/**
 * The base implementation for graphical figures.
 */
public class Figure implements IFigure {

	private static final Rectangle PRIVATE_RECT = new Rectangle();
	private static final Point PRIVATE_POINT = new Point();
	private static final int FLAG_VALID = new Integer(1).intValue(),
			FLAG_OPAQUE = new Integer(1 << 1).intValue(),
			FLAG_VISIBLE = new Integer(1 << 2).intValue(),
			FLAG_FOCUSABLE = new Integer(1 << 3).intValue(),
			FLAG_ENABLED = new Integer(1 << 4).intValue(),
			FLAG_FOCUS_TRAVERSABLE = new Integer(1 << 5).intValue();

	static final int FLAG_REALIZED = 1 << 31;

	/**
	 * The largest flag defined in this class. If subclasses define flags, they
	 * should declare them as larger than this value and redefine MAX_FLAG to be
	 * their largest flag value.
	 * <P>
	 * This constant is evaluated at runtime and will not be inlined by the
	 * compiler.
	 */
	protected static int MAX_FLAG = FLAG_FOCUS_TRAVERSABLE;

	/**
	 * The rectangular area that this Figure occupies.
	 */
	protected Rectangle bounds = new Rectangle(0, 0, 0, 0);

	private LayoutManager layoutManager;

	/**
	 * The flags for this Figure.
	 */
	protected int flags = FLAG_VISIBLE | FLAG_ENABLED;

	private IFigure parent;
	private IClippingStrategy clippingStrategy = null;
	private Cursor cursor;

	private PropertyChangeSupport propertyListeners;
	private EventListenerList eventListeners = new EventListenerList();

	private List children = Collections.EMPTY_LIST;

	/**
	 * This Figure's preferred size.
	 */
	protected Dimension prefSize;

	/**
	 * This Figure's minimum size.
	 */
	protected Dimension minSize;

	/**
	 * This Figure's maximum size.
	 */
	protected Dimension maxSize;

	/**
	 * @deprecated access using {@link #getLocalFont()}
	 */
	protected Font font;

	/**
	 * @deprecated access using {@link #getLocalBackgroundColor()}.
	 */
	protected Color bgColor;

	/**
	 * @deprecated access using {@link #getLocalForegroundColor()}.
	 */
	protected Color fgColor;

	/**
	 * @deprecated access using {@link #getBorder()}
	 */
	protected Border border;

	/**
	 * @deprecated access using {@link #getToolTip()}
	 */
	protected IFigure toolTip;

	private AncestorHelper ancestorHelper;

	/**
	 * Calls {@link #add(IFigure, Object, int)} with -1 as the index.
	 * 
	 * @see IFigure#add(IFigure, Object)
	 */
	public final void add(IFigure figure, Object constraint) {
		add(figure, constraint, -1);
	}

	/**
	 * @see IFigure#add(IFigure, Object, int)
	 */
	public void add(IFigure figure, Object constraint, int index) {
		if (children == Collections.EMPTY_LIST)
			children = new ArrayList(2);
		if (index < -1 || index > children.size())
			throw new IndexOutOfBoundsException("Index does not exist"); //$NON-NLS-1$

		// Check for Cycle in hierarchy
		for (IFigure f = this; f != null; f = f.getParent())
			if (figure == f)
				throw new IllegalArgumentException(
						"Figure being added introduces cycle"); //$NON-NLS-1$

		// Detach the child from previous parent
		if (figure.getParent() != null)
			figure.getParent().remove(figure);

		if (index == -1)
			children.add(figure);
		else
			children.add(index, figure);
		figure.setParent(this);

		if (layoutManager != null)
			layoutManager.setConstraint(figure, constraint);

		revalidate();

		if (getFlag(FLAG_REALIZED))
			figure.addNotify();
		figure.repaint();
	}

	/**
	 * Calls {@link #add(IFigure, Object, int)} with <code>null</code> as the
	 * constraint and -1 as the index.
	 * 
	 * @see IFigure#add(IFigure)
	 */
	public final void add(IFigure figure) {
		add(figure, null, -1);
	}

	/**
	 * Calls {@link #add(IFigure, Object, int)} with <code>null</code> as the
	 * constraint.
	 * 
	 * @see IFigure#add(IFigure, int)
	 */
	public final void add(IFigure figure, int index) {
		add(figure, null, index);
	}

	/**
	 * @see IFigure#addAncestorListener(AncestorListener)
	 */
	public void addAncestorListener(AncestorListener ancestorListener) {
		if (ancestorHelper == null)
			ancestorHelper = new AncestorHelper(this);
		ancestorHelper.addAncestorListener(ancestorListener);
	}

	/**
	 * @see IFigure#addCoordinateListener(CoordinateListener)
	 */
	public void addCoordinateListener(CoordinateListener listener) {
		eventListeners.addListener(CoordinateListener.class, listener);
	}

	/**
	 * @see IFigure#addFigureListener(FigureListener)
	 */
	public void addFigureListener(FigureListener listener) {
		eventListeners.addListener(FigureListener.class, listener);
	}

	/**
	 * @see IFigure#addFocusListener(FocusListener)
	 */
	public void addFocusListener(FocusListener listener) {
		eventListeners.addListener(FocusListener.class, listener);
	}

	/**
	 * @see IFigure#addKeyListener(KeyListener)
	 */
	public void addKeyListener(KeyListener listener) {
		eventListeners.addListener(KeyListener.class, listener);
	}

	/**
	 * Appends the given layout listener to the list of layout listeners.
	 * 
	 * @since 3.1
	 * @param listener
	 *            the listener being added
	 */
	public void addLayoutListener(LayoutListener listener) {
		if (layoutManager instanceof LayoutNotifier) {
			LayoutNotifier notifier = (LayoutNotifier) layoutManager;
			notifier.listeners.add(listener);
		} else
			layoutManager = new LayoutNotifier(layoutManager, listener);
	}

	/**
	 * Adds a listener of type <i>clazz</i> to this Figure's list of event
	 * listeners.
	 * 
	 * @param clazz
	 *            The listener type
	 * @param listener
	 *            The listener
	 */
	protected void addListener(Class clazz, Object listener) {
		eventListeners.addListener(clazz, listener);
	}

	/**
	 * @see IFigure#addMouseListener(MouseListener)
	 */
	public void addMouseListener(MouseListener listener) {
		eventListeners.addListener(MouseListener.class, listener);
	}

	/**
	 * @see IFigure#addMouseMotionListener(MouseMotionListener)
	 */
	public void addMouseMotionListener(MouseMotionListener listener) {
		eventListeners.addListener(MouseMotionListener.class, listener);
	}

	/**
	 * Called after the receiver's parent has been set and it has been added to
	 * its parent.
	 * 
	 * @since 2.0
	 */
	public void addNotify() {
		if (getFlag(FLAG_REALIZED))
			throw new RuntimeException(
					"addNotify() should not be called multiple times"); //$NON-NLS-1$
		setFlag(FLAG_REALIZED, true);
		for (int i = 0; i < children.size(); i++)
			((IFigure) children.get(i)).addNotify();
	}

	/**
	 * @see IFigure#addPropertyChangeListener(String, PropertyChangeListener)
	 */
	public void addPropertyChangeListener(String property,
			PropertyChangeListener listener) {
		if (propertyListeners == null)
			propertyListeners = new PropertyChangeSupport(this);
		propertyListeners.addPropertyChangeListener(property, listener);
	}

	/**
	 * @see IFigure#addPropertyChangeListener(PropertyChangeListener)
	 */
	public void addPropertyChangeListener(PropertyChangeListener listener) {
		if (propertyListeners == null)
			propertyListeners = new PropertyChangeSupport(this);
		propertyListeners.addPropertyChangeListener(listener);
	}

	/**
	 * This method is final. Override {@link #containsPoint(int, int)} if
	 * needed.
	 * 
	 * @see IFigure#containsPoint(Point)
	 * @since 2.0
	 */
	public final boolean containsPoint(Point p) {
		return containsPoint(p.x, p.y);
	}

	/**
	 * @see IFigure#containsPoint(int, int)
	 */
	public boolean containsPoint(int x, int y) {
		return getBounds().contains(x, y);
	}

	/**
	 * @see IFigure#erase()
	 */
	public void erase() {
		if (getParent() == null || !isVisible())
			return;

		Rectangle r = new Rectangle(getBounds());
		getParent().translateToParent(r);
		getParent().repaint(r.x, r.y, r.width, r.height);
	}

	/**
	 * Returns a descendant of this Figure such that the Figure returned
	 * contains the point (x, y), and is accepted by the given TreeSearch.
	 * Returns <code>null</code> if none found.
	 * 
	 * @param x
	 *            The X coordinate
	 * @param y
	 *            The Y coordinate
	 * @param search
	 *            the TreeSearch
	 * @return The descendant Figure at (x,y)
	 */
	protected IFigure findDescendantAtExcluding(int x, int y, TreeSearch search) {
		PRIVATE_POINT.setLocation(x, y);
		translateFromParent(PRIVATE_POINT);
		if (!getClientArea(Rectangle.SINGLETON).contains(PRIVATE_POINT))
			return null;

		x = PRIVATE_POINT.x;
		y = PRIVATE_POINT.y;
		IFigure fig;
		for (int i = children.size(); i > 0;) {
			i--;
			fig = (IFigure) children.get(i);
			if (fig.isVisible()) {
				fig = fig.findFigureAt(x, y, search);
				if (fig != null)
					return fig;
			}
		}
		// No descendants were found
		return null;
	}

	/**
	 * @see IFigure#findFigureAt(Point)
	 */
	public final IFigure findFigureAt(Point pt) {
		return findFigureAtExcluding(pt.x, pt.y, Collections.EMPTY_LIST);
	}

	/**
	 * @see IFigure#findFigureAt(int, int)
	 */
	public final IFigure findFigureAt(int x, int y) {
		return findFigureAt(x, y, IdentitySearch.INSTANCE);
	}

	/**
	 * @see IFigure#findFigureAt(int, int, TreeSearch)
	 */
	public IFigure findFigureAt(int x, int y, TreeSearch search) {
		if (!containsPoint(x, y))
			return null;
		if (search.prune(this))
			return null;
		IFigure child = findDescendantAtExcluding(x, y, search);
		if (child != null)
			return child;
		if (search.accept(this))
			return this;
		return null;
	}

	/**
	 * @see IFigure#findFigureAtExcluding(int, int, Collection)
	 */
	public final IFigure findFigureAtExcluding(int x, int y, Collection c) {
		return findFigureAt(x, y, new ExclusionSearch(c));
	}

	/**
	 * Returns the deepest descendant for which {@link #isMouseEventTarget()}
	 * returns <code>true</code> or <code>null</code> if none found. The
	 * Parameters <i>x</i> and <i>y</i> are absolute locations. Any Graphics
	 * transformations applied by this Figure to its children during
	 * {@link #paintChildren(Graphics)} (thus causing the children to appear
	 * transformed to the user) should be applied inversely to the points
	 * <i>x</i> and <i>y</i> when called on the children.
	 * 
	 * @param x
	 *            The X coordinate
	 * @param y
	 *            The Y coordinate
	 * @return The deepest descendant for which isMouseEventTarget() returns
	 *         true
	 */
	public IFigure findMouseEventTargetAt(int x, int y) {
		if (!containsPoint(x, y))
			return null;
		IFigure f = findMouseEventTargetInDescendantsAt(x, y);
		if (f != null)
			return f;
		if (isMouseEventTarget())
			return this;
		return null;
	}

	/**
	 * Searches this Figure's children for the deepest descendant for which
	 * {@link #isMouseEventTarget()} returns <code>true</code> and returns that
	 * descendant or <code>null</code> if none found.
	 * 
	 * @see #findMouseEventTargetAt(int, int)
	 * @param x
	 *            The X coordinate
	 * @param y
	 *            The Y coordinate
	 * @return The deepest descendant for which isMouseEventTarget() returns
	 *         true
	 */
	protected IFigure findMouseEventTargetInDescendantsAt(int x, int y) {
		PRIVATE_POINT.setLocation(x, y);
		translateFromParent(PRIVATE_POINT);

		if (!getClientArea(Rectangle.SINGLETON).contains(PRIVATE_POINT))
			return null;

		IFigure fig;
		for (int i = children.size(); i > 0;) {
			i--;
			fig = (IFigure) children.get(i);
			if (fig.isVisible() && fig.isEnabled()) {
				if (fig.containsPoint(PRIVATE_POINT.x, PRIVATE_POINT.y)) {
					fig = fig.findMouseEventTargetAt(PRIVATE_POINT.x,
							PRIVATE_POINT.y);
					return fig;
				}
			}
		}
		return null;
	}

	/**
	 * Notifies to all {@link CoordinateListener}s that this figure's local
	 * coordinate system has changed in a way which affects the absolute bounds
	 * of figures contained within.
	 * 
	 * @since 3.1
	 */
	protected void fireCoordinateSystemChanged() {
		if (!eventListeners.containsListener(CoordinateListener.class))
			return;
		Iterator figureListeners = eventListeners
				.getListeners(CoordinateListener.class);
		while (figureListeners.hasNext())
			((CoordinateListener) figureListeners.next())
					.coordinateSystemChanged(this);
	}

	/**
	 * Notifies to all {@link FigureListener}s that this figure has moved. Moved
	 * means that the bounds have changed in some way, location and/or size.
	 * 
	 * @since 3.1
	 */
	protected void fireFigureMoved() {
		if (!eventListeners.containsListener(FigureListener.class))
			return;
		Iterator figureListeners = eventListeners
				.getListeners(FigureListener.class);
		while (figureListeners.hasNext())
			((FigureListener) figureListeners.next()).figureMoved(this);
	}

	/**
	 * Fires both figuremoved and coordinate system changed. This method exists
	 * for compatibility. Some listeners which used to listen for figureMoved
	 * now listen for coordinates changed. So to be sure that those new
	 * listeners are notified, any client code which used called this method
	 * will also result in notification of coordinate changes.
	 * 
	 * @since 2.0
	 * @deprecated call fireFigureMoved() or fireCoordinateSystemChanged() as
	 *             appropriate
	 */
	protected void fireMoved() {
		fireFigureMoved();
		fireCoordinateSystemChanged();
	}

	/**
	 * Notifies any {@link PropertyChangeListener PropertyChangeListeners}
	 * listening to this Figure that the boolean property with id
	 * <i>property</i> has changed.
	 * 
	 * @param property
	 *            The id of the property that changed
	 * @param old
	 *            The old value of the changed property
	 * @param current
	 *            The current value of the changed property
	 * @since 2.0
	 */
	protected void firePropertyChange(String property, boolean old,
			boolean current) {
		if (propertyListeners == null)
			return;
		propertyListeners.firePropertyChange(property, old, current);
	}

	/**
	 * Notifies any {@link PropertyChangeListener PropertyChangeListeners}
	 * listening to this figure that the Object property with id <i>property</i>
	 * has changed.
	 * 
	 * @param property
	 *            The id of the property that changed
	 * @param old
	 *            The old value of the changed property
	 * @param current
	 *            The current value of the changed property
	 * @since 2.0
	 */
	protected void firePropertyChange(String property, Object old,
			Object current) {
		if (propertyListeners == null)
			return;
		propertyListeners.firePropertyChange(property, old, current);
	}

	/**
	 * Notifies any {@link PropertyChangeListener PropertyChangeListeners}
	 * listening to this figure that the integer property with id
	 * <code>property</code> has changed.
	 * 
	 * @param property
	 *            The id of the property that changed
	 * @param old
	 *            The old value of the changed property
	 * @param current
	 *            The current value of the changed property
	 * @since 2.0
	 */
	protected void firePropertyChange(String property, int old, int current) {
		if (propertyListeners == null)
			return;
		propertyListeners.firePropertyChange(property, old, current);
	}

	/**
	 * Returns this Figure's background color. If this Figure's background color
	 * is <code>null</code> and its parent is not <code>null</code>, the
	 * background color is inherited from the parent.
	 * 
	 * @see IFigure#getBackgroundColor()
	 */
	public Color getBackgroundColor() {
		if (bgColor == null && getParent() != null)
			return getParent().getBackgroundColor();
		return bgColor;
	}

	/**
	 * @see IFigure#getBorder()
	 */
	public Border getBorder() {
		return border;
	}

	/**
	 * Returns the smallest rectangle completely enclosing the figure.
	 * Implementors may return the Rectangle by reference. For this reason,
	 * callers of this method must not modify the returned Rectangle.
	 * 
	 * @return The bounds of this Figure
	 */
	public Rectangle getBounds() {
		return bounds;
	}

	/**
	 * @see IFigure#getChildren()
	 */
	public List getChildren() {
		return children;
	}

	/**
	 * @see IFigure#getClientArea(Rectangle)
	 */
	public Rectangle getClientArea(Rectangle rect) {
		rect.setBounds(getBounds());
		rect.crop(getInsets());
		if (useLocalCoordinates())
			rect.setLocation(0, 0);
		return rect;
	}

	/**
	 * @see IFigure#getClientArea()
	 */
	public final Rectangle getClientArea() {
		return getClientArea(new Rectangle());
	}

	/**
	 * Returns the IClippingStrategy used by this figure to clip its children
	 * 
	 * @return the IClipppingStrategy used to clip this figure's children.
	 * @since 3.6
	 */
	public IClippingStrategy getClippingStrategy() {
		return clippingStrategy;
	}

	/**
	 * @see IFigure#getCursor()
	 */
	public Cursor getCursor() {
		if (cursor == null && getParent() != null)
			return getParent().getCursor();
		return cursor;
	}

	/**
	 * Returns the value of the given flag.
	 * 
	 * @param flag
	 *            The flag to get
	 * @return The value of the given flag
	 */
	protected boolean getFlag(int flag) {
		return (flags & flag) != 0;
	}

	/**
	 * @see IFigure#getFont()
	 */
	public Font getFont() {
		if (font != null)
			return font;
		if (getParent() != null)
			return getParent().getFont();
		return null;
	}

	/**
	 * @see IFigure#getForegroundColor()
	 */
	public Color getForegroundColor() {
		if (fgColor == null && getParent() != null)
			return getParent().getForegroundColor();
		return fgColor;
	}

	/**
	 * Returns the border's Insets if the border is set. Otherwise returns
	 * NO_INSETS, an instance of Insets with all 0s. Returns Insets by
	 * reference. DO NOT Modify returned value. Cannot return null.
	 * 
	 * @return This Figure's Insets
	 */
	public Insets getInsets() {
		if (getBorder() != null)
			return getBorder().getInsets(this);
		return NO_INSETS;
	}

	/**
	 * @see IFigure#getLayoutManager()
	 */
	public LayoutManager getLayoutManager() {
		if (layoutManager instanceof LayoutNotifier)
			return ((LayoutNotifier) layoutManager).realLayout;
		return layoutManager;
	}

	/**
	 * Returns an Iterator over the listeners of type <i>clazz</i> that are
	 * listening to this Figure. If there are no listeners of type <i>clazz</i>,
	 * an empty iterator is returned.
	 * 
	 * @param clazz
	 *            The type of listeners to get
	 * @return An Iterator over the requested listeners
	 * @since 2.0
	 */
	protected Iterator getListeners(Class clazz) {
		if (eventListeners == null)
			return Collections.EMPTY_LIST.iterator();
		return eventListeners.getListeners(clazz);
	}

	/**
	 * Returns <code>null</code> or the local background Color of this Figure.
	 * Does not inherit this Color from the parent.
	 * 
	 * @return bgColor <code>null</code> or the local background Color
	 */
	public Color getLocalBackgroundColor() {
		return bgColor;
	}

	/**
	 * Returns <code>null</code> or the local font setting for this figure. Does
	 * not return values inherited from the parent figure.
	 * 
	 * @return <code>null</code> or the local font
	 * @since 3.1
	 */
	protected Font getLocalFont() {
		return font;
	}

	/**
	 * Returns <code>null</code> or the local foreground Color of this Figure.
	 * Does not inherit this Color from the parent.
	 * 
	 * @return fgColor <code>null</code> or the local foreground Color
	 */
	public Color getLocalForegroundColor() {
		return fgColor;
	}

	/**
	 * Returns the top-left corner of this Figure's bounds.
	 * 
	 * @return The top-left corner of this Figure's bounds
	 * @since 2.0
	 */
	public final Point getLocation() {
		return getBounds().getLocation();
	}

	/**
	 * @see IFigure#getMaximumSize()
	 */
	public Dimension getMaximumSize() {
		if (maxSize != null)
			return maxSize;
		return MAX_DIMENSION;
	}

	/**
	 * @see IFigure#getMinimumSize()
	 */
	public final Dimension getMinimumSize() {
		return getMinimumSize(-1, -1);
	}

	/**
	 * @see IFigure#getMinimumSize(int, int)
	 */
	public Dimension getMinimumSize(int wHint, int hHint) {
		if (minSize != null)
			return minSize;
		if (getLayoutManager() != null) {
			Dimension d = getLayoutManager().getMinimumSize(this, wHint, hHint);
			if (d != null)
				return d;
		}
		return getPreferredSize(wHint, hHint);
	}

	/**
	 * @see IFigure#getParent()
	 */
	public IFigure getParent() {
		return parent;
	}

	/**
	 * @see IFigure#getPreferredSize()
	 */
	public final Dimension getPreferredSize() {
		return getPreferredSize(-1, -1);
	}

	/**
	 * @see IFigure#getPreferredSize(int, int)
	 */
	public Dimension getPreferredSize(int wHint, int hHint) {
		if (prefSize != null)
			return prefSize;
		if (getLayoutManager() != null) {
			Dimension d = getLayoutManager().getPreferredSize(this, wHint,
					hHint);
			if (d != null)
				return d;
		}
		return getSize();
	}

	/**
	 * @see IFigure#getSize()
	 */
	public final Dimension getSize() {
		return getBounds().getSize();
	}

	/**
	 * @see IFigure#getToolTip()
	 */
	public IFigure getToolTip() {
		return toolTip;
	}

	/**
	 * @see IFigure#getUpdateManager()
	 */
	public UpdateManager getUpdateManager() {
		if (getParent() != null)
			return getParent().getUpdateManager();
		// Only happens when the figure has not been realized
		return NO_MANAGER;
	}

	/**
	 * @see IFigure#handleFocusGained(FocusEvent)
	 */
	public void handleFocusGained(FocusEvent event) {
		Iterator iter = eventListeners.getListeners(FocusListener.class);
		while (iter.hasNext())
			((FocusListener) iter.next()).focusGained(event);
	}

	/**
	 * @see IFigure#handleFocusLost(FocusEvent)
	 */
	public void handleFocusLost(FocusEvent event) {
		Iterator iter = eventListeners.getListeners(FocusListener.class);
		while (iter.hasNext())
			((FocusListener) iter.next()).focusLost(event);
	}

	/**
	 * @see IFigure#handleKeyPressed(KeyEvent)
	 */
	public void handleKeyPressed(KeyEvent event) {
		Iterator iter = eventListeners.getListeners(KeyListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((KeyListener) iter.next()).keyPressed(event);
	}

	/**
	 * @see IFigure#handleKeyReleased(KeyEvent)
	 */
	public void handleKeyReleased(KeyEvent event) {
		Iterator iter = eventListeners.getListeners(KeyListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((KeyListener) iter.next()).keyReleased(event);
	}

	/**
	 * @see IFigure#handleMouseDoubleClicked(MouseEvent)
	 */
	public void handleMouseDoubleClicked(MouseEvent event) {
		Iterator iter = eventListeners.getListeners(MouseListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((MouseListener) iter.next()).mouseDoubleClicked(event);
	}

	/**
	 * @see IFigure#handleMouseDragged(MouseEvent)
	 */
	public void handleMouseDragged(MouseEvent event) {
		Iterator iter = eventListeners.getListeners(MouseMotionListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((MouseMotionListener) iter.next()).mouseDragged(event);
	}

	/**
	 * @see IFigure#handleMouseEntered(MouseEvent)
	 */
	public void handleMouseEntered(MouseEvent event) {
		Iterator iter = eventListeners.getListeners(MouseMotionListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((MouseMotionListener) iter.next()).mouseEntered(event);
	}

	/**
	 * @see IFigure#handleMouseExited(MouseEvent)
	 */
	public void handleMouseExited(MouseEvent event) {
		Iterator iter = eventListeners.getListeners(MouseMotionListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((MouseMotionListener) iter.next()).mouseExited(event);
	}

	/**
	 * @see IFigure#handleMouseHover(MouseEvent)
	 */
	public void handleMouseHover(MouseEvent event) {
		Iterator iter = eventListeners.getListeners(MouseMotionListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((MouseMotionListener) iter.next()).mouseHover(event);
	}

	/**
	 * @see IFigure#handleMouseMoved(MouseEvent)
	 */
	public void handleMouseMoved(MouseEvent event) {
		Iterator iter = eventListeners.getListeners(MouseMotionListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((MouseMotionListener) iter.next()).mouseMoved(event);
	}

	/**
	 * @see IFigure#handleMousePressed(MouseEvent)
	 */
	public void handleMousePressed(MouseEvent event) {
		Iterator iter = eventListeners.getListeners(MouseListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((MouseListener) iter.next()).mousePressed(event);
	}

	/**
	 * @see IFigure#handleMouseReleased(MouseEvent)
	 */
	public void handleMouseReleased(MouseEvent event) {
		Iterator iter = eventListeners.getListeners(MouseListener.class);
		while (!event.isConsumed() && iter.hasNext())
			((MouseListener) iter.next()).mouseReleased(event);
	}

	/**
	 * @see IFigure#hasFocus()
	 */
	public boolean hasFocus() {
		EventDispatcher dispatcher = internalGetEventDispatcher();
		if (dispatcher == null)
			return false;
		return dispatcher.getFocusOwner() == this;
	}

	/**
	 * @see IFigure#internalGetEventDispatcher()
	 */
	public EventDispatcher internalGetEventDispatcher() {
		if (getParent() != null)
			return getParent().internalGetEventDispatcher();
		return null;
	}

	/**
	 * @see IFigure#intersects(Rectangle)
	 */
	public boolean intersects(Rectangle rect) {
		return getBounds().intersects(rect);
	}

	/**
	 * @see IFigure#invalidate()
	 */
	public void invalidate() {
		if (layoutManager != null)
			layoutManager.invalidate();
		setValid(false);
	}

	/**
	 * @see IFigure#invalidateTree()
	 */
	public void invalidateTree() {
		invalidate();
		for (Iterator iter = children.iterator(); iter.hasNext();) {
			IFigure child = (IFigure) iter.next();
			child.invalidateTree();
		}
	}

	/**
	 * @see IFigure#isCoordinateSystem()
	 */
	public boolean isCoordinateSystem() {
		return useLocalCoordinates();
	}

	/**
	 * @see IFigure#isEnabled()
	 */
	public boolean isEnabled() {
		return (flags & FLAG_ENABLED) != 0;
	}

	/**
	 * @see IFigure#isFocusTraversable()
	 */
	public boolean isFocusTraversable() {
		return (flags & FLAG_FOCUS_TRAVERSABLE) != 0;
	}

	/**
	 * Returns <code>true</code> if this Figure can receive {@link MouseEvent
	 * MouseEvents}.
	 * 
	 * @return <code>true</code> if this Figure can receive {@link MouseEvent
	 *         MouseEvents}
	 * @since 2.0
	 */
	protected boolean isMouseEventTarget() {
		return (eventListeners.containsListener(MouseListener.class) || eventListeners
				.containsListener(MouseMotionListener.class));
	}

	/**
	 * @see org.eclipse.draw2d.IFigure#isMirrored()
	 */
	public boolean isMirrored() {
		if (getParent() != null)
			return getParent().isMirrored();
		return false;
	}

	/**
	 * @see IFigure#isOpaque()
	 */
	public boolean isOpaque() {
		return (flags & FLAG_OPAQUE) != 0;
	}

	/**
	 * @see IFigure#isRequestFocusEnabled()
	 */
	public boolean isRequestFocusEnabled() {
		return (flags & FLAG_FOCUSABLE) != 0;
	}

	/**
	 * @see IFigure#isShowing()
	 */
	public boolean isShowing() {
		return isVisible() && (getParent() == null || getParent().isShowing());
	}

	/**
	 * Returns <code>true</code> if this Figure is valid.
	 * 
	 * @return <code>true</code> if this Figure is valid
	 * @since 2.0
	 */
	protected boolean isValid() {
		return (flags & FLAG_VALID) != 0;
	}

	/**
	 * Returns <code>true</code> if revalidating this Figure does not require
	 * revalidating its parent.
	 * 
	 * @return <code>true</code> if revalidating this Figure doesn't require
	 *         revalidating its parent.
	 * @since 2.0
	 */
	protected boolean isValidationRoot() {
		return false;
	}

	/**
	 * @see IFigure#isVisible()
	 */
	public boolean isVisible() {
		return getFlag(FLAG_VISIBLE);
	}

	/**
	 * Lays out this Figure using its {@link LayoutManager}.
	 * 
	 * @since 2.0
	 */
	protected void layout() {
		if (layoutManager != null)
			layoutManager.layout(this);
	}

	/**
	 * Paints this Figure and its children.
	 * 
	 * @param graphics
	 *            The Graphics object used for painting
	 * @see #paintFigure(Graphics)
	 * @see #paintClientArea(Graphics)
	 * @see #paintBorder(Graphics)
	 */
	public void paint(Graphics graphics) {
		if (getLocalBackgroundColor() != null)
			graphics.setBackgroundColor(getLocalBackgroundColor());
		if (getLocalForegroundColor() != null)
			graphics.setForegroundColor(getLocalForegroundColor());
		if (font != null)
			graphics.setFont(font);

		graphics.pushState();
		try {
			paintFigure(graphics);
			graphics.restoreState();
			paintClientArea(graphics);
			paintBorder(graphics);
		} finally {
			graphics.popState();
		}
	}

	/**
	 * Paints the border associated with this Figure, if one exists.
	 * 
	 * @param graphics
	 *            The Graphics used to paint
	 * @see Border#paint(IFigure, Graphics, Insets)
	 * @since 2.0
	 */
	protected void paintBorder(Graphics graphics) {
		if (getBorder() != null)
			getBorder().paint(this, graphics, NO_INSETS);
	}

	/**
	 * Paints this Figure's children. The caller must save the state of the
	 * graphics prior to calling this method, such that
	 * <code>graphics.restoreState()</code> may be called safely, and doing so
	 * will return the graphics to its original state when the method was
	 * entered.
	 * <P>
	 * This method must leave the Graphics in its original state upon return.
	 * 
	 * @param graphics
	 *            the graphics used to paint
	 * @since 2.0
	 */
	protected void paintChildren(Graphics graphics) {
		for (int i = 0; i < children.size(); i++) {
			IFigure child = (IFigure) children.get(i);
			if (child.isVisible()) {
				// determine clipping areas for child
				Rectangle[] clipping = null;
				if (clippingStrategy != null) {
					clipping = clippingStrategy.getClip(child);
				} else {
					// default clipping behaviour is to clip at bounds
					clipping = new Rectangle[] { child.getBounds() };
				}
				// child may now paint inside the clipping areas
				for (int j = 0; j < clipping.length; j++) {
					if (clipping[j].intersects(graphics
							.getClip(Rectangle.SINGLETON))) {
						graphics.clipRect(clipping[j]);
						child.paint(graphics);
						graphics.restoreState();
					}
				}
			}
		}
	}

	/**
	 * Paints this Figure's client area. The client area is typically defined as
	 * the anything inside the Figure's {@link Border} or {@link Insets}, and by
	 * default includes the children of this Figure. On return, this method must
	 * leave the given Graphics in its initial state.
	 * 
	 * @param graphics
	 *            The Graphics used to paint
	 * @since 2.0
	 */
	protected void paintClientArea(Graphics graphics) {
		if (children.isEmpty())
			return;

		boolean optimizeClip = getBorder() == null || getBorder().isOpaque();

		if (useLocalCoordinates()) {
			graphics.translate(getBounds().x + getInsets().left, getBounds().y
					+ getInsets().top);
			if (!optimizeClip)
				graphics.clipRect(getClientArea(PRIVATE_RECT));
			graphics.pushState();
			paintChildren(graphics);
			graphics.popState();
			graphics.restoreState();
		} else {
			if (optimizeClip)
				paintChildren(graphics);
			else {
				graphics.clipRect(getClientArea(PRIVATE_RECT));
				graphics.pushState();
				paintChildren(graphics);
				graphics.popState();
				graphics.restoreState();
			}
		}
	}

	/**
	 * Paints this Figure's primary representation, or background. Changes made
	 * to the graphics to the graphics current state will not affect the
	 * subsequent calls to {@link #paintClientArea(Graphics)} and
	 * {@link #paintBorder(Graphics)}. Furthermore, it is safe to call
	 * <code>graphics.restoreState()</code> within this method, and doing so
	 * will restore the graphics to its original state upon entry.
	 * 
	 * @param graphics
	 *            The Graphics used to paint
	 * @since 2.0
	 */
	protected void paintFigure(Graphics graphics) {
		if (isOpaque())
			graphics.fillRectangle(getBounds());
		if (getBorder() instanceof AbstractBackground)
			((AbstractBackground) getBorder()).paintBackground(this, graphics,
					NO_INSETS);
	}

	/**
	 * Translates this Figure's bounds, without firing a move.
	 * 
	 * @param dx
	 *            The amount to translate horizontally
	 * @param dy
	 *            The amount to translate vertically
	 * @see #translate(int, int)
	 * @since 2.0
	 */
	protected void primTranslate(int dx, int dy) {
		bounds.x += dx;
		bounds.y += dy;
		if (useLocalCoordinates()) {
			fireCoordinateSystemChanged();
			return;
		}
		for (int i = 0; i < children.size(); i++)
			((IFigure) children.get(i)).translate(dx, dy);
	}

	/**
	 * Removes the given child Figure from this Figure's hierarchy and
	 * revalidates this Figure. The child Figure's {@link #removeNotify()}
	 * method is also called.
	 * 
	 * @param figure
	 *            The Figure to remove
	 */
	public void remove(IFigure figure) {
		if ((figure.getParent() != this))
			throw new IllegalArgumentException("Figure is not a child"); //$NON-NLS-1$
		if (getFlag(FLAG_REALIZED))
			figure.removeNotify();
		if (layoutManager != null)
			layoutManager.remove(figure);
		// The updates in the UpdateManager *have* to be
		// done asynchronously, else will result in
		// incorrect dirty region corrections.
		figure.erase();
		figure.setParent(null);
		children.remove(figure);
		revalidate();
	}

	/**
	 * Removes all children from this Figure.
	 * 
	 * @see #remove(IFigure)
	 * @since 2.0
	 */
	public void removeAll() {
		List list = new ArrayList(getChildren());
		for (int i = 0; i < list.size(); i++) {
			remove((IFigure) list.get(i));
		}
	}

	/**
	 * @see IFigure#removeAncestorListener(AncestorListener)
	 */
	public void removeAncestorListener(AncestorListener listener) {
		if (ancestorHelper != null) {
			ancestorHelper.removeAncestorListener(listener);
			if (ancestorHelper.isEmpty()) {
				ancestorHelper.dispose();
				ancestorHelper = null;
			}
		}
	}

	/**
	 * @see IFigure#removeCoordinateListener(CoordinateListener)
	 */
	public void removeCoordinateListener(CoordinateListener listener) {
		eventListeners.removeListener(CoordinateListener.class, listener);
	}

	/**
	 * @see IFigure#removeFigureListener(FigureListener)
	 */
	public void removeFigureListener(FigureListener listener) {
		eventListeners.removeListener(FigureListener.class, listener);
	}

	/**
	 * @see IFigure#removeFocusListener(FocusListener)
	 */
	public void removeFocusListener(FocusListener listener) {
		eventListeners.removeListener(FocusListener.class, listener);
	}

	/**
	 * @see IFigure#removeKeyListener(KeyListener)
	 */
	public void removeKeyListener(KeyListener listener) {
		eventListeners.removeListener(KeyListener.class, listener);
	}

	/**
	 * Removes the first occurence of the given listener.
	 * 
	 * @since 3.1
	 * @param listener
	 *            the listener being removed
	 */
	public void removeLayoutListener(LayoutListener listener) {
		if (layoutManager instanceof LayoutNotifier) {
			LayoutNotifier notifier = (LayoutNotifier) layoutManager;
			notifier.listeners.remove(listener);
			if (notifier.listeners.isEmpty())
				layoutManager = notifier.realLayout;
		}
	}

	/**
	 * Removes <i>listener</i> of type <i>clazz</i> from this Figure's list of
	 * listeners.
	 * 
	 * @param clazz
	 *            The type of listener
	 * @param listener
	 *            The listener to remove
	 * @since 2.0
	 */
	protected void removeListener(Class clazz, Object listener) {
		if (eventListeners == null)
			return;
		eventListeners.removeListener(clazz, listener);
	}

	/**
	 * @see IFigure#removeMouseListener(MouseListener)
	 */
	public void removeMouseListener(MouseListener listener) {
		eventListeners.removeListener(MouseListener.class, listener);
	}

	/**
	 * @see IFigure#removeMouseMotionListener(MouseMotionListener)
	 */
	public void removeMouseMotionListener(MouseMotionListener listener) {
		eventListeners.removeListener(MouseMotionListener.class, listener);
	}

	/**
	 * Called prior to this figure's removal from its parent
	 */
	public void removeNotify() {
		for (int i = 0; i < children.size(); i++)
			((IFigure) children.get(i)).removeNotify();
		if (internalGetEventDispatcher() != null)
			internalGetEventDispatcher().requestRemoveFocus(this);
		setFlag(FLAG_REALIZED, false);
	}

	/**
	 * @see IFigure#removePropertyChangeListener(PropertyChangeListener)
	 */
	public void removePropertyChangeListener(PropertyChangeListener listener) {
		if (propertyListeners == null)
			return;
		propertyListeners.removePropertyChangeListener(listener);
	}

	/**
	 * @see IFigure#removePropertyChangeListener(String, PropertyChangeListener)
	 */
	public void removePropertyChangeListener(String property,
			PropertyChangeListener listener) {
		if (propertyListeners == null)
			return;
		propertyListeners.removePropertyChangeListener(property, listener);
	}

	/**
	 * @see IFigure#repaint(Rectangle)
	 */
	public final void repaint(Rectangle rect) {
		repaint(rect.x, rect.y, rect.width, rect.height);
	}

	/**
	 * @see IFigure#repaint(int, int, int, int)
	 */
	public void repaint(int x, int y, int w, int h) {
		if (isVisible())
			getUpdateManager().addDirtyRegion(this, x, y, w, h);
	}

	/**
	 * @see IFigure#repaint()
	 */
	public void repaint() {
		repaint(getBounds());
	}

	/**
	 * @see IFigure#requestFocus()
	 */
	public final void requestFocus() {
		if (!isRequestFocusEnabled() || hasFocus())
			return;
		EventDispatcher dispatcher = internalGetEventDispatcher();
		if (dispatcher == null)
			return;
		dispatcher.requestFocus(this);
	}

	/**
	 * @see IFigure#revalidate()
	 */
	public void revalidate() {
		invalidate();
		if (getParent() == null || isValidationRoot())
			getUpdateManager().addInvalidFigure(this);
		else
			getParent().revalidate();
	}

	/**
	 * @see IFigure#setBackgroundColor(Color)
	 */
	public void setBackgroundColor(Color bg) {
		// Set background color to bg unless in high contrast mode.
		// In that case, get the color from system
		if (bgColor != null && bgColor.equals(bg))
			return;
		Display display = Display.getCurrent();
		if (display == null) {
			display = Display.getDefault();
		}
		Color highContrastClr = null;
		try {
			if (display.getHighContrast()) {
				highContrastClr = display
						.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
			}
		} catch (SWTException e) {
			highContrastClr = null;
		}
		bgColor = highContrastClr == null ? bg : highContrastClr;
		repaint();
	}

	/**
	 * @see IFigure#setBorder(Border)
	 */
	public void setBorder(Border border) {
		this.border = border;
		revalidate();
		repaint();
	}

	/**
	 * Sets the bounds of this Figure to the Rectangle <i>rect</i>. Note that
	 * <i>rect</i> is compared to the Figure's current bounds to determine what
	 * needs to be repainted and/or exposed and if validation is required. Since
	 * {@link #getBounds()} may return the current bounds by reference, it is
	 * not safe to modify that Rectangle and then call setBounds() after making
	 * modifications. The figure would assume that the bounds are unchanged, and
	 * no layout or paint would occur. For proper behavior, always use a copy.
	 * 
	 * @param rect
	 *            The new bounds
	 * @since 2.0
	 */
	public void setBounds(Rectangle rect) {
		int x = bounds.x, y = bounds.y;

		boolean resize = (rect.width != bounds.width)
				|| (rect.height != bounds.height), translate = (rect.x != x)
				|| (rect.y != y);

		if ((resize || translate) && isVisible())
			erase();
		if (translate) {
			int dx = rect.x - x;
			int dy = rect.y - y;
			primTranslate(dx, dy);
		}

		bounds.width = rect.width;
		bounds.height = rect.height;

		if (translate || resize) {
			if (resize)
				invalidate();
			fireFigureMoved();
			repaint();
		}
	}

	/**
	 * Sets the direction of any {@link Orientable} children. Allowable values
	 * for <code>dir</code> are found in {@link PositionConstants}.
	 * 
	 * @param direction
	 *            The direction
	 * @see Orientable#setDirection(int)
	 * @since 2.0
	 */
	protected void setChildrenDirection(int direction) {
		FigureIterator iterator = new FigureIterator(this);
		IFigure child;
		while (iterator.hasNext()) {
			child = iterator.nextFigure();
			if (child instanceof Orientable)
				((Orientable) child).setDirection(direction);
		}
	}

	/**
	 * Sets all childrens' enabled property to <i>value</i>.
	 * 
	 * @param value
	 *            The enable value
	 * @see #setEnabled(boolean)
	 * @since 2.0
	 */
	protected void setChildrenEnabled(boolean value) {
		FigureIterator iterator = new FigureIterator(this);
		while (iterator.hasNext())
			iterator.nextFigure().setEnabled(value);
	}

	/**
	 * Sets the orientation of any {@link Orientable} children. Allowable values
	 * for <i>orientation</i> are found in {@link PositionConstants}.
	 * 
	 * @param orientation
	 *            The Orientation
	 * @see Orientable#setOrientation(int)
	 * @since 2.0
	 */
	protected void setChildrenOrientation(int orientation) {
		FigureIterator iterator = new FigureIterator(this);
		IFigure child;
		while (iterator.hasNext()) {
			child = iterator.nextFigure();
			if (child instanceof Orientable)
				((Orientable) child).setOrientation(orientation);
		}
	}

	/**
	 * @see IFigure#setConstraint(IFigure, Object)
	 */
	public void setConstraint(IFigure child, Object constraint) {
		if (child.getParent() != this)
			throw new IllegalArgumentException("Figure must be a child"); //$NON-NLS-1$

		if (layoutManager != null)
			layoutManager.setConstraint(child, constraint);
		revalidate();
	}

	/**
	 * Registers a clipping strategy to specify how clipping is performed for
	 * child figures.
	 * 
	 * @param clippingStrategy
	 * @since 3.6
	 */
	public void setClippingStrategy(IClippingStrategy clippingStrategy) {
		this.clippingStrategy = clippingStrategy;
	}

	/**
	 * @see IFigure#setCursor(Cursor)
	 */
	public void setCursor(Cursor cursor) {
		if (this.cursor == cursor)
			return;
		this.cursor = cursor;
		EventDispatcher dispatcher = internalGetEventDispatcher();
		if (dispatcher != null)
			dispatcher.updateCursor();
	}

	/**
	 * @see IFigure#setEnabled(boolean)
	 */
	public void setEnabled(boolean value) {
		if (isEnabled() == value)
			return;
		setFlag(FLAG_ENABLED, value);
	}

	/**
	 * Sets the given flag to the given value.
	 * 
	 * @param flag
	 *            The flag to set
	 * @param value
	 *            The value
	 * @since 2.0
	 */
	protected final void setFlag(int flag, boolean value) {
		if (value)
			flags |= flag;
		else
			flags &= ~flag;
	}

	/**
	 * @see IFigure#setFocusTraversable(boolean)
	 */
	public void setFocusTraversable(boolean focusTraversable) {
		if (isFocusTraversable() == focusTraversable)
			return;
		setFlag(FLAG_FOCUS_TRAVERSABLE, focusTraversable);
	}

	/**
	 * @see IFigure#setFont(Font)
	 */
	public void setFont(Font f) {
		if (font != f) {
			font = f;
			revalidate();
			repaint();
		}
	}

	/**
	 * @see IFigure#setForegroundColor(Color)
	 */
	public void setForegroundColor(Color fg) {
		// Set foreground color to fg unless in high contrast mode.
		// In that case, get the color from system
		if (fgColor != null && fgColor.equals(fg))
			return;
		Display display = Display.getCurrent();
		if (display == null) {
			display = Display.getDefault();
		}
		Color highContrastClr = null;
		try {
			if (display.getHighContrast()) {
				highContrastClr = display
						.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
			}
		} catch (SWTException e) {
			highContrastClr = null;
		}
		fgColor = highContrastClr == null ? fg : highContrastClr;
		repaint();
	}

	/**
	 * @see IFigure#setLayoutManager(LayoutManager)
	 */
	public void setLayoutManager(LayoutManager manager) {
		if (layoutManager instanceof LayoutNotifier)
			((LayoutNotifier) layoutManager).realLayout = manager;
		else
			layoutManager = manager;
		revalidate();
	}

	/**
	 * @see IFigure#setLocation(Point)
	 */
	public void setLocation(Point p) {
		if (getLocation().equals(p))
			return;
		Rectangle r = new Rectangle(getBounds());
		r.setLocation(p);
		setBounds(r);
	}

	/**
	 * @see IFigure#setMaximumSize(Dimension)
	 */
	public void setMaximumSize(Dimension d) {
		if (maxSize != null && maxSize.equals(d))
			return;
		maxSize = d;
		revalidate();
	}

	/**
	 * @see IFigure#setMinimumSize(Dimension)
	 */
	public void setMinimumSize(Dimension d) {
		if (minSize != null && minSize.equals(d))
			return;
		minSize = d;
		revalidate();
	}

	/**
	 * @see IFigure#setOpaque(boolean)
	 */
	public void setOpaque(boolean opaque) {
		if (isOpaque() == opaque)
			return;
		setFlag(FLAG_OPAQUE, opaque);
		repaint();
	}

	/**
	 * @see IFigure#setParent(IFigure)
	 */
	public void setParent(IFigure p) {
		IFigure oldParent = parent;
		parent = p;
		firePropertyChange("parent", oldParent, p);//$NON-NLS-1$
	}

	/**
	 * @see IFigure#setPreferredSize(Dimension)
	 */
	public void setPreferredSize(Dimension size) {
		if (prefSize != null && prefSize.equals(size))
			return;
		prefSize = size;
		revalidate();
	}

	/**
	 * Sets the preferred size of this figure.
	 * 
	 * @param w
	 *            The new preferred width
	 * @param h
	 *            The new preferred height
	 * @see #setPreferredSize(Dimension)
	 * @since 2.0
	 */
	public final void setPreferredSize(int w, int h) {
		setPreferredSize(new Dimension(w, h));
	}

	/**
	 * @see IFigure#setRequestFocusEnabled(boolean)
	 */
	public void setRequestFocusEnabled(boolean requestFocusEnabled) {
		if (isRequestFocusEnabled() == requestFocusEnabled)
			return;
		setFlag(FLAG_FOCUSABLE, requestFocusEnabled);
	}

	/**
	 * @see IFigure#setSize(Dimension)
	 */
	public final void setSize(Dimension d) {
		setSize(d.width, d.height);
	}

	/**
	 * @see IFigure#setSize(int, int)
	 */
	public void setSize(int w, int h) {
		Rectangle bounds = getBounds();
		if (bounds.width == w && bounds.height == h)
			return;
		Rectangle r = new Rectangle(getBounds());
		r.setSize(w, h);
		setBounds(r);
	}

	/**
	 * @see IFigure#setToolTip(IFigure)
	 */
	public void setToolTip(IFigure f) {
		if (toolTip == f)
			return;
		toolTip = f;
	}

	/**
	 * Sets this figure to be valid if <i>value</i> is <code>true</code> and
	 * invalid otherwise.
	 * 
	 * @param value
	 *            The valid value
	 * @since 2.0
	 */
	public void setValid(boolean value) {
		setFlag(FLAG_VALID, value);
	}

	/**
	 * @see IFigure#setVisible(boolean)
	 */
	public void setVisible(boolean visible) {
		boolean currentVisibility = isVisible();
		if (visible == currentVisibility)
			return;
		if (currentVisibility)
			erase();
		setFlag(FLAG_VISIBLE, visible);
		if (visible)
			repaint();
		revalidate();
	}

	/**
	 * @see IFigure#translate(int, int)
	 */
	public final void translate(int x, int y) {
		primTranslate(x, y);
		fireFigureMoved();
	}

	/**
	 * @see IFigure#translateFromParent(Translatable)
	 */
	public void translateFromParent(Translatable t) {
		if (useLocalCoordinates())
			t.performTranslate(-getBounds().x - getInsets().left,
					-getBounds().y - getInsets().top);
	}

	/**
	 * @see IFigure#translateToAbsolute(Translatable)
	 */
	public final void translateToAbsolute(Translatable t) {
		if (getParent() != null) {
			getParent().translateToParent(t);
			getParent().translateToAbsolute(t);
		}
	}

	/**
	 * @see IFigure#translateToParent(Translatable)
	 */
	public void translateToParent(Translatable t) {
		if (useLocalCoordinates())
			t.performTranslate(getBounds().x + getInsets().left, getBounds().y
					+ getInsets().top);
	}

	/**
	 * @see IFigure#translateToRelative(Translatable)
	 */
	public final void translateToRelative(Translatable t) {
		if (getParent() != null) {
			getParent().translateToRelative(t);
			getParent().translateFromParent(t);
		}
	}

	/**
	 * Returns <code>true</code> if this Figure uses local coordinates. This
	 * means its children are placed relative to this Figure's top-left corner.
	 * 
	 * @return <code>true</code> if this Figure uses local coordinates
	 * @since 2.0
	 */
	protected boolean useLocalCoordinates() {
		return false;
	}

	/**
	 * @see IFigure#validate()
	 */
	public void validate() {
		if (isValid())
			return;
		setValid(true);
		layout();
		for (int i = 0; i < children.size(); i++)
			((IFigure) children.get(i)).validate();
	}

	/**
	 * A search which does not filter any figures. since 3.0
	 */
	protected static final class IdentitySearch implements TreeSearch {
		/**
		 * The singleton instance.
		 */
		public static final TreeSearch INSTANCE = new IdentitySearch();

		private IdentitySearch() {
		}

		/**
		 * Always returns <code>true</code>.
		 * 
		 * @see TreeSearch#accept(IFigure)
		 */
		public boolean accept(IFigure f) {
			return true;
		}

		/**
		 * Always returns <code>false</code>.
		 * 
		 * @see TreeSearch#prune(IFigure)
		 */
		public boolean prune(IFigure f) {
			return false;
		}
	}

	final class LayoutNotifier implements LayoutManager {

		LayoutManager realLayout;
		List listeners = new ArrayList(1);

		LayoutNotifier(LayoutManager layout, LayoutListener listener) {
			realLayout = layout;
			listeners.add(listener);
		}

		public Object getConstraint(IFigure child) {
			if (realLayout != null)
				return realLayout.getConstraint(child);
			return null;
		}

		public Dimension getMinimumSize(IFigure container, int wHint, int hHint) {
			if (realLayout != null)
				return realLayout.getMinimumSize(container, wHint, hHint);
			return null;
		}

		public Dimension getPreferredSize(IFigure container, int wHint,
				int hHint) {
			if (realLayout != null)
				return realLayout.getPreferredSize(container, wHint, hHint);
			return null;
		}

		public void invalidate() {
			for (int i = 0; i < listeners.size(); i++)
				((LayoutListener) listeners.get(i)).invalidate(Figure.this);

			if (realLayout != null)
				realLayout.invalidate();
		}

		public void layout(IFigure container) {
			boolean consumed = false;
			for (int i = 0; i < listeners.size(); i++)
				consumed |= ((LayoutListener) listeners.get(i))
						.layout(container);

			if (realLayout != null && !consumed)
				realLayout.layout(container);
			for (int i = 0; i < listeners.size(); i++)
				((LayoutListener) listeners.get(i)).postLayout(container);
		}

		public void remove(IFigure child) {
			for (int i = 0; i < listeners.size(); i++)
				((LayoutListener) listeners.get(i)).remove(child);
			if (realLayout != null)
				realLayout.remove(child);
		}

		public void setConstraint(IFigure child, Object constraint) {
			for (int i = 0; i < listeners.size(); i++)
				((LayoutListener) listeners.get(i)).setConstraint(child,
						constraint);
			if (realLayout != null)
				realLayout.setConstraint(child, constraint);
		}
	}

	/**
	 * Iterates over a Figure's children.
	 */
	public static class FigureIterator {
		private List list;
		private int index;

		/**
		 * Constructs a new FigureIterator for the given Figure.
		 * 
		 * @param figure
		 *            The Figure whose children to iterate over
		 */
		public FigureIterator(IFigure figure) {
			list = figure.getChildren();
			index = list.size();
		}

		/**
		 * Returns the next Figure.
		 * 
		 * @return The next Figure
		 */
		public IFigure nextFigure() {
			return (IFigure) list.get(--index);
		}

		/**
		 * Returns <code>true</code> if there's another Figure to iterate over.
		 * 
		 * @return <code>true</code> if there's another Figure to iterate over
		 */
		public boolean hasNext() {
			return index > 0;
		}
	}

	/**
	 * An UpdateManager that does nothing.
	 */
	protected static final UpdateManager NO_MANAGER = new UpdateManager() {
		public void addDirtyRegion(IFigure figure, int x, int y, int w, int h) {
		}

		public void addInvalidFigure(IFigure f) {
		}

		public void performUpdate() {
		}

		public void performUpdate(Rectangle region) {
		}

		public void setRoot(IFigure root) {
		}

		public void setGraphicsSource(GraphicsSource gs) {
		}
	};

}
