blob: 429115eac4fda33fc7ab7cd4d10e8e84452a8dab [file] [log] [blame]
package org.eclipse.gmf.tooling.runtime.linklf;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities;
import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure;
import org.eclipse.gmf.runtime.gef.ui.figures.SlidableAnchor;
public class SlidableSnapToGridAnchor extends SlidableAnchor {
private EditPartViewer myGridProvider;
public SlidableSnapToGridAnchor(NodeFigure f, PrecisionPoint p) {
super(f, p);
}
public void setEditPartViewer(EditPartViewer viewer) {
myGridProvider = viewer;
}
@Override
public Point getOrthogonalLocation(Point orthoReference) {
// System.err.println("SlidableSnapToGridAnchor.getOrthogonalLocation(): " + orthoReference);
// System.err.println("\t" + this);
// Point ownRef = getReferencePoint();
// if (ownRef != null && ownRef.y > 430 && ownRef.y < 440) {
// System.err.println("here");
// }
Point result = super.getOrthogonalLocation(orthoReference);
return result;
}
private boolean myReentryLock = false;
@Override
public Point getLocation(Point reference) {
// System.err.println("SlidableSnapToGridAnchor.getLocation(): " + reference);
// System.err.println("\t" + this);
Rectangle gridSpecAbs = getAbsoluteGridSpec();
if (gridSpecAbs != null && !myReentryLock) {
myReentryLock = true;
try {
double gridX = gridSpecAbs.preciseWidth();
double gridY = gridSpecAbs.preciseWidth();
Point gridOrigin = gridSpecAbs.getLocation();
Point notOnGrid = super.getLocation(reference).getCopy();
PrecisionRectangle bounds = new PrecisionRectangle(FigureUtilities.getAnchorableFigureBounds(getOwner()));
getOwner().translateToAbsolute(bounds);
List<Point> onVerticalGridLocs = new LinkedList<Point>();
PrecisionPoint fakeRefAbove = new PrecisionPoint(notOnGrid);
PrecisionPoint fakeRefBelow = new PrecisionPoint(notOnGrid);
fakeRefAbove.setPreciseY(bounds.preciseY() - bounds.preciseHeight() / 2);
fakeRefBelow.setPreciseY(bounds.preciseY() + bounds.preciseHeight() / 2 + bounds.preciseHeight());
double reminderX = Math.IEEEremainder(notOnGrid.preciseX() - gridOrigin.preciseX(), gridX);
if (reminderX < 0) {
reminderX += gridX;
}
for (double nextX = notOnGrid.preciseX() - reminderX; nextX >= bounds.preciseX(); nextX -= gridX) {
fakeRefAbove.setPreciseX(nextX);
fakeRefBelow.setPreciseX(nextX);
Point onGridForAboveRef = getOrthogonalLocation2(fakeRefAbove);
Point onGridForBelowRef = getOrthogonalLocation2(fakeRefBelow);
onVerticalGridLocs.add(onGridForAboveRef);
if (!onGridForBelowRef.equals(onGridForAboveRef)) {
onVerticalGridLocs.add(onGridForBelowRef);
}
}
for (double nextX = gridX + notOnGrid.preciseX() - reminderX; nextX <= bounds.preciseX() + bounds.preciseWidth(); nextX += gridX) {
fakeRefAbove.setPreciseX(nextX);
fakeRefBelow.setPreciseX(nextX);
Point onGridForAboveRef = getOrthogonalLocation2(fakeRefAbove);
Point onGridForBelowRef = getOrthogonalLocation2(fakeRefBelow);
onVerticalGridLocs.add(onGridForAboveRef);
if (!onGridForBelowRef.equals(onGridForAboveRef)) {
onVerticalGridLocs.add(onGridForBelowRef);
}
}
List<Point> onHorizontalGridLocs = new LinkedList<Point>();
PrecisionPoint fakeRefLeft = new PrecisionPoint(notOnGrid);
PrecisionPoint fakeRefRight = new PrecisionPoint(notOnGrid);
fakeRefLeft.setPreciseX(bounds.preciseX() - bounds.preciseWidth() / 2);
fakeRefRight.setPreciseX(bounds.preciseX() + bounds.preciseWidth() + bounds.preciseWidth() / 2);
double reminderY = Math.IEEEremainder(notOnGrid.preciseY() - gridOrigin.preciseY(), gridY);
if (reminderY < 0) {
reminderY += gridY;
}
for (double nextY = notOnGrid.preciseY() - reminderY; nextY >= bounds.preciseY(); nextY -= gridY) {
fakeRefLeft.setPreciseY(nextY);
fakeRefRight.setPreciseY(nextY);
Point onGridForLeftRef = getOrthogonalLocation2(fakeRefLeft);
Point onGridForRightRef = getOrthogonalLocation2(fakeRefRight);
onHorizontalGridLocs.add(onGridForLeftRef);
if (!onGridForLeftRef.equals(onGridForRightRef)) {
onHorizontalGridLocs.add(onGridForRightRef);
}
}
for (double nextY = gridY + notOnGrid.preciseY() - reminderY; nextY <= bounds.preciseY() + bounds.preciseHeight(); nextY += gridY) {
fakeRefLeft.setPreciseY(nextY);
fakeRefRight.setPreciseY(nextY);
Point onGridForLeftRef = getOrthogonalLocation2(fakeRefLeft);
Point onGridForRightRef = getOrthogonalLocation2(fakeRefRight);
onHorizontalGridLocs.add(onGridForLeftRef);
if (!onGridForLeftRef.equals(onGridForRightRef)) {
onHorizontalGridLocs.add(onGridForRightRef);
}
}
//System.err.println("Found: on horizontal grid: " + onHorizontalGridLocs);
//System.err.println("Found: on vertical grid: " + onVerticalGridLocs);
if (!onHorizontalGridLocs.isEmpty() || !onVerticalGridLocs.isEmpty()) {
return pickClosestPointToSet(getReferencePoint(), onHorizontalGridLocs, onVerticalGridLocs);
}
} finally {
myReentryLock = false;
}
}
Point result = super.getLocation(reference);
return result;
}
@Override
public String toString() {
return "SSTGA:" + "terminal: " + getTerminal() + ", terminalLoc: " + getReferencePoint() + ", box: " + getBox();
}
/**
* @deprecated copy-pasted from super class, [GMFRT] make protected
*/
@Deprecated
private Point getOrthogonalLocation2(Point orthoReference) {
PrecisionPoint ownReference = new PrecisionPoint(getReferencePoint());
PrecisionRectangle bounds = new PrecisionRectangle(FigureUtilities.getAnchorableFigureBounds(getOwner()));
getOwner().translateToAbsolute(bounds);
bounds.expand(0.000001, 0.000001);
PrecisionPoint preciseOrthoReference = new PrecisionPoint(orthoReference);
int orientation = PositionConstants.NONE;
if (bounds.contains(preciseOrthoReference)) {
int side = getClosestSide2(ownReference, bounds);
switch (side) {
case PositionConstants.LEFT:
case PositionConstants.RIGHT:
ownReference.preciseY = preciseOrthoReference.preciseY();
orientation = PositionConstants.HORIZONTAL;
break;
case PositionConstants.TOP:
case PositionConstants.BOTTOM:
ownReference.preciseX = preciseOrthoReference.preciseX();
orientation = PositionConstants.VERTICAL;
break;
}
} else if (preciseOrthoReference.preciseX >= bounds.preciseX && preciseOrthoReference.preciseX <= bounds.preciseX + bounds.preciseWidth) {
ownReference.preciseX = preciseOrthoReference.preciseX;
orientation = PositionConstants.VERTICAL;
} else if (preciseOrthoReference.preciseY >= bounds.preciseY && preciseOrthoReference.preciseY <= bounds.preciseY + bounds.preciseHeight) {
ownReference.preciseY = preciseOrthoReference.preciseY;
orientation = PositionConstants.HORIZONTAL;
}
ownReference.updateInts();
Point location = getLocation(ownReference, preciseOrthoReference);
if (location == null) {
location = getLocation(orthoReference);
orientation = PositionConstants.NONE;
}
if (orientation != PositionConstants.NONE) {
PrecisionPoint loc = new PrecisionPoint(location);
if (orientation == PositionConstants.VERTICAL) {
loc.preciseX = preciseOrthoReference.preciseX;
} else {
loc.preciseY = preciseOrthoReference.preciseY;
}
loc.updateInts();
location = loc;
}
return location;
}
/**
* Returns the position of the closest edge of the rectangle closest to the point
* @param p the point
* @param r the rectangle
* @return position of the closest edge
* @deprecated copy-pasted from super class, [GMFRT] make protected
*/
@Deprecated
private static int getClosestSide2(Point p, Rectangle r) {
double diff = Math.abs(r.preciseX() + r.preciseWidth() - p.preciseX());
int side = PositionConstants.RIGHT;
double currentDiff = Math.abs(r.preciseX() - p.preciseX());
if (currentDiff < diff) {
diff = currentDiff;
side = PositionConstants.LEFT;
}
currentDiff = Math.abs(r.preciseY() + r.preciseHeight() - p.preciseY());
if (currentDiff < diff) {
diff = currentDiff;
side = PositionConstants.BOTTOM;
}
currentDiff = Math.abs(r.preciseY() - p.preciseY());
if (currentDiff < diff) {
diff = currentDiff;
side = PositionConstants.TOP;
}
return side;
}
/**
* If grid provider had been set up and has grid enabled then returns active grid specification in absolute coordinates.
* Otherwise returns null.
* @return <code>null</code> if no active grid or grid provider had not been set up.
*/
protected Rectangle getAbsoluteGridSpec() {
return myGridProvider == null ? null : DiagramGridSpec.getAbsoluteGridSpec(myGridProvider);
}
private static Point pickClosestPointToSet(Point source, Collection<? extends Point> set1, Collection<? extends Point> set2) {
double bestDistSquared = Double.MAX_VALUE;
Point result = null;
for (Point next : set1) {
double nextDistSquared = source.getDistance(next);
if (nextDistSquared < bestDistSquared) {
result = next;
bestDistSquared = nextDistSquared;
}
}
for (Point next : set2) {
double nextDistSquared = source.getDistance(next);
if (nextDistSquared < bestDistSquared) {
result = next;
bestDistSquared = nextDistSquared;
}
}
return result;
}
}