javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/common_j2me/org/eclipse/swt/internal/qt/UIThreadHandOverManager.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/common_j2me/org/eclipse/swt/internal/qt/UIThreadHandOverManager.java Mon Oct 04 11:29:25 2010 +0300
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * 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:
+ * Nokia Corporation - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.swt.internal.qt;
+
+import org.eclipse.swt.internal.qt.ApplicationUIListener;
+import org.eclipse.swt.internal.qt.midp.UIThreadLauncher;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Internal_PackageSupport;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A class that manages the UI thread hand-over from the internal UI event
+ * loop to the application.
+ */
+public final class UIThreadHandOverManager {
+ private static Object lock = new Object();
+ private static boolean threadWaitingForApplication;
+ private static Runnable applicationRunnable;
+ private static ApplicationUIListener applicationUIListener;
+
+ /**
+ * Pass the control of the thread to the application by calling a Runnable
+ * provided by the application. If the Runnable has not yet been provided
+ * then the thread waits until it becomes available, or the wait is aborted
+ * by calling <code>abortWait()</code>.
+ */
+ public static void runApplicationUI() {
+ synchronized(lock) {
+ if(!applicationWaiting()) {
+ waitForApplication();
+ } else {
+ // Release the waiting application thread
+ lock.notify();
+ }
+ }
+ callback();
+ }
+
+ /**
+ * If the UI thread is waiting for the application to request the callback
+ * in the UI thread then calling this will abort the wait and make the UI
+ * thread to return back from the <code>runApplicationUI()</code>.
+ */
+ public static void abortWait() {
+ synchronized(lock) {
+ if(threadWaitingForApplication) {
+ lock.notify();
+ }
+ }
+ }
+
+ /**
+ * Called indirectly by the application when it's requesting the UI thread.
+ * Application will pass a Runnable as a parameter and expects it to get called
+ * in the UI thread.
+ *
+ * @param runnable
+ * The Runnable to call in the UI thread.
+ * @return True if obtaining the UI thread was successful and the runnable
+ * will be called.
+ */
+ public static boolean startInUIThread(Runnable runnable) {
+ // Make sure that the internal event loop is started.
+ EventLoop.getInternalDisplay();
+
+ synchronized(lock) {
+ applicationRunnable = runnable;
+ if(threadWaitingForApplication) {
+ lock.notify();
+ } else {
+ if(!waitForUIThread()) {
+ // If the internal UI has not been created then it can't be
+ // signaled and we can't wait for it. This must mean there's
+ // no UI thread yet in the process and we can create it here.
+ if(!UIThreadLauncher.startInUIThread(runnable)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Sets the listener that will be notified of the state of the UI during its
+ * life-time.
+ */
+ public static void setApplicationUIListener(ApplicationUIListener listener) {
+ synchronized(lock) {
+ applicationUIListener = listener;
+ }
+ }
+
+ /*
+ * Signal the internal UI loop and wait until it passes the control of the
+ * UI thread into runApplicationUI(). Return false if the internal UI can't
+ * be signaled.
+ */
+ private static boolean waitForUIThread() {
+ if(signalUIThreadRequest()) {
+ try {
+ lock.wait();
+ } catch(InterruptedException e) {
+ // Nothing to do
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * Wait until signaled by the application requesting the callback to its
+ * Runnable, or by abortWait().
+ */
+ private static void waitForApplication() {
+ threadWaitingForApplication = true;
+ try {
+ lock.wait();
+ } catch(InterruptedException e) {
+ // Nothing to do
+ } finally {
+ threadWaitingForApplication = false;
+ }
+ }
+
+ /*
+ * Returns true if application has provided the Runnable and is thus waiting
+ * for the callback.
+ */
+ private static boolean applicationWaiting() {
+ return (applicationRunnable != null);
+ }
+
+ /*
+ * Post an event to the internal Display to request the control of the UI
+ * thread. After this runApplication() should get called in the UI thread.
+ */
+ private static boolean signalUIThreadRequest() {
+ Display internalDisplay = Internal_PackageSupport.getInternalDisplayInstance();
+ if(internalDisplay != null) {
+ if(applicationUIListener != null) {
+ applicationUIListener.applicationUIThreadRequest();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * Call back the application's runnable
+ */
+ private static void callback() {
+ try {
+ boolean runnableOk;
+ synchronized(lock) {
+ runnableOk = (applicationRunnable != null);
+ }
+ if(runnableOk) {
+ flushInternals();
+ applicationRunnable.run();
+ }
+ } finally {
+ synchronized(lock) {
+ applicationRunnable = null;
+ }
+ }
+ }
+
+ /*
+ * Clear any events or other items possibly left over by any previous usage
+ * of the UI resources. There must not be anything that can interfere with
+ * the application. It must appear as the application starts with an
+ * uninitialized UI.
+ */
+ private static void flushInternals() {
+ Display internalDisplay = Internal_PackageSupport.getInternalDisplayInstance();
+
+ // Dispose all widgets
+ Shell[] shells = internalDisplay.getShells();
+ for(int i = 0; i < shells.length; ++i) {
+ if(shells[i] != null && !shells[i].isDisposed()) {
+ shells[i].dispose();
+ }
+ }
+
+ // Flush the event queue
+ while(internalDisplay.readAndDispatch()) {}
+ }
+}