/*******************************************************************************
 * Copyright (c) 2000, 2005 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 org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;

/**
 * Places a figure relative to a point determined by the subclass. The figure may be
 * placed in some location relative to the point with a configurable amount of spacing.
 */
public abstract class AbstractLocator
	implements Locator
{

private int relativePosition = PositionConstants.CENTER;
private int gap;

/**
 * Creates a new AbstractLocator.
 */
public AbstractLocator() { }

/**
 * Returns the number of pixels to leave between the figure being located and the
 * reference point. Only used if {@link #getRelativePosition()} returns something other
 * than {@link PositionConstants#CENTER}.
 * 
 * @return The gap
 * @since 2.0
 */
public int getGap() {
	return gap;
}

/**
 * Returns the reference point in absolute coordinates used to calculate the location.
 * @return The reference point in absolute coordinates
 * @since 2.0
 */
protected abstract Point getReferencePoint();

/**
 * Recalculate the location of the figure according to its desired position relative to
 * the center point.
 * 
 * @param size The size of the figure
 * @param center The center point
 * @return The new bounds
 * @since 2.0
 */
protected Rectangle getNewBounds(Dimension size, Point center) {
	Rectangle bounds = new Rectangle(center, size);

	bounds.x -= bounds.width / 2;
	bounds.y -= bounds.height / 2;

	int xFactor = 0, yFactor = 0;
	int position = getRelativePosition();

	if ((position & PositionConstants.NORTH) != 0) 
		yFactor = -1;
	else if ((position & PositionConstants.SOUTH) != 0) 
		yFactor = 1;

	if ((position & PositionConstants.WEST) != 0) 
		xFactor = -1;
	else if ((position & PositionConstants.EAST) != 0) 
		xFactor = 1;

	bounds.x += xFactor * (bounds.width / 2 + getGap());
	bounds.y += yFactor * (bounds.height / 2 + getGap());

	return bounds;
}

/**
 * Returns the position of the figure with respect to the center point. Possible values
 * can be found in {@link PositionConstants} and include CENTER, NORTH, SOUTH, EAST, WEST,
 * NORTH_EAST, NORTH_WEST, SOUTH_EAST, or SOUTH_WEST.
 * 
 * @return An int constant representing the relative position
 * @since 2.0
 */
public int getRelativePosition() {
	return relativePosition;
}

/**
 * Recalculates the position of the figure and returns the updated bounds.
 * @param target The figure to relocate
 */
public void relocate(IFigure target) {
	Dimension prefSize = target.getPreferredSize();
	Point center = getReferencePoint();
	target.translateToRelative(center);
	target.setBounds(getNewBounds(prefSize, center));
}

/**
 * Sets the gap between the reference point and the figure being placed. Only used if
 * getRelativePosition() returns something other than  {@link PositionConstants#CENTER}.
 * 
 * @param i The gap
 * @since 2.0
 */
public void setGap(int i) {
	gap = i;
}

/**
 * Sets the position of the figure with respect to the center point. Possible values can
 * be found in {@link PositionConstants} and include CENTER, NORTH, SOUTH, EAST, WEST,
 * NORTH_EAST, NORTH_WEST, SOUTH_EAST, or SOUTH_WEST.
 * 
 * @param pos The relative position
 * @since 2.0
 */
public void setRelativePosition(int pos) {
	relativePosition = pos;
}

}
