]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/internal/awt/AwtEnvironment.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / internal / awt / AwtEnvironment.java
index 9a9d84ae1bc96f976dc646b03a56212ab1d5cf7b..9baf6a6e1b7517b649856b8ff2ca888a247eda03 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007 SAS Institute.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     SAS Institute - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.utils.ui.internal.awt;\r
-\r
-import java.awt.EventQueue;\r
-import java.awt.Frame;\r
-import java.lang.reflect.InvocationTargetException;\r
-\r
-import javax.swing.UIManager;\r
-import javax.swing.UnsupportedLookAndFeelException;\r
-\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.SWTException;\r
-import org.eclipse.swt.awt.SWT_AWT;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.eclipse.swt.widgets.Shell;\r
-\r
-\r
-\r
-/**\r
- * An environment to enable the proper display of AWT/Swing windows within a SWT or RCP \r
- * application. This class extends the base {@link org.eclipse.swt.awt.SWT_AWT Eclipse SWT/AWT integration}\r
- * support by\r
- * <ul>\r
- * <li>Using the platform-specific system Look and Feel. \r
- * <li>Ensuring AWT modal dialogs are modal across the SWT application.\r
- * <li>Working around various AWT/Swing bugs  \r
- * </ul>\r
- * <p>\r
- * This class is most helpful to applications which create new AWT/Swing windows (e.g. dialogs) rather\r
- * than those which embed AWT/Swing components in SWT windows. For support specific to embedding\r
- * AWT/Swing components see {@link EmbeddedSwingComposite}.\r
- * <p>\r
- * There is at most one instance of this class per SWT\r
- * {@link org.eclipse.swt.widgets.Display Display}. In almost all applications\r
- * this means that there is exactly one instance for the entire application. In fact, the\r
- * current implementation always limits the number of instances to exactly one.\r
- * <p>\r
- * An instance of this class can be obtained with the static\r
- * {@link #getInstance(Display)} method.\r
-*/\r
-public final class AwtEnvironment {\r
-    // TODO: add pop-up dismissal and font synchronization support to this level?\r
-    \r
-    private static final String GTK_LOOK_AND_FEEL_NAME = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; //$NON-NLS-1$\r
-\r
-    private static AwtEnvironment instance = null;\r
-    private static boolean isLookAndFeelInitialized = false;\r
-\r
-    private final Display display;\r
-    private final AwtDialogListener dialogListener;\r
-\r
-    /**\r
-     * Returns the single instance of AwtEnvironment for the given display. On\r
-     * the first call to this method, the necessary initialization to allow\r
-     * AWT/Swing code to run properly within an Eclipse application is done.\r
-     * This initialization includes setting the approprite look and feel and\r
-     * registering the necessary listeners to ensure proper behavior of modal\r
-     * dialogs.\r
-     * <p>\r
-     * The first call to this method must occur before any AWT/Swing APIs are\r
-     * called. \r
-     * <p>\r
-     * The current implementation limits the number of instances of\r
-     * AwtEnvironment to one. If this method is called with a display different\r
-     * to one used on a previous call, {@link UnsupportedOperationException} is\r
-     * thrown.\r
-     * \r
-     * @param display\r
-     *            the non-null SWT display\r
-     * @return the AWT environment\r
-     * @exception IllegalArgumentException\r
-     *                <ul>\r
-     *                <li>ERROR_NULL_ARGUMENT - if the display is null</li>\r
-     *                </ul>\r
-     * @exception UnsupportedOperationException -\r
-     *                on attempt to use multiple displays.\r
-     */\r
-    public static AwtEnvironment getInstance(Display display) {\r
-        // For now assume a single display. If necessary, this implementation\r
-        // can be changed to create multiple environments for multiple display\r
-        // applications.\r
-        // TODO: add multiple display support\r
-        if (display == null) {\r
-            SWT.error(SWT.ERROR_NULL_ARGUMENT);\r
-        }\r
-        if ((instance != null) && !display.equals(instance.display)) {\r
-            throw new UnsupportedOperationException("Multiple displays not supported");\r
-        }\r
-        synchronized (AwtEnvironment.class) {\r
-            if (instance == null) {\r
-                instance = new AwtEnvironment(display);\r
-            }\r
-        }\r
-        return instance;\r
-    }\r
-\r
-    // Private constructor - clients use getInstance() to obtain instances\r
-    private AwtEnvironment(Display display) {\r
-        assert display != null;\r
-\r
-        /*\r
-         * This property removes a large amount of flicker from embedded swing\r
-         * components. Ideally it would not be set until EmbeddedSwingComposite\r
-         * is used, but since its value is read once and cached by AWT, it needs\r
-         * to be set before any AWT/Swing APIs are called.\r
-         */       \r
-        // TODO: this is effective only on Windows.\r
-        System.setProperty("sun.awt.noerasebackground", "true"); //$NON-NLS-1$//$NON-NLS-2$\r
-\r
-        /*\r
-         * RCP apps always want the standard platform look and feel It's\r
-         * important to wait for the L&F to be set so that any subsequent calls\r
-         * to createFrame() will be return a frame with the proper L&F (note\r
-         * that createFrame() happens on the SWT thread).\r
-         * \r
-         * The call to invokeAndWait is safe because\r
-         * the first call AwtEnvironment.getInstance should happen\r
-         * before any (potential deadlocking) activity occurs on the \r
-         * AWT thread.\r
-         */\r
-        try {\r
-            EventQueue.invokeAndWait(new Runnable() {\r
-                public void run() {\r
-                    setSystemLookAndFeel();\r
-                }\r
-            });\r
-        } catch (InterruptedException e) {\r
-            SWT.error(SWT.ERROR_FAILED_EXEC, e);\r
-        } catch (InvocationTargetException e) {\r
-            SWT.error(SWT.ERROR_FAILED_EXEC, e.getCause());\r
-        }\r
-\r
-        this.display = display;\r
-\r
-        // Listen for AWT modal dialogs to make them modal application-wide\r
-        dialogListener = new AwtDialogListener(display);\r
-    }\r
-\r
-    /**\r
-     * Invokes the given runnable in the AWT event thread while blocking user\r
-     * input on the SWT event thread. The SWT event thread will remain blocked\r
-     * until the runnable task completes, at which point this method will\r
-     * return.\r
-     * <p>\r
-     * This method is useful for displayng modal AWT/Swing dialogs from the SWT\r
-     * event thread. The modal AWT/Swing dialog will always block input across\r
-     * the whole application, but not until it appears. By calling this method,\r
-     * it is guaranteed that SWT input is blocked immediately, even before the\r
-     * AWT/Swing dialog appears.\r
-     * <p>\r
-     * To avoid unnecessary flicker, AWT/Swing dialogs should have their parent\r
-     * set to a frame returned by {@link #createDialogParentFrame()}.\r
-     * <p>\r
-     * This method must be called from the SWT event thread.\r
-     * \r
-     * @param runnable\r
-     *            the code to schedule on the AWT event thread\r
-     * @exception IllegalArgumentException\r
-     *                <ul>\r
-     *                <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>\r
-     *                </ul>\r
-     * @exception SWTException\r
-     *                <ul>\r
-     *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the\r
-     *                SWT event thread\r
-     *                </ul>\r
-     */\r
-    public void invokeAndBlockSwt(final Runnable runnable) {\r
-        assert display != null;\r
-\r
-        /*\r
-         * This code snippet is based on the following thread on\r
-         * news.eclipse.platform.swt:\r
-         * http://dev.eclipse.org/newslists/news.eclipse.platform.swt/msg24234.html\r
-         */\r
-        if (runnable == null) {\r
-            SWT.error(SWT.ERROR_NULL_ARGUMENT);\r
-        }\r
-        if (display != Display.getCurrent()) {\r
-            SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);\r
-        }\r
-\r
-        // Switch to the AWT thread...\r
-        EventQueue.invokeLater(new Runnable() {\r
-            public void run() {\r
-                try {\r
-                    // do swing work...\r
-                    runnable.run();\r
-                } finally {\r
-                    display.asyncExec(new Runnable() {\r
-                        public void run() {\r
-                            // Unblock SWT\r
-                            SwtInputBlocker.unblock();\r
-                        }\r
-                    });\r
-                }\r
-            }\r
-        });\r
-\r
-        // Prevent user input on SWT components\r
-        SwtInputBlocker.block();\r
-    }\r
-\r
-    /**\r
-     * Creates an AWT frame suitable as a parent for AWT/Swing dialogs. \r
-     * <p>\r
-     * This method must be called from the SWT event thread. There must be an active\r
-     * shell associated with the environment's display.  \r
-     * <p>\r
-     * The created frame is a non-visible child of the active shell and will be disposed when that shell\r
-     * is disposed.\r
-     * <p>\r
-     * See {@link #createDialogParentFrame(Shell)} for more details. \r
-     * \r
-     * @return a {@link java.awt.Frame} to be used for parenting dialogs\r
-     * @exception SWTException\r
-     *                <ul>\r
-     *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the\r
-     *                SWT event thread\r
-     *                </ul>\r
-     * @exception IllegalStateException\r
-     *                if the current display has no shells\r
-     */\r
-    public Frame createDialogParentFrame() {\r
-        if (display != Display.getCurrent()) {\r
-            SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);\r
-        }\r
-        Shell parent = display.getActiveShell();\r
-        if (parent == null) {\r
-            throw new IllegalStateException("No Active Shell");\r
-        }\r
-        return createDialogParentFrame(parent);\r
-    }\r
-    \r
-    /**\r
-     * Creates an AWT frame suitable as a parent for AWT/Swing dialogs. \r
-     * <p>\r
-     * This method must be called from the SWT event thread. There must be an active\r
-     * shell associated with the environment's display.\r
-     * <p>\r
-     * The created frame is a non-visible child of the given shell and will be disposed when that shell\r
-     * is disposed.\r
-     * <p>\r
-     * This method is useful for creating a frame to parent any AWT/Swing\r
-     * dialogs created for use inside a SWT application. A modal AWT/Swing\r
-     * dialogs will flicker less if its parent is set to the returned frame\r
-     * rather than to null or to an independently created {@link java.awt.Frame}.  \r
-     * \r
-     * @return a {@link java.awt.Frame} to be used for parenting dialogs\r
-     * @exception SWTException\r
-     *                <ul>\r
-     *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the\r
-     *                SWT event thread\r
-     *                </ul>\r
-     * @exception IllegalStateException\r
-     *                if the current display has no shells\r
-     */\r
-    public Frame createDialogParentFrame(Shell parent) {\r
-        if (parent == null) {\r
-            SWT.error(SWT.ERROR_NULL_ARGUMENT);\r
-        }\r
-        if (display != Display.getCurrent()) {\r
-            SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);\r
-        }\r
-        Shell shell = new Shell(parent);\r
-        shell.setVisible(false);\r
-        Composite composite = new Composite(shell, SWT.EMBEDDED);\r
-        return SWT_AWT.new_Frame(composite);\r
-    }\r
-\r
-    // Find a shell to use, giving preference to the active shell.\r
-    Shell getShell() {\r
-        Shell shell = display.getActiveShell();\r
-        if (shell == null) {\r
-            Shell[] allShells = display.getShells();\r
-            if (allShells.length > 0) {\r
-                shell = allShells[0];\r
-            }\r
-        }\r
-        return shell;\r
-    }\r
-\r
-    void requestAwtDialogFocus() {\r
-        assert dialogListener != null;\r
-\r
-        dialogListener.requestFocus();\r
-    }\r
-\r
-    private void setSystemLookAndFeel() {\r
-        assert EventQueue.isDispatchThread(); // On AWT event thread\r
-\r
-        if (!isLookAndFeelInitialized) {\r
-            isLookAndFeelInitialized = true;\r
-            try {\r
-                String systemLaf = UIManager.getSystemLookAndFeelClassName();\r
-                String xplatLaf = UIManager.getCrossPlatformLookAndFeelClassName();\r
-\r
-                // Java makes metal the system look and feel if running under a\r
-                // non-gnome Linux desktop. Fix that here, if the RCP itself is\r
-                // running\r
-                // with the GTK windowing system set.\r
-                if (xplatLaf.equals(systemLaf) && Platform.isGtk()) {\r
-                    systemLaf = GTK_LOOK_AND_FEEL_NAME;\r
-                }\r
-                UIManager.setLookAndFeel(systemLaf);\r
-            } catch (ClassNotFoundException e) {\r
-                // TODO Auto-generated catch block\r
-                e.printStackTrace();\r
-            } catch (InstantiationException e) {\r
-                // TODO Auto-generated catch block\r
-                e.printStackTrace();\r
-            } catch (IllegalAccessException e) {\r
-                // TODO Auto-generated catch block\r
-                e.printStackTrace();\r
-            } catch (UnsupportedLookAndFeelException e) {\r
-                // TODO Auto-generated catch block\r
-                e.printStackTrace();\r
-            }\r
-        }\r
-    }\r
-    \r
-    // This method is called by unit tests\r
-    static void reset() {\r
-        instance = null;\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007 SAS Institute.
+ * 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:
+ *     SAS Institute - initial API and implementation
+ *******************************************************************************/
+package org.simantics.utils.ui.internal.awt;
+
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.awt.SWT_AWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+
+
+/**
+ * An environment to enable the proper display of AWT/Swing windows within a SWT or RCP 
+ * application. This class extends the base {@link org.eclipse.swt.awt.SWT_AWT Eclipse SWT/AWT integration}
+ * support by
+ * <ul>
+ * <li>Using the platform-specific system Look and Feel. 
+ * <li>Ensuring AWT modal dialogs are modal across the SWT application.
+ * <li>Working around various AWT/Swing bugs  
+ * </ul>
+ * <p>
+ * This class is most helpful to applications which create new AWT/Swing windows (e.g. dialogs) rather
+ * than those which embed AWT/Swing components in SWT windows. For support specific to embedding
+ * AWT/Swing components see {@link EmbeddedSwingComposite}.
+ * <p>
+ * There is at most one instance of this class per SWT
+ * {@link org.eclipse.swt.widgets.Display Display}. In almost all applications
+ * this means that there is exactly one instance for the entire application. In fact, the
+ * current implementation always limits the number of instances to exactly one.
+ * <p>
+ * An instance of this class can be obtained with the static
+ * {@link #getInstance(Display)} method.
+*/
+public final class AwtEnvironment {
+    // TODO: add pop-up dismissal and font synchronization support to this level?
+    
+    private static final String GTK_LOOK_AND_FEEL_NAME = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; //$NON-NLS-1$
+
+    private static AwtEnvironment instance = null;
+    private static boolean isLookAndFeelInitialized = false;
+
+    private final Display display;
+    private final AwtDialogListener dialogListener;
+
+    /**
+     * Returns the single instance of AwtEnvironment for the given display. On
+     * the first call to this method, the necessary initialization to allow
+     * AWT/Swing code to run properly within an Eclipse application is done.
+     * This initialization includes setting the approprite look and feel and
+     * registering the necessary listeners to ensure proper behavior of modal
+     * dialogs.
+     * <p>
+     * The first call to this method must occur before any AWT/Swing APIs are
+     * called. 
+     * <p>
+     * The current implementation limits the number of instances of
+     * AwtEnvironment to one. If this method is called with a display different
+     * to one used on a previous call, {@link UnsupportedOperationException} is
+     * thrown.
+     * 
+     * @param display
+     *            the non-null SWT display
+     * @return the AWT environment
+     * @exception IllegalArgumentException
+     *                <ul>
+     *                <li>ERROR_NULL_ARGUMENT - if the display is null</li>
+     *                </ul>
+     * @exception UnsupportedOperationException -
+     *                on attempt to use multiple displays.
+     */
+    public static AwtEnvironment getInstance(Display display) {
+        // For now assume a single display. If necessary, this implementation
+        // can be changed to create multiple environments for multiple display
+        // applications.
+        // TODO: add multiple display support
+        if (display == null) {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        if ((instance != null) && !display.equals(instance.display)) {
+            throw new UnsupportedOperationException("Multiple displays not supported");
+        }
+        synchronized (AwtEnvironment.class) {
+            if (instance == null) {
+                instance = new AwtEnvironment(display);
+            }
+        }
+        return instance;
+    }
+
+    // Private constructor - clients use getInstance() to obtain instances
+    private AwtEnvironment(Display display) {
+        assert display != null;
+
+        /*
+         * This property removes a large amount of flicker from embedded swing
+         * components. Ideally it would not be set until EmbeddedSwingComposite
+         * is used, but since its value is read once and cached by AWT, it needs
+         * to be set before any AWT/Swing APIs are called.
+         */       
+        // TODO: this is effective only on Windows.
+        System.setProperty("sun.awt.noerasebackground", "true"); //$NON-NLS-1$//$NON-NLS-2$
+
+        /*
+         * RCP apps always want the standard platform look and feel It's
+         * important to wait for the L&F to be set so that any subsequent calls
+         * to createFrame() will be return a frame with the proper L&F (note
+         * that createFrame() happens on the SWT thread).
+         * 
+         * The call to invokeAndWait is safe because
+         * the first call AwtEnvironment.getInstance should happen
+         * before any (potential deadlocking) activity occurs on the 
+         * AWT thread.
+         */
+        try {
+            EventQueue.invokeAndWait(new Runnable() {
+                public void run() {
+                    setSystemLookAndFeel();
+                }
+            });
+        } catch (InterruptedException e) {
+            SWT.error(SWT.ERROR_FAILED_EXEC, e);
+        } catch (InvocationTargetException e) {
+            SWT.error(SWT.ERROR_FAILED_EXEC, e.getCause());
+        }
+
+        this.display = display;
+
+        // Listen for AWT modal dialogs to make them modal application-wide
+        dialogListener = new AwtDialogListener(display);
+    }
+
+    /**
+     * Invokes the given runnable in the AWT event thread while blocking user
+     * input on the SWT event thread. The SWT event thread will remain blocked
+     * until the runnable task completes, at which point this method will
+     * return.
+     * <p>
+     * This method is useful for displayng modal AWT/Swing dialogs from the SWT
+     * event thread. The modal AWT/Swing dialog will always block input across
+     * the whole application, but not until it appears. By calling this method,
+     * it is guaranteed that SWT input is blocked immediately, even before the
+     * AWT/Swing dialog appears.
+     * <p>
+     * To avoid unnecessary flicker, AWT/Swing dialogs should have their parent
+     * set to a frame returned by {@link #createDialogParentFrame()}.
+     * <p>
+     * This method must be called from the SWT event thread.
+     * 
+     * @param runnable
+     *            the code to schedule on the AWT event thread
+     * @exception IllegalArgumentException
+     *                <ul>
+     *                <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
+     *                </ul>
+     * @exception SWTException
+     *                <ul>
+     *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+     *                SWT event thread
+     *                </ul>
+     */
+    public void invokeAndBlockSwt(final Runnable runnable) {
+        assert display != null;
+
+        /*
+         * This code snippet is based on the following thread on
+         * news.eclipse.platform.swt:
+         * http://dev.eclipse.org/newslists/news.eclipse.platform.swt/msg24234.html
+         */
+        if (runnable == null) {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        if (display != Display.getCurrent()) {
+            SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+        }
+
+        // Switch to the AWT thread...
+        EventQueue.invokeLater(new Runnable() {
+            public void run() {
+                try {
+                    // do swing work...
+                    runnable.run();
+                } finally {
+                    display.asyncExec(new Runnable() {
+                        public void run() {
+                            // Unblock SWT
+                            SwtInputBlocker.unblock();
+                        }
+                    });
+                }
+            }
+        });
+
+        // Prevent user input on SWT components
+        SwtInputBlocker.block();
+    }
+
+    /**
+     * Creates an AWT frame suitable as a parent for AWT/Swing dialogs. 
+     * <p>
+     * This method must be called from the SWT event thread. There must be an active
+     * shell associated with the environment's display.  
+     * <p>
+     * The created frame is a non-visible child of the active shell and will be disposed when that shell
+     * is disposed.
+     * <p>
+     * See {@link #createDialogParentFrame(Shell)} for more details. 
+     * 
+     * @return a {@link java.awt.Frame} to be used for parenting dialogs
+     * @exception SWTException
+     *                <ul>
+     *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+     *                SWT event thread
+     *                </ul>
+     * @exception IllegalStateException
+     *                if the current display has no shells
+     */
+    public Frame createDialogParentFrame() {
+        if (display != Display.getCurrent()) {
+            SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+        }
+        Shell parent = display.getActiveShell();
+        if (parent == null) {
+            throw new IllegalStateException("No Active Shell");
+        }
+        return createDialogParentFrame(parent);
+    }
+    
+    /**
+     * Creates an AWT frame suitable as a parent for AWT/Swing dialogs. 
+     * <p>
+     * This method must be called from the SWT event thread. There must be an active
+     * shell associated with the environment's display.
+     * <p>
+     * The created frame is a non-visible child of the given shell and will be disposed when that shell
+     * is disposed.
+     * <p>
+     * This method is useful for creating a frame to parent any AWT/Swing
+     * dialogs created for use inside a SWT application. A modal AWT/Swing
+     * dialogs will flicker less if its parent is set to the returned frame
+     * rather than to null or to an independently created {@link java.awt.Frame}.  
+     * 
+     * @return a {@link java.awt.Frame} to be used for parenting dialogs
+     * @exception SWTException
+     *                <ul>
+     *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+     *                SWT event thread
+     *                </ul>
+     * @exception IllegalStateException
+     *                if the current display has no shells
+     */
+    public Frame createDialogParentFrame(Shell parent) {
+        if (parent == null) {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        if (display != Display.getCurrent()) {
+            SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+        }
+        Shell shell = new Shell(parent);
+        shell.setVisible(false);
+        Composite composite = new Composite(shell, SWT.EMBEDDED);
+        return SWT_AWT.new_Frame(composite);
+    }
+
+    // Find a shell to use, giving preference to the active shell.
+    Shell getShell() {
+        Shell shell = display.getActiveShell();
+        if (shell == null) {
+            Shell[] allShells = display.getShells();
+            if (allShells.length > 0) {
+                shell = allShells[0];
+            }
+        }
+        return shell;
+    }
+
+    void requestAwtDialogFocus() {
+        assert dialogListener != null;
+
+        dialogListener.requestFocus();
+    }
+
+    private void setSystemLookAndFeel() {
+        assert EventQueue.isDispatchThread(); // On AWT event thread
+
+        if (!isLookAndFeelInitialized) {
+            isLookAndFeelInitialized = true;
+            try {
+                String systemLaf = UIManager.getSystemLookAndFeelClassName();
+                String xplatLaf = UIManager.getCrossPlatformLookAndFeelClassName();
+
+                // Java makes metal the system look and feel if running under a
+                // non-gnome Linux desktop. Fix that here, if the RCP itself is
+                // running
+                // with the GTK windowing system set.
+                if (xplatLaf.equals(systemLaf) && Platform.isGtk()) {
+                    systemLaf = GTK_LOOK_AND_FEEL_NAME;
+                }
+                UIManager.setLookAndFeel(systemLaf);
+            } catch (ClassNotFoundException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (InstantiationException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (UnsupportedLookAndFeelException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+    }
+    
+    // This method is called by unit tests
+    static void reset() {
+        instance = null;
+    }
+
+}