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; } }