/***************************************************************************** * Copyright (c) 2009-2010 CEA LIST. * * * 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: * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.layout; import org.eclipse.core.runtime.Assert; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.emf.common.command.IdentityCommand; import org.eclipse.gef.ConnectionEditPart; import org.eclipse.gef.EditPart; import org.eclipse.gef.Request; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.CompoundCommand; import org.eclipse.gef.commands.UnexecutableCommand; import org.eclipse.gef.editparts.AbstractConnectionEditPart; import org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy; import org.eclipse.gef.requests.ReconnectRequest; import org.eclipse.gmf.runtime.draw2d.ui.figures.PolylineConnectionEx; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.commands.wrappers.EMFtoGEFCommandWrapper; import org.eclipse.papyrus.uml.diagram.common.Activator; /** * * This class allow to represent easily a link for the Layout Action * */ public class LinkRepresentationForLayoutAction { /** the source of the link */ private EditPart source = null; /** the target of the link */ private EditPart target = null; /** new source position */ private Point newSourcePosition = null; /** old source position */ private Point oldSourcePosition = null; /** new target position */ private Point newTargetPosition = null; /** old target position */ private Point oldTargetPosition = null; /** the link represented by this class */ private ConnectionEditPart link; /** * * Constructor. * * @param link * the represented link * */ public LinkRepresentationForLayoutAction(ConnectionEditPart link) { this.link = link; this.source = link.getSource(); this.target = link.getTarget(); IFigure fig = ((AbstractConnectionEditPart)link).getFigure(); Assert.isTrue(fig instanceof PolylineConnectionEx); PolylineConnectionEx linkFigure = (PolylineConnectionEx)fig; Point start = linkFigure.getStart();// source Point end = linkFigure.getEnd();// target linkFigure.translateToAbsolute(start); linkFigure.translateToAbsolute(end); oldSourcePosition = start; oldTargetPosition = end; } /** * * @see java.lang.Object#toString() * * @return */ @Override public String toString() { return ((View)(link.getModel())).getElement().toString(); } /** * Return the command to move this link, following {@link #newSourcePosition} and {@link #newTargetPosition} * * @return the command to move this link, following {@link #newSourcePosition} and {@link #newTargetPosition} */ public Command getCommand() { /* * Sometimes, the anchors of the link move on the diagram, even if the * location is the same! see GMF bug 324208 */ if((newSourcePosition == null && newTargetPosition == null) || (oldSourcePosition.equals(newSourcePosition)) && oldTargetPosition.equals(newTargetPosition)) { return new EMFtoGEFCommandWrapper(new IdentityCommand()); } else { CompoundCommand command = new CompoundCommand(); command.add(source.getCommand(getRequestForSource())); command.add(target.getCommand(getRequestForTarget())); return command.canExecute() ? command : UnexecutableCommand.INSTANCE; } } /** * Returns the request to move the source anchor. * * @return the request to move the source anchor. */ public Request getRequestForSource() { ReconnectRequest request = new ReconnectRequest(GraphicalNodeEditPolicy.REQ_RECONNECT_SOURCE); request.setConnectionEditPart(this.link); request.setTargetEditPart(this.source); request.setLocation(getNewSourceLocation()); return request; } /** * Return the source location to move this link * * @return the source location to move this link * <ul> * <li> {@link #newSourcePosition} if not <code>null</code></li> * <li>{@link #oldSourcePosition} if {@link #newSourcePosition} is <code>null</code></li> * </ul> */ protected Point getNewSourceLocation() { if(this.newSourcePosition != null) { return this.newSourcePosition; } else { return this.oldSourcePosition; } } /** * Return the target location to move this link * * @return the target location to move this link * <ul> * <li> {@link #newTargetPosition} if not <code>null</code></li> * <li>{@link #oldTargetPosition} if {@link #newTargetPosition} is <code>null</code></li> * </ul> */ protected Point getNewTargetLocation() { if(this.newTargetPosition != null) { return this.newTargetPosition; } else { return this.oldTargetPosition; } } /** * Setter for {@link #newSourcePosition} and {@link #newTargetPosition} * * @param node * a node, should be the source or the target of the link * @param location * the neuw location on this node */ public void setNewLocationFor(EditPart node, Point location) { if(source == node) { newSourcePosition = location; } else if(target == node) { newTargetPosition = location; } else { Activator.log.error("Can't find the EditPart " + node + " (from " + this.getClass().getName() + ")", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } /** * Returns the request to relocate the fixed anchor. * * @return The request to locate the fixed anchor. */ public Request getRequestForTarget() { ReconnectRequest request = new ReconnectRequest(GraphicalNodeEditPolicy.REQ_RECONNECT_TARGET); request.setConnectionEditPart(this.link); request.setTargetEditPart(this.target); request.setLocation(getNewTargetLocation()); return request; } /** * Return the current position of the link on the node * * @param node * node should be the source or the target of the link * @return * @see LayoutUtils#getAnchorPosition(EditPart, Point) */ public int getCurrentSideOn(EditPart node) { if(node == source) { return LayoutUtils.getAnchorPosition(source, oldSourcePosition); } else if(node == target) { return LayoutUtils.getAnchorPosition(target, oldTargetPosition); } else { Activator.log.error("Can't find the EditPart " + node + " (from " + this.getClass().getName() + ")", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } return 0; } /** * Gets the represented link. * * @return the represented link */ public ConnectionEditPart getRepresentedLink() { return this.link; } /** * Return a PrecisionRectangle representing the current position of the * anchor on this node (with width=height=1) * * @param node * node should be the source or the target of the link * @return A PrecisionRectangle representing the current position of the * anchor on this node (with width=height=1) */ public PrecisionRectangle getAbsolutePositionOn(EditPart node) { PrecisionRectangle rect = new PrecisionRectangle(); rect.setSize(new Dimension(1, 1)); if(source == node) { rect.setX(oldSourcePosition.x); rect.setY(oldSourcePosition.y); } else if(target == node) { rect.setX(oldTargetPosition.x); rect.setY(oldTargetPosition.y); } else { Activator.log.error("Can't find the EditPart " + node + " (from " + this.getClass().getName() + ")", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } return rect; } /** * Return the current absolute location of the anchor on this node * * @param node * node should be the source or the target of the link * @return the current absolute location of the anchor on this node */ public Point getAbsoluteLocationOn(EditPart node) { if(source == node) { return oldSourcePosition; } else if(target == node) { return oldTargetPosition; } else { Activator.log.error("Can't find the EditPart " + node + " (from " + this.getClass().getName() + ")", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } return new Point(); } /** * Gets the side on source. * * @return the side on source */ public int getSideOnSource() { return getCurrentSideOn(source); } /** * Gets the side on target. * * @return the side on target */ public int getSideOnTarget() { return getCurrentSideOn(target); } }