blob: 6f88d94a994d07026a10f788eb561a153c2e0cba [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2006, 2009 IBM Corporation 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:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.diagram.ui;
import java.lang.ref.WeakReference;
import org.eclipse.emf.transaction.ResourceSetChangeEvent;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.common.ui.util.DisplayUtils;
import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
import org.eclipse.swt.widgets.Display;
/**
* This is an extension of the DiagramEventBroker that has special handling for notifications that
* occurs from a worker thread / non-UI thread. If the notification occurs on the main thread
* then execution is delegated to the super class immediately. If execution is not on the main thread
* then there are 2 scenarios that have to be considered.
*
* The first scenario is for a long operation
* that has been executed with a progress meter, where the progress meter is displaying UI on the main
* thread and there is a background thread that is being executed that the progress meter is monitoring.
* For this scenario, the UI updates on the diagram viewer have been disabled so as to avoid concurrency
* issues. When notifications are handled, they are synchronized to the main thread to avoid
* SWTExceptions when UI tries to access SWT resources when updating figures or other UI.
*
* The second scenario is for when a job has been executed on a worker thread, but has not been executed
* through the OperationHistory. Consequently, there is no hook for turning off display updates. This
* means that if the notifications were to continue on the worker thread, then the display could update
* at the same time on the main thread thereby causing concurrent modification errors and other errors.
* In this case, we need to resynchronize the notifications with the main thread. In order to do this
* it is necessary to run the notifications in an synchronous runnable that will run immediately
* on the main thread.
*
* @author sshaw
* @since 1.2
*/
public class DiagramEventBrokerThreadSafe extends DiagramEventBroker {
WeakReference editingDomainRef;
public DiagramEventBrokerThreadSafe(TransactionalEditingDomain editingDomain) {
super();
editingDomainRef = new WeakReference(editingDomain);
}
/* (non-Javadoc)
* @see org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker#resourceSetChanged(org.eclipse.emf.transaction.ResourceSetChangeEvent)
*/
public void resourceSetChanged(ResourceSetChangeEvent event) {
if (shouldSynchronizeWithMainThread(event)) {
// force synchronization with the main thread
final ResourceSetChangeEvent eventToHandle = event;
TransactionalEditingDomain editingDomain = (TransactionalEditingDomain)editingDomainRef.get();
if (editingDomain != null) {
DisplayUtils.getDisplay().syncExec(editingDomain.createPrivilegedRunnable(new Runnable() {
public void run() {
internal_resourceSetChanged(eventToHandle);
}
}));
return;
}
}
super.resourceSetChanged(event);
}
private boolean shouldSynchronizeWithMainThread(ResourceSetChangeEvent event) {
if (Display.getCurrent() == null)
return true;
return false;
}
private void internal_resourceSetChanged(ResourceSetChangeEvent event) {
super.resourceSetChanged(event);
}
}