blob: 3ab027379d767d7e09d6f61d7d6a91754452e2a9 [file] [log] [blame]
/*****************************************************************************
* 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);
}
}
}