Java Source Code: org.eclipse.swt.awt.SWT_AWT


   1: /*******************************************************************************
   2:  * Copyright (c) 2000, 2007 IBM Corporation and others.
   3:  * All rights reserved. This program and the accompanying materials
   4:  * are made available under the terms of the Eclipse Public License v1.0
   5:  * which accompanies this distribution, and is available at
   6:  * http://www.eclipse.org/legal/epl-v10.html
   7:  *
   8:  * Contributors:
   9:  *     IBM Corporation - initial API and implementation
  10:  *******************************************************************************/
  11: package org.eclipse.swt.awt;
  12: 
  13: import java.lang.reflect.Constructor;
  14: import java.lang.reflect.Field;
  15: import java.lang.reflect.Method;
  16: 
  17: /* SWT Imports */
  18: import org.eclipse.swt.*;
  19: import org.eclipse.swt.graphics.Rectangle;
  20: import org.eclipse.swt.widgets.Shell;
  21: import org.eclipse.swt.widgets.Composite;
  22: import org.eclipse.swt.widgets.Display;
  23: import org.eclipse.swt.widgets.Listener;
  24: import org.eclipse.swt.widgets.Event;
  25: import org.eclipse.swt.internal.*;
  26: 
  27: /* AWT Imports */
  28: import java.awt.EventQueue;
  29: import java.awt.Canvas;
  30: import java.awt.Frame;
  31: import java.awt.Dimension;
  32: import java.awt.Toolkit;
  33: import java.awt.event.ComponentAdapter;
  34: import java.awt.event.ComponentEvent;
  35: import java.awt.event.WindowEvent;
  36: import java.awt.event.FocusEvent;
  37: 
  38: /**
  39:  * This class provides a bridge between SWT and AWT, so that it
  40:  * is possible to embed AWT components in SWT and vice versa.
  41:  * 
  42:  * @since 3.0
  43:  */
  44:	  public class SWT_AWT {
  45:
  46:    /**
  47:     * The name of the embedded Frame class. The default class name
  48:     * for the platform will be used if <code>null</code>. 
  49:     */
  50:    public static String embeddedFrameClass;
  51:
  52:    /**
  53:     * Key for looking up the embedded frame for a Composite using
  54:     * getData(). 
  55:     */
  56:    static String EMBEDDED_FRAME_KEY = "org.eclipse.swt.awt.SWT_AWT.embeddedFrame";
  57:
  58:    static boolean loaded, swingInitialized;
  59:
  60:static native final int getAWTHandle (Canvas canvas);
  61:
  62:	  static synchronized void loadLibrary () {
  63:    if (loaded) return;
  64:    loaded = true;
  65:    Toolkit.getDefaultToolkit();
  66:    /*
  67:    * Note that the jawt library is loaded explicitly
  68:    * because it cannot be found by the library loader.
  69:    * All exceptions are caught because the library may
  70:    * have been loaded already.
  71:    */
  72:	      try {
  73:        System.loadLibrary("jawt");
  74:    } catch (Throwable e) {}
  75:    Library.loadLibrary("swt-awt");
  76:}
  77:
  78:	  static synchronized void initializeSwing() {
  79:    if (swingInitialized) return;
  80:    swingInitialized = true;
  81:	      try {
  82:        /* Initialize the default focus traversal policy */
  83:        Class[] emptyClass = new Class[0];
  84:        Object[] emptyObject = new Object[0];
  85:        Class clazz = Class.forName("javax.swing.UIManager");
  86:        Method method = clazz.getMethod("getDefaults", emptyClass);
  87:        if (method != null) method.invoke(clazz, emptyObject);
  88:    } catch (Throwable e) {}
  89:}
  90:
  91:/**
  92: * Returns a <code>java.awt.Frame</code> which is the embedded frame
  93: * associated with the specified composite.
  94: * 
  95: * @param parent the parent <code>Composite</code> of the <code>java.awt.Frame</code>
  96: * @return a <code>java.awt.Frame</code> the embedded frame or <code>null</code>.
  97: * 
  98: * @exception IllegalArgumentException <ul>
  99: *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 100: * </ul>
 101: * 
 102: * @since 3.2
 103: */
 104:	  public static Frame getFrame (Composite parent) {
 105:    if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
 106:    if ((parent.getStyle () & SWT.EMBEDDED) == 0) return null;
 107:    return (Frame)parent.getData(EMBEDDED_FRAME_KEY);
 108:}
 109:
 110:/**
 111: * Creates a new <code>java.awt.Frame</code>. This frame is the root for
 112: * the AWT components that will be embedded within the composite. In order
 113: * for the embedding to succeed, the composite must have been created
 114: * with the SWT.EMBEDDED style.
 115: * <p>
 116: * IMPORTANT: As of JDK1.5, the embedded frame does not receive mouse events.
 117: * When a lightweight component is added as a child of the embedded frame,
 118: * the cursor does not change. In order to work around both these problems, it is
 119: * strongly recommended that a heavyweight component such as <code>java.awt.Panel</code>
 120: * be added to the frame as the root of all components.
 121: * </p>
 122: * 
 123: * @param parent the parent <code>Composite</code> of the new <code>java.awt.Frame</code>
 124: * @return a <code>java.awt.Frame</code> to be the parent of the embedded AWT components
 125: * 
 126: * @exception IllegalArgumentException <ul>
 127: *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 128: *    <li>ERROR_INVALID_ARGUMENT - if the parent Composite does not have the SWT.EMBEDDED style</li> 
 129: * </ul>
 130: * 
 131: * @since 3.0
 132: */
 133:	  public static Frame new_Frame (final Composite parent) {
 134:    if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
 135:	      if ((parent.getStyle () & SWT.EMBEDDED) == 0) {
 136:        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
 137:    }
 138:    int handle = parent.handle;    
 139:    /*
 140:     * Some JREs have implemented the embedded frame constructor to take an integer
 141:     * and other JREs take a long.  To handle this binary incompatibility, use
 142:     * reflection to create the embedded frame.
 143:     */
 144:    Class clazz = null;
 145:	      try {
 146:        String className = embeddedFrameClass != null ? embeddedFrameClass : "sun.awt.windows.WEmbeddedFrame";
 147:        clazz = Class.forName(className);
 148:    } catch (Throwable e) {
 149:        SWT.error (SWT.ERROR_NOT_IMPLEMENTED, e);
 150:    }
 151:    Constructor constructor = null;
 152:	      try {
 153:        constructor = clazz.getConstructor (new Class [] {int.class});
 154:    } catch (Throwable e1) {
 155:	          try {
 156:            constructor = clazz.getConstructor (new Class [] {long.class});
 157:        } catch (Throwable e2) {
 158:            SWT.error (SWT.ERROR_NOT_IMPLEMENTED, e2);
 159:        }
 160:    }
 161:    initializeSwing ();
 162:    Object value = null;
 163:	      try {
 164:        value = constructor.newInstance (new Object [] {new Integer (handle)});
 165:    } catch (Throwable e) {
 166:        SWT.error (SWT.ERROR_NOT_IMPLEMENTED, e);
 167:    }
 168:    final Frame frame = (Frame) value;
 169:    /*
 170:     * This is necessary to make lightweight components
 171:     * directly added to the frame receive mouse events
 172:     * properly.
 173:     */
 174:    frame.addNotify();
 175:
 176:    parent.setData(EMBEDDED_FRAME_KEY, frame);    
 177:    
 178:    /* Forward the iconify and deiconify events */
 179:	      final Listener shellListener = new Listener () {
 180:	          public void handleEvent (Event e) {
 181:	              switch (e.type) {
 182:                case SWT.Deiconify:
 183:	                      EventQueue.invokeLater(new Runnable () {
 184:	                          public void run () {
 185:                            frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_DEICONIFIED));
 186:                        }
 187:                    });
 188:                    break;
 189:                case SWT.Iconify:
 190:	                      EventQueue.invokeLater(new Runnable () {
 191:	                          public void run () {
 192:                            frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_ICONIFIED));
 193:                        }
 194:                    });
 195:                    break;
 196:            }
 197:        }
 198:    };
 199:    Shell shell = parent.getShell ();
 200:    shell.addListener (SWT.Deiconify, shellListener);
 201:    shell.addListener (SWT.Iconify, shellListener);
 202:    
 203:    /*
 204:    * Generate the appropriate events to activate and deactivate
 205:    * the embedded frame. This is needed in order to make keyboard
 206:    * focus work properly for lightweights.
 207:    */
 208:	      Listener listener = new Listener () {
 209:	          public void handleEvent (Event e) {
 210:	              switch (e.type) {
 211:                case SWT.Dispose:
 212:                    Shell shell = parent.getShell ();
 213:                    shell.removeListener (SWT.Deiconify, shellListener);
 214:                    shell.removeListener (SWT.Iconify, shellListener);
 215:                    parent.setVisible(false);
 216:	                      EventQueue.invokeLater(new Runnable () {
 217:	                          public void run () {
 218:                            frame.dispose ();
 219:                        }
 220:                    });
 221:                    break;
 222:                case SWT.Activate:
 223:	                      EventQueue.invokeLater(new Runnable () {
 224:	                          public void run () {
 225:	                              if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0)) {
 226:                                frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_ACTIVATED));
 227:                                frame.dispatchEvent (new FocusEvent (frame, FocusEvent.FOCUS_GAINED));
 228:                            } else {
 229:                                frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_ACTIVATED));
 230:                                frame.dispatchEvent (new WindowEvent (frame, 207 /*WindowEvent.WINDOW_GAINED_FOCUS*/));
 231:                            }
 232:                        }
 233:                    });
 234:                    break;
 235:                case SWT.Deactivate:
 236:	                      EventQueue.invokeLater(new Runnable () {
 237:	                          public void run () {
 238:	                              if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0)) {
 239:                                frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_DEACTIVATED));
 240:                                frame.dispatchEvent (new FocusEvent (frame, FocusEvent.FOCUS_LOST));
 241:                            } else {
 242:                                frame.dispatchEvent (new WindowEvent (frame, 208 /*WindowEvent.WINDOW_LOST_FOCUS*/));
 243:                                frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_DEACTIVATED));
 244:                            }
 245:                        }
 246:                    });
 247:                    break;
 248:            }
 249:        }
 250:    };
 251:    parent.addListener (SWT.Activate, listener);
 252:    parent.addListener (SWT.Deactivate, listener);
 253:    parent.addListener (SWT.Dispose, listener);
 254:    
 255:	      parent.getDisplay().asyncExec(new Runnable() {
 256:	          public void run () {
 257:            if (parent.isDisposed()) return;
 258:            final Rectangle clientArea = parent.getClientArea();
 259:	              EventQueue.invokeLater(new Runnable () {
 260:	                  public void run () {
 261:                    frame.setSize (clientArea.width, clientArea.height);
 262:                    frame.validate ();
 263:                }
 264:            });
 265:        }
 266:    });
 267:    /*
 268:    * TEMPORARY CODE
 269:    * 
 270:    * For some reason, the graphics configuration of the embedded
 271:    * frame is not initialized properly. This causes an exception
 272:    * when the depth of the screen is changed.
 273:    */
 274:	      EventQueue.invokeLater(new Runnable () {
 275:	          public void run () {
 276:	              try {
 277:                Class clazz = Class.forName("sun.awt.windows.WComponentPeer");
 278:                Field field = clazz.getDeclaredField("winGraphicsConfig");
 279:                field.setAccessible(true);
 280:                field.set(frame.getPeer(), frame.getGraphicsConfiguration());
 281:            } catch (Throwable e) {}
 282:        }
 283:    });
 284:    return frame;
 285:}
 286:
 287:/**
 288: * Creates a new <code>Shell</code>. This Shell is the root for
 289: * the SWT widgets that will be embedded within the AWT canvas. 
 290: * 
 291: * @param display the display for the new Shell
 292: * @param parent the parent <code>java.awt.Canvas</code> of the new Shell
 293: * @return a <code>Shell</code> to be the parent of the embedded SWT widgets
 294: * 
 295: * @exception IllegalArgumentException <ul>
 296: *    <li>ERROR_NULL_ARGUMENT - if the display is null</li>
 297: *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 298: *    <li>ERROR_INVALID_ARGUMENT - if the parent's peer is not created</li>
 299: * </ul>
 300: * 
 301: * @since 3.0
 302: */
 303:	  public static Shell new_Shell (final Display display, final Canvas parent) {
 304:    if (display == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
 305:    if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
 306:    int handle = 0;
 307:	      try {
 308:        loadLibrary ();
 309:        handle = getAWTHandle (parent);
 310:    } catch (Throwable e) {
 311:        SWT.error (SWT.ERROR_NOT_IMPLEMENTED, e);
 312:    }
 313:    if (handle == 0) SWT.error (SWT.ERROR_INVALID_ARGUMENT, null, " [peer not created]");
 314:
 315:    final Shell shell = Shell.win32_new (display, handle);
 316:	      parent.addComponentListener(new ComponentAdapter () {
 317:	          public void componentResized (ComponentEvent e) {
 318:	              display.syncExec (new Runnable () {
 319:	                  public void run () {
 320:                    Dimension dim = parent.getSize ();
 321:                    shell.setSize (dim.width, dim.height);
 322:                }
 323:            });
 324:        }
 325:    });
 326:    shell.setVisible (true);
 327:    return shell;
 328:}
 329:}