/** * Copyright (c) 2007 Borland Software Corporation * * 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: * bblajer - initial API and implementation */ package org.eclipse.gmf.runtime.lite.figures; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Locator; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.GraphicalEditPart; public class BorderItemLocator extends SideAffixedElementPositioner implements Locator { private final GraphicalEditPart myHostEditPart; private Rectangle myModelConstraint; private int preferredSide = PositionConstants.WEST; private int currentSide = PositionConstants.WEST; /** * Constructs an instance of BorderItemLocator. * @param editPart the side affixed edit part */ public BorderItemLocator(GraphicalEditPart editPart) { myHostEditPart = editPart; } public void setModelConstraint(Rectangle rectangle) { myModelConstraint = rectangle; if (getTargetFigure().getParent() != null) { getTargetFigure().getParent().revalidate(); } } protected final IFigure getTargetFigure() { return myHostEditPart.getFigure(); } public Rectangle getModelConstraint() { return myModelConstraint; } /** * Get the preferred location. If none has been previously set, use the * preferred side to take an initial guess. * * @return {@link Rectangle} A new rectangle representing the preferred location. */ protected Rectangle getPreferredLocation() { if (getModelConstraint() == null) { return getPreferredLocation(getPreferredSideOfParent()); } return toContainerCoordinates(getModelConstraint().getCopy()); } /** * Get an initial location based on the side. ( choose middle of the side ) * * @param side * the preferred side of the parent figure on which to place this * border item as defined in {@link PositionConstants} * @return point */ protected Rectangle getPreferredLocation(int side) { Rectangle bounds = getParentBorder(); int parentFigureWidth = bounds.width; int parentFigureHeight = bounds.height; int parentFigureX = bounds.x; int parentFigureY = bounds.y; int x = parentFigureX; int y = parentFigureY; Dimension borderItemSize = getBorderItemSize(); if (side == PositionConstants.WEST) { x += getBorderItemOffset().width - borderItemSize.width; y += (parentFigureHeight - borderItemSize.height) / 2; } else if (side == PositionConstants.EAST) { x += parentFigureWidth - getBorderItemOffset().width; y += (parentFigureHeight - borderItemSize.height) / 2; } else if (side == PositionConstants.NORTH) { x += (parentFigureWidth - borderItemSize.width) / 2; y += getBorderItemOffset().height - borderItemSize.height; } else if (side == PositionConstants.SOUTH) { x += (parentFigureWidth - borderItemSize.width) / 2; y += parentFigureHeight - getBorderItemOffset().height; } return new Rectangle(x, y, borderItemSize.width, borderItemSize.height); } /** * Convert the relative coordinates in the model to ones that are relative to the * container. * This is an auxiliary method. * @param relativeOffset * @return point */ public Rectangle toContainerCoordinates(Rectangle relativeOffset) { Point parentOrigin = getParentBorder().getTopLeft(); relativeOffset.translate(parentOrigin); return relativeOffset; } public void relocate(IFigure borderItem) { assert getTargetFigure() == borderItem; Rectangle rectSuggested = getPreferredLocation(); int closestSide = findClosestSideOfParent(rectSuggested, getParentBorder()); setPreferredSideOfParent(closestSide); Rectangle newLocation = locateOnBorder(rectSuggested, getPreferredSideOfParent(), 0); borderItem.setBounds(newLocation); setCurrentSideOfParent(findClosestSideOfParent(newLocation, getParentBorder())); } /** * getter for the parent figure * * @return <code>IFigure</code> */ public IFigure getHostFigure() { return ((GraphicalEditPart) myHostEditPart.getParent()).getFigure(); } /** * Returns the preferred side of the parent figure on which to place this * border item. * * @return the preferred side of the parent figure on which to place this * border item as defined in {@link PositionConstants} */ public int getPreferredSideOfParent() { return preferredSide; } /** * Sets the preferred side of the parent figure on which to place this * border item. * * @param preferredSide * the preferred side of the parent figure on which to place this * border item as defined in {@link PositionConstants} */ public void setPreferredSideOfParent(int preferredSide) { this.preferredSide = preferredSide; setCurrentSideOfParent(preferredSide); } public int getCurrentSideOfParent() { return currentSide; } /** * Sets the side of the parent figure on which the border item should * appear. * * @param side * the side on which this border item appears as defined in * {@link PositionConstants} */ public void setCurrentSideOfParent(int side) { this.currentSide = side; } /** * Gets the size of the border item figure. * @param borderItem * @return the size of the border item figure. */ protected Dimension getBorderItemSize() { Rectangle offset = getModelConstraint(); Dimension size = offset == null ? null : offset.getSize(); if (size == null || size.isEmpty()) { size = getTargetFigure().getPreferredSize().getCopy(); } return size; } @Override protected Collection<? extends IFigure> getSiblings() { List<?> children = myHostEditPart.getParent().getChildren(); Collection<IFigure> result = new ArrayList<IFigure>(children.size()); for (Object next : children) { GraphicalEditPart nextChild = (GraphicalEditPart) next; if (!nextChild.isActive()) { continue; } if (nextChild == myHostEditPart) { continue; } IFigure nextFigure = nextChild.getFigure(); if (nextFigure.getParent() == myHostEditPart.getFigure().getParent()) { result.add(nextChild.getFigure()); } } return result; } }