diff options
| author | Laurent Redor | 2016-03-10 10:52:56 +0000 |
|---|---|---|
| committer | Laurent Redor | 2016-03-14 14:28:39 +0000 |
| commit | 3bbe6132bb525e572a9064fa78de2a35f85f05e2 (patch) | |
| tree | 5aad83d9145191627d69247b23898067a091635e | |
| parent | 5831f2366a888270b3197bfbf78e1e67212183d4 (diff) | |
| download | org.eclipse.sirius-3bbe6132bb525e572a9064fa78de2a35f85f05e2.tar.gz org.eclipse.sirius-3bbe6132bb525e572a9064fa78de2a35f85f05e2.tar.xz org.eclipse.sirius-3bbe6132bb525e572a9064fa78de2a35f85f05e2.zip | |
[489183] Fix the detected regressions
* Move all code concerning EdgeLayoutUpdaterModelChangeTrigger in this
class (instead of in the associated notification filter class
RefreshEdgeLayoutNotificationFilter).
* Consider the figure in case of one notification
* Keep all notifications (not only REFRESH_FEATURES) for the
EdgeLayoutUpdaterModelChangeTrigger to be able to detect if other
notifications are consequences of the first one.
Bug: 489183
Change-Id: I763254bf15a9b13b80c8b18cbf5666b1cf8a004e
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
2 files changed, 143 insertions, 80 deletions
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/listeners/EdgeLayoutUpdaterModelChangeTrigger.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/listeners/EdgeLayoutUpdaterModelChangeTrigger.java index 80e7160f76..dfd873e48c 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/listeners/EdgeLayoutUpdaterModelChangeTrigger.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/listeners/EdgeLayoutUpdaterModelChangeTrigger.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 THALES GLOBAL SERVICES. + * Copyright (c) 2014, 2016 THALES GLOBAL SERVICES. * 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 @@ -13,26 +13,35 @@ package org.eclipse.sirius.diagram.ui.internal.refresh.listeners; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.Set; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.Edge; +import org.eclipse.gmf.runtime.notation.NotationPackage; +import org.eclipse.gmf.runtime.notation.RelativeBendpoints; import org.eclipse.gmf.runtime.notation.RoutingStyle; import org.eclipse.sirius.business.api.session.ModelChangeTrigger; import org.eclipse.sirius.business.api.session.Session; import org.eclipse.sirius.business.api.session.SessionEventBroker; import org.eclipse.sirius.diagram.DDiagram; import org.eclipse.sirius.diagram.DEdge; +import org.eclipse.sirius.diagram.DiagramPackage; import org.eclipse.sirius.diagram.EdgeStyle; import org.eclipse.sirius.diagram.ui.business.api.view.SiriusGMFHelper; import org.eclipse.sirius.diagram.ui.business.internal.operation.AbstractModelChangeOperation; import org.eclipse.sirius.diagram.ui.internal.operation.CenterEdgeEndModelChangeOperation; import org.eclipse.sirius.ext.base.Option; import org.eclipse.sirius.ext.base.Options; +import org.eclipse.sirius.viewpoint.ViewpointPackage; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; /** * A Model Change Trigger that execute the @@ -45,6 +54,36 @@ public class EdgeLayoutUpdaterModelChangeTrigger implements ModelChangeTrigger { public static final int PRIORITY = FilterListener.COMPOSITE_FILTER_REFRESH_PRIORITY + 1; + /** + * List of features for which we consider that the edge layout must be + * recompute. + */ + private static final Set<EStructuralFeature> REFRESH_FEATURES = new HashSet<EStructuralFeature>(); + + /** + * Sublist of <code>REFRESH_FEATURES</code> that also have other features as + * consequence. + */ + private static final Set<EStructuralFeature> REFRESH_FEATURES_WITH_CONSEQUENCE = new HashSet<EStructuralFeature>(); + + /** + * List of features that are standard consequences of + * <code>REFRESH_FEATURES_WITH_CONSEQUENCE</code>. + */ + private static final Set<EStructuralFeature> CONSEQUENCE_FEATURES = new HashSet<EStructuralFeature>(); + + static { + REFRESH_FEATURES_WITH_CONSEQUENCE.add(DiagramPackage.Literals.EDGE_STYLE__CENTERED); + REFRESH_FEATURES_WITH_CONSEQUENCE.add(NotationPackage.Literals.ROUTING_STYLE__ROUTING); + + REFRESH_FEATURES.addAll(REFRESH_FEATURES_WITH_CONSEQUENCE); + REFRESH_FEATURES.add(DiagramPackage.Literals.DEDGE__OWNED_STYLE); + REFRESH_FEATURES.add(NotationPackage.Literals.DIAGRAM__PERSISTED_EDGES); + + CONSEQUENCE_FEATURES.add(ViewpointPackage.Literals.CUSTOMIZABLE__CUSTOM_FEATURES); + CONSEQUENCE_FEATURES.add(DiagramPackage.Literals.EDGE_STYLE__ROUTING_STYLE); + } + private TransactionalEditingDomain domain; private SessionEventBroker eventBroker; @@ -80,30 +119,18 @@ public class EdgeLayoutUpdaterModelChangeTrigger implements ModelChangeTrigger { Collection<Edge> edgesWithCreatedCommand = new HashSet<Edge>(); Collection<AbstractModelChangeOperation<Void>> operations = new ArrayList<AbstractModelChangeOperation<Void>>(); for (Notification notification : notifications) { - Object notifier = notification.getNotifier(); - Edge gmfEdge = null; - if (notifier instanceof DEdge) { - gmfEdge = SiriusGMFHelper.getGmfEdge((DEdge) notifier); - } else if (notifier instanceof EdgeStyle) { - EObject container = ((EdgeStyle) notifier).eContainer(); - if (container instanceof DEdge) { - gmfEdge = SiriusGMFHelper.getGmfEdge((DEdge) container); - } - } else if (notifier instanceof RoutingStyle) { - EObject container = ((RoutingStyle) notifier).eContainer(); - if (container instanceof Edge) { - gmfEdge = ((Edge) container); + // Only consider notification of + // RefreshEdgeLayoutNotificationFilter.REFRESH_FEATURES list + if (isRefreshEdgeLayoutNeededForNotification(notification)) { + Option<Edge> optionalGmfEdge = getCorrespondingEdge(notification); + if (optionalGmfEdge.some() && edgesWithCreatedCommand.add(optionalGmfEdge.get())) { + // if there are several notifications, we do not try to + // retrieve draw2D informations since they could be out of + // date. + boolean useFigure = otherNotificationsAreConsequences(notification, optionalGmfEdge.get(), notifications); + AbstractModelChangeOperation<Void> operation = new CenterEdgeEndModelChangeOperation(optionalGmfEdge.get(), useFigure); + operations.add(operation); } - } else if (notifier instanceof Diagram && notification.getNewValue() instanceof Edge) { - gmfEdge = (Edge) notification.getNewValue(); - } - if (gmfEdge != null && edgesWithCreatedCommand.add(gmfEdge)) { - // if there are several notifications, we do not try to - // retrieve draw2D informations since they could be out of - // date. - boolean useFigure = refreshEdgeLayoutNotificationFilter.otherNotificationsAreIndirectlyConcerned(notification, notifications); - AbstractModelChangeOperation<Void> operation = new CenterEdgeEndModelChangeOperation(gmfEdge, useFigure); - operations.add(operation); } } if (!operations.isEmpty()) { @@ -147,4 +174,92 @@ public class EdgeLayoutUpdaterModelChangeTrigger implements ModelChangeTrigger { domain = null; } + + /** + * Test whether the other notifications are consequences of the given one. + * For instance, in case of a manual modification of the Sirius routing + * style (from Style tab of Properties view), we also update the GMF style + * and we add the routing style within the custom features. This method aims + * to check whether we are in the case of an individual modification or a + * global one. + * + * @param notification + * the notification for which we are notified. + * @param gmfEdge + * the GMF edge associated to the <code>notification</code> + * @param notifications + * the whole notification list. + * @return true if the notifications list contains only notifications + * induced by the first one. + */ + public boolean otherNotificationsAreConsequences(final Notification notification, final Edge gmfEdge, Collection<Notification> notifications) { + boolean otherNotificationsAreIndirectlyConcerned = false; + if (notifications.size() == 1 && REFRESH_FEATURES.contains(notifications.iterator().next().getFeature())) { + otherNotificationsAreIndirectlyConcerned = true; + } else if (REFRESH_FEATURES_WITH_CONSEQUENCE.contains(notification.getFeature())) { + otherNotificationsAreIndirectlyConcerned = Iterables.all(notifications, new Predicate<Notification>() { + @Override + public boolean apply(Notification currentNotification) { + boolean considerAsConsequence = false; + if (currentNotification == notification) { + considerAsConsequence = true; + } else { + Option<Edge> optionalEdge = getCorrespondingEdge(currentNotification); + if (optionalEdge.some()) { + considerAsConsequence = optionalEdge.get().equals(gmfEdge) && CONSEQUENCE_FEATURES.contains(currentNotification.getFeature()); + } + } + return considerAsConsequence; + } + }); + } + return otherNotificationsAreIndirectlyConcerned; + } + + /** + * Test whether the edge centering should be refreshed for this + * notification. + * + * @param notification + * The {@link Notification} to check. + * @return true if this notification concerns the edge ends centering, false + * otherwise. + */ + private boolean isRefreshEdgeLayoutNeededForNotification(Notification notification) { + return REFRESH_FEATURES.contains(notification.getFeature()); + } + + /** + * Search the corresponding GMF edge associated to this notification. + * + * @param notification + * The {@link Notification} to analyze + * @return an optional {@link Edge} + */ + private Option<Edge> getCorrespondingEdge(Notification notification) { + Edge gmfEdge = null; + Object notifier = notification.getNotifier(); + if (notifier instanceof DEdge) { + gmfEdge = SiriusGMFHelper.getGmfEdge((DEdge) notifier); + } else if (notifier instanceof EdgeStyle) { + EObject container = ((EdgeStyle) notifier).eContainer(); + if (container instanceof DEdge) { + gmfEdge = SiriusGMFHelper.getGmfEdge((DEdge) container); + } + } else if (notifier instanceof RoutingStyle) { + EObject container = ((RoutingStyle) notifier).eContainer(); + if (container instanceof Edge) { + gmfEdge = ((Edge) container); + } + } else if (notifier instanceof Diagram && notification.getNewValue() instanceof Edge) { + gmfEdge = (Edge) notification.getNewValue(); + } else if (notifier instanceof RelativeBendpoints) { + gmfEdge = (Edge) ((RelativeBendpoints) notifier).eContainer(); + } + if (gmfEdge == null) { + return Options.newNone(); + } else { + return Options.newSome(gmfEdge); + } + } } diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/listeners/RefreshEdgeLayoutNotificationFilter.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/listeners/RefreshEdgeLayoutNotificationFilter.java index 27f65686c9..7164acb3d3 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/listeners/RefreshEdgeLayoutNotificationFilter.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/listeners/RefreshEdgeLayoutNotificationFilter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 THALES GLOBAL SERVICES. + * Copyright (c) 2014, 2016 THALES GLOBAL SERVICES. * 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 @@ -10,76 +10,24 @@ *******************************************************************************/ package org.eclipse.sirius.diagram.ui.internal.refresh.listeners; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - import org.eclipse.emf.common.notify.Notification; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.sirius.business.api.dialect.DRepresentationNotificationFilter; import org.eclipse.sirius.diagram.DDiagram; -import org.eclipse.sirius.diagram.DiagramPackage; -import org.eclipse.sirius.viewpoint.ViewpointPackage; /** - * A NotificationFilter to restrict the scope of RefreshEdgeLayoutChangeTrigger. + * A NotificationFilter to restrict the scope of RefreshEdgeLayoutChangeTrigger + * (all notifications of the current diagram that have a new value). * * @author Florian Barbin */ public class RefreshEdgeLayoutNotificationFilter extends DRepresentationNotificationFilter { - private static final Set<EStructuralFeature> INTERESTING_FEATURES = new HashSet<EStructuralFeature>(); - - static { - INTERESTING_FEATURES.add(DiagramPackage.Literals.DEDGE__OWNED_STYLE); - INTERESTING_FEATURES.add(DiagramPackage.Literals.EDGE_STYLE__CENTERED); - INTERESTING_FEATURES.add(NotationPackage.Literals.ROUTING_STYLE__ROUTING); - INTERESTING_FEATURES.add(NotationPackage.Literals.DIAGRAM__PERSISTED_EDGES); - } - - private static final Set<EStructuralFeature> INDIRECT_INTERESTING_FEATURES = new HashSet<EStructuralFeature>(); - - static { - INDIRECT_INTERESTING_FEATURES.add(ViewpointPackage.Literals.CUSTOMIZABLE__CUSTOM_FEATURES); - INDIRECT_INTERESTING_FEATURES.add(DiagramPackage.Literals.EDGE_STYLE__ROUTING_STYLE); - } - public RefreshEdgeLayoutNotificationFilter(DDiagram dDiagram) { super(dDiagram); } @Override public boolean matches(Notification notification) { - boolean matches = super.matches(notification) && notification.getNewValue() != null && INTERESTING_FEATURES.contains(notification.getFeature()); - return matches; + return super.matches(notification) && notification.getNewValue() != null; } - - /** - * Test whether the other notifications concern the given one. For instance, - * in case of a manual modification of the GMF routing style, we also update - * the Sirius style and we add the routing style within the custom features. - * This method aims to check whether we are in the case of an individual - * modification or a global one. - * - * @param notification - * the notification for which we are notified. - * @param notifications - * the whole notification list. - * @return true if the notifications list contains only notifications - * induced by the first one. - */ - public boolean otherNotificationsAreIndirectlyConcerned(Notification notification, Collection<Notification> notifications) { - boolean otherNotificationsAreIndirectlyConcerned = false; - if (NotationPackage.Literals.ROUTING_STYLE__ROUTING == notification.getFeature() || DiagramPackage.Literals.EDGE_STYLE__CENTERED == notification.getFeature()) { - for (Notification currentNotification : notifications) { - if (currentNotification != notification && !INDIRECT_INTERESTING_FEATURES.contains(currentNotification.getFeature())) { - otherNotificationsAreIndirectlyConcerned = true; - break; - } - } - } - return otherNotificationsAreIndirectlyConcerned; - } - } |
