Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.tooling.runtime/src/org/eclipse/papyrus/infra/gmfdiag/tooling/runtime/linklf/policies/ConnectionBendpointEditPolicy2.java')
-rwxr-xr-xplugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.tooling.runtime/src/org/eclipse/papyrus/infra/gmfdiag/tooling/runtime/linklf/policies/ConnectionBendpointEditPolicy2.java1000
1 files changed, 1000 insertions, 0 deletions
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.tooling.runtime/src/org/eclipse/papyrus/infra/gmfdiag/tooling/runtime/linklf/policies/ConnectionBendpointEditPolicy2.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.tooling.runtime/src/org/eclipse/papyrus/infra/gmfdiag/tooling/runtime/linklf/policies/ConnectionBendpointEditPolicy2.java
new file mode 100755
index 00000000000..9fe76ba1020
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.tooling.runtime/src/org/eclipse/papyrus/infra/gmfdiag/tooling/runtime/linklf/policies/ConnectionBendpointEditPolicy2.java
@@ -0,0 +1,1000 @@
+/*****************************************************************************
+ * Copyright (c) (c) 2002, 2007 IBM Corporation, 2014 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.gmfdiag.tooling.runtime.linklf.policies;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.draw2d.AbsoluteBendpoint;
+import org.eclipse.draw2d.AutomaticRouter;
+import org.eclipse.draw2d.Bendpoint;
+import org.eclipse.draw2d.BendpointLocator;
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.ConnectionAnchor;
+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.gef.AccessibleHandleProvider;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editpolicies.SelectionHandlesEditPolicy;
+import org.eclipse.gef.handles.BendpointCreationHandle;
+import org.eclipse.gef.handles.BendpointMoveHandle;
+import org.eclipse.gef.requests.BendpointRequest;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ConnectionBendpointEditPolicy;
+import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities;
+import org.eclipse.gmf.runtime.draw2d.ui.geometry.LineSeg;
+import org.eclipse.gmf.runtime.draw2d.ui.geometry.PointListUtilities;
+import org.eclipse.gmf.runtime.draw2d.ui.internal.figures.FeedbackConnection;
+import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
+import org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.LineMode;
+import org.eclipse.gmf.runtime.gef.ui.internal.handles.BendpointCreationInvisibleHandle;
+import org.eclipse.gmf.runtime.gef.ui.internal.handles.BendpointMoveHandleEx;
+import org.eclipse.gmf.runtime.gef.ui.internal.handles.LineSegMoveInvisibleHandle;
+
+/**
+ * [GMFRT] make protected in
+ * {@link org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.ConnectionBendpointEditPolicy}
+ * <p/>
+ * This class is a temporary workaround for bunch of private methods in the
+ * hierarchy of {@link ConnectionBendpointEditPolicy} we would like to override.
+ * <p/>
+ * We would like to avoid the mix of the copy-pasted now-protected code in this
+ * class with the actual modifications made in the
+ * {@link LinksLFConnectionBendpointEditPolicy}.
+ * <p/>
+ * The changes made in this class are:
+ * <ul>
+ * <li>{@link #showMoveOrthogonalBenspointFeedback()} is made protected</li>
+ * <li>{@link #showOutsideSourceFeedback()} is made protected</li>
+ * <li>{@link #showOutsideTargetFeedback()} is made protected</li>
+ * </ul>
+ * This class as a whole should be removed when the GMFT runtime will make the
+ * corresponding methods protected.
+ * <p/>
+ * This class is intentionally package local and should be removed after patch
+ * for bug 331779 is merged.
+ *
+ * @since 3.3
+ * @see also {@link ConnectionBendpointEditPolicy3} which is parallel
+ * replacement for a similarly named
+ * {@link org.eclipse.gmf.runtime.diagram.ui.editpolicies.ConnectionBendpointEditPolicy}
+ * from gmf.runtime.diagram.ui
+ * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=331779
+ *
+ */
+@Deprecated
+abstract class ConnectionBendpointEditPolicy2 extends
+ SelectionHandlesEditPolicy implements PropertyChangeListener {
+
+ private static List NULL_CONSTRAINT = new ArrayList();
+ private static final int STICKY_TOLERANCE_DP = 6;
+
+ private LineMode lineSegMode = LineMode.OBLIQUE;
+
+ static private class FeedbackState {
+ public List originalConstraint;
+ public Point ref1 = new Point();
+ public Point ref2 = new Point();
+ public boolean isDeleting = false;
+ public boolean isOutsideSource = false;
+ public boolean isOutsideTarget = false;
+ public boolean init = false;
+ }
+
+ private FeedbackState feedbackState = null;
+
+ private FeedbackState getFeedbackState() {
+ if (feedbackState == null) {
+ feedbackState = new FeedbackState();
+ }
+
+ return feedbackState;
+ }
+
+ private boolean useRealtimeFeedback() {
+ return false;
+ }
+
+ /**
+ * Constructor for EditPolicy
+ *
+ * @param lineSegMode
+ */
+ public ConnectionBendpointEditPolicy2(LineMode lineSegMode) {
+ super();
+ this.lineSegMode = lineSegMode;
+ }
+
+ /**
+ * @return Returns the lineSegMode.
+ */
+ public LineMode getLineSegMode() {
+ return lineSegMode;
+ }
+
+ /**
+ * Adds a PropertyChangeListener to the Connection so we can react to point
+ * changes in the connection.
+ *
+ * @see SelectionHandlesEditPolicy#activate()
+ */
+ public void activate() {
+ super.activate();
+ getConnection().addPropertyChangeListener(Connection.PROPERTY_POINTS,
+ this);
+ }
+
+ /**
+ * @return <code>Connection</code> representing drag source feedback
+ */
+ protected Connection createDragSourceFeedbackConnection() {
+ if (useRealtimeFeedback()) {
+ // Use the actual figure for feedback
+ return getConnection();
+ } else {
+ // Use a ghost rectangle for feedback
+ FeedbackConnection r = new FeedbackConnection(getConnection());
+ addFeedback(r);
+ return r;
+ }
+ }
+
+ /**
+ * Adds selection handles to the connection for the bendpoints. In this
+ * class, this method just decides if it is appropriate to add the handles,
+ * and then calls on the superclass to do the dirty work.s
+ */
+ protected void addSelectionHandles() {
+ if (handles == null)
+ super.addSelectionHandles();
+ else {
+ int count = handles.size();
+ int points = getConnection().getPoints().size();
+ if (count != points * 2 - 3)
+ super.addSelectionHandles();
+ }
+ }
+
+ /**
+ * @return list of manual handles
+ */
+ protected List createManualHandles() {
+ List list = new ArrayList();
+ ConnectionEditPart connEP = (ConnectionEditPart) getHost();
+ PointList points = getConnection().getPoints();
+ for (int i = 1; i < points.size() - 1; i++) {
+ addInvisibleCreationHandle(list, connEP, i - 1);
+ list.add(new BendpointMoveHandleEx(connEP, i, new BendpointLocator(
+ getConnection(), i)));
+ }
+ addInvisibleCreationHandle(list, connEP, points.size() - 2);
+ return list;
+ }
+
+ /**
+ * Method addInvisibleCreationHandle. This handle is necessary for the
+ * accessibility feature to allow keyboard navigation to the add bendpoint
+ * feature.
+ *
+ * @param list
+ * @param connEP
+ * @param i
+ */
+ protected void addInvisibleCreationHandle(List list,
+ ConnectionEditPart connEP, int i) {
+ if (getLineSegMode() != LineMode.OBLIQUE) {
+ list.add(new LineSegMoveInvisibleHandle(connEP, i));
+ } else {
+ list.add(new BendpointCreationInvisibleHandle(connEP, i));
+ }
+ }
+
+ /**
+ * Creates selection handles for the bendpoints. Explicit (user-defined)
+ * bendpoints will have {@link BendpointMoveHandle}s on them with a single
+ * {@link BendpointCreationHandle} between 2 consecutive explicit
+ * bendpoints. If implicit bendpoints (such as those created by the
+ * {@link AutomaticRouter}) are used, one {@link BendpointCreationHandle} is
+ * placed in the middle of the Connection.
+ */
+ protected List createSelectionHandles() {
+ return createManualHandles();
+ }
+
+ /**
+ * Removes this from the Connection's list of PropertyChangeListeners.
+ *
+ * @see SelectionHandlesEditPolicy#deactivate()
+ */
+ public void deactivate() {
+ getConnection().removePropertyChangeListener(
+ Connection.PROPERTY_POINTS, this);
+
+ super.deactivate();
+ }
+
+ /**
+ * Erases bendpoint feedback. Since the original figure is used for
+ * feedback, we just restore the original constraint that was saved before
+ * feedback started to show.
+ */
+ protected void eraseConnectionFeedback(BendpointRequest request,
+ boolean removeFeedbackFigure) {
+ restoreOriginalConstraint();
+ getFeedbackState().originalConstraint = null;
+ if (removeFeedbackFigure)
+ feedbackState = null;
+ }
+
+ /**
+ * Erases feedback, when appropriate.
+ *
+ * @see #eraseConnectionFeedback(BendpointRequest, boolean)
+ */
+ public void eraseSourceFeedback(Request request) {
+ if (REQ_MOVE_BENDPOINT.equals(request.getType())
+ || REQ_CREATE_BENDPOINT.equals(request.getType()))
+ eraseConnectionFeedback((BendpointRequest) request, true);
+ }
+
+ /**
+ * Returns the appropriate Command for the request type given. Handles
+ * creating, moving and deleting bendpoints. The actual creation of the
+ * command is taken care of by subclasses implementing the appropriate
+ * methods.
+ *
+ * @see #getCreateBendpointCommand(BendpointRequest)
+ * @see #getMoveBendpointCommand(BendpointRequest)
+ * @see #getDeleteBendpointCommand(BendpointRequest)
+ */
+ public Command getCommand(Request request) {
+ if (REQ_MOVE_BENDPOINT.equals(request.getType())) {
+ if (getLineSegMode() != LineMode.OBLIQUE) {
+ return getMoveLineSegCommand((BendpointRequest) request);
+ } else {
+ if (getFeedbackState().isDeleting)
+ return getDeleteBendpointCommand((BendpointRequest) request);
+ return getMoveBendpointCommand((BendpointRequest) request);
+ }
+ }
+ if (REQ_CREATE_BENDPOINT.equals(request.getType()))
+ return getCreateBendpointCommand((BendpointRequest) request);
+
+ return null;
+ }
+
+ /**
+ * Returns the Connection associated with this EditPolicy.
+ */
+ protected Connection getConnection() {
+ return (Connection) ((ConnectionEditPart) getHost()).getFigure();
+ }
+
+ /**
+ * @return Point cached value representing the first reference point.
+ */
+ private Point getFirstReferencePoint() {
+ return getFeedbackState().ref1;
+ }
+
+ /**
+ * @return Point cached value representing the second reference point.
+ */
+ private Point getSecondReferencePoint() {
+ return getFeedbackState().ref2;
+ }
+
+ /**
+ * Utility method to determine if point p passes through the line segment
+ * defined by p1 and p2.
+ *
+ * @param p1
+ * Point that is the first point in the line segment to test
+ * against.
+ * @param p2
+ * Point that is the second point in the line segment to test
+ * against.
+ * @param p
+ * Point that is tested to see if it falls in the line segment
+ * defined by p1 and p2.
+ * @return true if line segment contains Point p, false otherwise.
+ */
+ private boolean lineContainsPoint(Point p1, Point p2, Point p) {
+ LineSeg line = new LineSeg(p1, p2);
+ return line.containsPoint(p, getStickyTolerance() / 3);
+ }
+
+ /**
+ * Adds selection handles to the Connection, if it is selected, when the
+ * points property changes. Since we only listen for changes in the points
+ * property, this method is only called when the points of the Connection
+ * have changed.
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (getHost().getSelected() != EditPart.SELECTED_NONE) {
+ // int count = handles.size();
+ // int points = getConnection().getPoints().size();
+ // if (count != points * 2 - 3)
+ addSelectionHandles();
+ }
+ }
+
+ /**
+ * Restores the original constraint that was saved before feedback began to
+ * show.
+ */
+ protected void restoreOriginalConstraint() {
+ if (getFeedbackState().originalConstraint != null) {
+ Assert.isTrue(getFeedbackState().originalConstraint.size() >= 2);
+ getConnection().setRoutingConstraint(
+ getFeedbackState().originalConstraint);
+ }
+ }
+
+ /**
+ * Since the original figure is used for feedback, this method saves the
+ * original constraint, so that is can be restored when the feedback is
+ * erased.
+ */
+ protected void saveOriginalConstraint() {
+ getFeedbackState().originalConstraint = (List) getConnection()
+ .getRoutingConstraint();
+ if (getFeedbackState().originalConstraint == null)
+ getFeedbackState().originalConstraint = NULL_CONSTRAINT;
+
+ if (getLineSegMode() != LineMode.OBLIQUE && !getFeedbackState().init) {
+ // Update the constraint based on the current figure
+ List newConstraint = new ArrayList(
+ getFeedbackState().originalConstraint.size());
+ PointList pts = PointListUtilities.copyPoints(getConnection()
+ .getPoints());
+ // OrthogonalRouterUtilities.resetEndPointsToCenter(getConnection(),
+ // pts);
+
+ for (int i = 0; i < pts.size(); i++) {
+ Bendpoint abp = new AbsoluteBendpoint(pts.getPoint(i));
+ newConstraint.add(abp);
+ }
+
+ Assert.isTrue(getFeedbackState().originalConstraint.size() >= 2);
+ getConnection().setRoutingConstraint(newConstraint);
+
+ // reset booleans
+ getFeedbackState().isOutsideSource = false;
+ getFeedbackState().isOutsideTarget = false;
+ } else {
+ // if the constraint and the connection figure points list don't
+ // match then reset the constraint
+ // based on the connection figure list. This could happen in certain
+ // cases - sepcifically when
+ // fan router detects a collision or when a self relation is routed.
+ int nConstraintSize = getFeedbackState().originalConstraint.size();
+ PointList pts = getConnection().getPoints();
+ int nPointSize = pts.size();
+
+ if (!getFeedbackState().init && nConstraintSize != nPointSize) {
+
+ while (getFeedbackState().originalConstraint.size() > 0) {
+ getFeedbackState().originalConstraint.remove(0);
+ }
+
+ for (int i = 0; i < pts.size(); i++) {
+ Bendpoint bpNew = new AbsoluteBendpoint(pts.getPoint(i));
+ getFeedbackState().originalConstraint.add(i, bpNew);
+ }
+ }
+
+ Assert.isTrue(getFeedbackState().originalConstraint.size() >= 2);
+ getConnection().setRoutingConstraint(
+ new ArrayList(getFeedbackState().originalConstraint));
+ }
+
+ getFeedbackState().init = true;
+ }
+
+ /**
+ * Method setReferencePoints. This method will calculate the two end
+ * reference points for a point that is being moved or created. The
+ * reference points are used to determine if the request point can be
+ * deleted or not (for straight line tolerance).
+ *
+ * @param request
+ * BendpointRequest object containing index information.
+ */
+ private void setReferencePoints(BendpointRequest request) {
+ if (getFeedbackState().originalConstraint == null) {
+ saveOriginalConstraint();
+ }
+
+ List constraint = (List) getConnection().getRoutingConstraint();
+ Bendpoint bp = (Bendpoint) constraint.get(Math.max(0,
+ request.getIndex() - 1));
+ getFeedbackState().ref1 = bp.getLocation();
+
+ bp = (Bendpoint) constraint.get(Math.min(request.getIndex() + 1,
+ constraint.size() - 1));
+ getFeedbackState().ref2 = bp.getLocation();
+ }
+
+ private void setNewFeedbackConstraint(List constraint) {
+ Assert.isTrue(constraint.size() >= 2);
+ getConnection().setRoutingConstraint(constraint);
+ }
+
+ /**
+ * Shows feedback when a bendpoint is being created. The original figure is
+ * used for feedback and the original constraint is saved, so that it can be
+ * restored when feedback is erased.
+ */
+ protected void showCreateBendpointFeedback(BendpointRequest request) {
+ Point p = new Point(request.getLocation());
+ List constraint;
+
+ getConnection().translateToRelative(p);
+
+ Bendpoint bp = new AbsoluteBendpoint(p);
+ if (getFeedbackState().originalConstraint == null) {
+ saveOriginalConstraint();
+ constraint = (List) getConnection().getRoutingConstraint();
+ constraint.add(request.getIndex() + 1, bp);
+ } else {
+ constraint = (List) getConnection().getRoutingConstraint();
+ }
+
+ stickyStraightLineFeedback(constraint, request.getIndex() + 1, bp);
+
+ setNewFeedbackConstraint(constraint);
+ }
+
+ /**
+ * Shows feedback when a bendpoint is being deleted. This method is only
+ * called once when the bendpoint is first deleted, not every mouse move.
+ * The original figure is used for feedback and the original constraint is
+ * saved, so that it can be restored when feedback is erased.
+ */
+ protected void showDeleteBendpointFeedback(BendpointRequest request) {
+ if (getFeedbackState().originalConstraint == null) {
+ saveOriginalConstraint();
+ List constraint = (List) getConnection().getRoutingConstraint();
+ constraint.remove(request.getIndex());
+
+ setNewFeedbackConstraint(constraint);
+ }
+ }
+
+ /**
+ * Shows feedback when a bendpoint is being moved. Also checks to see if the
+ * bendpoint should be deleted and then calls
+ * {@link #showDeleteBendpointFeedback(BendpointRequest)} if needed. The
+ * original figure is used for feedback and the original constraint is
+ * saved, so that it can be restored when feedback is erased.
+ */
+ protected void showMoveBendpointFeedback(BendpointRequest request) {
+ Point p = new Point(request.getLocation());
+ if (!getFeedbackState().isDeleting) {
+ setReferencePoints(request);
+ }
+
+ getConnection().translateToRelative(p);
+ Bendpoint bp = new AbsoluteBendpoint(p);
+
+ if (getFeedbackState().originalConstraint == null) {
+ saveOriginalConstraint();
+ }
+
+ if (lineContainsPoint(getFirstReferencePoint(),
+ getSecondReferencePoint(), p)) {
+ if (!getFeedbackState().isDeleting) {
+ getFeedbackState().isDeleting = true;
+ eraseConnectionFeedback(request, false);
+ showDeleteBendpointFeedback(request);
+ }
+ return;
+ }
+ if (getFeedbackState().isDeleting) {
+ getFeedbackState().isDeleting = false;
+ eraseConnectionFeedback(request, false);
+ }
+
+ List constraint = (List) getConnection().getRoutingConstraint();
+ stickyStraightLineFeedback(constraint, request.getIndex(), bp);
+
+ setNewFeedbackConstraint(constraint);
+ }
+
+ /**
+ * This method will set the constraint with the given bendpoint, with the
+ * additional behavior of "sticking" the point around a tolerance to a
+ * straight line. If it's within a tolerance of the previous point, stick it
+ * to the horizontal or vertical coordinates that make it straight.
+ */
+ protected void stickyStraightLineFeedback(List constraint, int nIndex,
+ Bendpoint bp) {
+ Point ptLoc = new Point(bp.getLocation());
+
+ int sticky_tolerance = getStickyTolerance();
+
+ if (nIndex > 0) {
+ Point ptPrev;
+ if ((nIndex - 1) == 0) {
+ ptPrev = getConnection().getSourceAnchor().getReferencePoint();
+ getConnection().translateToRelative(ptPrev);
+ } else
+ ptPrev = ((Bendpoint) constraint.get(nIndex - 1)).getLocation();
+
+ if (Math.abs(ptPrev.x - ptLoc.x) < sticky_tolerance)
+ ptLoc.x = ptPrev.x;
+ if (Math.abs(ptPrev.y - ptLoc.y) < sticky_tolerance)
+ ptLoc.y = ptPrev.y;
+ }
+
+ if (nIndex < constraint.size() - 1) {
+ Point ptNext;
+ if ((nIndex + 1) == (constraint.size() - 1)) {
+ ptNext = getConnection().getTargetAnchor().getReferencePoint();
+ getConnection().translateToRelative(ptNext);
+ } else
+ ptNext = ((Bendpoint) constraint.get(nIndex + 1)).getLocation();
+
+ if (Math.abs(ptNext.x - ptLoc.x) < sticky_tolerance)
+ ptLoc.x = ptNext.x;
+ if (Math.abs(ptNext.y - ptLoc.y) < sticky_tolerance)
+ ptLoc.y = ptNext.y;
+ }
+
+ if (!ptLoc.equals(bp.getLocation())) {
+ Bendpoint bpNew = new AbsoluteBendpoint(ptLoc);
+ constraint.set(nIndex, bpNew);
+ } else {
+ constraint.set(nIndex, bp);
+ }
+ }
+
+ private int getStickyTolerance() {
+ int sticky_tolerance = MapModeUtil.getMapMode(getConnection()).DPtoLP(
+ STICKY_TOLERANCE_DP);
+ return sticky_tolerance;
+ }
+
+ /**
+ * Shows feedback, when appropriate. Calls a different method depending on
+ * the request type.
+ *
+ * @see #showCreateBendpointFeedback(BendpointRequest)
+ * @see #showMoveBendpointFeedback(BendpointRequest)
+ */
+ public void showSourceFeedback(Request request) {
+ if (getLineSegMode() != LineMode.OBLIQUE) {
+ if (REQ_CREATE_BENDPOINT.equals(request.getType())) {
+ showMoveLineSegFeedback((BendpointRequest) request);
+ } else if (REQ_MOVE_BENDPOINT.equals(request.getType())) {
+ showMoveOrthogonalBenspointFeedback((BendpointRequest) request);
+ }
+
+ } else {
+ if (REQ_MOVE_BENDPOINT.equals(request.getType()))
+ showMoveBendpointFeedback((BendpointRequest) request);
+ else if (REQ_CREATE_BENDPOINT.equals(request.getType()))
+ showCreateBendpointFeedback((BendpointRequest) request);
+ }
+
+ super.showSourceFeedback(request);
+ }
+
+ /**
+ * Method getBendpointsChangedCommand. This method will return a
+ * SetBendpointsCommand with the points retrieved from the user feedback in
+ * the figure.
+ *
+ * @param request
+ * BendpointRequest from the user gesture for moving / creating a
+ * bendpoint
+ * @return Command SetBendpointsCommand that contains the point changes for
+ * the connection.
+ */
+ abstract protected Command getBendpointsChangedCommand(
+ BendpointRequest request);
+
+ protected Command getCreateBendpointCommand(BendpointRequest request) {
+ return getBendpointsChangedCommand(request);
+ }
+
+ protected Command getMoveBendpointCommand(BendpointRequest request) {
+ return getBendpointsChangedCommand(request);
+ }
+
+ protected Command getDeleteBendpointCommand(BendpointRequest request) {
+ return getBendpointsChangedCommand(request);
+ }
+
+ protected final LineSeg getLineSeg(List bendPoints, int nIndex) {
+ Point pt1 = new Point(
+ ((Bendpoint) bendPoints.get(nIndex - 1)).getLocation());
+ Point pt2 = new Point(
+ ((Bendpoint) bendPoints.get(nIndex)).getLocation());
+
+ return new LineSeg(pt1, pt2);
+ }
+
+ /**
+ * @param bendPoints
+ * @param nIndex
+ * @param newLine
+ */
+ protected void setLineSeg(List bendPoints, int nIndex, LineSeg newLine) {
+ Bendpoint bp1 = new AbsoluteBendpoint(newLine.getOrigin());
+ Bendpoint bp2 = new AbsoluteBendpoint(newLine.getTerminus());
+
+ bendPoints.set(nIndex - 1, bp1);
+ bendPoints.set(nIndex, bp2);
+ }
+
+ /**
+ * @param request
+ * @return move line segment command
+ */
+ protected Command getMoveLineSegCommand(BendpointRequest request) {
+ return getBendpointsChangedCommand(request);
+ }
+
+ /**
+ * Method lineOutsideSource. Utility method to determine if the constraint
+ * needs to be adjusted becauase the line is outside of the source bounds.
+ *
+ * @param line
+ * LineSeg defining the new line moved by the user gesture
+ * @return boolean true if origin of line lies outside the starting source
+ * element, false otherwise.
+ */
+ protected boolean lineOutsideSource(LineSeg line) {
+
+ // check if end points are outside of bounds and if so - add a new point
+ PrecisionRectangle startRect = new PrecisionRectangle(
+ FigureUtilities.getAnchorableFigureBounds(getConnection()
+ .getSourceAnchor().getOwner()));
+ getConnection().getSourceAnchor().getOwner()
+ .translateToAbsolute(startRect);
+ if (getLineSegMode().equals(LineMode.ORTHOGONAL_CONSTRAINED)) {
+ if (line.isHorizontal()) {
+ startRect.shrink(0, 2);
+ } else {
+ startRect.shrink(2, 0);
+ }
+ }
+
+ getConnection().translateToRelative(startRect);
+ /*
+ * Rectangle needs to be expanded by the "odd" number below because the
+ * number after translations could be N.999999999...
+ */
+ if (!startRect.expand(0.000001, 0.000001).contains(
+ new PrecisionPoint(line.getOrigin()))) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Method lineOutsideTarget. Utility method to determine if the constraint
+ * needs to be adjusted because the line is outside of the target bounds.
+ *
+ * @param line
+ * LineSeg defining the new line moved by the user gesture.
+ * @return boolean true if terminus of line lies outside the target element,
+ * false otherwise.
+ */
+ protected boolean lineOutsideTarget(LineSeg line) {
+
+ // check if end points are outside of bounds and if so - add a new point
+ PrecisionRectangle endRect = new PrecisionRectangle(
+ FigureUtilities.getAnchorableFigureBounds(getConnection()
+ .getTargetAnchor().getOwner()));
+ getConnection().getTargetAnchor().getOwner()
+ .translateToAbsolute(endRect);
+ if (getLineSegMode().equals(LineMode.ORTHOGONAL_CONSTRAINED)) {
+ if (line.isHorizontal()) {
+ endRect.shrink(0, 2);
+ } else {
+ endRect.shrink(2, 0);
+ }
+ }
+
+ /*
+ * Rectangle needs to be expanded by the "odd" number below because the
+ * number after translations could be N.999999999...
+ */
+ getConnection().translateToRelative(endRect);
+ if (!endRect.expand(0.00001, 0.00001).contains(
+ new PrecisionPoint(line.getTerminus()))) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Method removeOutsideSourceFeedback. Removes a bendpoint from the
+ * beginning of the constraint.
+ *
+ * @param constraint
+ * List of bendpoints that the source point will be added too.
+ */
+ protected void removeOutsideSourceFeedback(List constraint) {
+ constraint.remove(0);
+ }
+
+ /**
+ * Method removeOutsideTargetFeedback. Removes a bendpoint from the end of
+ * the constraint.
+ *
+ * @param constraint
+ * List of bendpoints that the target point will be added too.
+ */
+ protected void removeOutsideTargetFeedback(List constraint) {
+ constraint.remove(constraint.size() - 1);
+ }
+
+ /**
+ * Draws feedback for moving a bend point of a rectilinear connection
+ *
+ * @param request
+ * Benndpoint request
+ */
+ protected void showMoveOrthogonalBenspointFeedback(BendpointRequest request) {
+ if (getFeedbackState().originalConstraint == null) {
+ saveOriginalConstraint();
+ }
+
+ Point ptLoc = new Point(request.getLocation());
+ List constraint = (List) getConnection().getRoutingConstraint();
+
+ getConnection().translateToRelative(ptLoc);
+
+ int index = getFeedbackState().isOutsideSource ? request.getIndex() + 1
+ : request.getIndex();
+
+ Point previous = ((Bendpoint) constraint.get(index - 1)).getLocation();
+ Point moving = ((Bendpoint) constraint.get(index)).getLocation();
+ Point next = ((Bendpoint) constraint.get(index + 1)).getLocation();
+
+ LineSeg originalFirst = new LineSeg(previous.getCopy(),
+ moving.getCopy());
+ LineSeg originalSecond = new LineSeg(moving.getCopy(), next.getCopy());
+
+ Dimension diff = ptLoc.getDifference(moving);
+
+ if (originalFirst.isHorizontal()) {
+ previous.y += diff.height;
+ next.x += diff.width;
+ } else {
+ previous.x += diff.width;
+ next.y += diff.height;
+ }
+
+ LineSeg movedFirst = new LineSeg(previous, ptLoc.getCopy());
+ LineSeg movedSecond = new LineSeg(ptLoc.getCopy(), next);
+
+ index = adjustOutsideBoundsLineFeedback(movedFirst, index - 1,
+ constraint, originalFirst);
+ constraint.set(index, new AbsoluteBendpoint(movedFirst.getOrigin()));
+ constraint.set(index + 1,
+ new AbsoluteBendpoint(movedFirst.getTerminus()));
+
+ index = adjustOutsideBoundsLineFeedback(movedSecond, index + 1,
+ constraint, originalSecond);
+ constraint.set(index + 1,
+ new AbsoluteBendpoint(movedSecond.getTerminus()));
+
+ getConnection().setRoutingConstraint(constraint);
+ }
+
+ /**
+ * Shows feedback when a line segment is being moved. Also checks to see if
+ * the bendpoint should be deleted and then calls
+ * {@link #showDeleteBendpointFeedback(BendpointRequest)} if needed. The
+ * original figure is used for feedback and the original constraint is
+ * saved, so that it can be restored when feedback is erased.
+ */
+ protected void showMoveLineSegFeedback(BendpointRequest request) {
+
+ if (getFeedbackState().originalConstraint == null) {
+ saveOriginalConstraint();
+ }
+
+ Point ptLoc = new Point(request.getLocation());
+ List constraint = (List) getConnection().getRoutingConstraint();
+
+ getConnection().translateToRelative(ptLoc);
+
+ // adjust request index to account for source bendpoint if needed
+ int index = getFeedbackState().isOutsideSource ? request.getIndex() + 1
+ : request.getIndex();
+
+ LineSeg moveLine = getLineSeg(constraint, index + 1);
+ LineSeg newLine = moveLine.getParallelLineSegThroughPoint(ptLoc);
+
+ index = adjustOutsideBoundsLineFeedback(newLine, index, constraint,
+ moveLine);
+
+ setLineSeg(constraint, index + 1, newLine);
+
+ getConnection().setRoutingConstraint(constraint);
+ }
+
+ /**
+ * adjustOutsideBoundsLineFeedback Method to handle feedback where the line
+ * is dragged outside of the source or target shapes bounding box.
+ *
+ * @param newLine
+ * LineSeg representing the line currently being manipulated.
+ * @param index
+ * the index
+ * @param constraint
+ * List of Bendpoint objects that is the constraint to the
+ * gesture.
+ * @param moveLine
+ * original segment that is being manipulated
+ * @return int new index value after the constraint and feedback have been
+ * adjusted.
+ */
+ private int adjustOutsideBoundsLineFeedback(LineSeg newLine, int index,
+ List constraint, LineSeg moveLine) {
+ if (getLineSegMode().equals(LineMode.ORTHOGONAL_CONSTRAINED)) {
+ // merely enforce the fact that we can't adjust the line outside the
+ // bounds of the source and target.
+ if ((index == 0 && lineOutsideSource(newLine))
+ || ((index + 1 == constraint.size() - 1) && lineOutsideTarget(newLine))) {
+ newLine.setOrigin(moveLine.getOrigin());
+ newLine.setTerminus(moveLine.getTerminus());
+ }
+
+ return index;
+ }
+
+ boolean bRemoveSource = false;
+ boolean bRemoveTarget = false;
+ boolean bSetNewSource = false;
+ boolean bSetNewTarget = false;
+
+ // Check source to see if we need to add a bendpoint
+ if (index == 0 && lineOutsideSource(newLine)) {
+ if (!getFeedbackState().isOutsideSource) {
+ getFeedbackState().isOutsideSource = true;
+ bSetNewSource = true;
+ }
+ } else if (index == 1 && getFeedbackState().isOutsideSource
+ && !lineOutsideSource(newLine)) {
+ getFeedbackState().isOutsideSource = false;
+ bRemoveSource = true;
+ }
+
+ // Check target to see if we need to add a bendpoint
+ int checkTargetIndex = index + 1
+ + (getFeedbackState().isOutsideTarget ? 1 : 0);
+ if ((checkTargetIndex == constraint.size() - 1)
+ && lineOutsideTarget(newLine)) {
+ if (!getFeedbackState().isOutsideTarget) {
+ getFeedbackState().isOutsideTarget = true;
+ bSetNewTarget = true;
+ }
+ } else if (checkTargetIndex == constraint.size() - 2
+ && getFeedbackState().isOutsideTarget
+ && !lineOutsideTarget(newLine)) {
+ getFeedbackState().isOutsideTarget = false;
+ bRemoveTarget = true;
+ }
+ if (bRemoveSource) {
+ removeOutsideSourceFeedback(constraint);
+ index--;
+ }
+
+ if (bRemoveTarget) {
+ removeOutsideTargetFeedback(constraint);
+ }
+
+ if (bSetNewSource) {
+ showOutsideSourceFeedback(newLine, moveLine, constraint);
+ index++;
+ }
+
+ if (bSetNewTarget) {
+ showOutsideTargetFeedback(newLine, moveLine, constraint);
+ }
+ return index;
+ }
+
+ /**
+ * Method showOutsideSourceFeedback. Adds a bendpoint to the beginning of
+ * the constraint. Also adjusts the new segment with respect to added
+ * constraint
+ *
+ * @param constraint
+ * List of bendpoints that the source point will be added too.
+ */
+ protected void showOutsideSourceFeedback(LineSeg newLine, LineSeg moveLine,
+ List constraint) {
+ Connection conn = (Connection) getHostFigure();
+ ConnectionAnchor anchor = conn.getSourceAnchor();
+ PrecisionPoint startPoint = new PrecisionPoint(anchor.getOwner()
+ .getBounds().getCenter());
+ anchor.getOwner().translateToAbsolute(startPoint);
+ conn.translateToRelative(startPoint);
+ PrecisionRectangle bounds = new PrecisionRectangle(anchor.getOwner()
+ .getBounds());
+ anchor.getOwner().translateToAbsolute(bounds);
+ conn.translateToRelative(bounds);
+ Point origin = new Point(newLine.getOrigin());
+ if (moveLine.isHorizontal()) {
+ origin.x = startPoint.x;
+ } else {
+ origin.y = startPoint.y;
+ }
+ newLine.setOrigin(origin);
+ constraint.add(0, new AbsoluteBendpoint(startPoint));
+
+ }
+
+ /**
+ * Method showOutsideTargetFeedback. Adds a bendpoint to the end of the
+ * constraint. Also adjusts the new segment with respect to added constraint
+ *
+ * @param constraint
+ * List of bendpoints that the target point will be added too.
+ */
+ protected void showOutsideTargetFeedback(LineSeg newLine, LineSeg moveLine,
+ List constraint) {
+ Connection conn = (Connection) getHostFigure();
+ ConnectionAnchor anchor = conn.getTargetAnchor();
+ PrecisionPoint endPoint = new PrecisionPoint(anchor.getOwner()
+ .getBounds().getCenter());
+ anchor.getOwner().translateToAbsolute(endPoint);
+ conn.translateToRelative(endPoint);
+ PrecisionRectangle bounds = new PrecisionRectangle(anchor.getOwner()
+ .getBounds());
+ anchor.getOwner().translateToAbsolute(bounds);
+ conn.translateToRelative(bounds);
+ Point terminus = new Point(newLine.getTerminus());
+ if (moveLine.isHorizontal()) {
+ terminus.x = endPoint.x;
+ } else {
+ terminus.y = endPoint.y;
+ }
+ newLine.setTerminus(terminus);
+ constraint.add(new AbsoluteBendpoint(endPoint));
+ }
+
+ /**
+ * Override for AccessibleHandleProvider when deactivated
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=69316
+ *
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class key) {
+ if (key == AccessibleHandleProvider.class)
+ // handles == null when deactivated
+ if (handles == null) {
+ return null;
+ }
+ return super.getAdapter(key);
+ }
+}

Back to the top