diff options
author | Christian W. Damus | 2016-05-10 21:30:22 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2016-05-13 17:41:08 +0000 |
commit | 39b2279c74535bb53d530b48e87c80441695a028 (patch) | |
tree | 9e23243219c81b2354ba2bb518f9c81684091487 /plugins/uml | |
parent | 3e461b4650c6b162f9d4392f3ce9d176fc4d1fcd (diff) | |
download | org.eclipse.papyrus-39b2279c74535bb53d530b48e87c80441695a028.tar.gz org.eclipse.papyrus-39b2279c74535bb53d530b48e87c80441695a028.tar.xz org.eclipse.papyrus-39b2279c74535bb53d530b48e87c80441695a028.zip |
Bug 492482: [Stereotype Display] Undo of "Show all related links" failure for stereotyped connectors (with model corruption)
https://bugs.eclipse.org/bugs/show_bug.cgi?id=492482
Try as much as necessary to make the undo/redo scenario of dropping
Capsules to create CapsuleParts in Papyrus-RT Capsule State Machines
work. That is, not to fail to undo with an index-out-of-bounds
exception in undoing a ListChange in the ChangeDescription.
Several things:
* add a new mix-in interface for edit-policies that perform
automatic edits to the notation model à la CanonicalEditPolicy
with operations for execution of commands that prefer to reuse a
read/write transaction if available, instead of an unprotected write
* use this new protocol in the applied-stereotype edit-policies
to try whenever possible to record the changes for correct undo/redo
* change the applied-stereotype edit-policies to use a private
pre-commit listener on the DiagramEventBroker to react to
changes within a transaction instead of post-commit, again to promote
the recording of changes as much as possible for undo/redo
* update the default canonical child views strategy to enable
registration of view types that it should not attempt to manage
* use the new view-type filtering mechanism to exclude applied-
stereotype views from canonical control
* update all of the CommandUtil APIs for command execution that are
only used by the applied-stereotype display controllers to piggy-
back on the active read/write transaction if there is one, for
plausible undo/redo support
Note that this patch does include API changes, but not breaking
changes, after the Neon M7 feature-freeze milestone.
Change-Id: Ibe7978416d26c81474ccc4608e1090de5e5ac473
Diffstat (limited to 'plugins/uml')
18 files changed, 538 insertions, 383 deletions
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/canonical/DefaultUMLVisualChildrenStrategy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/canonical/DefaultUMLVisualChildrenStrategy.java index 92aef80a9a5..845c4c26eb2 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/canonical/DefaultUMLVisualChildrenStrategy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/canonical/DefaultUMLVisualChildrenStrategy.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2015 Christian W. Damus and others. + * Copyright (c) 2015, 2016 Christian W. Damus and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -13,8 +13,9 @@ package org.eclipse.papyrus.uml.diagram.common.canonical; +import java.util.Collection; import java.util.Collections; -import java.util.Iterator; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -23,6 +24,7 @@ import org.eclipse.gef.EditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.infra.gmfdiag.canonical.strategy.IVisualChildrenStrategy; +import org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.AutomaticNotationEditPolicy; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.Stereotype; @@ -33,11 +35,25 @@ import com.google.common.collect.ImmutableSet; * that present applied stereotypes, which have nothing to do with model-view synchronization. */ public class DefaultUMLVisualChildrenStrategy implements IVisualChildrenStrategy { + /** View types that are managed by other edit-policies. */ + private static final Set<String> excludedViewTypes = new HashSet<>(); public DefaultUMLVisualChildrenStrategy() { super(); } + /** + * Registers view types that should be ignored by the CanonicalEditPolicy for + * the purposes of view creation and deletion, because (usually) they are managed + * {@linkplain AutomaticNotationEditPolicy automatically} by other edit-policies. + * + * @param viewTypes + * view types to be excluded from canonical management + */ + public static void registerExcludedViewTypes(Collection<String> viewTypes) { + excludedViewTypes.addAll(viewTypes); + } + @Override public List<? extends View> getCanonicalChildren(EditPart editPart, View view) { List<? extends View> result = DEFAULT.getCanonicalChildren(editPart, view); @@ -48,15 +64,9 @@ public class DefaultUMLVisualChildrenStrategy implements IVisualChildrenStrategy ? ImmutableSet.copyOf(((Element) semantic).getAppliedStereotypes()) : Collections.<Stereotype> emptySet(); - if (!appliedStereotypes.isEmpty()) { - for (Iterator<? extends View> iter = result.iterator(); iter.hasNext();) { - final EObject nextElement = iter.next().getElement(); - - if (appliedStereotypes.contains(nextElement)) { - iter.remove(); - } - } - } + // And the transient views that support CSS-driven presentation + result.removeIf(v -> excludedViewTypes.contains(v.getType()) + || appliedStereotypes.contains(v.getElement())); return result; } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/AbstractAppliedStereotypeDisplayEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/AbstractAppliedStereotypeDisplayEditPolicy.java index 7487aee2bad..55a003a3451 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/AbstractAppliedStereotypeDisplayEditPolicy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/AbstractAppliedStereotypeDisplayEditPolicy.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2009, 2014 CEA LIST and others. + * Copyright (c) 2009, 2016 CEA LIST, Christian W. Damus, and others. * * * All rights reserved. This program and the accompanying materials @@ -13,6 +13,7 @@ * Christian W. Damus (CEA) - bug 440197 * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Bug 393532 * Celine JANSSENS (ALL4TEC) celine.janssens@all4tec.net - Bug 455311 Stereotype Display + * Christian W. Damus - bug 492482 * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.editpolicies; @@ -22,14 +23,17 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.EList; 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.diagram.core.commands.DeleteCommand; import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker; import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener; +import org.eclipse.gmf.runtime.diagram.core.listener.NotificationPreCommitListener; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.GraphicalEditPolicyEx; import org.eclipse.gmf.runtime.notation.BasicCompartment; @@ -39,15 +43,16 @@ import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.infra.core.listenerservice.IPapyrusListener; import org.eclipse.papyrus.infra.gmfdiag.common.editpart.ConnectionEditPart; +import org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.AutomaticNotationEditPolicy; import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationUtils; import org.eclipse.papyrus.uml.diagram.common.Activator; +import org.eclipse.papyrus.uml.diagram.common.canonical.DefaultUMLVisualChildrenStrategy; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.command.CreateAppliedStereotypeCompartmentCommand; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.command.CreateAppliedStereotypePropertyViewCommand; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.command.CreateStereotypeLabelCommand; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper.StereotypeDisplayConstant; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper.StereotypeDisplayUtil; import org.eclipse.papyrus.uml.diagram.common.stereotype.migration.StereotypeMigrationHelper; -import org.eclipse.papyrus.uml.diagram.common.util.CommandUtil; import org.eclipse.papyrus.uml.tools.listeners.StereotypeElementListener.StereotypeExtensionNotification; import org.eclipse.swt.graphics.Image; import org.eclipse.uml2.uml.Element; @@ -59,7 +64,7 @@ import org.eclipse.uml2.uml.Stereotype; * Specific edit policy for label displaying stereotypes and their properties * for representing UML elements. */ -public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends GraphicalEditPolicyEx implements NotificationListener, IPapyrusListener { +public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends GraphicalEditPolicyEx implements AutomaticNotationEditPolicy, NotificationListener, IPapyrusListener { /** * @@ -90,8 +95,15 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic protected View hostView = null; protected List<Stereotype> stereotypeList = Collections.emptyList(); + + private final NotificationPreCommitListener precommitListener = this::handlePrecommit; - + static { + // Tell the Canonical Edit Policy not to manage applied-stereotype views + DefaultUMLVisualChildrenStrategy.registerExcludedViewTypes(StereotypeDisplayConstant.APPLIED_STEREOTYPE_VIEW_TYPES); + } + + /** * Creates a new AppliedStereotype display edit policy */ @@ -108,9 +120,9 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic if (getHost() instanceof IGraphicalEditPart) { initialisation(); - // getDiagramEventBroker().addNotificationListener(view, this); - getDiagramEventBroker().addNotificationListener(hostSemanticElement, this); - getDiagramEventBroker().addNotificationListener(hostView, this); + // subscribe(view); + subscribe(hostSemanticElement); + subscribe(hostView); // Create and Delete nodes if necessary refreshNotationStructure(); @@ -119,6 +131,27 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic } + /** + * Subscribes to a {@code notifier} for notifications from the + * {@link #getDiagramEventBroker() event broker}. + * + * @param notifier a notifier to subscribe to + */ + protected void subscribe(EObject notifier) { + // Subscribe to pre-commit, not post-commit events + getDiagramEventBroker().addNotificationListener(notifier, precommitListener); + } + + /** + * Unsubscribes from a {@code notifier} for notifications from the + * {@link #getDiagramEventBroker() event broker}. + * + * @param notifier a notifier to unsubscribe from + */ + protected void unsubscribe(EObject notifier) { + // Unsubscribe from pre-commit, not post-commit events + getDiagramEventBroker().removeNotificationListener(notifier, precommitListener); + } /** @@ -155,6 +188,26 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic public abstract void refreshDisplay(); + /** + * React to a transaction pre-commit notification by returning a command that + * encapsulates follow-up changes in the applied-stereotype visualizaiton of + * my host edit-part. + * + * @param notification + * some model or notation change notification + * + * @return a trigger command that may or may not perform some modifications + * to the applied-stereotype notation in consequence + */ + private Command handlePrecommit(Notification notification) { + return new RecordingCommand(((IGraphicalEditPart) getHost()).getEditingDomain()) { + + @Override + protected void doExecute() { + notifyChanged(notification); + } + }; + } /** * @@ -287,7 +340,7 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic BasicCompartment compartment = helper.getStereotypeBraceCompartment(hostView, stereotype); if (compartment == null) { // No Compartment Exists for this Stereotype createAppliedStereotypeBraceCompartment(stereotype); - getDiagramEventBroker().addNotificationListener(helper.getStereotypeBraceCompartment(hostView, stereotype), this); + subscribe(helper.getStereotypeBraceCompartment(hostView, stereotype)); } @@ -310,7 +363,7 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic DecorationNode label = helper.getStereotypeLabel(hostView, stereotype); if (null == label) { // No Label Exist for this Stereotype createAppliedStereotypeLabel(stereotype); - getDiagramEventBroker().addNotificationListener(helper.getStereotypeLabel(hostView, stereotype), this); + subscribe(helper.getStereotypeLabel(hostView, stereotype)); } } @@ -383,7 +436,7 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic EList<Property> properties = stereotype.allAttributes(); for (Property property : properties) { createAppliedStereotypeBraceProperty(compartment, property); - getDiagramEventBroker().addNotificationListener(helper.getStereotypePropertyInBrace(hostView, stereotype, property), this); + subscribe(helper.getStereotypePropertyInBrace(hostView, stereotype, property)); } } @@ -447,8 +500,7 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic */ protected void executeAppliedStereotypeBraceCompartmentCreation(final IGraphicalEditPart editPart, final Stereotype stereotype) { CreateAppliedStereotypeCompartmentCommand command = new CreateAppliedStereotypeCompartmentCommand(editPart.getEditingDomain(), editPart.getNotationView(), stereotype, StereotypeDisplayConstant.STEREOTYPE_BRACE_TYPE); - CommandUtil.executeUnsafeCommand(command, editPart); - + execute(command); } @@ -464,8 +516,7 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic */ protected void executeAppliedStereotypeBracePropertyViewCreation(final IGraphicalEditPart editPart, final Node compartment, final Property stereotypeProperty) { CreateAppliedStereotypePropertyViewCommand command = new CreateAppliedStereotypePropertyViewCommand(editPart.getEditingDomain(), compartment, stereotypeProperty, StereotypeDisplayConstant.STEREOTYPE_PROPERTY_BRACE_TYPE); - CommandUtil.executeUnsafeCommand(command, editPart); - + execute(command); } /** @@ -478,9 +529,7 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic */ protected void executeStereotypeLabelCreation(final IGraphicalEditPart editPart, final Stereotype stereotype) { CreateStereotypeLabelCommand command = new CreateStereotypeLabelCommand(editPart.getEditingDomain(), editPart.getNotationView(), stereotype); - CommandUtil.executeUnsafeCommand(command, editPart); - - + execute(command); } /** @@ -527,10 +576,8 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic * DecorationNode of the Stereotype Label that has to be removed */ protected void executeStereotypeViewRemove(final IGraphicalEditPart editPart, final View view) { - DeleteCommand command = new DeleteCommand(view); - CommandUtil.executeUnsafeCommand(command, editPart); - + execute(command); } @@ -550,15 +597,15 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic public void removeListener() { View view = getView(); if (null != view) { - getDiagramEventBroker().removeNotificationListener(view, this); + unsubscribe(view); if (null != hostSemanticElement) { // remove listeners to applied stereotyped for (EObject stereotypeApplication : hostSemanticElement.getStereotypeApplications()) { - getDiagramEventBroker().removeNotificationListener(stereotypeApplication, this); + unsubscribe(stereotypeApplication); } // remove notification on element - getDiagramEventBroker().removeNotificationListener(hostSemanticElement, this); + unsubscribe(hostSemanticElement); // removes the reference to the semantic element hostSemanticElement = null; } @@ -570,18 +617,18 @@ public abstract class AbstractAppliedStereotypeDisplayEditPolicy extends Graphic // Remove label Listener View label = helper.getStereotypeLabel(hostView, stereotype); if (null != label) { - getDiagramEventBroker().removeNotificationListener(label, this); + unsubscribe(label); } // Remove Brace Compartment Listener BasicCompartment compartment = helper.getStereotypeBraceCompartment(hostView, stereotype); if (null != compartment) { - getDiagramEventBroker().addNotificationListener(helper.getStereotypeBraceCompartment(hostView, stereotype), this); + subscribe(helper.getStereotypeBraceCompartment(hostView, stereotype)); } // Remove Brace Properties Listener if (null != compartment && null != stereotype) { EList<Property> properties = stereotype.allAttributes(); for (Property property : properties) { - getDiagramEventBroker().removeNotificationListener(helper.getStereotypePropertyInBrace(hostView, stereotype, property), this); + unsubscribe(helper.getStereotypePropertyInBrace(hostView, stereotype, property)); } } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/AppliedStereotypeExternalNodeEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/AppliedStereotypeExternalNodeEditPolicy.java index 5e5931cc0e4..e07e88c0782 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/AppliedStereotypeExternalNodeEditPolicy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/AppliedStereotypeExternalNodeEditPolicy.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2009 CEA LIST. + * Copyright (c) 2009, 2016 CEA LIST, Christian W. Damus, and others. * * * All rights reserved. This program and the accompanying materials @@ -11,6 +11,7 @@ * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation * Patrick Tessier (CEA LIST) - Initial API and implementation * Celine JANSSENS (ALL4TEC) celine.janssens@all4tec.net - Bug 455311 Stereotype Display + * Christian W. Damus - bug 492482 *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.editpolicies; @@ -47,7 +48,7 @@ public class AppliedStereotypeExternalNodeEditPolicy extends AppliedStereotypeLa EObject parent = view.eContainer(); if (parent instanceof View) { parentView = (View) parent; - getDiagramEventBroker().addNotificationListener(parentView, this); + subscribe(parentView); } @@ -57,7 +58,7 @@ public class AppliedStereotypeExternalNodeEditPolicy extends AppliedStereotypeLa @Override public void deactivate() { if (parentView != null) { - getDiagramEventBroker().removeNotificationListener(parentView, this); + unsubscribe(parentView); } super.deactivate(); diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/CommentShapeForAppliedStereotypeEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/CommentShapeForAppliedStereotypeEditPolicy.java index 0169460c962..0e742df6772 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/CommentShapeForAppliedStereotypeEditPolicy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/editpolicies/CommentShapeForAppliedStereotypeEditPolicy.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2012, 2014 CEA LIST and others. + * Copyright (c) 2012, 2016 CEA LIST, Christian W. Damus, and others. * * * All rights reserved. This program and the accompanying materials @@ -11,6 +11,7 @@ * Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation * Christian W. Damus (CEA) - bug 323802 * Celine Janssens (ALL4TEC) celine.janssens@all4tec.net - Bug 460356 : Refactor Stereotype Display + * Christian W. Damus - bug 492482 * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.editpolicies; @@ -23,10 +24,7 @@ import org.eclipse.gef.Request; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.UnexecutableCommand; import org.eclipse.gmf.runtime.diagram.core.commands.DeleteCommand; -import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker; -import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; -import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper; import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest; import org.eclipse.gmf.runtime.notation.View; @@ -45,7 +43,7 @@ import org.eclipse.uml2.uml.util.UMLUtil; * and launch command of deletion if it detect that no property of applied stereotype are displayed. * */ -public class CommentShapeForAppliedStereotypeEditPolicy extends AbstractAppliedStereotypeDisplayEditPolicy implements NotificationListener, IPapyrusListener { +public class CommentShapeForAppliedStereotypeEditPolicy extends AbstractAppliedStereotypeDisplayEditPolicy implements IPapyrusListener { /** @@ -139,7 +137,7 @@ public class CommentShapeForAppliedStereotypeEditPolicy extends AbstractAppliedS // adds a listener on the view and the element controlled by the // editpartrefr - getDiagramEventBroker().addNotificationListener(view, this); + subscribe(view); } @@ -155,21 +153,7 @@ public class CommentShapeForAppliedStereotypeEditPolicy extends AbstractAppliedS return; } - getDiagramEventBroker().removeNotificationListener(view, this); - } - - /** - * Gets the diagram event broker from the editing domain. - * - * @return the diagram event broker - */ - @Override - protected DiagramEventBroker getDiagramEventBroker() { - TransactionalEditingDomain theEditingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain(); - if (null != theEditingDomain) { - return DiagramEventBroker.getInstance(theEditingDomain); - } - return null; + unsubscribe(view); } /** diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/stereotype/display/helper/StereotypeDisplayCommandExecution.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/stereotype/display/helper/StereotypeDisplayCommandExecution.java index 745baa1bc12..c0490fa0a4c 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/stereotype/display/helper/StereotypeDisplayCommandExecution.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/stereotype/display/helper/StereotypeDisplayCommandExecution.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2015 CEA LIST and others. + * Copyright (c) 2015, 2016 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -9,6 +9,7 @@ * Contributors: * Celine Janssens (ALL4TEC) celine.janssens@all4tec.net - Initial API and implementation * Celine Janssens (ALL4TEC) celine.janssens@all4tec.net - Bug 455311 : Refactor Stereotype Display + * Christian W. Damus - bug 492482 * *****************************************************************************/ @@ -59,36 +60,6 @@ public final class StereotypeDisplayCommandExecution { } /** - * Runnable class for setting visibility of a View - * Required if no Command has to be added into the stack - */ - class SetVisibilityRunnable implements Runnable { - - private boolean visible; - private View view; - - /** - * Constructor. - * - */ - public SetVisibilityRunnable(boolean visible, View view) { - this.visible = visible; - this.view = view; - } - - /** - * @see java.lang.Runnable#run() - * - */ - @Override - public void run() { - if (view.isVisible() != visible) { - view.setVisible(visible); - } - } - } - - /** * Set the visibility of a view * * @param view @@ -97,12 +68,11 @@ public final class StereotypeDisplayCommandExecution { * True to make the Compartment visible */ public void setVisibility(final TransactionalEditingDomain domain, final View view, final boolean isVisible, final boolean inCommandStack) { - + SetNodeVisibilityCommand visibility = new SetNodeVisibilityCommand(domain, view, isVisible); if (!inCommandStack) { - CommandUtil.executeUnsafeCommand(new SetVisibilityRunnable(isVisible, view), domain); + CommandUtil.executeCommand(visibility, domain); } else { - SetNodeVisibilityCommand visibility = new SetNodeVisibilityCommand(domain, view, isVisible); CommandUtil.executeCommandInStack(visibility, domain); } } @@ -117,23 +87,11 @@ public final class StereotypeDisplayCommandExecution { * True to make the Compartment visible */ public void setPersistency(final TransactionalEditingDomain domain, final View view, boolean inCommandStack) { - if (!inCommandStack) { + SetPersistentViewCommand persitence = new SetPersistentViewCommand(domain, view); - class SetPersistencyRunnable implements Runnable { - - /** - * @see java.lang.Runnable#run() - * - */ - @Override - public void run() { - makeViewPersistant(view); - } - - } - CommandUtil.executeUnsafeCommand(new SetPersistencyRunnable(), domain); + if (!inCommandStack) { + CommandUtil.executeCommand(persitence, domain); } else { - SetPersistentViewCommand persitence = new SetPersistentViewCommand(domain, view); CommandUtil.executeCommandInStack(persitence, domain); } @@ -148,24 +106,11 @@ public final class StereotypeDisplayCommandExecution { * True to make the Compartment visible */ public void unsetPersistency(final TransactionalEditingDomain domain, final View view, boolean inCommandStack) { + UnsetPersistentViewCommand persistence = new UnsetPersistentViewCommand(domain, view); if (!inCommandStack) { - - class UnsetPersistencyRunnable implements Runnable { - - /** - * @see java.lang.Runnable#run() - * - */ - @Override - public void run() { - removeViewPersistant(view); - } - - } - CommandUtil.executeUnsafeCommand(new UnsetPersistencyRunnable(), domain); + CommandUtil.executeCommand(persistence, domain); } else { - UnsetPersistentViewCommand persitence = new UnsetPersistentViewCommand(domain, view); - CommandUtil.executeCommandInStack(persitence, domain); + CommandUtil.executeCommandInStack(persistence, domain); } } @@ -228,7 +173,7 @@ public final class StereotypeDisplayCommandExecution { if (inCommandStack) { CommandUtil.executeCommandInStack(command, domain); } else { - CommandUtil.executeUnsafeCommand(command, domain); + CommandUtil.executeCommand(command, domain); } } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/stereotype/display/helper/StereotypeDisplayConstant.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/stereotype/display/helper/StereotypeDisplayConstant.java index b03aa885035..e83aaeeb5cc 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/stereotype/display/helper/StereotypeDisplayConstant.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/stereotype/display/helper/StereotypeDisplayConstant.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2015 CEA LIST and others.
+ * Copyright (c) 2015, 2016 CEA LIST, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -9,13 +9,18 @@ * Contributors:
* Celine Janssens (ALL4TEC) celine.janssens@all4tec.net - Initial API and implementation
* Celine Janssens (ALL4TEC) celine.janssens@all4tec.net - Bug 455311 : Refactor Stereotypes Display
+ * Christian W. Damus - bug 492482
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper;
+import java.util.Set;
+
import org.eclipse.papyrus.uml.diagram.common.Activator;
+import com.google.common.collect.ImmutableSet;
+
/**
@@ -43,6 +48,17 @@ public class StereotypeDisplayConstant { public static final String STEREOTYPE_COMMENT_TYPE = "StereotypeComment";//$NON-NLS-1$
public static final String STEREOTYPE_COMMENT_LINK_TYPE = "StereotypeCommentLink";
+
+ /**
+ * The applied-stereotype view types.
+ */
+ public static final Set<String> APPLIED_STEREOTYPE_VIEW_TYPES = ImmutableSet.of(
+ STEREOTYPE_LABEL_TYPE,
+ STEREOTYPE_BRACE_TYPE,
+ STEREOTYPE_COMPARTMENT_TYPE,
+ STEREOTYPE_COMMENT_TYPE, STEREOTYPE_COMMENT_LINK_TYPE,
+ STEREOTYPE_PROPERTY_TYPE, STEREOTYPE_PROPERTY_BRACE_TYPE);
+
// Name notation value
public static final String STEREOTYPE_LABEL_NAME = "stereotype";//$NON-NLS-1$
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/util/CommandUtil.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/util/CommandUtil.java index 05422fbc1f3..b40821a493f 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/util/CommandUtil.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/util/CommandUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Obeo. + * Copyright (c) 2008, 2016 Obeo, Christian W. Damus, 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 @@ -8,6 +8,7 @@ * Contributors: * Obeo - initial API and implementation * Celine Janssens (ALL4TEC) celine.janssens@all4tec.net - Enrich Execution Command + * Christian W. Damus - bug 492482 *******************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.util; @@ -24,6 +25,7 @@ import org.eclipse.emf.common.command.Command; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.Transaction; import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.impl.InternalTransactionalEditingDomain; import org.eclipse.emf.workspace.AbstractEMFOperation; import org.eclipse.gef.EditPartViewer; import org.eclipse.gmf.runtime.common.core.command.ICommand; @@ -32,8 +34,9 @@ import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer; import org.eclipse.gmf.runtime.diagram.ui.util.EditPartUtil; import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.emf.gmf.command.GMFtoEMFCommandWrapper; +import org.eclipse.papyrus.infra.emf.gmf.util.GMFUnsafe; import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; -import org.eclipse.papyrus.infra.gmfdiag.common.utils.GMFUnsafe; import org.eclipse.papyrus.uml.diagram.common.Activator; /** @@ -88,15 +91,15 @@ public class CommandUtil { } /** - * Execute a command as unsafe. - * Consequence: the command doesn't appear in the Command Stack and does not make the diagram dirty. + * Executes a {@code command} in the safest possible way within the context of + * an {@code object}. This is as a (possibly nested) + * read/write transaction if there is already a read/write transaction active, + * otherwise in a (possibly nested) "unprotected write" transaction. * * @param command - * The command to execute unsafe + * the command to execute * @param object - * The EObject that is required to define the Transactional domain. - * @param synch - * Define if the command should be execute synchronously or not. + * the contextual object from which to infer the editing domain * @see {@link #resolveEditingDomain} */ public static void executeUnsafeCommand(final ICommand command, final Object object) { @@ -109,15 +112,15 @@ public class CommandUtil { } /** - * Execute a command as unsafe. - * Consequence: the command doesn't appear in the Command Stack and does not make the diagram dirty. + * Executes a {@code command} in the safest possible way within the context of + * an {@code object}. This is as a (possibly nested) + * read/write transaction if there is already a read/write transaction active, + * otherwise in a (possibly nested) "unprotected write" transaction. * * @param command - * The command to execute unsafe + * the command to execute * @param object - * The EObject that is required to define the Transactional domain. - * @param synch - * Define if the command should be execute synchronously or not. + * the contextual object from which to infer the editing domain * @see {@link #resolveEditingDomain} */ public static void executeUnsafeCommand(final Command command, final Object object) { @@ -129,15 +132,15 @@ public class CommandUtil { } /** - * Execute a command as unsafe. - * Consequence: the command doesn't appear in the Command Stack and does not make the diagram dirty. + * Executes a {@code command} in the safest possible way within the context of + * an {@code object}. This is as a (possibly nested) + * read/write transaction if there is already a read/write transaction active, + * otherwise in a (possibly nested) "unprotected write" transaction. * * @param command - * The command to execute unsafe + * the command to execute * @param object - * The EObject that is required to define the Transactional domain. - * @param synch - * Define if the command should be execute synchronously or not. + * the contextual object from which to infer the editing domain * @see {@link #resolveEditingDomain} */ public static void executeUnsafeCommand(final Runnable command, final Object object) { @@ -150,21 +153,25 @@ public class CommandUtil { } /** - * Execute a command as unsafe. - * Consequence: the command doesn't appear in the Command Stack and does not make the diagram dirty. + * Execute a {@code command} in the command stack as usual, unless there's + * already a write transaction in progress, then just execute it directly. * * @param command - * The command to execute unsafe + * The command to execute * @param object * The EObject that is required to define the Transactional domain. * * @see {@link #resolveEditingDomain} */ public static void executeCommandInStack(final org.eclipse.emf.common.command.Command command, final Object object) { - TransactionalEditingDomain domain = resolveEditingDomain(object); - domain.getCommandStack().execute(command); + if (canWrite(domain) && command.canExecute()) { + // Just re-use the existing transaction + command.execute(); + } else { + domain.getCommandStack().execute(command); + } } /** @@ -196,58 +203,90 @@ public class CommandUtil { } /** - * Run the Command Asynchronously + * Executes a {@code command} in the safest possible way within the context of + * a transactional editing {@code domain}. This is as a (possibly nested) + * read/write transaction if there is already a read/write transaction active, + * otherwise in a (possibly nested) "unprotected write" transaction. * * @param command - * The command to execute + * the command to execute * @param domain - * The Transactional Editing Domain - * + * the editing domain in which to execute a command */ public static void executeCommand(final Command command, final TransactionalEditingDomain domain) { - + if (!canWrite(domain)) { + // Have to go the unprotected route. Hopefully the context is an + // edit-part refresh or something else that is not in a higher + // recorded edit command scope that needs to be undoable try { GMFUnsafe.write(domain, command); } catch (Exception e) { - Activator.log.error(e); + // Failed to create the unprotected transaction or it rolled back + Activator.log.error("Unprotected command execution failed.", e); //$NON-NLS-1$ + } + } else { + // There's a change recorder in progress or an unprotected write + // that can't be overridden with a read/write transaction anyways, + // or we're not an edit-part that provides editing domains, + // so just roll with it + if (command.canExecute()) { + command.execute(); + } + } + } + + private static boolean canWrite(TransactionalEditingDomain domain) { + Transaction activeTransaction = null; + if (domain instanceof InternalTransactionalEditingDomain) { + activeTransaction = ((InternalTransactionalEditingDomain) domain).getActiveTransaction(); } + return (activeTransaction != null) && !activeTransaction.isReadOnly(); } /** - * Run the Command Asynchronously + * Executes a {@code command} in the safest possible way within the context of + * a transactional editing {@code domain}. This is as a (possibly nested) + * read/write transaction if there is already a read/write transaction active, + * otherwise in a (possibly nested) "unprotected write" transaction. * * @param command - * The command to execute + * the command to execute * @param domain - * The Transactional Editing Domain - * + * the editing domain in which to execute a command */ private static void executeCommand(final ICommand command, final TransactionalEditingDomain domain) { - try { - GMFUnsafe.write(domain, command); - } catch (Exception e) { - Activator.log.error(e); + executeCommand(GMFtoEMFCommandWrapper.wrap(command), domain); } - } /** - * Run the Command Asynchronously + * Executes a {@code command} in the safest possible way within the context of + * a transactional editing {@code domain}. This is as a (possibly nested) + * read/write transaction if there is already a read/write transaction active, + * otherwise in a (possibly nested) "unprotected write" transaction. * * @param command - * The command to execute + * the command to execute * @param domain - * The Transactional Editing Domain - * + * the editing domain in which to execute a command */ private static void executeCommand(final Runnable command, final TransactionalEditingDomain domain) { - // use to avoid to put it in the command stack + if (!canWrite(domain)) { + // Have to go the unprotected route. Hopefully the context is an + // edit-part refresh or something else that is not in a higher + // recorded edit command scope that needs to be undoable try { GMFUnsafe.write(domain, command); } catch (Exception e) { - Activator.log.error(e); + // Failed to create the unprotected transaction or it rolled back + Activator.log.error("Unprotected command execution failed.", e); //$NON-NLS-1$ + } + } else { + // There's a change recorder in progress or an unprotected write + // that can't be overridden with a read/write transaction anyways, + // or we're not an edit-part that provides editing domains, + // so just roll with it + command.run(); } } - - } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/AppliedStereotypeExternalNodeLabelEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/AppliedStereotypeExternalNodeLabelEditPolicy.java index 3f447635dce..24b03fef792 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/AppliedStereotypeExternalNodeLabelEditPolicy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/AppliedStereotypeExternalNodeLabelEditPolicy.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA
+ * Copyright (c) 2013, 2016 CEA, Christian W. Damus, and others
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@ *
* Contributors:
* Soyatec - Initial API and implementation
+ * Christian W. Damus - bug 492482
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.edit.policies;
@@ -63,7 +64,7 @@ public class AppliedStereotypeExternalNodeLabelEditPolicy extends AppliedStereot hostView = (View) parent;
}
}
- getDiagramEventBroker().addNotificationListener(hostView, this);
+ subscribe(hostView);
refreshDisplay();
@@ -72,7 +73,7 @@ public class AppliedStereotypeExternalNodeLabelEditPolicy extends AppliedStereot @Override
public void deactivate() {
if (hostView != null) {
- getDiagramEventBroker().removeNotificationListener(hostView, this);
+ unsubscribe(hostView);
}
super.deactivate();
}
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/.classpath b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/.classpath index 2d1a4302f04..eca7bdba8f0 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/.classpath +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/.classpath @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/.settings/org.eclipse.jdt.core.prefs b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/.settings/org.eclipse.jdt.core.prefs index 4759947300a..62a08f4494d 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/.settings/org.eclipse.jdt.core.prefs +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/META-INF/MANIFEST.MF b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/META-INF/MANIFEST.MF index ff439fa68bd..31a868b0a97 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/META-INF/MANIFEST.MF +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/META-INF/MANIFEST.MF @@ -1,10 +1,12 @@ Manifest-Version: 1.0 Export-Package: org.eclipse.papyrus.uml.diagram.stereotype.edition.editpart, org.eclipse.papyrus.uml.diagram.stereotype.edition.editpolicies, + org.eclipse.papyrus.uml.diagram.stereotype.edition.internal.edithelper.advice;x-internal:=true,
org.eclipse.papyrus.uml.diagram.stereotype.edition.provider Require-Bundle: org.eclipse.papyrus.uml.diagram.common;bundle-version="[2.0.0,3.0.0)";visibility:=reexport, org.eclipse.papyrus.uml.appearance;bundle-version="[1.2.0,2.0.0)", - org.eclipse.papyrus.uml.profile;bundle-version="[2.0.0,3.0.0)" + org.eclipse.papyrus.uml.profile;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.papyrus.infra.types;bundle-version="[2.0.0,3.0.0)" Bundle-Vendor: %providerName Bundle-ActivationPolicy: lazy Bundle-Version: 1.2.0.qualifier @@ -14,4 +16,4 @@ Bundle-Activator: org.eclipse.papyrus.uml.diagram.stereotype.edition.Activator Bundle-ManifestVersion: 2 Bundle-Description: %pluginDescription Bundle-SymbolicName: org.eclipse.papyrus.uml.diagram.stereotype.edition;singleton:=true -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/build.properties b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/build.properties index bc40c8bd26b..85541d0f03d 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/build.properties +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/build.properties @@ -4,6 +4,7 @@ bin.includes = META-INF/,\ .,\
plugin.xml,\
about.html,\
- plugin.properties
+ plugin.properties,\
+ model/
src.includes = about.html,\
docs/,\
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/model/stereotype-edit.elementtypesconfigurations b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/model/stereotype-edit.elementtypesconfigurations new file mode 100644 index 00000000000..865e3bc537f --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/model/stereotype-edit.elementtypesconfigurations @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="ASCII"?> +<elementtypesconfigurations:ElementTypeSetConfiguration + xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:elementtypesconfigurations="http://www.eclipse.org/papyrus/infra/elementtypesconfigurations/1.1" + xmi:id="_ScP1oFYCEeS0WsAAtVmToA" + name="Stereotype Editing Advice" + description="Advice definitions supporting the editing of stereotypes." + identifier="org.eclipse.papyrus.uml.diagram.stereotype.edition.advice" + metamodelNsURI="http://www.eclipse.org/uml2/5.0.0/UML"> + <adviceBindingsConfigurations + xsi:type="elementtypesconfigurations:AdviceBindingConfiguration" + xmi:id="_4rSa8Dm8EeWMHpLNzlgfaQ" + description="Adds applied-stereotype views to the dependents of a notation view that is being deleted." + identifier="org.eclipse.papyrus.uml.diagram.stereotype.edition.advice.AppliedStereotypeNotationDependents" + editHelperAdviceClassName="org.eclipse.papyrus.uml.diagram.stereotype.edition.internal.edithelper.advice.AppliedStereotypeNotationDependentsAdvice" + inheritance="all"> + <target + xsi:type="elementtypesconfigurations:MetamodelTypeConfiguration" + href="../../org.eclipse.papyrus.uml.service.types/model/uml.elementtypesconfigurations#_ScgUUFYCEeS0WsAAtVmToA"/> + </adviceBindingsConfigurations> +</elementtypesconfigurations:ElementTypeSetConfiguration> diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/plugin.xml b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/plugin.xml index 6ec94f1bff2..4eeaf1f1345 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/plugin.xml +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/plugin.xml @@ -30,4 +30,13 @@ </object>
</editpartProvider>
</extension>
+
+ <extension
+ point="org.eclipse.papyrus.infra.types.core.elementTypeSetConfiguration">
+ <elementTypeSet
+ clientContextID="org.eclipse.papyrus.infra.services.edit.TypeContext"
+ path="model/stereotype-edit.elementtypesconfigurations">
+ </elementTypeSet>
+ </extension>
+
</plugin>
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/editpolicies/AppliedStereotypeCommentEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/editpolicies/AppliedStereotypeCommentEditPolicy.java index a6c48b59a85..4e43436339c 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/editpolicies/AppliedStereotypeCommentEditPolicy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/editpolicies/AppliedStereotypeCommentEditPolicy.java @@ -11,7 +11,7 @@ * Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation * Christian W. Damus (CEA) - bug 323802 * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.fr - Bug 393532 - * Christian W. Damus - bug 492407 + * Christian W. Damus - bugs 492407, 492482 * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.stereotype.edition.editpolicies; @@ -34,15 +34,12 @@ import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.LayoutConstraint; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.View; -import org.eclipse.papyrus.infra.gmfdiag.common.utils.GMFUnsafe; -import org.eclipse.papyrus.uml.diagram.common.Activator; import org.eclipse.papyrus.uml.diagram.common.editpolicies.AppliedStereotypeNodeLabelDisplayEditPolicy; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.command.CreateAppliedStereotypeCommentViewCommand; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.command.CreateAppliedStereotypeCompartmentCommand; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.command.CreateAppliedStereotypePropertyViewCommand; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper.StereotypeDisplayConstant; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper.StereotypeDisplayUtil; -import org.eclipse.swt.widgets.Display; import org.eclipse.uml2.uml.Extension; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.Stereotype; @@ -72,7 +69,7 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab @Override public void activate() { super.activate(); - getDiagramEventBroker().addNotificationListener(hostView.eContainer(), this); + subscribe(hostView.eContainer()); }; @@ -82,7 +79,7 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab */ @Override public void deactivate() { - getDiagramEventBroker().removeNotificationListener(hostView.eContainer(), this); + unsubscribe(hostView.eContainer()); super.deactivate(); } @@ -114,20 +111,20 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab @Override public void notifyChanged(Notification notification) { super.notifyChanged(notification); - + // Don't react if the comment is not attached to a diagram if ((comment != null) && (comment.getDiagram() != null)) { int eventType = notification.getEventType(); EObject object = StereotypeDisplayUtil.getInstance().getCommentSemanticElement(comment); // If the reference object of the comment is removed, delete the Comment node itself. if (eventType == Notification.REMOVE && notification.getOldValue().equals(hostView) && object == null) { - executeAppliedStereotypeCommentDeletion(hostEditPart.getEditingDomain(), comment); + executeAppliedStereotypeCommentDeletion(comment); } if (comment.getTargetEdges() != null) { // If the Target View is null then remove the Comment View if (eventType == Notification.REMOVE && notification.getOldValue().equals(hostView) && comment.getTargetEdges().size() == 0) { - executeAppliedStereotypeCommentDeletion(hostEditPart.getEditingDomain(), comment); + executeAppliedStereotypeCommentDeletion(comment); } } } @@ -152,12 +149,10 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab for (Stereotype stereotype : stereotypeList) { refreshStereotypeCompartmentStructure(stereotype); - getDiagramEventBroker().addNotificationListener(helper.getStereotypeCompartment(comment, stereotype), this); + subscribe(helper.getStereotypeCompartment(comment, stereotype)); refreshStereotypeBraceStructure(stereotype); - getDiagramEventBroker().addNotificationListener(helper.getStereotypeBraceCompartment(comment, stereotype), this); - - + subscribe(helper.getStereotypeBraceCompartment(comment, stereotype)); } } } @@ -175,8 +170,8 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab if (!stereotypeList.isEmpty()) { if (null != comment) { for (Stereotype stereotype : stereotypeList) { - getDiagramEventBroker().removeNotificationListener(helper.getStereotypeCompartment(comment, stereotype), this); - getDiagramEventBroker().removeNotificationListener(helper.getStereotypeBraceCompartment(comment, stereotype), this); + unsubscribe(helper.getStereotypeCompartment(comment, stereotype)); + unsubscribe(helper.getStereotypeBraceCompartment(comment, stereotype)); } } } @@ -193,7 +188,7 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab super.refreshStereotypeDisplay(); // If no more Compartment, delete the Comment if (comment != null && getAppliedStereotypeCompartmentNumber(comment) == 0) { - executeAppliedStereotypeCommentDeletion(hostEditPart.getEditingDomain(), comment); + executeAppliedStereotypeCommentDeletion(comment); } } @@ -376,30 +371,10 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab */ protected void executeAppliedStereotypeCompartmentCreation(final IGraphicalEditPart editPart, final Stereotype stereotype, final String type) { - try { - editPart.getEditingDomain().runExclusive(new Runnable() { - - public void run() { - Display.getCurrent().syncExec(new Runnable() { - - - public void run() { - CreateAppliedStereotypeCompartmentCommand command = new CreateAppliedStereotypeCompartmentCommand(editPart.getEditingDomain(), comment, stereotype, type); - - // use to avoid to put it in the command stack - try { - GMFUnsafe.write(editPart.getEditingDomain(), command); - } catch (Exception e) { - Activator.log.error(e); - } - } - }); + CreateAppliedStereotypeCompartmentCommand command = new CreateAppliedStereotypeCompartmentCommand(editPart.getEditingDomain(), comment, stereotype, type); - } - }); - } catch (Exception e) { - Activator.log.error(e); - } + // Record for undo if possible, otherwise unprotected + execute(command); } @@ -415,29 +390,9 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab */ protected void executeAppliedStereotypePropertyViewCreation(final IGraphicalEditPart editPart, final Node compartment, final Property stereotypeProperty) { - try { - editPart.getEditingDomain().runExclusive(new Runnable() { - - public void run() { - Display.getCurrent().syncExec(new Runnable() { - - public void run() { - - // use to avoid to put it in the command stack - CreateAppliedStereotypePropertyViewCommand command = new CreateAppliedStereotypePropertyViewCommand(editPart.getEditingDomain(), compartment, stereotypeProperty, StereotypeDisplayConstant.STEREOTYPE_PROPERTY_TYPE); - try { - GMFUnsafe.write(editPart.getEditingDomain(), command); - } catch (Exception e) { - Activator.log.error(e); - } - } - }); - } - }); - - } catch (Exception e) { - Activator.log.error(e); - } + // Record for undo if possible, otherwise unprotected + CreateAppliedStereotypePropertyViewCommand command = new CreateAppliedStereotypePropertyViewCommand(editPart.getEditingDomain(), compartment, stereotypeProperty, StereotypeDisplayConstant.STEREOTYPE_PROPERTY_TYPE); + execute(command); } @@ -454,71 +409,50 @@ public class AppliedStereotypeCommentEditPolicy extends AppliedStereotypeNodeLab protected void executeAppliedStereotypeCommentCreation(final EObject node) { final TransactionalEditingDomain domain = hostEditPart.getEditingDomain(); - Display.getCurrent().syncExec(new Runnable() { - - public void run() { - int x = 200; - int y = 100; - if (hostEditPart.getModel() instanceof Node) { - LayoutConstraint constraint = ((Node) hostEditPart.getModel()).getLayoutConstraint(); - if (constraint instanceof Bounds) { - x = x + ((Bounds) constraint).getX(); - y = ((Bounds) constraint).getY(); - } - } - if (hostEditPart.getModel() instanceof Edge && ((((Edge) hostEditPart.getModel()).getSource()) instanceof Node)) { + int x = 200; + int y = 100; + if (hostEditPart.getModel() instanceof Node) { + LayoutConstraint constraint = ((Node) hostEditPart.getModel()).getLayoutConstraint(); + if (constraint instanceof Bounds) { + x = x + ((Bounds) constraint).getX(); + y = ((Bounds) constraint).getY(); + } - LayoutConstraint constraint = ((Node) ((Edge) hostEditPart.getModel()).getSource()).getLayoutConstraint(); - if (constraint instanceof Bounds) { - x = x + ((Bounds) constraint).getX(); - y = ((Bounds) constraint).getY() - 100; - } + } + if (hostEditPart.getModel() instanceof Edge && ((((Edge) hostEditPart.getModel()).getSource()) instanceof Node)) { - } - boolean isBorderElement = false; - if (hostEditPart instanceof BorderedBorderItemEditPart) { - isBorderElement = true; - } - if (helper.getStereotypeComment((View) getHost().getModel()) == null) { - CreateAppliedStereotypeCommentViewCommand command = new CreateAppliedStereotypeCommentViewCommand(domain, (View) hostEditPart.getModel(), x, y, node, isBorderElement); - // use to avoid to put it in the command stack - try { - GMFUnsafe.write(domain, command); - } catch (Exception e) { - Activator.log.error(e); - } - } + LayoutConstraint constraint = ((Node) ((Edge) hostEditPart.getModel()).getSource()).getLayoutConstraint(); + if (constraint instanceof Bounds) { + x = x + ((Bounds) constraint).getX(); + y = ((Bounds) constraint).getY() - 100; } - }); + } + boolean isBorderElement = false; + if (hostEditPart instanceof BorderedBorderItemEditPart) { + isBorderElement = true; + } + if (helper.getStereotypeComment((View) getHost().getModel()) == null) { + CreateAppliedStereotypeCommentViewCommand command = new CreateAppliedStereotypeCommentViewCommand(domain, (View) hostEditPart.getModel(), x, y, node, isBorderElement); + // Record for undo if possible, otherwise unprotected + execute(command); + } } /** * In Charge to delete the Comment Node. * - * @param domain - * the transactional editing domain * @param commentNode * the view that represent the comment of stereotype */ - - protected void executeAppliedStereotypeCommentDeletion(final TransactionalEditingDomain domain, final View commentNode) { - Display.getCurrent().syncExec(new Runnable() { - - public void run() { - // because it is asynchrony the comment node maybe become s null - if (commentNode != null && TransactionUtil.getEditingDomain(commentNode) != null) { - DeleteCommand command = new DeleteCommand(commentNode); - // use to avoid to put it in the command stack - try { - GMFUnsafe.write(domain, command); - } catch (Exception e) { - Activator.log.error(e); - } - } - } - }); + protected void executeAppliedStereotypeCommentDeletion(final View commentNode) { + // because it is asynchronous the comment node maybe become s null + if (commentNode != null && TransactionUtil.getEditingDomain(commentNode) != null) { + DeleteCommand command = new DeleteCommand(commentNode); + // Record for undo if possible, otherwise unprotected + execute(command); + } } /** diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/editpolicies/AppliedStereotypeCompartmentEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/editpolicies/AppliedStereotypeCompartmentEditPolicy.java index 200eb779d27..28a8dc6b181 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/editpolicies/AppliedStereotypeCompartmentEditPolicy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/editpolicies/AppliedStereotypeCompartmentEditPolicy.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2012, 2014 CEA LIST and others. + * Copyright (c) 2012, 2016 CEA LIST, Christian W. Damus, and others. * * * All rights reserved. This program and the accompanying materials @@ -12,6 +12,7 @@ * Christian W. Damus (CEA) - bug 323802 * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.fr - Bug 393532 * Celine Janssens (ALL4TEC) celine.janssens@all4tec.net - Bug 455311 : Refactor Stereotypes Display + * Christian W. Damus - bug 492482 * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.stereotype.edition.editpolicies; @@ -22,14 +23,11 @@ import org.eclipse.gmf.runtime.notation.BasicCompartment; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.infra.gmfdiag.common.editpart.IPapyrusEditPart; -import org.eclipse.papyrus.infra.gmfdiag.common.utils.GMFUnsafe; -import org.eclipse.papyrus.uml.diagram.common.Activator; import org.eclipse.papyrus.uml.diagram.common.editpolicies.AppliedStereotypeNodeLabelDisplayEditPolicy; import org.eclipse.papyrus.uml.diagram.common.figure.node.IPapyrusNodeUMLElementFigure; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.command.CreateAppliedStereotypeCompartmentCommand; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.command.CreateAppliedStereotypePropertyViewCommand; import org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper.StereotypeDisplayConstant; -import org.eclipse.swt.widgets.Display; import org.eclipse.uml2.uml.Extension; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.Stereotype; @@ -66,7 +64,7 @@ public class AppliedStereotypeCompartmentEditPolicy extends AppliedStereotypeNod if (!stereotypeList.isEmpty()) { for (Stereotype stereotype : stereotypeList) { refreshStereotypeCompartmentStructure(stereotype); - getDiagramEventBroker().addNotificationListener(helper.getStereotypeCompartment(hostView, stereotype), this); + subscribe(helper.getStereotypeCompartment(hostView, stereotype)); } } @@ -93,11 +91,10 @@ public class AppliedStereotypeCompartmentEditPolicy extends AppliedStereotypeNod Node compartment = helper.getStereotypeCompartment(hostView, stereotype); if (null != compartment && null != stereotype) { - getDiagramEventBroker().removeNotificationListener(compartment, this); + unsubscribe(compartment); EList<Property> properties = stereotype.allAttributes(); for (Property property : properties) { - getDiagramEventBroker().removeNotificationListener(helper.getStereotypeProperty(hostView, stereotype, property), this); - + unsubscribe(helper.getStereotypeProperty(hostView, stereotype, property)); } @@ -154,7 +151,7 @@ public class AppliedStereotypeCompartmentEditPolicy extends AppliedStereotypeNod EList<Property> properties = stereotype.allAttributes(); for (Property property : properties) { createAppliedStereotypeProperty(compartment, property); - getDiagramEventBroker().addNotificationListener(helper.getStereotypeProperty(hostView, stereotype, property), this); + subscribe(helper.getStereotypeProperty(hostView, stereotype, property)); } @@ -193,33 +190,11 @@ public class AppliedStereotypeCompartmentEditPolicy extends AppliedStereotypeNod * @param appliedstereotype * the stereotype application */ - protected void executeAppliedStereotypeCompartmentCreation(final IGraphicalEditPart editPart, final Stereotype stereotype) { - try { - editPart.getEditingDomain().runExclusive(new Runnable() { - - - public void run() { - Display.getCurrent().syncExec(new Runnable() { - + CreateAppliedStereotypeCompartmentCommand command = new CreateAppliedStereotypeCompartmentCommand(editPart.getEditingDomain(), editPart.getNotationView(), stereotype, StereotypeDisplayConstant.STEREOTYPE_COMPARTMENT_TYPE); - public void run() { - CreateAppliedStereotypeCompartmentCommand command = new CreateAppliedStereotypeCompartmentCommand(editPart.getEditingDomain(), editPart.getNotationView(), stereotype, StereotypeDisplayConstant.STEREOTYPE_COMPARTMENT_TYPE); - - // use to avoid to put it in the command stack - try { - GMFUnsafe.write(editPart.getEditingDomain(), command); - } catch (Exception e) { - Activator.log.error(e); - } - } - }); - - } - }); - } catch (Exception e) { - Activator.log.error(e); - } + // Record for undo if possible, otherwise unprotected + execute(command); } @@ -233,33 +208,11 @@ public class AppliedStereotypeCompartmentEditPolicy extends AppliedStereotypeNod * @param stereotype * the stereotype associated to compartment node */ - protected void executeAppliedStereotypePropertyViewCreation(final IGraphicalEditPart editPart, final Node compartment, final Property stereotypeProperty) { - try { - editPart.getEditingDomain().runExclusive(new Runnable() { - - - public void run() { - Display.getCurrent().syncExec(new Runnable() { - + CreateAppliedStereotypePropertyViewCommand command = new CreateAppliedStereotypePropertyViewCommand(editPart.getEditingDomain(), compartment, stereotypeProperty, StereotypeDisplayConstant.STEREOTYPE_PROPERTY_TYPE); - public void run() { - - // use to avoid to put it in the command stack - CreateAppliedStereotypePropertyViewCommand command = new CreateAppliedStereotypePropertyViewCommand(editPart.getEditingDomain(), compartment, stereotypeProperty, StereotypeDisplayConstant.STEREOTYPE_PROPERTY_TYPE); - try { - GMFUnsafe.write(editPart.getEditingDomain(), command); - } catch (Exception e) { - Activator.log.error(e); - } - } - }); - } - }); - - } catch (Exception e) { - Activator.log.error(e); - } + // Record for undo if possible, otherwise unprotected + execute(command); } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/internal/edithelper/advice/AppliedStereotypeNotationDependentsAdvice.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/internal/edithelper/advice/AppliedStereotypeNotationDependentsAdvice.java new file mode 100644 index 00000000000..bbe2f46fd96 --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.stereotype.edition/src/org/eclipse/papyrus/uml/diagram/stereotype/edition/internal/edithelper/advice/AppliedStereotypeNotationDependentsAdvice.java @@ -0,0 +1,98 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.stereotype.edition.internal.edithelper.advice; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice; +import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyDependentsRequest; +import org.eclipse.gmf.runtime.notation.Node; +import org.eclipse.gmf.runtime.notation.View; +import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil; +import org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper.StereotypeDisplayUtil; +import org.eclipse.uml2.uml.Element; + +/** + * Dependents advice for deletion of the applied-stereotype views associated with + * UML elements being deleted. + */ +public class AppliedStereotypeNotationDependentsAdvice extends AbstractEditHelperAdvice { + + /** + * Initializes me. + */ + public AppliedStereotypeNotationDependentsAdvice() { + super(); + } + + @Override + protected ICommand getAfterDestroyDependentsCommand(DestroyDependentsRequest request) { + ICommand result = super.getAfterDestroyDependentsCommand(request); + + EObject element = request.getElementToDestroy(); + if (element instanceof Element) { + Collection<View> appliedStereotypeViews = getAppliedStereotypeViews(element); + if (!appliedStereotypeViews.isEmpty()) { + ICommand destroy = request.getDestroyDependentsCommand(appliedStereotypeViews); + + if (result == null) { + result = destroy; + } else { + result = result.compose(destroy); + } + } + } + + return result; + } + + protected Collection<View> getAppliedStereotypeViews(EObject object) { + Collection<View> result = null; + + @SuppressWarnings("unchecked") + List<View> views = (List<View>) DiagramEditPartsUtil.getEObjectViews(object); + if (!views.isEmpty()) { + // Assume three applied-stereotype views for each and on average + // one and a half child views also to consider + result = new ArrayList<View>(views.size() * 3 * 3 / 2); + + collectAppliedStereotypeViews(new LinkedList<View>(views), result, StereotypeDisplayUtil.getInstance()); + } + + + return (result == null) ? Collections.<View> emptyList() : result; + } + + @SuppressWarnings("unchecked") + protected void collectAppliedStereotypeViews(Queue<View> views, Collection<? super View> result, StereotypeDisplayUtil helper) { + for (View next = views.poll(); next != null; next = views.poll()) { + Node comment = helper.getStereotypeComment(next); + if (comment != null) { + result.add(comment); + result.addAll(comment.getSourceEdges()); + result.addAll(comment.getTargetEdges()); + } + + // Add its children to the work queue + views.addAll(next.getChildren()); + } + } +} diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/listeners/StereotypeElementListener.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/listeners/StereotypeElementListener.java index 5b035036e75..7505329b864 100644 --- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/listeners/StereotypeElementListener.java +++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/listeners/StereotypeElementListener.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014 CEA LIST, Christian W. Damus, and others. + * Copyright (c) 2014, 2016 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -9,15 +9,22 @@ * Contributors: * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.fr - Bug 393532 - * Christian W. Damus - bug 450523 - * Christian W. Damus - bug 399859 + * Christian W. Damus - bugs 450523, 399859, 492482 * *****************************************************************************/ package org.eclipse.papyrus.uml.tools.listeners; +import java.util.ArrayList; import java.util.List; +import org.eclipse.emf.common.command.AbstractCommand; +import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.notify.NotificationChain; +import org.eclipse.emf.common.notify.impl.NotificationChainImpl; +import org.eclipse.emf.common.notify.impl.NotificationImpl; +import org.eclipse.emf.common.util.ECollections; +import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.ENamedElement; import org.eclipse.emf.ecore.EObject; @@ -30,6 +37,7 @@ import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.transaction.NotificationFilter; import org.eclipse.emf.transaction.ResourceSetChangeEvent; import org.eclipse.emf.transaction.ResourceSetListenerImpl; +import org.eclipse.emf.transaction.RollbackException; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.Extension; @@ -76,24 +84,79 @@ public class StereotypeElementListener extends ResourceSetListenerImpl { } /** - * Resource set changed. + * I am a pre-commit listener. Trigger listeners need to be able to react to + * these events. And they will be captured and automatically distributed again + * when the transaction commits (if it doesn't roll back). * - * @param event - * the event - * @see org.eclipse.emf.transaction.ResourceSetListenerImpl#resourceSetChanged(org.eclipse.emf.transaction.ResourceSetChangeEvent) + * @return {@code true} */ @Override - public void resourceSetChanged(ResourceSetChangeEvent event) { + public boolean isPrecommitOnly() { + return true; + } - // Get filtered notifications - List<Notification> filteredNotificationsList = event.getNotifications(); + @Override + public Command transactionAboutToCommit(ResourceSetChangeEvent event) throws RollbackException { + Command result = null; - // Handle each filtered notification - for (Notification notification : filteredNotificationsList) { - handleFilteredNotification(notification); - } + if (!event.getNotifications().isEmpty()) { + // Get filtered notifications + final NotificationChain chain = new NotificationChainImpl(); + List<Notification> filteredNotificationsList = new ArrayList<Notification>(event.getNotifications()); + + // Handle each filtered notification + for (Notification notification : filteredNotificationsList) { + handleFilteredNotification(notification, chain); + } + + result = new AbstractCommand("Inject Stereotype Notifications") { + private NotificationChain notifications; + + @Override + protected boolean prepare() { + this.notifications = chain; + return true; + } + + @Override + public void execute() { + dispatchAndInvert(); + } + + @Override + public void undo() { + dispatchAndInvert(); + } + + @Override + public void redo() { + dispatchAndInvert(); + } + + private void dispatchAndInvert() { + notifications.dispatch(); + this.notifications = invertNotifications(notifications); + } + + private NotificationChain invertNotifications(NotificationChain notifications) { + // The chain is implemented as an EList + @SuppressWarnings("unchecked") + EList<Notification> list = (EList<Notification>) notifications; + // Reverse the order + ECollections.reverse(list); + // And flip the type from applied <--> unapplied + for (Notification next : list) { + ((StereotypeExtensionNotification) next).invert(); + } + + return notifications; + } + }; + } + + return result; } /** @@ -101,9 +164,10 @@ public class StereotypeElementListener extends ResourceSetListenerImpl { * * @param notification * the notification + * @param notifications + * a notification chain on which to collect notifications for later dispatch. If {@code null}, then dispatch immediately */ - private void handleFilteredNotification(Notification notification) { - + private void handleFilteredNotification(Notification notification, NotificationChain notifications) { final Object notifier = notification.getNotifier(); Element extendedElement = null; @@ -150,6 +214,7 @@ public class StereotypeElementListener extends ResourceSetListenerImpl { case StereotypeExtensionNotification.MODIFIED_STEREOTYPE_OF_ELEMENT: // New value is the modified element newValue = notification.getNewValue(); + oldValue = notification.getOldValue(); break; default: // Nothing to do @@ -158,8 +223,13 @@ public class StereotypeElementListener extends ResourceSetListenerImpl { // Bug 450523: If element is null, the notification has already been sent. Simply ignore this case if (element != null) { - element.eNotify( - new StereotypeExtensionNotification(element, eventType, oldValue, newValue, stereotype)); + NotificationImpl newNotification = new StereotypeExtensionNotification(element, eventType, oldValue, newValue, stereotype); + if (notifications == null) { + // Dispatch it now + newNotification.dispatch(); + } else { + notifications.add(newNotification); + } } } @@ -398,6 +468,28 @@ public class StereotypeElementListener extends ResourceSetListenerImpl { public Stereotype getStereotype() { return stereotype; } + + /** + * Flips an "applied" notification to "unapplied" and vice versa. + */ + void invert() { + switch (getEventType()) { + case STEREOTYPE_APPLIED_TO_ELEMENT: + eventType = STEREOTYPE_UNAPPLIED_FROM_ELEMENT; + break; + case STEREOTYPE_UNAPPLIED_FROM_ELEMENT: + eventType = STEREOTYPE_APPLIED_TO_ELEMENT; + break; + default: + // Stereotype-modified events are their own inverses + break; + } + + // Swap the old and new values + Object swap = oldValue; + oldValue = newValue; + newValue = swap; + } } } |