diff options
author | Christian W. Damus | 2016-09-22 15:52:07 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2016-10-07 08:34:49 +0000 |
commit | c6273756089c46770af1f38e8e0c543d7c4a27c7 (patch) | |
tree | 009e6f7c851342dfbd3044c265a688049f1ed3ba /plugins/infra/ui | |
parent | 721ef7d021121732a8ec45f5df6daab3ee4abce7 (diff) | |
download | org.eclipse.papyrus-c6273756089c46770af1f38e8e0c543d7c4a27c7.tar.gz org.eclipse.papyrus-c6273756089c46770af1f38e8e0c543d7c4a27c7.tar.xz org.eclipse.papyrus-c6273756089c46770af1f38e8e0c543d7c4a27c7.zip |
Bug 501946: Undo creation of capsule with structure diagram open causes exception to be thrown
https://bugs.eclipse.org/bugs/show_bug.cgi?id=501946
Ensure that, when a notation view is removed from the notation resource,
then if any editor pages open on it are not closed deliberately, they
are closed implicitly. Also do not attempt to refresh a diagram edit
part that has lots its semantic element, on the assumption that it is
being deleted.
In order to reuse the asynchronous executor for an editing domain,
factor it out of the DiagramHelper into a more suitable common API.
(cherry-picked from streams/2.0-maintenance)
Change-Id: Ic0b59ff9b3475f8ab4e7d852b0719c9ba479758b
Diffstat (limited to 'plugins/infra/ui')
-rw-r--r-- | plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/TransactionUIHelper.java | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/TransactionUIHelper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/TransactionUIHelper.java index 6ee4ed2b14c..92c977dce87 100644 --- a/plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/TransactionUIHelper.java +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/TransactionUIHelper.java @@ -8,12 +8,13 @@ * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation - * Christian W. Damus - bugs 465416, 498140 + * Christian W. Damus - bugs 465416, 498140, 501946 * *****************************************************************************/ package org.eclipse.papyrus.infra.ui.util; import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.Executor; import java.util.function.Consumer; import org.eclipse.core.runtime.IProgressMonitor; @@ -21,6 +22,14 @@ import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.papyrus.infra.core.utils.IExecutorPolicy; +import org.eclipse.papyrus.infra.core.utils.TransactionHelper; +import org.eclipse.papyrus.infra.tools.util.CoreExecutors; +import org.eclipse.swt.widgets.Display; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; /** @@ -30,6 +39,56 @@ import org.eclipse.jface.operation.IRunnableWithProgress; */ public class TransactionUIHelper { + private static final Executor uiExecutor = CoreExecutors.getUIExecutorService(); + + // Don't need weak values because the executor doesn't retain a reference to the domain + private static final LoadingCache<TransactionalEditingDomain, Executor> domainExecutors = CacheBuilder.newBuilder().weakKeys().build(new CacheLoader<TransactionalEditingDomain, Executor>() { + @Override + public Executor load(TransactionalEditingDomain domain) { + // Diagram refreshes must happen on the UI thread, so we must exclude the transaction + // executor, itself, in the case that the transaction is not running on the UI thread + IExecutorPolicy policy = new IExecutorPolicy() { + @Override + public Ranking rank(Runnable task, Executor executor) { + if (executor == uiExecutor) { + // Always OK to fall back to the UI-thread executor + return Ranking.ACCEPTABLE; + } else { + // The case of the transaction executor + return (Display.getCurrent() == null) ? Ranking.DEPRECATED : Ranking.PREFERRED; + } + } + }; + + // Edit-parts will be asked to refresh, and they would do this in read-only transaction, which subsequently + // requires canonical edit policies invoked recursively to run unprotected transactions, breaking undo/redo + return TransactionHelper.createTransactionExecutor(domain, uiExecutor, policy, TransactionHelper.mergeReadOnlyOption(true)); + } + }); + + /** + * Obtains an executor for asynchronous execution of UI updates (such as + * refreshes) in the context of a transactional editing domain. This executor + * is optimized to minimally postpone any task: it is run at commit of the + * current transaction, if the UI thread currently has a transaction active, + * otherwise as usually as an {@linkplain Display#asyncExec(Runnable) async runnable} + * on the UI thread. + * + * @param domain + * an editing domain (may be {@code null}) + * @return an asynchronous executor for the {@code domain}. If the + * {@code domain} is {@code null}, a UI-thread executor is returned. + * Exactly one executor exists per {@code domain} (including the + * {@code null} domain) + * + * @since 2.0 + */ + public static Executor getExecutor(TransactionalEditingDomain domain) { + return (domain != null) + ? domainExecutors.getUnchecked(domain) + : uiExecutor; + } + /** * <p> * Create a privileged runnable with progress, which is like a regular {@linkplain TransactionalEditingDomain#createPrivilegedRunnable(Runnable) |