| /***************************************************************************** |
| * Copyright (c) 2019 CEA LIST. |
| * |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Xavier Le Pallec (for CEA LIST) xlepallec@lilo.org - Bug 558456 |
| * |
| *****************************************************************************/ |
| |
| package org.eclipse.papyrus.uml.diagram.clazz.lf.associationlabellayout.locators; |
| |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.gef.editparts.AbstractGraphicalEditPart; |
| import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.AssociationEditPart; |
| |
| /** |
| * This class defines objects that are helpers for associationEditPart for |
| * geometric operations.<BR> |
| * This class will be specialized for source and for target sides. <BR> |
| * Instances will allow to calculate: |
| * <UL> |
| * <LI>the gradient of segment (of the association) attached to the |
| * source/target class/side</LI> |
| * <LI>the angle of this segment from the attached class</LI> |
| * <LI>the direction of the segment (to the back ?)</LI> |
| * <LI>a point on the segment with a given distant to the beginning of the |
| * segment (connector segment-class)</LI> |
| * </UL> |
| * |
| */ |
| public abstract class AbstractAssociatedSegment { |
| protected IFigure target; |
| protected Point startingPoint = null; |
| protected Point endPoint = null; |
| protected AssociationEditPart associationEditPart; |
| |
| /** |
| * The object need the visual element (figure) and the whole association edit |
| * part |
| * |
| * @param target the visual element |
| * @param associationEditPart the whole manager of the association (the |
| * association edit part) |
| */ |
| public AbstractAssociatedSegment(IFigure target, AssociationEditPart associationEditPart) { |
| this.target = target; |
| this.associationEditPart = associationEditPart; |
| } |
| |
| /** |
| * Abstract method that will be implemented to give the starting point of the |
| * related segment |
| * |
| * @return the starting point of the segment (connector segment-class) |
| */ |
| public abstract Point getStartingPoint(); |
| |
| /** |
| * Abstract method that will be implemented to give the end point of the related |
| * segment (that can be the connector segment-class of the other side if the |
| * association is not multi-segmented) |
| * |
| * @return the end point of the segment (connector segment-class) |
| */ |
| public abstract Point getEndPoint(); |
| |
| /** |
| * Abstract method that will be implemented to give the class concerned by this |
| * side of the association (starting point is on this class) |
| * |
| * @return class related to this side of the association |
| */ |
| public abstract AbstractGraphicalEditPart getConnectedElement(); |
| |
| /** |
| * Gets the gradient of the segment (of the association if it is not |
| * multi-segmented) |
| * |
| * @return the gradiant |
| */ |
| public double getGradient() { |
| Point p1 = getStartingPoint(); |
| Point p2 = getEndPoint(); |
| return (double) (p2.y - p1.y) / (double) (p2.x - p1.x); |
| } |
| |
| /** |
| * Gets the angle of the segment (of the association if it is not |
| * multi-segmented) compared to a horizontal line. |
| * |
| * @return the angle (not in degrees) |
| */ |
| public double getAngle() { |
| return Math.atan(getGradient()); |
| } |
| |
| /** |
| * This method returns true if the end of the segment is "before" the start. |
| * |
| * @return true if the segment get back to the left. |
| */ |
| public boolean doesSegmentPointToBack() { |
| Point p1 = getStartingPoint(); |
| Point p2 = getEndPoint(); |
| return (p2.x < p1.x); |
| } |
| |
| /** |
| * Important method: gives a point on the segment with a given distant to the |
| * beginning of the segment |
| * |
| * @param distance distance between the starting point and the returned point |
| * @return the point at the wanted distant and on the segment |
| */ |
| public Point getThePointDistantOf(double distance) { |
| try { |
| |
| double angle = getAngle(); |
| double dx = distance * Math.cos(angle); |
| double dy = distance * Math.sin(angle); |
| Point currentStartingPoint = getStartingPoint(); |
| if (doesSegmentPointToBack()) |
| return new Point((int) (currentStartingPoint.x - dx), (int) (currentStartingPoint.y - dy)); |
| |
| return new Point((int) (currentStartingPoint.x + dx), (int) (currentStartingPoint.y + dy)); |
| |
| } catch (ArithmeticException ex) { |
| int x = getStartingPoint().x; |
| int y = getStartingPoint().y; |
| if (getStartingPoint().y < getEndPoint().y) |
| y += distance; |
| else |
| y -= distance; |
| return new Point(x, y); |
| } |
| |
| } |
| } |