Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCamille Letavernier2018-08-06 14:08:20 +0000
committerCamille Letavernier2018-09-24 10:48:44 +0000
commit63817502e3206935970da7d1f4513b5b5a604185 (patch)
treebb39c44b1472ea6350be157585c40cca471d0bbe /plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse
parentf6434672e029f00aea79baea587d9ff587915a84 (diff)
downloadorg.eclipse.papyrus-63817502e3206935970da7d1f4513b5b5a604185.tar.gz
org.eclipse.papyrus-63817502e3206935970da7d1f4513b5b5a604185.tar.xz
org.eclipse.papyrus-63817502e3206935970da7d1f4513b5b5a604185.zip
Bug 537724: Workaround for false-positive Connection Cycles during
Reconnect Change-Id: Ia6ec800216969f836f68c85e61ee2a458457aee6 Signed-off-by: Camille Letavernier <cletavernier@eclipsesource.com>
Diffstat (limited to 'plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse')
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/AbstractMessageEditPart.java131
1 files changed, 131 insertions, 0 deletions
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/AbstractMessageEditPart.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/AbstractMessageEditPart.java
index 2d82fef3fdd..4b7072b863a 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/AbstractMessageEditPart.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/AbstractMessageEditPart.java
@@ -16,10 +16,15 @@
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.edit.parts;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.Cursors;
+import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.emf.common.notify.Notification;
@@ -43,6 +48,7 @@ import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.IMaskManagedLabelEditPolicy;
import org.eclipse.papyrus.uml.diagram.common.editparts.UMLConnectionNodeEditPart;
import org.eclipse.papyrus.uml.diagram.common.figure.edge.UMLEdgeFigure;
+import org.eclipse.papyrus.uml.diagram.common.service.ApplyStereotypeRequest;
import org.eclipse.papyrus.uml.diagram.sequence.anchors.ConnectionSourceAnchor;
import org.eclipse.papyrus.uml.diagram.sequence.anchors.ConnectionTargetAnchor;
import org.eclipse.papyrus.uml.diagram.sequence.edit.policies.MessageGraphicalNodeEditPolicy;
@@ -296,10 +302,135 @@ public abstract class AbstractMessageEditPart extends UMLConnectionNodeEditPart
if (con instanceof MessageLostEditPart || con instanceof MessageFoundEditPart) {
return null;
}
+ // Workaround for Bug 537724: GMF does not support reconnection of links if link.source == link.target and
+ // the source/target is a link.
+ // We need to copy all inherited implementations, except the problematic GMF one... To be safe, only do
+ // that for DurationLinks and GeneralOrderings, since that's the case we want to support
+ ReconnectRequest reconnectRequest = (ReconnectRequest) request;
+ if (DurationLinkUtil.isDurationLink(reconnectRequest) || GeneralOrderingUtil.isGeneralOrderingLink(reconnectRequest)) {
+ return doGetTargetEditPart(reconnectRequest);
+ }
}
return super.getTargetEditPart(request);
}
+ /**
+ * Workaround for Bug 537724: GMF's implementation of cyclic dependency is incorrect,
+ * and we need to bypass it. Unfortunately, that means we need to copy all inherited
+ * implementations.
+ *
+ * @param reconnectRequest
+ * @return
+ */
+ protected EditPart doGetTargetEditPart(ReconnectRequest reconnectRequest) {
+ // From UMLConnectionNodeEditPart
+ if (ApplyStereotypeRequest.APPLY_STEREOTYPE_REQUEST.equals(reconnectRequest.getType())) {
+ return this;
+ }
+
+ // From GEF's AbstractEditPart
+ EditPolicyIterator i = getEditPolicyIterator();
+ EditPart targetEditPart = null;
+ while (i.hasNext()) {
+ targetEditPart = i.next().getTargetEditPart(reconnectRequest);
+ if (targetEditPart != null) {
+ break;
+ }
+ }
+
+ // From GMF's ConnectionNodeEditPart (The buggy part)
+
+ if (reconnectRequest.isMovingStartAnchor()) {
+ if (reconnectRequest.getConnectionEditPart().getSource() == targetEditPart) {
+ return targetEditPart;
+ }
+ } else if (reconnectRequest.getConnectionEditPart().getTarget() == targetEditPart) {
+ return targetEditPart;
+ }
+
+ // If source anchor is moved, the connection's source edit part
+ // should not be taken into account for a cyclic dependency
+ // check so as to avoid false checks. Same goes for the target
+ // anchor. See bugzilla# 155243 -- we do not want to target a
+ // connection that is already connected to us so that we do not
+ // introduce a cyclic connection
+ if (isCyclicConnectionRequest((org.eclipse.gef.ConnectionEditPart) targetEditPart,
+ reconnectRequest.getConnectionEditPart(), false, reconnectRequest.isMovingStartAnchor())) {
+ return null;
+ }
+
+ return targetEditPart;
+ }
+
+ // Custom implementation of the parent method, which is buggy
+ // This is a workaround for Bug 537724
+ // TODO This implementation should be properly tested... It allows more cases than
+ // the parent one, and may potentially allow cycles
+ private boolean isCyclicConnectionRequest(org.eclipse.gef.ConnectionEditPart targetCEP,
+ org.eclipse.gef.ConnectionEditPart sourceCEP,
+ boolean checkSourceAndTargetEditParts, boolean doNotCheckSourceEditPart) {
+ if (targetCEP == null || sourceCEP == null) {
+ return false;
+ }
+
+ // first, do a cyclic check on source and target connections
+ // of the source connection itself.
+ // (as every connection is also a node).
+
+ Set<IFigure> set = new HashSet<>();
+ getSourceAndTargetConnections(set, sourceCEP);
+ if (set.contains(targetCEP.getFigure())) {
+ return true;
+ }
+
+ // now do the cyclic check on the source and target of the source connection...
+ EditPart sourceEP = sourceCEP.getSource(),
+ targetEP = sourceCEP.getTarget();
+
+ if (!checkSourceAndTargetEditParts && doNotCheckSourceEditPart) {
+ // .
+ } else if (sourceEP instanceof org.eclipse.gef.ConnectionEditPart &&
+ isCyclicConnectionRequest(targetCEP,
+ (org.eclipse.gef.ConnectionEditPart) sourceEP,
+ true, doNotCheckSourceEditPart)) {
+ return true;
+ }
+
+ if (!checkSourceAndTargetEditParts && !doNotCheckSourceEditPart) {
+ // .
+ } else if (targetEP instanceof org.eclipse.gef.ConnectionEditPart &&
+ isCyclicConnectionRequest(targetCEP,
+ (org.eclipse.gef.ConnectionEditPart) targetEP,
+ true, doNotCheckSourceEditPart)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private void getSourceAndTargetConnections(Set<IFigure> set,
+ org.eclipse.gef.ConnectionEditPart connectionEditPart) {
+
+ if (connectionEditPart == null || set == null) {
+ return;
+ }
+
+ for (Iterator<?> i = connectionEditPart.getSourceConnections().iterator(); i.hasNext();) {
+ org.eclipse.gef.ConnectionEditPart next = (org.eclipse.gef.ConnectionEditPart) i.next();
+ Connection sourceConnection = (Connection) next.getFigure();
+ set.add(sourceConnection);
+ getSourceAndTargetConnections(set, next);
+ }
+
+ for (Iterator<?> i = connectionEditPart.getTargetConnections().iterator(); i.hasNext();) {
+ org.eclipse.gef.ConnectionEditPart next = (org.eclipse.gef.ConnectionEditPart) i.next();
+ Connection targetConnection = (Connection) next.getFigure();
+ set.add(targetConnection);
+ getSourceAndTargetConnections(set, next);
+ }
+ }
+
+
@Override
protected void handleNotificationEvent(Notification notification) {
super.handleNotificationEvent(notification);

Back to the top