Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 54c9a22667ea65fd0797066446ee0c255148b52a (plain) (tree)

















































                                                                                    

                                                                                  
                                                                                
                                                                               

























                                                                                         




                                                                                                                




















                                                                                     
                                                                            






























































































                                                                                                                                                                               
















                                                                                                                           
                                                                            



























                                                                                                                                                         
                                                                    









                                                                                               































































                                                                                                                                                                                            











                                                                                                                          












































                                                                                                                                                                    
/*****************************************************************************
 * Copyright (c) 2013 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:
 *   Soyatec - Initial API and implementation
 *
 *****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.util;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.OrderedLayout;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart;
import org.eclipse.gmf.runtime.draw2d.ui.figures.BaseSlidableAnchor;
import org.eclipse.gmf.runtime.notation.Anchor;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.IdentityAnchor;
import org.eclipse.gmf.runtime.notation.LayoutConstraint;
import org.eclipse.gmf.runtime.notation.Location;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.Shape;
import org.eclipse.gmf.runtime.notation.Size;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.CombinedFragmentEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.InteractionUseEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.MessageFoundEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.MessageLostEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.figures.LifelineFigure;
import org.eclipse.swt.widgets.Display;
import org.eclipse.uml2.uml.CombinedFragment;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.InteractionUse;
import org.eclipse.uml2.uml.Lifeline;


/**
 * @author Jin Liu (jin.liu@soyatec.com)
 */
public class LifelineHeadUtil {

	public static int computeLifelineVerticalPosition(final EditPart parent) {
		if (parent instanceof GraphicalEditPart) {
			List<?> children = parent.getChildren();
			int bottom = -1;
			for (Object object : children) {
				if (!(object instanceof LifelineEditPart)) {
					continue;
				}
				LifelineEditPart lifeline = (LifelineEditPart) object;
				if (SequenceUtil.isCreateMessageEndLifeline(lifeline)) {
					continue;
				}
				LifelineFigure primaryShape = lifeline.getPrimaryShape();
				// RectangleFigure figure = primaryShape.getFigureLifelineNameContainerFigure();
				// Rectangle r = figure.getBounds().getCopy();
				// if (!r.isEmpty()) {
				// bottom = Math.max(bottom, r.bottom());
				// }
			}
			if (bottom != -1) {
				RectangleFigure figure = new RectangleFigure();
				figure.setBorder(new MarginBorder(7));
				ToolbarLayout layout = new ToolbarLayout();
				layout.setMinorAlignment(OrderedLayout.ALIGN_CENTER);
				Label label = new Label("Lifeline");
				label.setFont(Display.getDefault().getSystemFont());
				figure.add(label);
				figure.setLayoutManager(layout);
				int height = figure.getPreferredSize().height;
				return bottom - height - 1;
			}
		}
		return SequenceUtil.LIFELINE_VERTICAL_OFFSET;
	}

	public static void updateHead(LifelineEditPart lifeline, int resized) {
		if (lifeline == null || resized == 0) {
			return;
		}
		List<LifelineEditPart> toMovedLifelines = new ArrayList<>();
		collectLifelines(toMovedLifelines, lifeline);
		List<ShapeNodeEditPart> children = LifelineEditPartUtil.getChildShapeNodeEditPart(lifeline);
		for (ShapeNodeEditPart child : children) {
			collectLifelines(toMovedLifelines, child);
		}
		EditPart parent = lifeline.getParent();
		while (parent instanceof LifelineEditPart) {
			parent = parent.getParent();
		}
		if (!SequenceUtil.isCreateMessageEndLifeline(lifeline)) {
			List<?> childrenList = parent.getChildren();
			for (Object object : childrenList) {
				if (toMovedLifelines.contains(object) || !(object instanceof LifelineEditPart)) {
					continue;
				}
				toMovedLifelines.add((LifelineEditPart) object);
			}
		}
		if (toMovedLifelines.isEmpty()) {
			return;
		}
		CompoundCommand command = new CompoundCommand();
		computeUpdateHeadCommand(command, lifeline, false, resized, new ArrayList<EditPart>());
		if (command.canExecute()) {
			CommandHelper.executeCommandWithoutHistory(lifeline.getEditingDomain(), command, true);
		}
	}

