org.eclipse.swt.awt.SWT_AWT.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.swt.awt.SWT_AWT.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2012 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.awt;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/* SWT Imports */
import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Event;

/* AWT Imports */
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Canvas;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.FocusEvent;

/**
 * This class provides a bridge between SWT and AWT, so that it
 * is possible to embed AWT components in SWT and vice versa.
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#awt">Swing/AWT snippets</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * 
 * @since 3.0
 */
@SuppressWarnings("rawtypes")
public class SWT_AWT {

    /**
     * The name of the embedded Frame class. The default class name
     * for the platform will be used if <code>null</code>. 
     */
    public static String embeddedFrameClass;

    /**
     * Key for looking up the embedded frame for a Composite using
     * getData(). 
     */
    static String EMBEDDED_FRAME_KEY = "org.eclipse.swt.awt.SWT_AWT.embeddedFrame";

    static boolean loaded, swingInitialized;

    static native final long /*int*/ getAWTHandle(Canvas canvas);

    static synchronized void loadLibrary() {
        if (loaded)
            return;
        loaded = true;
        Toolkit.getDefaultToolkit();
        /*
        * Note that the jawt library is loaded explicitly
        * because it cannot be found by the library loader.
        * All exceptions are caught because the library may
        * have been loaded already.
        */
        try {
            System.loadLibrary("jawt");
        } catch (Throwable e) {
        }
        Library.loadLibrary("swt-awt");
    }

    static synchronized void initializeSwing() {
        if (swingInitialized)
            return;
        swingInitialized = true;
        try {
            /* Initialize the default focus traversal policy */
            Class[] emptyClass = new Class[0];
            Object[] emptyObject = new Object[0];
            Class clazz = Class.forName("javax.swing.UIManager");
            Method method = clazz.getMethod("getDefaults", emptyClass);
            if (method != null)
                method.invoke(clazz, emptyObject);
        } catch (Throwable e) {
        }
    }

