X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.utils.ui%2Fsrc%2Forg%2Fsimantics%2Futils%2Fui%2FSWTUtils.java;fp=bundles%2Forg.simantics.utils.ui%2Fsrc%2Forg%2Fsimantics%2Futils%2Fui%2FSWTUtils.java;h=7ac2ce07ff4d344fcc188060fa0380e3417875ea;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/SWTUtils.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/SWTUtils.java
new file mode 100644
index 000000000..7ac2ce07f
--- /dev/null
+++ b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/SWTUtils.java
@@ -0,0 +1,165 @@
+package org.simantics.utils.ui;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Widget;
+import org.simantics.utils.threads.IThreadWorkQueue;
+import org.simantics.utils.threads.ThreadUtils;
+
+public class SWTUtils {
+
+ /**
+ * When scheduling a runnable to be executed asynchronously in the SWT
+ * thread it is not possible to do this in a safe manner based on a
+ * {@link Display} instance. When invoking
+ * {@link Display#asyncExec(Runnable)} from a non-SWT thread, it may throw
+ * {@link SWTException} even if you've first checked
+ * {@link Display#isDisposed()}.
+ *
+ * This method will run {@link Display#asyncExec(Runnable)} using the
+ * display returned by the specified widget if the widget is or does not
+ * become disposed while trying to get the display from it.
+ *
+ * @param display the display to asyncExec with
+ * @param runnable the runnable to execute with
+ * {@link Display#asyncExec(Runnable)}
+ * @return true
if the executable was scheduled, false
+ * otherwise
+ */
+ public static boolean asyncExec(Display display, Runnable runnable) {
+ try {
+ if (display.isDisposed())
+ return false;
+ display.asyncExec(runnable);
+ return true;
+ } catch (SWTException e) {
+ // widget was disposed between isDisposed and getDisplay.
+ return false;
+ }
+ }
+
+ /**
+ * When scheduling a runnable to be executed asynchronously in the SWT
+ * thread it is not possible to do this in a safe manner based on a
+ * {@link Widget} instance. When invoking {@link Widget#getDisplay()} from a
+ * non-SWT thread, it may throw {@link SWTException} even if you've first
+ * checked {@link Widget#isDisposed()}.
+ *
+ * This method will run {@link Display#asyncExec(Runnable)} using the
+ * display returned by the specified widget if the widget is or does not
+ * become disposed while trying to get the display from it.
+ *
+ * @param widget the widget to get {@link Display} from
+ * @param runnable the runnable to execute with {@link Display#asyncExec(Runnable)}
+ * @return true
if the executable was scheduled, false otherwise
+ */
+ public static boolean asyncExec(Widget widget, Runnable runnable) {
+ try {
+ if (widget.isDisposed())
+ return false;
+ widget.getDisplay().asyncExec(runnable);
+ return true;
+ } catch (SWTException e) {
+ // widget was disposed between isDisposed and getDisplay.
+ return false;
+ }
+ }
+
+ /**
+ * Invokes a runnable in a specified thread and dispatches SWT events while
+ * waiting for the runnable to complete.
+ *
+ *
+ * The runnable must not perform any operations that may cause more SWT + * events to be dispatched. + * + *
+ * To be invoked from SWT thread only.
+ *
+ * @param control
+ * @param inThread
+ * @param invoke
+ * @throws InterruptedException
+ */
+ public static void invokeAndDispatchEvents(Display display, IThreadWorkQueue inThread, final Runnable invoke) throws InterruptedException {
+ if (display.isDisposed())
+ throw new IllegalArgumentException("display is disposed");
+ final Semaphore sem = new Semaphore(0);
+ ThreadUtils.asyncExec(inThread, new Runnable() {
+ @Override
+ public void run() {
+ try {
+ invoke.run();
+ } finally {
+ sem.release();
+ }
+ }
+ });
+ boolean done = false;
+ while (!done) {
+ done = sem.tryAcquire(10, TimeUnit.MILLISECONDS);
+ while (!done && display.readAndDispatch()) {
+ /*
+ * Note: readAndDispatch can cause this to be disposed.
+ */
+ done = sem.tryAcquire();
+ }
+ }
+ }
+
+ /**
+ * Look for an object starting from an SWT (composite) control with a
+ * specific filter that can inspect the control freely.
+ *
+ * @return the first T returned by the control filter or null
+ * if the filter returned no results.
+ */
+ public static