	private static void computeUpdateHeadCommand(CompoundCommand commands, LifelineEditPart lifeline, boolean moveChildren, int moveDelta, List<EditPart> movedEditParts) {
		// 1. move children of current lifeline.
		if (moveChildren) {
			ShapeNodeEditPart nodeToMove = lifeline;
			EditPart parent = lifeline.getParent();
			while (parent instanceof LifelineEditPart) {
				nodeToMove = (ShapeNodeEditPart) parent;
				parent = parent.getParent();
			}
			Command cmd = getVerticalMoveShapeCommand(nodeToMove, moveDelta, false);
			commands.appendIfCanExecute(cmd);
		} else {
			View view = lifeline.getNotationView();
			LayoutConstraint constraint = ((Shape) view).getLayoutConstraint();
			if (constraint instanceof Size) {
				int height = ((Size) constraint).getHeight();
				if (height == -1) {
					height = lifeline.getFigure().getBounds().height;
				}
				height += moveDelta;
				commands.appendIfCanExecute(SetCommand.create(lifeline.getEditingDomain(), constraint, NotationPackage.eINSTANCE.getSize_Height(), height));
			}
		}
		movedEditParts.add(lifeline);

		// 2. move covered CombinedFragment and InteractionUse
		EObject elt = lifeline.resolveSemanticElement();
		if (elt instanceof Lifeline) {
			EList<InteractionFragment> coveredBys = ((Lifeline) elt).getCoveredBys();
			EditPartViewer viewer = lifeline.getViewer();
			for (InteractionFragment fragment : coveredBys) {
				if (!(fragment instanceof CombinedFragment || fragment instanceof InteractionUse)) {
					continue;
				}
				List<View> views = DiagramEditPartsUtil.findViews(fragment, viewer);
				if (views.isEmpty()) {
					continue;
				}
				for (View view : views) {
					EditPart ep = (EditPart) viewer.getEditPartRegistry().get(view);
					if (ep == null) {
						continue;
					}
					if (movedEditParts.contains(ep)) {
						continue;
					}
					EditPart parent = ep.getParent();
					boolean parentMoved = false;
					while (parent != null) {
						if (movedEditParts.contains(parent)) {
							parentMoved = true;
							break;
						}
						parent = parent.getParent();
					}
					if (parentMoved) {
						continue;
					}
					if (ep instanceof CombinedFragmentEditPart || ep instanceof InteractionUseEditPart) {
						Command cmd = getVerticalMoveShapeCommand((ShapeNodeEditPart) ep, moveDelta, false);
						commands.appendIfCanExecute(cmd);
						movedEditParts.add(ep);
						List<?> children = ep.getChildren();
						for (Object object : children) {
							if (movedEditParts.contains(object)) {
								continue;
							}
						}
					}
				}
			}
		}

		// 3. move Gate if existed.
		fillMoveDownMessageEnds(commands, lifeline, moveDelta, movedEditParts);
		List<ShapeNodeEditPart> childShapeNodeEditParts = LifelineEditPartUtil.getChildShapeNodeEditPart(lifeline);
		for (ShapeNodeEditPart shapeNodeEditPart : childShapeNodeEditParts) {
			fillMoveDownMessageEnds(commands, shapeNodeEditPart, moveDelta, movedEditParts);
		}

		// 4. move children of linked lifelines.
		if (SequenceUtil.isCreateMessageEndLifeline(lifeline)) {
			return;
		}
		List<LifelineEditPart> toMovedLifelines = new ArrayList<>();
		collectLifelines(toMovedLifelines, lifeline);
		List<ShapeNodeEditPart> children = LifelineEditPartUtil.getChildShapeNodeEditPart(lifeline);
		for (ShapeNodeEditPart child : children) {
			collectLifelines(toMovedLifelines, child);
		}
		EditPart parent = lifeline.getParent();
		while (parent instanceof LifelineEditPart) {
			parent = parent.getParent();
		}
		List<?> childrenList = parent.getChildren();
		for (Object object : childrenList) {
			if (toMovedLifelines.contains(object) || !(object instanceof LifelineEditPart)) {
				continue;
			}
			toMovedLifelines.add((LifelineEditPart) object);
		}
		for (LifelineEditPart editPart : toMovedLifelines) {
			if (movedEditParts.contains(editPart)) {
				continue;
			}
			computeUpdateHeadCommand(commands, editPart, true, moveDelta, movedEditParts);
		}
	}

	private static void fillMoveDownMessageEnds(CompoundCommand commands, GraphicalEditPart editPart, int moveDelta, List<EditPart> movedEditParts) {
		List<?> sourceConnections = editPart.getSourceConnections();
		for (Object object : sourceConnections) {
			ConnectionEditPart conn = (ConnectionEditPart) object;
			if (object instanceof MessageLostEditPart) {
				Command command = getMoveAnchorCommand(conn, moveDelta, false);
				commands.appendIfCanExecute(command);
			}
		}
		List<?> targetConnections = editPart.getTargetConnections();
		for (Object object : targetConnections) {
			ConnectionEditPart conn = (ConnectionEditPart) object;
			if (conn instanceof MessageFoundEditPart) {
				Command command = getMoveAnchorCommand(conn, moveDelta, true);
				commands.appendIfCanExecute(command);
			}
		}
	}