    /**
     * Returns a <code>java.awt.Frame</code> which is the embedded frame
     * associated with the specified composite.
     * 
     * @param parent the parent <code>Composite</code> of the <code>java.awt.Frame</code>
     * @return a <code>java.awt.Frame</code> the embedded frame or <code>null</code>.
     * 
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
     * </ul>
     * 
     * @since 3.2
     */
    public static Frame getFrame(Composite parent) {
        if (parent == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        if ((parent.getStyle() & SWT.EMBEDDED) == 0)
            return null;
        return (Frame) parent.getData(EMBEDDED_FRAME_KEY);
    }

    /**
     * Creates a new <code>java.awt.Frame</code>. This frame is the root for
     * the AWT components that will be embedded within the composite. In order
     * for the embedding to succeed, the composite must have been created
     * with the SWT.EMBEDDED style.
     * <p>
     * IMPORTANT: As of JDK1.5, the embedded frame does not receive mouse events.
     * When a lightweight component is added as a child of the embedded frame,
     * the cursor does not change. In order to work around both these problems, it is
     * strongly recommended that a heavyweight component such as <code>java.awt.Panel</code>
     * be added to the frame as the root of all components.
     * </p>
     * 
     * @param parent the parent <code>Composite</code> of the new <code>java.awt.Frame</code>
     * @return a <code>java.awt.Frame</code> to be the parent of the embedded AWT components
     * 
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
     *    <li>ERROR_INVALID_ARGUMENT - if the parent Composite does not have the SWT.EMBEDDED style</li> 
     * </ul>
     * 
     * @since 3.0
     */
    public static Frame new_Frame(final Composite parent) {
        if (parent == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        if ((parent.getStyle() & SWT.EMBEDDED) == 0) {
            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
        }
        final long /*int*/ handle = parent.handle;
        final Frame[] result = new Frame[1];
        final Throwable[] exception = new Throwable[1];
        Runnable runnable = new Runnable() {
            public void run() {
                try {
                    /*
                     * Some JREs have implemented the embedded frame constructor to take an integer
                     * and other JREs take a long.  To handle this binary incompatibility, use
                     * reflection to create the embedded frame.
                     */
                    Class clazz = null;
                    try {
                        String className = embeddedFrameClass != null ? embeddedFrameClass
                                : "sun.awt.windows.WEmbeddedFrame";
                        clazz = Class.forName(className);
                    } catch (Throwable e) {
                        exception[0] = e;
                        return;
                    }
                    initializeSwing();
                    Object value = null;
                    Constructor constructor = null;
                    try {
                        constructor = clazz.getConstructor(new Class[] { int.class });
                        value = constructor.newInstance(new Object[] { new Integer((int) /*64*/handle) });
                    } catch (Throwable e1) {
                        try {
                            constructor = clazz.getConstructor(new Class[] { long.class });
                            value = constructor.newInstance(new Object[] { new Long(handle) });
                        } catch (Throwable e2) {
                            exception[0] = e2;
                            return;
                        }
                    }
                    final Frame frame = (Frame) value;
                    /*
                     * This is necessary to make lightweight components
                     * directly added to the frame receive mouse events
                     * properly.
                     */
                    frame.addNotify();

                    /*
                    * TEMPORARY CODE
                    * 
                    * For some reason, the graphics configuration of the embedded
                    * frame is not initialized properly. This causes an exception
                    * when the depth of the screen is changed.
                    */
                    try {
                        clazz = Class.forName("sun.awt.windows.WComponentPeer");
                        Field field = clazz.getDeclaredField("winGraphicsConfig");
                        field.setAccessible(true);
                        field.set(frame.getPeer(), frame.getGraphicsConfiguration());
                    } catch (Throwable e) {
                    }

                    result[0] = frame;
                } finally {
                    synchronized (result) {
                        result.notify();
                    }
                }
            }
        };
        if (EventQueue.isDispatchThread() || parent.getDisplay().getSyncThread() != null) {
            runnable.run();
        } else {
            EventQueue.invokeLater(runnable);
            OS.ReplyMessage(0);
            boolean interrupted = false;
            MSG msg = new MSG();
            int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE;
            while (result[0] == null && exception[0] == null) {
                OS.PeekMessage(msg, 0, 0, 0, flags);
                try {
                    synchronized (result) {
                        result.wait(50);
                    }
                } catch (InterruptedException e) {
                    interrupted = true;
                }
            }
            if (interrupted) {
                Compatibility.interrupt();
            }
        }
        if (exception[0] != null) {
            SWT.error(SWT.ERROR_NOT_IMPLEMENTED, exception[0]);
        }
        final Frame frame = result[0];

        parent.setData(EMBEDDED_FRAME_KEY, frame);

        /* Forward the iconify and deiconify events */
        final Listener shellListener = new Listener() {
            public void handleEvent(Event e) {
                switch (e.type) {
                case SWT.Deiconify:
                    EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_DEICONIFIED));
                        }
                    });
                    break;
                case SWT.Iconify:
                    EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_ICONIFIED));
                        }
                    });
                    break;
                }
            }
        };
        Shell shell = parent.getShell();
        shell.addListener(SWT.Deiconify, shellListener);
        shell.addListener(SWT.Iconify, shellListener);

        /*
        * Generate the appropriate events to activate and deactivate
        * the embedded frame. This is needed in order to make keyboard
        * focus work properly for lightweights.
        */
        Listener listener = new Listener() {
            public void handleEvent(Event e) {
                switch (e.type) {
                case SWT.Dispose:
                    Shell shell = parent.getShell();
                    shell.removeListener(SWT.Deiconify, shellListener);
                    shell.removeListener(SWT.Iconify, shellListener);
                    parent.setVisible(false);
                    EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            try {
                                frame.dispose();
                            } catch (Throwable e) {
                            }
                        }
                    });
                    break;
                case SWT.FocusIn:
                case SWT.Activate:
                    EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0)) {
                                frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_ACTIVATED));
                                frame.dispatchEvent(new FocusEvent(frame, FocusEvent.FOCUS_GAINED));
                            } else if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 5, 0)) {
                                frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_ACTIVATED));
                                frame.dispatchEvent(
                                        new WindowEvent(frame, 207 /*WindowEvent.WINDOW_GAINED_FOCUS*/));
                            } else {
                                if (frame.isActive())
                                    return;
                                try {
                                    Class clazz = frame.getClass();
                                    Method method = clazz.getMethod("synthesizeWindowActivation",
                                            new Class[] { boolean.class });
                                    if (method != null)
                                        method.invoke(frame, new Object[] { new Boolean(true) });
                                } catch (Throwable e) {
                                }
                            }
                        }
                    });
                    break;
                case SWT.Deactivate:
                    EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0)) {
                                frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_DEACTIVATED));
                                frame.dispatchEvent(new FocusEvent(frame, FocusEvent.FOCUS_LOST));
                            } else if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 5, 0)) {
                                frame.dispatchEvent(new WindowEvent(frame, 208 /*WindowEvent.WINDOW_LOST_FOCUS*/));
                                frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_DEACTIVATED));
                            } else {
                                if (!frame.isActive())
                                    return;
                                try {
                                    Class clazz = frame.getClass();
                                    Method method = clazz.getMethod("synthesizeWindowActivation",
                                            new Class[] { boolean.class });
                                    if (method != null)
                                        method.invoke(frame, new Object[] { new Boolean(false) });
                                } catch (Throwable e) {
                                }
                            }
                        }
                    });
                    break;
                }
            }
        };
        if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 5, 0)) {
            parent.addListener(SWT.Activate, listener);
        } else {
            parent.addListener(SWT.FocusIn, listener);
        }
        parent.addListener(SWT.Deactivate, listener);
        parent.addListener(SWT.Dispose, listener);

        parent.getDisplay().asyncExec(new Runnable() {
            public void run() {
                if (parent.isDisposed())
                    return;
                final Rectangle clientArea = parent.getClientArea();
                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        frame.setSize(clientArea.width, clientArea.height);
                        frame.validate();
                    }
                });
            }
        });
        return frame;
    }

    /**
     * Creates a new <code>Shell</code>. This Shell is the root for
     * the SWT widgets that will be embedded within the AWT canvas. 
     * 
     * @param display the display for the new Shell
     * @param parent the parent <code>java.awt.Canvas</code> of the new Shell
     * @return a <code>Shell</code> to be the parent of the embedded SWT widgets
     * 
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the display is null</li>
     *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
     *    <li>ERROR_INVALID_ARGUMENT - if the parent's peer is not created</li>
     * </ul>
     * 
     * @since 3.0
     */
    public static Shell new_Shell(final Display display, final Canvas parent) {
        if (display == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        if (parent == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        long /*int*/ handle = 0;
        try {
            loadLibrary();
            handle = getAWTHandle(parent);
        } catch (Throwable e) {
            SWT.error(SWT.ERROR_NOT_IMPLEMENTED, e);
        }
        if (handle == 0)
            SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, " [peer not created]");

        final Shell shell = Shell.win32_new(display, handle);
        final ComponentListener listener = new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                display.syncExec(new Runnable() {
                    public void run() {
                        if (shell.isDisposed())
                            return;
                        Dimension dim = parent.getSize();
                        shell.setSize(dim.width, dim.height);
                    }
                });
            }
        };
        parent.addComponentListener(listener);
        shell.addListener(SWT.Dispose, new Listener() {
            public void handleEvent(Event event) {
                parent.removeComponentListener(listener);
            }
        });
        shell.setVisible(true);
        return shell;
    }
}