1 package org.simantics.utils.ui;
3 import java.util.concurrent.Semaphore;
4 import java.util.concurrent.TimeUnit;
6 import org.eclipse.swt.SWTException;
7 import org.eclipse.swt.custom.CTabFolder;
8 import org.eclipse.swt.custom.CTabItem;
9 import org.eclipse.swt.widgets.Composite;
10 import org.eclipse.swt.widgets.Control;
11 import org.eclipse.swt.widgets.Display;
12 import org.eclipse.swt.widgets.TabFolder;
13 import org.eclipse.swt.widgets.TabItem;
14 import org.eclipse.swt.widgets.Widget;
15 import org.simantics.utils.threads.IThreadWorkQueue;
16 import org.simantics.utils.threads.ThreadUtils;
18 public class SWTUtils {
21 * When scheduling a runnable to be executed asynchronously in the SWT
22 * thread it is not possible to do this in a safe manner based on a
23 * {@link Display} instance. When invoking
24 * {@link Display#asyncExec(Runnable)} from a non-SWT thread, it may throw
25 * {@link SWTException} even if you've first checked
26 * {@link Display#isDisposed()}.
28 * This method will run {@link Display#asyncExec(Runnable)} using the
29 * display returned by the specified widget if the widget is or does not
30 * become disposed while trying to get the display from it.
32 * @param display the display to asyncExec with
33 * @param runnable the runnable to execute with
34 * {@link Display#asyncExec(Runnable)}
35 * @return <code>true</code> if the executable was scheduled, false
38 public static boolean asyncExec(Display display, Runnable runnable) {
40 if (display.isDisposed())
42 display.asyncExec(runnable);
44 } catch (SWTException e) {
45 // widget was disposed between isDisposed and getDisplay.
51 * When scheduling a runnable to be executed asynchronously in the SWT
52 * thread it is not possible to do this in a safe manner based on a
53 * {@link Widget} instance. When invoking {@link Widget#getDisplay()} from a
54 * non-SWT thread, it may throw {@link SWTException} even if you've first
55 * checked {@link Widget#isDisposed()}.
57 * This method will run {@link Display#asyncExec(Runnable)} using the
58 * display returned by the specified widget if the widget is or does not
59 * become disposed while trying to get the display from it.
61 * @param widget the widget to get {@link Display} from
62 * @param runnable the runnable to execute with {@link Display#asyncExec(Runnable)}
63 * @return <code>true</code> if the executable was scheduled, false otherwise
65 public static boolean asyncExec(Widget widget, Runnable runnable) {
67 if (widget.isDisposed())
69 widget.getDisplay().asyncExec(runnable);
71 } catch (SWTException e) {
72 // widget was disposed between isDisposed and getDisplay.
78 * Invokes a runnable in a specified thread and dispatches SWT events while
79 * waiting for the runnable to complete.
82 * The runnable must not perform any operations that may cause more SWT
83 * events to be dispatched.
86 * To be invoked from SWT thread only.
91 * @throws InterruptedException
93 public static void invokeAndDispatchEvents(Display display, IThreadWorkQueue inThread, final Runnable invoke) throws InterruptedException {
94 if (display.isDisposed())
95 throw new IllegalArgumentException("display is disposed");
96 final Semaphore sem = new Semaphore(0);
97 ThreadUtils.asyncExec(inThread, new Runnable() {
107 boolean done = false;
109 done = sem.tryAcquire(10, TimeUnit.MILLISECONDS);
110 while (!done && display.readAndDispatch()) {
112 * Note: readAndDispatch can cause this to be disposed.
114 done = sem.tryAcquire();
120 * Look for an object starting from an SWT (composite) control with a
121 * specific filter that can inspect the control freely.
123 * @return the first T returned by the control filter or <code>null</code>
124 * if the filter returned no results.
126 public static <T> T tryGetObject(Control control, ControlFilter<T> filter) {
127 if (control == null || control.isDisposed())
129 T t = filter.accept(control);
132 if (control instanceof Composite) {
133 if (control instanceof TabFolder) {
134 TabFolder tf = (TabFolder) control;
135 for (TabItem item : tf.getSelection()) {
136 t = tryGetObject(item.getControl(), filter);
140 } else if (control instanceof CTabFolder) {
141 CTabFolder tf = (CTabFolder) control;
142 CTabItem item = tf.getSelection();
144 t = tryGetObject(item.getControl(), filter);
149 Composite c = (Composite) control;
150 for (Control child : c.getChildren()) {
151 t = tryGetObject(child, filter);
161 public interface ControlFilter<T> {
162 T accept(Control control);