	private static Command getMoveAnchorCommand(ConnectionEditPart conn, int moveDelta, boolean moveSource) {
		EditPart editPart = moveSource ? conn.getSource() : conn.getTarget();
		if (!(editPart instanceof IGraphicalEditPart)) {
			return null;
		}
		Object model = conn.getModel();
		if (!(model instanceof Edge)) {
			return null;
		}
		Edge edge = (Edge) model;
		Anchor anchor = moveSource ? edge.getSourceAnchor() : edge.getTargetAnchor();
		if (!(anchor instanceof IdentityAnchor)) {
			return null;
		}
		String terminal = ((IdentityAnchor) anchor).getId();
		PrecisionPoint pt = BaseSlidableAnchor.parseTerminalString(terminal);
		PrecisionPoint p = null;
		if (pt.preciseX() > 1 || pt.preciseY() > 1) {
			p = new PrecisionPoint(pt.preciseX(), pt.preciseY() + moveDelta);
		} else {
			Rectangle bounds = SequenceUtil.getAbsoluteBounds((IGraphicalEditPart) editPart);
			PrecisionPoint location = new PrecisionPoint(pt.preciseX() * bounds.preciseWidth() + bounds.preciseX(), pt.preciseY() * bounds.preciseHeight() + bounds.preciseY());
			location.translate(0, moveDelta);
			Dimension d = location.getDifference(bounds.getTopLeft());
			p = new PrecisionPoint(d.preciseWidth() / bounds.width, d.preciseHeight() / bounds.height);
		}
		StringBuffer s = new StringBuffer(24);
		s.append('('); // 1 char
		s.append(p.preciseX()); // 10 chars
		s.append(','); // 1 char
		s.append(p.preciseY()); // 10 chars
		s.append(')');
		return SetCommand.create(getEditingDomain((GraphicalEditPart) editPart), anchor, NotationPackage.eINSTANCE.getIdentityAnchor_Id(), s.toString());
	}

	private static void collectLifelines(List<LifelineEditPart> toMovedLifelines, GraphicalEditPart editPart) {
		if (editPart == null) {
			return;
		}
		// 1. links from current lifeline
		List<?> sourceConnections = editPart.getSourceConnections();
		for (Object object : sourceConnections) {
			ConnectionEditPart conn = (ConnectionEditPart) object;
			LifelineEditPart target = getLifeline(conn.getTarget());
			if (target == null || toMovedLifelines.contains(target) || editPart == target) {
				continue;
			}
			toMovedLifelines.add(target);
		}

		// 2. links to current lifeline.
		List<?> targetConnections = editPart.getTargetConnections();
		for (Object object : targetConnections) {
			ConnectionEditPart conn = (ConnectionEditPart) object;
			LifelineEditPart source = getLifeline(conn.getSource());
			if (source == null || toMovedLifelines.contains(source) || editPart == source) {
				continue;
			}
			toMovedLifelines.add(source);
		}
		//
		// if (editPart instanceof CustomLifelineEditPart && ((CustomLifelineEditPart) editPart).isInlineMode()) {
		// List<?> children = ((CustomLifelineEditPart) editPart).getChildren();
		// for (Object object : children) {
		// if (object instanceof LifelineEditPart) {
		// collectLifelines(toMovedLifelines, (LifelineEditPart) object);
		// }
		// }
		// if (toMovedLifelines.isEmpty()) {
		// toMovedLifelines.add((LifelineEditPart) editPart);
		// }
		// }
	}

	private static Command getVerticalMoveShapeCommand(GraphicalEditPart shapeEditPart, int moveDelta, boolean increaseHeight) {
		if (shapeEditPart == null || moveDelta == 0) {
			return null;
		}
		Object view = shapeEditPart.getModel();
		if (!(view instanceof Shape)) {
			return null;
		}
		LayoutConstraint constraint = ((Shape) view).getLayoutConstraint();
		if (!(constraint instanceof Location)) {
			return null;
		}
		int y = ((Location) constraint).getY();
		int value = y + moveDelta;
		Command command = SetCommand.create(getEditingDomain(shapeEditPart), constraint, NotationPackage.eINSTANCE.getLocation_Y(), value);
		if (increaseHeight && constraint instanceof Size) {
			int height = ((Size) constraint).getHeight();
			if (height == -1) {
				height = shapeEditPart.getFigure().getBounds().height;
			}
			height += moveDelta;
			command = command.chain(SetCommand.create(getEditingDomain(shapeEditPart), constraint, NotationPackage.eINSTANCE.getSize_Height(), height));
		}
		return command;
	}

	private static EditingDomain getEditingDomain(GraphicalEditPart editPart) {
		if (editPart instanceof IGraphicalEditPart) {
			return ((IGraphicalEditPart) editPart).getEditingDomain();
		}
		return null;
	}

	private static LifelineEditPart getLifeline(EditPart editPart) {
		if (editPart == null) {
			return null;
		}
		if (editPart instanceof LifelineEditPart) {
			return (LifelineEditPart) editPart;
		}
		return getLifeline(editPart.getParent());
	}
}

Back to the top