diff options
author | Christian W. Damus | 2016-04-12 19:37:45 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2016-04-18 17:57:00 +0000 |
commit | 928852a40e704d8d53906edfe78f27f5e66c6c95 (patch) | |
tree | 867c1e4b425a81a5936d56b669035bcc8c475dd1 /plugins/infra/emf | |
parent | 89480a4d658a3ae3c5cc7b9be54bdbfc60eba49d (diff) | |
download | org.eclipse.papyrus-928852a40e704d8d53906edfe78f27f5e66c6c95.tar.gz org.eclipse.papyrus-928852a40e704d8d53906edfe78f27f5e66c6c95.tar.xz org.eclipse.papyrus-928852a40e704d8d53906edfe78f27f5e66c6c95.zip |
Bug 491542: [All Diagrams] Undo doesn't work with RuntimeValuesAdvice
dialog for creation
https://bugs.eclipse.org/bugs/show_bug.cgi?id=491542
Support re-entrant command execution in the CheckedOperationHistory,
which is used by both the CheckedDiagramCommandStack (used by the
diagrams) and the NestingNotifyingWorkspaceCommandStack (used by
everything else), in much the same way as the latter supports
nested execution. This ensures that, in the case where the execution
of a top-level operation in the diagram triggers nested execution of
operations in the EMF editing domain, which both delegate to the same
CheckedOperationHistory, the nested operations are executed strictly
within the context of the root operation, not separately as a sequence
of operations in the history.
Change-Id: I0967a62940d5c1030edf14d39994eeda2d3bdf9b
Diffstat (limited to 'plugins/infra/emf')
-rw-r--r-- | plugins/infra/emf/org.eclipse.papyrus.infra.emf.gmf/src/org/eclipse/papyrus/infra/emf/gmf/command/CheckedOperationHistory.java | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.gmf/src/org/eclipse/papyrus/infra/emf/gmf/command/CheckedOperationHistory.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.gmf/src/org/eclipse/papyrus/infra/emf/gmf/command/CheckedOperationHistory.java index a9cc62ba62a..41dba170748 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.gmf/src/org/eclipse/papyrus/infra/emf/gmf/command/CheckedOperationHistory.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.gmf/src/org/eclipse/papyrus/infra/emf/gmf/command/CheckedOperationHistory.java @@ -9,7 +9,7 @@ * Contributors: * Mathieu Velten (Atos) - Initial API and implementation * Christian W. Damus (CEA) - bugs 357250, 323802 - * Christian W. Damus - bug 485220 + * Christian W. Damus - bugs 485220, 491542 * *****************************************************************************/ package org.eclipse.papyrus.infra.emf.gmf.command; @@ -56,6 +56,9 @@ public class CheckedOperationHistory implements IOperationHistory { protected IOperationHistory history; + // Whether the current thread is executing an operation + private ThreadLocal<IUndoableOperation> executing = new ThreadLocal<>(); + private static class ApproverPriorityPair implements Comparable<ApproverPriorityPair> { public IOperationApprover2 approver; @@ -189,7 +192,49 @@ public class CheckedOperationHistory implements IOperationHistory { // not approved. No notifications are sent, just return the status. return status; } - return history.execute(operation, monitor, info); + return doExecute(operation, monitor, info); + } + + protected IStatus doExecute(IUndoableOperation operation, IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + IStatus result; + + final IUndoableOperation current = executing.get(); + if (current == null) { + // Initial execution. Fine + executing.set(operation); + try { + result = history.execute(operation, monitor, info); + } finally { + executing.remove(); + } + } else { + // Re-entrant operation execution is done free-floating + try { + // Don't notify start/done events because the reconciliation + // between resource-set changes and operation contexts + // performed by various listeners will lose information or + // it won't bubble up to the top operation where it belongs + result = operation.execute(monitor, info); + + // On successful execution, propagate any contexts that may + // not already be on currently executing operation + if (result.isOK()) { + for (IUndoContext next : operation.getContexts()) { + if (!current.hasContext(next)) { + current.addContext(next); + } + } + } + } finally { + // Dispose the operation because we're not adding it + // to the history. Recorded EMF operations that know + // they are not the root operation will not dispose + // their change-descriptions, so they are safe + operation.dispose(); + } + } + + return result; } @Override |