package org.eclipse.papyrus.uml.diagram.sequence.edit.helpers;
import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.transaction.RunnableWithResult;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.requests.DropRequest;
import org.eclipse.gef.requests.ReconnectRequest;
import org.eclipse.gmf.runtime.common.core.util.Log;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIPlugin;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIStatusCodes;
import org.eclipse.gmf.runtime.gef.ui.figures.DefaultSizeNodeFigure;
import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure;
import org.eclipse.gmf.runtime.gef.ui.figures.SlidableAnchor;
import org.eclipse.gmf.runtime.notation.Anchor;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.IdentityAnchor;
import org.eclipse.papyrus.uml.diagram.common.draw2d.anchors.FixedAnchor;
public class AnchorHelper {
public static String getAnchorId(TransactionalEditingDomain domain, ConnectionEditPart connEditPart, final boolean isSource) {
final org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart connection =
(org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart)connEditPart;
String t = ""; //$NON-NLS-1$
try {
t = (String) domain.runExclusive(
new RunnableWithResult.Impl() {
public void run() {
Anchor a = null;
if(isSource)
a = ((Edge)connection.getModel()).getSourceAnchor();
else
a = ((Edge)connection.getModel()).getTargetAnchor();
if (a instanceof IdentityAnchor)
setResult(((IdentityAnchor) a).getId());
else
setResult(""); //$NON-NLS-1$
}
});
} catch (InterruptedException e) {
Log.error(DiagramUIPlugin.getInstance(),
DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING,
"getTargetConnectionAnchor", e); //$NON-NLS-1$
}
return t;
}
public static Point getRequestLocation(Request request){
if (request instanceof ReconnectRequest) {
if (((DropRequest) request).getLocation() != null) {
Point pt = ((DropRequest) request).getLocation().getCopy();
return pt;
}
}
else if (request instanceof DropRequest){
return ((DropRequest) request).getLocation();
}
return null;
}
public static class CombinedFragmentNodeFigure extends DefaultSizeNodeFigure{
public CombinedFragmentNodeFigure(int width, int height) {
super(width, height);
}
protected ConnectionAnchor createAnchor(PrecisionPoint p) {
if (p==null)
// If the old terminal for the connection anchor cannot be resolved (by SlidableAnchor) a null
// PrecisionPoint will passed in - this is handled here
return createDefaultAnchor();
return new AnchorHelper.IntersectionPointAnchor(this, p);
}
}
public static class IntersectionPointAnchor extends SlidableAnchor{
public IntersectionPointAnchor(IFigure fig, PrecisionPoint p) {
super(fig,p);
}
public IntersectionPointAnchor(IFigure fig) {
super(fig);
}
protected Point getLocation(Point ownReference, Point foreignReference) {
PointList intersections = getIntersectionPoints(ownReference, foreignReference);
if (intersections!=null && intersections.size()!=0) {
int size = intersections.size();
double dist = foreignReference.getDistance(ownReference);
for(int i = 0; i < size; i ++){
Point loc = intersections.getPoint(i);
if(isInOrder(foreignReference,ownReference,dist, loc)){
return loc;
}
}
return intersections.getFirstPoint();
}
return null;
}
private boolean isInOrder(Point start, Point end, double dist, Point loc) {
double total = loc.getDistance(start);
double dist2 = loc.getDistance(end);
if(total < dist || total < dist2)
return false;
if(Math.abs(total - dist - dist2) < 0.01)
return true;
return false;
}
}
public static class FixedAnchorEx extends FixedAnchor {
private int location;
public FixedAnchorEx(IFigure f, int location) {
super(f, location);
this.location = location;
}
public Point getLocation(Point reference) {
if(location == TOP)
return getBox().getTop();
else if(location == BOTTOM)
return getBox().getBottom();
return super.getLocation(reference);
}
}
public static class SideAnchor extends SlidableAnchor{
private boolean isRight;
public SideAnchor(NodeFigure nodeFigure, PrecisionPoint pt,
boolean isRight) {
super(nodeFigure, pt);
this.isRight = isRight;
}
public boolean isRight() {
return isRight;
}
public String getTerminal() {
String side = isRight? "R": "L";
return super.getTerminal() + "{" + side + "}";
}
}
public static class InnerPointAnchor extends SlidableAnchor{
private PrecisionPoint percent;
private IFigure figure;
public InnerPointAnchor(IFigure fig, PrecisionPoint percent) {
super(fig,percent);
this.figure = fig;
this.percent = percent;
}
public static InnerPointAnchor createAnchorAtLocation(IFigure fig, PrecisionPoint loc) {
PrecisionPoint p = loc.getPreciseCopy();
Rectangle b = fig.getBounds().getCopy();
fig.translateToAbsolute(b);
Dimension d = p.getDifference(b.getTopLeft());
PrecisionPoint per = new PrecisionPoint( d.preciseWidth()/ b.width , d.preciseHeight() / b.height);
return new InnerPointAnchor(fig, per);
}
protected Point getLocation(Point ownReference, Point foreignReference) {
PrecisionRectangle bounds = new PrecisionRectangle(figure.getBounds());
bounds.setPreciseWidth((bounds.width * percent.preciseX()));
bounds.setPreciseHeight((bounds.height * percent.preciseY()));
figure.translateToAbsolute(bounds);
return bounds.getBottomRight();
}
}
}