/***************************************************************************** * Copyright (c) 2010 CEA * * * 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: * Atos Origin - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.sequence.locator; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gmf.runtime.diagram.ui.figures.BorderItemLocator; import org.eclipse.gmf.runtime.diagram.ui.internal.figures.BorderItemContainerFigure; import org.eclipse.gmf.runtime.gef.ui.figures.DefaultSizeNodeFigure; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart.LifelineFigure; import org.eclipse.papyrus.uml.diagram.sequence.figures.DestructionEventFigure; import org.eclipse.papyrus.uml.diagram.sequence.figures.LifelineDotLineCustomFigure; public class CenterLocator extends BorderItemLocator { /** * The LifelineDotLineFigure. It must be access through the method {@link #getLifelineDotLineFigure()} */ private LifelineDotLineCustomFigure lifelineDotLineFigure = null; /** * The BorderItemContainerFigure. It must be access through the method {@link #getBorderItemContainerFigure()} */ private BorderItemContainerFigure borderItemContainerFigure = null; /** * The DestructionEventFigure. * * It must be access through the method {@link #getDestructionEventFigure()} */ private DestructionEventFigure destructionEventFigure = null; /** * Constructor * * @param parentFigure * the parent figure * @param location * ContinuationLocator.TOP or ContinuationLocator.BOTTOM */ public CenterLocator(IFigure parentFigure, int location) { super(parentFigure, location); } /** * Get the LifelineDotLineFigure * * @return the lifelineDotLineFigure or null */ private LifelineDotLineCustomFigure getLifelineDotLineFigure() { if(lifelineDotLineFigure == null) { for(Object childFig : getParentFigure().getChildren()) { if(childFig instanceof LifelineFigure) { lifelineDotLineFigure = ((LifelineFigure)childFig).getFigureLifelineDotLineFigure(); return lifelineDotLineFigure; } } } return lifelineDotLineFigure; } /** * Get the BorderItemContainerFigure * * @return the borderItemContainerFigure or null */ private BorderItemContainerFigure getBorderItemContainerFigure() { if(borderItemContainerFigure == null) { IFigure figure = getParentFigure().getParent(); for(Object object : figure.getChildren()) { if(object instanceof BorderItemContainerFigure) { borderItemContainerFigure = (BorderItemContainerFigure)object; return borderItemContainerFigure; } } } return borderItemContainerFigure; } /** * Get the DestructionEventFigure of the lifeline, if it is drawn. * * @return the DestructionEventFigure or null */ private DestructionEventFigure getDestructionEventFigure() { if(destructionEventFigure == null) { BorderItemContainerFigure borderItemContainerFigure = getBorderItemContainerFigure(); if(borderItemContainerFigure != null) { for(Object child : borderItemContainerFigure.getChildren()) { if(child instanceof DefaultSizeNodeFigure) { for(Object figure : ((DefaultSizeNodeFigure)child).getChildren()) { if(figure instanceof DestructionEventFigure) { destructionEventFigure = (DestructionEventFigure)figure; return destructionEventFigure; } } } } } } return destructionEventFigure; } /** * Overrides : * - the destructionEventFigure is always drawn at the end of the figure * * @see org.eclipse.draw2d.Locator#relocate(org.eclipse.draw2d.IFigure) */ public void relocate(IFigure borderItem) { if(getDestructionEventFigure() != null) { if(borderItem.equals(getDestructionEventFigure().getParent())) { borderItem.setLocation(new Point(getHorizontalPosition(borderItem), getParentBorder().y + getParentBorder().height - borderItem.getBounds().height)); return; } } super.relocate(borderItem); } public Rectangle getValidLocation(Rectangle proposedLocation, IFigure borderItem) { if(getDestructionEventFigure() != null) { if(borderItem.equals(getDestructionEventFigure().getParent())) { Rectangle realLocation = new Rectangle(proposedLocation); Point point = new Point(getParentBorder().getCenter().x - realLocation.getSize().width / 2, getParentBorder().y + getParentBorder().height - realLocation.height); realLocation.setLocation(point); return realLocation; } } return super.getValidLocation(proposedLocation, borderItem); } /** * Get the parent dotLine border * * @return <code>Rectangle</code> that is the bounds of the parent dot line. */ protected Rectangle getParentDotLineBorder() { LifelineDotLineCustomFigure dotline = getLifelineDotLineFigure(); if(dotline != null) { return dotline.getBounds().getCopy(); } return super.getParentBorder(); } /** * Locate the figure on its parent * * @param suggestedLocation * @param suggestedSide * @return point */ protected Point locateOnParent(Point suggestedLocation, int suggestedSide, IFigure borderItem) { Dimension borderItemSize = getSize(borderItem); int y = getVerticalPosition(suggestedLocation.y, borderItemSize.height); int x = getHorizontalPosition(borderItem); return new Point(x, y); } /** * Get the vertical position of the itemBorder * * @param y * the suggested location * @param height * the border item height * @return the vertical position of the item border on the lifeline */ private int getVerticalPosition(int y, int height) { int validY = y; Rectangle parentDotLineBorder = getParentDotLineBorder(); int maxY = parentDotLineBorder.y + parentDotLineBorder.height - getSouthInsets(); if(y + height > maxY) { validY = maxY - height; } else if(y < parentDotLineBorder.y) { validY = parentDotLineBorder.y; } return validY; } /** * Get the horizontal position of the borderItem drawn on a lifeline. * Those elements are drawn at the center of the lifeline, ie on the dot line. * * @param borderItem * the borderItem * @return the horizontal position of the border item */ private int getHorizontalPosition(IFigure borderItem) { return getParentBorder().getCenter().x - borderItem.getSize().width / 2; } /** * Get the insets to use at the bottom of the figure. * It is used to prevent others borderItems to be drawn on or below the destructionEventFigure * * @return If a destructionEventFigure is drawn, it returns the height of its figure, otherwise it returns 0 */ private int getSouthInsets() { DestructionEventFigure destructionEventFigure = getDestructionEventFigure(); if(destructionEventFigure != null) { return destructionEventFigure.getBounds().height; } return 0; } }