]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scenegraph.swing/src/org/simantics/scenegraph/example/SWTAWTComponent.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.scenegraph.swing / src / org / simantics / scenegraph / example / SWTAWTComponent.java
index ae5c68444395d213e29624076ba227d8bfef2210..0f6044a5d60586213256555bc8fa02b0b03fd3b1 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\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
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.scenegraph.example;\r
-\r
-import java.awt.AWTEvent;\r
-import java.awt.Component;\r
-import java.awt.Container;\r
-import java.awt.Frame;\r
-import java.awt.GridLayout;\r
-import java.awt.Toolkit;\r
-import java.awt.event.AWTEventListener;\r
-import java.awt.event.MouseEvent;\r
-import java.util.concurrent.Semaphore;\r
-import java.util.concurrent.TimeUnit;\r
-import java.util.concurrent.atomic.AtomicBoolean;\r
-\r
-import javax.swing.JApplet;\r
-\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.awt.SWT_AWT;\r
-import org.eclipse.swt.events.ControlAdapter;\r
-import org.eclipse.swt.events.ControlEvent;\r
-import org.eclipse.swt.graphics.GC;\r
-import org.eclipse.swt.graphics.Rectangle;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.simantics.utils.threads.AWTThread;\r
-import org.simantics.utils.threads.ThreadUtils;\r
-\r
-\r
-/**\r
- * <pre>\r
- *        embeddedComposite = new SWTAWTComposite(parent, SWT.NONE) {\r
- *            protected JComponent createSwingComponent() {\r
- *                scrollPane = new JScrollPane();\r
- *                table = new JTable();\r
- *                scrollPane.setViewportView(table);\r
- *                return scrollPane;\r
- *            }\r
- *        };\r
- *        // For asynchronous AWT UI population of the swing components:\r
- *        embeddedComposite.populate();\r
- *        // and optionally you can wait until the AWT UI population\r
- *        // has finished:\r
- *        embeddedComposite.waitUntilPopulated();\r
- *\r
- *        // OR:\r
- *\r
- *        // Do both things above in one call to block until the\r
- *        // AWT UI population is complete:\r
- *        embeddedComposite.syncPopulate();\r
- *\r
- *        // Both methods assume all invocations are made from the SWT display thread.\r
- * </pre>\r
- * <p>\r
- * \r
- * @author Tuukka Lehtonen\r
- */\r
-public abstract class SWTAWTComponent extends Composite {\r
-\r
-    private Frame               frame;\r
-\r
-    private Component           awtComponent;\r
-\r
-    private JApplet             panel;\r
-\r
-    private final AtomicBoolean populationStarted   = new AtomicBoolean(false);\r
-\r
-    private final AtomicBoolean populated           = new AtomicBoolean(false);\r
-\r
-    private final Semaphore     populationSemaphore = new Semaphore(0);\r
-\r
-    private static AWTEventListener awtListener = null;\r
-    \r
-    public SWTAWTComponent(Composite parent, int style) {\r
-        super(parent, style | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.EMBEDDED);\r
-    }\r
-    \r
-    /**\r
-     * Create a global AWTEventListener for focus management.\r
-     * NOTE: There is really no need to dispose this once it's been initialized\r
-     * \r
-     */\r
-    private synchronized void initAWTEventListener() {\r
-       if(awtListener == null) {\r
-               awtListener = new AWTEventListener() {\r
-                               public void eventDispatched(AWTEvent e) {\r
-                                       if(e.getID() == MouseEvent.MOUSE_PRESSED) {\r
-                                               Object src = e.getSource();\r
-                                               if(src instanceof Component) {\r
-                                                       ((Component)src).requestFocus();\r
-                                               }\r
-                                       }\r
-                               }};\r
-                       // Execute in AWT thread..\r
-               ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
-                               @Override\r
-                               public void run() {\r
-                               Toolkit.getDefaultToolkit().addAWTEventListener(awtListener, AWTEvent.MOUSE_EVENT_MASK);\r
-                               }\r
-               });\r
-       }\r
-    }\r
-\r
-    protected Container getContainer() {\r
-        return panel;\r
-    }\r
-\r
-    public Component getAWTComponent() {\r
-        return awtComponent;\r
-    }\r
-\r
-    @Override\r
-    public void dispose() {\r
-        if (!isDisposed()) {\r
-            frame.dispose();\r
-            super.dispose();\r
-        }\r
-    }\r
-\r
-    /**\r
-     * This method must always be called from SWT thread. This prevents the\r
-     * possibility of deadlock (reported between AWT and SWT) by servicing SWT\r
-     * events while waiting for AWT initialization\r
-     */\r
-    public void syncPopulate() {\r
-        populate();\r
-        waitUntilPopulated();\r
-    }\r
-\r
-    /**\r
-     * This method will create an AWT {@link Frame} through {@link SWT_AWT} and\r
-     * schedule AWT canvas initialization into the AWT thread. The AWT thread initialization will release\r
-     */\r
-    public void populate() {\r
-        if (!populationStarted.compareAndSet(false, true))\r
-            throw new IllegalStateException(this + ".populate was invoked multiple times");\r
-\r
-        checkWidget();\r
-        //ITask task = ThreadLogger.getInstance().begin("createFrame");\r
-        createFrame();\r
-        //task.finish();\r
-        scheduleComponentCreation();\r
-    }\r
-\r
-    public void waitUntilPopulated() {\r
-        if (populated.get())\r
-            return;\r
-\r
-        try {\r
-            boolean done = false;\r
-            while (!done) {\r
-                done = populationSemaphore.tryAcquire(10, TimeUnit.MILLISECONDS);\r
-                while (!done && getDisplay().readAndDispatch()) {\r
-                    /*\r
-                     * Note: readAndDispatch can cause this to be disposed.\r
-                     */\r
-                    if(isDisposed()) return;\r
-                    done = populationSemaphore.tryAcquire();\r
-                }\r
-            }\r
-        } catch (InterruptedException e) {\r
-            throw new Error("EmbeddedSwingComposite population interrupted for class " + this, e);\r
-        }\r
-    }\r
-\r
-    private void createFrame() {\r
-        /*\r
-         * Set a Windows specific AWT property that prevents heavyweight\r
-         * components from erasing their background. Note that this is a global\r
-         * property and cannot be scoped. It might not be suitable for your\r
-         * application.\r
-         */\r
-        System.setProperty("sun.awt.noerasebackground", "true");\r
-\r
-        if (frame==null)\r
-            frame = SWT_AWT.new_Frame(this);\r
-\r
-        // This listener clears garbage during resizing, making it looker much cleaner\r
-        addControlListener(new CleanResizeListener());\r
-        initAWTEventListener();\r
-    }\r
-\r
-    private void scheduleComponentCreation() {\r
-        // Create AWT/Swing components on the AWT thread. This is\r
-        // especially necessary to avoid an AWT leak bug (6411042).\r
-        ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                panel = new JApplet();\r
-                panel.setLayout(new GridLayout(1,1,0,0));\r
-                frame.add(panel);\r
-                try {\r
-                    awtComponent = createSwingComponent();\r
-                    panel.add(awtComponent);\r
-                } finally {\r
-                    // Needed to support #waitUntilPopulated\r
-                    populated.set(true);\r
-                    if (populationSemaphore != null)\r
-                        populationSemaphore.release();\r
-                }\r
-            }\r
-        });\r
-    }\r
-\r
-    protected abstract Component createSwingComponent();\r
-\r
-    private static class CleanResizeListener extends ControlAdapter {\r
-        private Rectangle oldRect = null;\r
-\r
-        @Override\r
-        public void controlResized(ControlEvent e) {\r
-            assert e != null;\r
-            assert Display.getCurrent() != null; // On SWT event thread\r
-\r
-            // Prevent garbage from Swing lags during resize. Fill exposed areas\r
-            // with background color.\r
-            Composite composite = (Composite) e.widget;\r
-            //Rectangle newRect = composite.getBounds();\r
-            //newRect = composite.getDisplay().map(composite.getParent(), composite, newRect);\r
-            Rectangle newRect = composite.getClientArea();\r
-            if (oldRect != null) {\r
-                int heightDelta = newRect.height - oldRect.height;\r
-                int widthDelta = newRect.width - oldRect.width;\r
-                if ((heightDelta > 0) || (widthDelta > 0)) {\r
-                    GC gc = new GC(composite);\r
-                    try {\r
-                        gc.fillRectangle(newRect.x, oldRect.height, newRect.width, heightDelta);\r
-                        gc.fillRectangle(oldRect.width, newRect.y, widthDelta, newRect.height);\r
-                    } finally {\r
-                        gc.dispose();\r
-                    }\r
-                }\r
-            }\r
-            oldRect = newRect;\r
-        }\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * 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:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.scenegraph.example;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.Toolkit;
+import java.awt.event.AWTEventListener;
+import java.awt.event.MouseEvent;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.swing.JApplet;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.awt.SWT_AWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.simantics.utils.threads.AWTThread;
+import org.simantics.utils.threads.ThreadUtils;
+
+
+/**
+ * <pre>
+ *        embeddedComposite = new SWTAWTComposite(parent, SWT.NONE) {
+ *            protected JComponent createSwingComponent() {
+ *                scrollPane = new JScrollPane();
+ *                table = new JTable();
+ *                scrollPane.setViewportView(table);
+ *                return scrollPane;
+ *            }
+ *        };
+ *        // For asynchronous AWT UI population of the swing components:
+ *        embeddedComposite.populate();
+ *        // and optionally you can wait until the AWT UI population
+ *        // has finished:
+ *        embeddedComposite.waitUntilPopulated();
+ *
+ *        // OR:
+ *
+ *        // Do both things above in one call to block until the
+ *        // AWT UI population is complete:
+ *        embeddedComposite.syncPopulate();
+ *
+ *        // Both methods assume all invocations are made from the SWT display thread.
+ * </pre>
+ * <p>
+ * 
+ * @author Tuukka Lehtonen
+ */
+public abstract class SWTAWTComponent extends Composite {
+
+    private Frame               frame;
+
+    private Component           awtComponent;
+
+    private JApplet             panel;
+
+    private final AtomicBoolean populationStarted   = new AtomicBoolean(false);
+
+    private final AtomicBoolean populated           = new AtomicBoolean(false);
+
+    private final Semaphore     populationSemaphore = new Semaphore(0);
+
+    private static AWTEventListener awtListener = null;
+    
+    public SWTAWTComponent(Composite parent, int style) {
+        super(parent, style | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.EMBEDDED);
+    }
+    
+    /**
+     * Create a global AWTEventListener for focus management.
+     * NOTE: There is really no need to dispose this once it's been initialized
+     * 
+     */
+    private synchronized void initAWTEventListener() {
+       if(awtListener == null) {
+               awtListener = new AWTEventListener() {
+                               public void eventDispatched(AWTEvent e) {
+                                       if(e.getID() == MouseEvent.MOUSE_PRESSED) {
+                                               Object src = e.getSource();
+                                               if(src instanceof Component) {
+                                                       ((Component)src).requestFocus();
+                                               }
+                                       }
+                               }};
+                       // Execute in AWT thread..
+               ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
+                               @Override
+                               public void run() {
+                               Toolkit.getDefaultToolkit().addAWTEventListener(awtListener, AWTEvent.MOUSE_EVENT_MASK);
+                               }
+               });
+       }
+    }
+
+    protected Container getContainer() {
+        return panel;
+    }
+
+    public Component getAWTComponent() {
+        return awtComponent;
+    }
+
+    @Override
+    public void dispose() {
+        if (!isDisposed()) {
+            frame.dispose();
+            super.dispose();
+        }
+    }
+
+    /**
+     * This method must always be called from SWT thread. This prevents the
+     * possibility of deadlock (reported between AWT and SWT) by servicing SWT
+     * events while waiting for AWT initialization
+     */
+    public void syncPopulate() {
+        populate();
+        waitUntilPopulated();
+    }
+
+    /**
+     * This method will create an AWT {@link Frame} through {@link SWT_AWT} and
+     * schedule AWT canvas initialization into the AWT thread. The AWT thread initialization will release
+     */
+    public void populate() {
+        if (!populationStarted.compareAndSet(false, true))
+            throw new IllegalStateException(this + ".populate was invoked multiple times");
+
+        checkWidget();
+        //ITask task = ThreadLogger.getInstance().begin("createFrame");
+        createFrame();
+        //task.finish();
+        scheduleComponentCreation();
+    }
+
+    public void waitUntilPopulated() {
+        if (populated.get())
+            return;
+
+        try {
+            boolean done = false;
+            while (!done) {
+                done = populationSemaphore.tryAcquire(10, TimeUnit.MILLISECONDS);
+                while (!done && getDisplay().readAndDispatch()) {
+                    /*
+                     * Note: readAndDispatch can cause this to be disposed.
+                     */
+                    if(isDisposed()) return;
+                    done = populationSemaphore.tryAcquire();
+                }
+            }
+        } catch (InterruptedException e) {
+            throw new Error("EmbeddedSwingComposite population interrupted for class " + this, e);
+        }
+    }
+
+    private void createFrame() {
+        /*
+         * Set a Windows specific AWT property that prevents heavyweight
+         * components from erasing their background. Note that this is a global
+         * property and cannot be scoped. It might not be suitable for your
+         * application.
+         */
+        System.setProperty("sun.awt.noerasebackground", "true");
+
+        if (frame==null)
+            frame = SWT_AWT.new_Frame(this);
+
+        // This listener clears garbage during resizing, making it looker much cleaner
+        addControlListener(new CleanResizeListener());
+        initAWTEventListener();
+    }
+
+    private void scheduleComponentCreation() {
+        // Create AWT/Swing components on the AWT thread. This is
+        // especially necessary to avoid an AWT leak bug (6411042).
+        ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
+            @Override
+            public void run() {
+                panel = new JApplet();
+                panel.setLayout(new GridLayout(1,1,0,0));
+                frame.add(panel);
+                try {
+                    awtComponent = createSwingComponent();
+                    panel.add(awtComponent);
+                } finally {
+                    // Needed to support #waitUntilPopulated
+                    populated.set(true);
+                    if (populationSemaphore != null)
+                        populationSemaphore.release();
+                }
+            }
+        });
+    }
+
+    protected abstract Component createSwingComponent();
+
+    private static class CleanResizeListener extends ControlAdapter {
+        private Rectangle oldRect = null;
+
+        @Override
+        public void controlResized(ControlEvent e) {
+            assert e != null;
+            assert Display.getCurrent() != null; // On SWT event thread
+
+            // Prevent garbage from Swing lags during resize. Fill exposed areas
+            // with background color.
+            Composite composite = (Composite) e.widget;
+            //Rectangle newRect = composite.getBounds();
+            //newRect = composite.getDisplay().map(composite.getParent(), composite, newRect);
+            Rectangle newRect = composite.getClientArea();
+            if (oldRect != null) {
+                int heightDelta = newRect.height - oldRect.height;
+                int widthDelta = newRect.width - oldRect.width;
+                if ((heightDelta > 0) || (widthDelta > 0)) {
+                    GC gc = new GC(composite);
+                    try {
+                        gc.fillRectangle(newRect.x, oldRect.height, newRect.width, heightDelta);
+                        gc.fillRectangle(oldRect.width, newRect.y, widthDelta, newRect.height);
+                    } finally {
+                        gc.dispose();
+                    }
+                }
+            }
+            oldRect = newRect;
+        }
+    }
+
+}