Package swingintegration.example

Source Code of swingintegration.example.AwtFocusHandler

/*******************************************************************************
* 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 swingintegration.example;

import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.FocusTraversalPolicy;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JPopupMenu;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;

class AwtFocusHandler implements FocusListener, ContainerListener,
                                      WindowFocusListener {

    private final Frame frame;
    private SwtFocusHandler swtHandler;
    private boolean awtHasFocus = false;
    private Component currentComponent = null;
   
    AwtFocusHandler(Frame frame) {
        assert frame != null;
       
        this.frame = frame;
        frame.addContainerListener(new RecursiveContainerListener(this));
        frame.addWindowFocusListener(this);
    }

    void setSwtHandler(SwtFocusHandler handler) {
        assert handler != null;
        assert swtHandler == null// this method is meant to be called once
       
        swtHandler = handler;
    }

    void gainFocus() {
        assert frame != null;
        // assert !awtHasFocus;
        assert EventQueue.isDispatchThread();    // On AWT event thread
       
        FocusTraversalPolicy policy = frame.getFocusTraversalPolicy();
        Component component;
        if (policy instanceof EmbeddedChildFocusTraversalPolicy) {
            EmbeddedChildFocusTraversalPolicy embeddedPolicy = (EmbeddedChildFocusTraversalPolicy) policy;
            component = embeddedPolicy.getCurrentComponent(frame);
        } else {
            // TODO: direction based?
            component = policy.getDefaultComponent(frame);
        }
        if (component != null) {
            // System.out.println("Requesting focus for component: " + component);
            component.requestFocus();
            // TODO: else case error? If not, consider moving flag setting below into this if
        }
        awtHasFocus = true;
    }
   
    /**
     * Moves focus back to the next SWT component
     */
    void transferFocusNext() {
        assert swtHandler != null;
        assert awtHasFocus;
       
        awtHasFocus = false;
        swtHandler.gainFocusNext();
    }
   
    /**
     * Moves focus back to the previous SWT component
     */
    void transferFocusPrevious() {
        assert swtHandler != null;
        assert awtHasFocus;
       
        awtHasFocus = false;
        swtHandler.gainFocusPrevious();
    }
   
    boolean awtHasFocus() {
        return awtHasFocus;
    }

    Component getCurrentComponent() {
        return currentComponent;
    }
   
    // ..................... Listener implementations

    public void focusGained(FocusEvent e) {
        assert e != null;
        assert EventQueue.isDispatchThread();    // On AWT event thread
       
        // System.out.println("gained (awt). component = " + e.getComponent() + ", opposite = " + e.getOppositeComponent());
        currentComponent  = e.getComponent();
    }

    public void focusLost(FocusEvent e) {
        // System.out.println("component focus lost (awt). opposite = " + e.getOppositeComponent());
       
        // Intentionally leaving currentComponent set. When window focus is lost,
        // it will be needed.
    }

    public void componentAdded(ContainerEvent e) {
        assert e != null;
        assert EventQueue.isDispatchThread();    // On AWT event thread
       
        e.getChild().addFocusListener(this);
    }

    public void componentRemoved(ContainerEvent e) {
        assert e != null;
        assert EventQueue.isDispatchThread();    // On AWT event thread
       
        e.getChild().removeFocusListener(this);
    }
   
    public void windowGainedFocus(WindowEvent e) {
        assert EventQueue.isDispatchThread();    // On AWT event thread
        // System.out.println("WindowFocusListener.windowGainedFocus");
        awtHasFocus = true;
    }

    public void windowLostFocus(WindowEvent e) {
        assert e != null;
        assert swtHandler != null;
        assert EventQueue.isDispatchThread();    // On AWT event thread
       
        // System.out.println("WindowFocusListener.windowLostFocus");
       
        // Dismiss any popup menus that are
        // open when losing focus. This prevents situations where
        // multiple popup menus are visible at the same time. In JDK 1.4 and earlier,
        // the dismissal is not done automatically. In JDK 1.5, this code is
        // unnecessary, but it doesn't seem to hurt anything.
        // TODO: verify this is OK on other windowing systems
        // TODO: disable in post-1.4 environments
        /* boolean popupShown = */hidePopups();
       
        // If focus is being lost to the parent SWT composite, then
        // grab it back for AWT and return. Normally the parent SWT composite will
        // do this for us, but it will not see a focus gained event when focus
        // is transferred to it from its AWT frame child.
        // This happens, for example, if an AWT control has focus and the
        // tab of a containing (already active) view is clicked.
        //
        // However, don't grab back focus if a popup was hidden above. The popup
        // area will not be properly redrawn (the popup, or part of it, will
        // appear to be still there.
        //if (!popupShown && swtHandler.hasFocus()) {
            // System.out.println("**** Taking back focus: " + e);
            // This seems to have side effects, so it's commented out for now.
            // (Sometimes, it forces the workbench window to the foreground when another
            // program's window is selected.)
            // TODO: find an alternate approach to reassert focus
            // gainFocus();
            // return;
        //}
       
        // On a normal change of focus, Swing will turn off any selection
        // in a text field to help indicate focus is lost. This won't happen
        // automatically when transferring to SWT, so turn off the selection
        // manually.
        if (currentComponent instanceof JTextComponent) {
            Caret caret = ((JTextComponent)currentComponent).getCaret();
            if (caret != null) {
                caret.setSelectionVisible(false);
            }
        }
        awtHasFocus = false;
    }

    // Returns true if any popup has been hidden
    @SuppressWarnings("unchecked")
  private boolean hidePopups() {
        boolean result = false;
        List popups = new ArrayList();
        assert EventQueue.isDispatchThread();    // On AWT event thread
       
        // Look for popups inside the frame's component hierarchy.
        // Lightweight popups will be found here.
        findContainedPopups(frame, popups);
       
        // Also look for popups in the frame's window hierachy.
        // Heavyweight popups will be found here.
        findOwnedPopups(frame, popups);
       
        // System.out.println("Hiding popups, count=" + popups.size());
        for (Iterator iter = popups.iterator(); iter.hasNext();) {
            Component popup = (Component)iter.next();
            if (popup.isVisible()) {
                result = true;
                popup.setVisible(false);
            }
        }
        return result;
    }

    private void findOwnedPopups(Window window, List popups) {
        assert window != null;
        assert EventQueue.isDispatchThread();    // On AWT event thread
       
        Window[] ownedWindows = window.getOwnedWindows();
        for (int i = 0; i < ownedWindows.length; i++) {
            findContainedPopups(ownedWindows[i], popups);
            findOwnedPopups(ownedWindows[i], popups);
        }
    }

    private void findContainedPopups(Container container, List popups) {
        assert container != null;
        assert popups != null;
        assert EventQueue.isDispatchThread();    // On AWT event thread
       
        Component[] components = container.getComponents();
        for (int i = 0; i < components.length; i++) {
            Component c = components[i];
            // JPopupMenu is a container, so check for it first
            if (c instanceof JPopupMenu) {
                popups.add(c);
            } else if (c instanceof Container) {
                findContainedPopups((Container)c, popups);
            }
        }
    }

    void postHidePopups() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                hidePopups();
            }
        });
    }
}
TOP

Related Classes of swingintegration.example.AwtFocusHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.