package rocks.inspectit.ui.rcp.util; import org.apache.commons.lang.ArrayUtils; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Widget; /** * Safe executor enables calling the {@link Display#asyncExec(Runnable)} and * {@link Display#syncExec(Runnable)} with checking in a UI thread if any of the widgets that are * going to be updated in the given {@link Runnable} are disposed. The class enables easy avoiding * of <i>Widget already disposed</i> exceptions. * <p> * <b>IMPORTANT:</b> The class code is inspired from * <a href="https://gist.github.com/rherrmann/7324823630a089217f46#file-uithreadsynchronizer-L60"> * RĂ¼diger Herrmann's UIThreadSynchronizer</a>. Original author is RĂ¼diger Herrmann. License info * can be found * <a href="hhttps://gist.github.com/rherrmann/7324823630a089217f46#file-uithreadsynchronizer-L60"> * here</a>. * * @author Ivan Senic, * */ public final class SafeExecutor { /** * Private constructor (utility class). */ private SafeExecutor() { } /** * Executes the given runnable asynchronously within the {@link Display#asyncExec(Runnable)}, * but checks prior to execution that all of the given widgets are not disposed. Disposed checks * are done in UI thread and if any check fails runnable will not be run. * <p> * Display to execute operation on will be retrieved by {@link Display#getDefault()}. Use * {@link #asyncExec(Runnable, Display, Widget...)} if you want to use specific display. * * @param runnable * Runnable to run. * @param widgets * Widgets to check for disposal. * @see SafeExecutor#asyncExec(Runnable, Display, Widget...) */ public static void asyncExec(Runnable runnable, Widget... widgets) { asyncExec(runnable, Display.getDefault(), widgets); } /** * Executes the given runnable asynchronously within the {@link Display#asyncExec(Runnable)}, * but checks prior to execution that all of the given widgets are not disposed. Disposed checks * are done in UI thread and if any check fails runnable will not be run. * <p> * If given display is null or already disposed runnable will not be run, the method will simply * return. * * @param runnable * Runnable to run. * @param display * Display to use. * @param widgets * Widgets to check for disposal. */ public static void asyncExec(Runnable runnable, Display display, Widget... widgets) { if ((null == display) || display.isDisposed()) { return; } display.asyncExec(new GuardedRunnable(runnable, widgets)); } /** * Executes the given runnable synchronously within the {@link Display#syncExec(Runnable)}, but * checks prior to execution that all of the given widgets are not disposed. Disposed checks are * done in UI thread and if any check fails runnable will not be run. * <p> * Display to execute operation on will be retrieved by {@link Display#getDefault()}. Use * {@link #syncExec(Runnable, Display, Widget...)} if you want to use specific display. * * @param runnable * Runnable to run. * @param widgets * Widgets to check for disposal. * @see SafeExecutor#syncExec(Runnable, Display, Widget...) */ public static void syncExec(Runnable runnable, Widget... widgets) { syncExec(runnable, Display.getDefault(), widgets); } /** * Executes the given runnable synchronously within the {@link Display#syncExec(Runnable)}, but * checks prior to execution that all of the given widgets are not disposed. Disposed checks are * done in UI thread and if any check fails runnable will not be run. * <p> * If given display is null or already disposed runnable will not be run, the method will simply * return. * * @param runnable * Runnable to run. * @param display * Display to use. * @param widgets * Widgets to check for disposal. */ public static void syncExec(Runnable runnable, Display display, Widget... widgets) { if ((null == display) || display.isDisposed()) { return; } display.syncExec(new GuardedRunnable(runnable, widgets)); } /** * Runnable that guards from {@link Widget} disposal prior to running the delegate * {@link Runnable}. * * @author Ivan Senic * */ private static class GuardedRunnable implements Runnable { /** * Delegate {@link Runnable}. */ private final Runnable runnable; /** * {@link Widget}s to check for disposal. */ private final Widget[] widgets; /** * Default constructor. * * @param runnable * Delegate {@link Runnable}. * @param widgets * {@link Widget}s to check for disposal. */ GuardedRunnable(Runnable runnable, Widget... widgets) { this.runnable = runnable; this.widgets = widgets; } /** * {@inheritDoc} */ @Override public void run() { if (ArrayUtils.isNotEmpty(widgets)) { for (Widget widget : widgets) { if (widget == null) { continue; } else if (widget.isDisposed()) { return; } } } runnable.run(); } } }