diff options
Diffstat (limited to 'plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/TimeElementEditPartHelper.java')
-rw-r--r-- | plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/TimeElementEditPartHelper.java | 137 |
1 files changed, 118 insertions, 19 deletions
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/TimeElementEditPartHelper.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/TimeElementEditPartHelper.java index f950853d680..c427bbf30c0 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/TimeElementEditPartHelper.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/parts/TimeElementEditPartHelper.java @@ -15,29 +15,39 @@ package org.eclipse.papyrus.uml.diagram.sequence.edit.parts; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.Optional; +import java.util.concurrent.Executor; import java.util.function.Supplier; 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.Rectangle; import org.eclipse.gef.ConnectionEditPart; -import org.eclipse.gef.EditPart; +import org.eclipse.gef.Disposable; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.figures.IBorderItemLocator; import org.eclipse.gmf.runtime.notation.NotationPackage; +import org.eclipse.papyrus.infra.core.utils.OneShotExecutor; +import org.eclipse.papyrus.infra.gmfdiag.common.helper.DiagramHelper; import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil; +import org.eclipse.papyrus.infra.ui.util.TransactionUIHelper; import org.eclipse.uml2.uml.MessageEnd; /** * Common behaviour that time-element edit-parts can delegate. */ class TimeElementEditPartHelper { + private static final MessageTracker NONE = new MessageTracker(); private final IGraphicalEditPart owner; private final Supplier<? extends Optional<MessageEnd>> messageEndSupplier; + private final Executor executor; + private MessageTracker messageTracker = NONE; /** * Initializes me with the edit-part that I help. @@ -54,14 +64,16 @@ class TimeElementEditPartHelper { this.owner = owner; this.messageEndSupplier = messageEndSupplier; + + // Don't post redundant refreshes + this.executor = new OneShotExecutor(TransactionUIHelper.getExecutor(owner.getEditingDomain())); } boolean refreshBounds(IBorderItemLocator locator) { boolean result = false; if (locator != null) { - Optional<Point> messageEndLoc = getMessageEnd().map(this::getLocation); - + Optional<Point> messageEndLoc = Optional.ofNullable(getLocation()); if (messageEndLoc.isPresent()) { // We are fixed by a message end, then Dimension size = new Dimension( @@ -76,6 +88,11 @@ class TimeElementEditPartHelper { return result; } + // Asynchronously post a refresh of my owner edit-part + private void postRefresh() { + executor.execute(() -> DiagramHelper.refresh(owner, true)); + } + /** * Obtain the message end that is my observedor constrained event, if any. * @@ -93,25 +110,107 @@ class TimeElementEditPartHelper { * @return the location of that end relative to my parent, or {@code null} if it cannot * be determined */ - Point getLocation(MessageEnd messageEnd) { - Point result = null; - - if (messageEnd != null) { - EditPart messageEP = DiagramEditPartsUtil.getChildByEObject(messageEnd.getMessage(), - (IGraphicalEditPart) owner.getRoot().getContents(), true); - if (messageEP instanceof ConnectionEditPart) { - Connection connection = (Connection) ((ConnectionEditPart) messageEP).getFigure(); - ConnectionAnchor anchor = messageEnd.isSend() - ? connection.getSourceAnchor() - : connection.getTargetAnchor(); - if (anchor != null) { - result = anchor.getReferencePoint().getCopy(); - owner.getFigure().getParent().translateToRelative(result); - } + Point getLocation() { + return getMessage().getLocation(); + } + + private MessageTracker getMessage() { + if (!messageTracker.isValid()) { + messageTracker.dispose(); + + // Refresh our idea of what the message is + messageTracker = messageEndSupplier.get() + .map(end -> new MessageTracker(this, end)) + .filter(MessageTracker::isValid) + .orElse(NONE); + } + + return messageTracker; + } + + // + // Nested types + // + + /** + * A helper for tracking the message, if any, the end of which is linked to a time + * element to cause that time element to follow (track) the movement of the message + * end. + */ + private static final class MessageTracker implements Supplier<ConnectionEditPart>, Disposable { + private final PropertyChangeListener connectionListener = this::connectionMoved; + private final TimeElementEditPartHelper owner; + private final ConnectionEditPart connectionEP; + private final Connection connection; + private final boolean source; + private final Point anchor = new Point(); + + MessageTracker() { + super(); + + this.owner = null; + connectionEP = null; + connection = null; + source = false; + } + + MessageTracker(TimeElementEditPartHelper owner, MessageEnd end) { + super(); + + this.owner = owner; + + IGraphicalEditPart ep = DiagramEditPartsUtil.getChildByEObject(end.getMessage(), + (IGraphicalEditPart) owner.owner.getRoot().getContents(), true); + if ((ep instanceof ConnectionEditPart) && ep.isActive()) { + connectionEP = (ConnectionEditPart) ep; + connection = (Connection) connectionEP.getFigure(); + connection.addPropertyChangeListener(Connection.PROPERTY_POINTS, connectionListener); + source = end.isSend(); + anchor.setLocation(source ? connection.getPoints().getFirstPoint() : connection.getPoints().getLastPoint()); + } else { + connectionEP = null; + connection = null; + source = false; } } - return result; + @Override + public void dispose() { + if (connection != null) { + connection.removePropertyChangeListener(Connection.PROPERTY_POINTS, connectionListener); + } + } + + @Override + public ConnectionEditPart get() { + return isValid() ? connectionEP : null; + } + + public Point getLocation() { + Point result = null; + + if (isValid()) { + // If we were ever valid, we have a connection + ConnectionAnchor anchor = source ? connection.getSourceAnchor() : connection.getTargetAnchor(); + result = anchor.getReferencePoint().getCopy(); + owner.owner.getFigure().getParent().translateToRelative(result); + } + + return result; + } + + boolean isValid() { + return (connectionEP != null) && connectionEP.isActive(); + } + + private void connectionMoved(PropertyChangeEvent event) { + PointList points = (PointList) event.getNewValue(); + Point newAnchor = source ? points.getFirstPoint() : points.getLastPoint(); + if (!anchor.equals(newAnchor)) { + anchor.setLocation(newAnchor); + owner.postRefresh(); + } + } } } |