Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: e5a1ef9a54f1db51ab6cbe7bb518868b01d50dfe (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13












                                                                                
                                                                






                                      
                                         























                                                                                   
                                                          



                                                                               
                                                   






















































































                                                                                                                                                                                                                
                                                    

































































































                                                                                                                                                                     

                                                                                                       
















































                                                                                                                         

                                                                                     

                                 

                                                                        










































































                                                                                                    
/*****************************************************************************
 * Copyright (c) 2010 Atos Origin.
 *
 *    
 * 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.activity.edit.policies;

import java.util.Collections;
import java.util.List;

import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PolylineShape;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.handles.MoveHandle;
import org.eclipse.gef.requests.AlignmentRequest;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand;
import org.eclipse.gmf.runtime.diagram.ui.editparts.AbstractBorderedShapeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.NonResizableEditPolicyEx;
import org.eclipse.gmf.runtime.diagram.ui.figures.IBorderItemLocator;
import org.eclipse.gmf.runtime.diagram.ui.internal.figures.LabelHelper;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure;
import org.eclipse.gmf.runtime.notation.View;

public class BehaviorPropertyNodeEditPolicy extends NonResizableEditPolicyEx {

	private PolylineShape linkFeedback = null;

	/**
	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#createSelectionHandles()
	 */
	protected List createSelectionHandles() {
		MoveHandle mh = new MoveHandle((GraphicalEditPart)getHost());
		mh.setBorder(null);
		return Collections.singletonList(mh);
	}

	/**
	 * Calls other methods as appropriate.
	 */
	public void eraseSourceFeedback(Request request) {
		if((REQ_MOVE.equals(request.getType()) && isDragAllowed()) || REQ_CLONE.equals(request.getType()) || REQ_ADD.equals(request.getType()) || RequestConstants.REQ_DROP.equals(request.getType()))
			eraseChangeBoundsFeedback((ChangeBoundsRequest)request);
	}

	/**
	 * Calls other methods as appropriate.
	 */
	public void showSourceFeedback(Request request) {
		if((REQ_MOVE.equals(request.getType()) && isDragAllowed()) || REQ_ADD.equals(request.getType()) || REQ_CLONE.equals(request.getType()) || RequestConstants.REQ_DROP.equals(request.getType()))
			showChangeBoundsFeedback((ChangeBoundsRequest)request);
	}

	/**
	 * Returns the command contribution to a change bounds request.
	 * 
	 * @param request
	 *        the change bounds requesgt
	 * @return the command contribution to the request
	 */
	protected Command getMoveCommand(ChangeBoundsRequest request) {

		// translate the feedback figure
		PrecisionRectangle rect = new PrecisionRectangle(getInitialFeedbackBounds().getCopy());
		getHostFigure().translateToAbsolute(rect);
		rect.translate(request.getMoveDelta());
		rect.resize(request.getSizeDelta());
		getHostFigure().translateToRelative(rect);

		if(getHost() instanceof IBorderItemEditPart) {
			IBorderItemEditPart borderItemEP = (IBorderItemEditPart)getHost();
			IBorderItemLocator borderItemLocator = borderItemEP.getBorderItemLocator();
			if(borderItemLocator != null) {
				Rectangle realLocation = borderItemLocator.getValidLocation(rect.getCopy(), borderItemEP.getFigure());
				Point parentOrigin = borderItemEP.getFigure().getParent().getBounds().getTopLeft();
				Dimension d = realLocation.getTopLeft().getDifference(parentOrigin);
				Point location = new Point(d.width, d.height);
				ICommand moveCommand = new SetBoundsCommand(borderItemEP.getEditingDomain(), DiagramUIMessages.Commands_MoveElement, new EObjectAdapter((View)getHost().getModel()), location);
				return new ICommandProxy(moveCommand);
			}
		} else if(getHost() instanceof LabelEditPart) {
			LabelEditPart editPart = (LabelEditPart)getHost();
			Point refPoint = editPart.getReferencePoint();
			Point normalPoint = LabelHelper.offsetFromRelativeCoordinate(getHostFigure(), rect, refPoint);
			ICommand moveCommand = new SetBoundsCommand(editPart.getEditingDomain(), DiagramUIMessages.Commands_MoveElement, new EObjectAdapter((View)editPart.getModel()), normalPoint);
			return new ICommandProxy(moveCommand);
		}
		return null;
	}

	/** Return <tt>null</tt> to avoid handling the request. */
	protected Command getAlignCommand(AlignmentRequest request) {
		return null;
	}

	/**
	 * Erase the feedback link figure
	 * 
	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#eraseChangeBoundsFeedback(org.eclipse.gef.requests.ChangeBoundsRequest)
	 */
	protected void eraseChangeBoundsFeedback(ChangeBoundsRequest request) {
		super.eraseChangeBoundsFeedback(request);
		if(linkFeedback != null)
			removeFeedback(linkFeedback);
		linkFeedback = null;
	}

	/**
	 * Create the feedback link figure
	 * 
	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#createDragSourceFeedbackFigure()
	 */
	protected IFigure createDragSourceFeedbackFigure() {
		IFigure feedback = super.createDragSourceFeedbackFigure();
		linkFeedback = new PolylineShape();
		linkFeedback.setLineWidth(1);
		linkFeedback.setLineStyle(Graphics.LINE_DASHDOT);
		linkFeedback.setForegroundColor(((IGraphicalEditPart)getHost()).getFigure().getForegroundColor());
		addFeedback(linkFeedback);
		return feedback;
	}

	/**
	 * Show link feedback
	 * 
	 * @see org.eclipse.gmf.runtime.diagram.ui.editpolicies.BorderItemSelectionEditPolicy#showChangeBoundsFeedback(org.eclipse.gef.requests.ChangeBoundsRequest)
	 */
	protected void showChangeBoundsFeedback(org.eclipse.gef.requests.ChangeBoundsRequest request) {
		if(getHost() instanceof IBorderItemEditPart) {
			IBorderItemEditPart borderItemEP = (IBorderItemEditPart)getHost();
			IBorderItemLocator borderItemLocator = borderItemEP.getBorderItemLocator();

			if(borderItemLocator != null) {
				IFigure feedback = getDragSourceFeedbackFigure();
				PrecisionRectangle rect = new PrecisionRectangle(getInitialFeedbackBounds().getCopy());
				getHostFigure().translateToAbsolute(rect);
				rect.translate(request.getMoveDelta());
				rect.resize(request.getSizeDelta());
				getHostFigure().translateToRelative(rect);
				Rectangle realLocation = borderItemLocator.getValidLocation(rect.getCopy(), borderItemEP.getFigure());
				getHostFigure().translateToAbsolute(realLocation);
				feedback.translateToRelative(realLocation);
				feedback.setBounds(realLocation);
			}
		} else {
			super.showChangeBoundsFeedback(request);
		}

		// translate the feedback figure
		IFigure p = getDragSourceFeedbackFigure();

		PrecisionRectangle rect = new PrecisionRectangle(getInitialFeedbackBounds().getCopy());
		getHostFigure().translateToAbsolute(rect);
		rect.translate(request.getMoveDelta());
		rect.resize(request.getSizeDelta());

		p.translateToRelative(rect);
		p.setBounds(rect);

		Point referencePoint = getReferencePoint(request);
		Point end = getLinkEndPoint(request, referencePoint);
		linkFeedback.setEnd(end);
		Point start = getLinkStartPoint(request, referencePoint, end);
		if(start != null) {
			linkFeedback.setStart(start);
		} else {
			linkFeedback.setStart(referencePoint);
		}
	};

	/**
	 * Get the reference point at the center of the parent figure
	 * 
	 * @param request
	 *        change bounds request
	 * @return point
	 */
	private Point getReferencePoint(ChangeBoundsRequest request) {

		Point refPoint = ((LabelEditPart)getHost()).getReferencePoint();

		Rectangle centerMain = null;
		if(((IGraphicalEditPart)getHost().getParent()).getFigure() instanceof Connection) {
			centerMain = new Rectangle(refPoint.x, refPoint.y, 0, 0);
		} else {
			centerMain = ((IGraphicalEditPart)getHost().getParent()).getFigure().getBounds().getCopy();
			centerMain.translate(centerMain.width / 2, centerMain.height / 2);
		}

		PrecisionRectangle ref = new PrecisionRectangle(centerMain);
		getHostFigure().translateToAbsolute(ref);
		getDragSourceFeedbackFigure().translateToRelative(ref);
		return ref.getLocation();
	}

	/**
	 * Get the point for starting the link
	 * 
	 * @param request
	 *        change bounds request
	 * @param referencePoint
	 *        the reference point at the center of the start figure
	 * @param endPoint
	 *        the end point at the border of the end figure
	 * @return point where to start the link
	 */
	private Point getLinkStartPoint(ChangeBoundsRequest request, Point referencePoint, Point endPoint) {
		Point u1 = referencePoint;
		Point u2 = endPoint;
		if(getHost().getParent() instanceof AbstractBorderedShapeEditPart) {
			// the parent figure is a node : choose a point on its border
			AbstractBorderedShapeEditPart parentPart = (AbstractBorderedShapeEditPart)getHost().getParent();
			IFigure fig = parentPart.getMainFigure();
			if(fig instanceof NodeFigure) {
				PointList pointsList = ((NodeFigure)fig).getPolygonPoints().getCopy();
				// translate points relatively to drag feedback
				fig.translateToAbsolute(pointsList);
				getDragSourceFeedbackFigure().translateToRelative(pointsList);
				return getIntersectionPoint(pointsList, u1, u2);
			}
		}
		// either computation failed or the parent figure is a link
		return referencePoint;
	}

	/**
	 * Get the point for ending the link
	 * 
	 * @param request
	 *        change bounds request
	 * @param referencePoint
	 *        the reference point at the center of the start figure
	 * @return point
	 */
	private Point getLinkEndPoint(ChangeBoundsRequest request, Point referencePoint) {
		Rectangle rect = getDragSourceFeedbackFigure().getBounds();
		Point endPoint = getAppropriateBorderPoint(referencePoint, rect);
		return endPoint;
	}

	/**
	 * Get the point on the border intersection the segment
	 * 
	 * @param polygonalBounds
	 *        the list of points tracing the border
	 * @param insidePoint
	 *        first segment extremity
	 * @param outsideExtremity
	 *        second segment extremity
	 * @return the intersection point or null if none
	 */
	public static Point getIntersectionPoint(PointList polygonalBounds, Point insidePoint, Point outsideExtremity) {
		Point intersection = null;
		int i = 0;
		while(intersection == null && i < polygonalBounds.size() - 1) {
			Point v1 = polygonalBounds.getPoint(i).getCopy();
			Point v2 = polygonalBounds.getPoint(i + 1).getCopy();
			intersection = getIntersection(insidePoint, outsideExtremity, v1, v2);
			i++;
		}
		return intersection;
	}

	/**
	 * Get the point of the border which is the more appropriated to link to the
	 * reference point
	 * 
	 * @param referencePoint
	 *        point to refer to, which the link is directed to (not
	 *        necessary an end of the link)
	 * @param border
	 *        the border on which an anchoring point must be chosen
	 * @return a point of the border to use as link end
	 */
	public static Point getAppropriateBorderPoint(Point referencePoint, Rectangle border) {
		Point midTop = new Point(border.x + border.width / 2, border.y);
		Point midBottom = new Point(border.x + border.width / 2, border.y + border.height);
		Point midLeft = new Point(border.x, border.y + border.height / 2);
		Point midRight = new Point(border.x + border.width, border.y + border.height / 2);

		Dimension diffTop = referencePoint.getDifference(midTop);
		Dimension diffBottom = referencePoint.getDifference(midBottom);
		Dimension diffRight = referencePoint.getDifference(midRight);
		Dimension diffLeft = referencePoint.getDifference(midLeft);

		Point startPoint = midBottom;
		if(diffBottom.height > 0) {
			// check if right or left is more appropriated
			if(diffLeft.width < 0 && diffBottom.height < -diffLeft.width) {
				startPoint = midLeft;
			} else if(diffRight.width > 0 && diffBottom.height < diffRight.width) {
				startPoint = midRight;
			} else {
				startPoint = midBottom;
			}
		} else if(diffTop.height < 0) {
			// check if right or left is more appropriated
			if(diffLeft.width < 0 && -diffTop.height < -diffLeft.width) {
				startPoint = midLeft;
			} else if(diffRight.width > 0 && -diffTop.height < diffRight.width) {
				startPoint = midRight;
			} else {
				startPoint = midTop;
			}
		} else if(diffLeft.width < 0) {
			startPoint = midLeft;
		} else if(diffRight.width > 0) {
			startPoint = midRight;
		}
		return startPoint;
	}

	/**
	 * Get the intersection between segments joining the points
	 * 
	 * @param u1
	 *        the first extremity of the u segment
	 * @param u2
	 *        the second extremity of the u segment
	 * @param v1
	 *        the first extremity of the v segment
	 * @param v2
	 *        the second extremity of the v segment
	 * @return the intersection point or null if none
	 */
	public static Point getIntersection(Point u1, Point u2, Point v1, Point v2) {
		float denom = ((u2.y - u1.y) * (v2.x - v1.x)) - ((u2.x - u1.x) * (v2.y - v1.y));
		float nume_a = ((u2.x - u1.x) * (v1.y - u1.y)) - ((u2.y - u1.y) * (v1.x - u1.x));
		float nume_b = ((v2.x - v1.x) * (v1.y - u1.y)) - ((v2.y - v1.y) * (v1.x - u1.x));

		if(denom == 0.0f) {
			return null;
		}
		float ua = nume_a / denom;
		float ub = nume_b / denom;

		if(ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f) {
			// Get the intersection point.
			Float x = v1.x + ua * (v2.x - v1.x);
			Float y = v1.y + ua * (v2.y - v1.y);
			return new Point(x.intValue(), y.intValue());
		}
		return null;
	}
}

Back to the top