]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/internal/awt/AwtFocusHandler.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / internal / awt / AwtFocusHandler.java
index 15b9d967df2d673cbcf44cc36e635945fdbe2c33..0cfcbda3c26ebd19a30abb114f9176eb7483be9c 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.Component;\r
-import java.awt.Container;\r
-import java.awt.EventQueue;\r
-import java.awt.FocusTraversalPolicy;\r
-import java.awt.Frame;\r
-import java.awt.Window;\r
-import java.awt.event.ContainerEvent;\r
-import java.awt.event.ContainerListener;\r
-import java.awt.event.FocusEvent;\r
-import java.awt.event.FocusListener;\r
-import java.awt.event.WindowEvent;\r
-import java.awt.event.WindowFocusListener;\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import javax.swing.JPopupMenu;\r
-import javax.swing.text.Caret;\r
-import javax.swing.text.JTextComponent;\r
-\r
-\r
-@SuppressWarnings({"rawtypes", "unchecked"})\r
-public class AwtFocusHandler implements FocusListener, ContainerListener, \r
-                                      WindowFocusListener {\r
-\r
-    private Frame frame;\r
-    private SwtFocusHandler swtHandler;\r
-    private RecursiveContainerListener containerListener;\r
-    private boolean awtHasFocus = false;\r
-    private Component currentComponent = null;\r
-\r
-    public AwtFocusHandler(Frame frame) {\r
-        assert frame != null;\r
-\r
-        this.frame = frame;\r
-        this.containerListener = new RecursiveContainerListener(this);\r
-        frame.addContainerListener(this.containerListener);\r
-        frame.addWindowFocusListener(this);\r
-    }\r
-\r
-    public void setSwtHandler(SwtFocusHandler handler) {\r
-        assert handler != null;\r
-        assert swtHandler == null;  // this method is meant to be called once\r
-\r
-        swtHandler = handler;\r
-    }\r
-\r
-    /**\r
-     * Invoked from {@link SwtFocusHandler} DisposeListener.\r
-     * Only intended to be invoked once.\r
-     */\r
-    public void dispose() {\r
-        assert frame != null;\r
-        frame.removeWindowFocusListener(this);\r
-        frame.removeContainerListener(containerListener);\r
-        frame = null;\r
-        currentComponent = null;\r
-    }\r
-\r
-    void gainFocus() {\r
-        // assert frame != null;\r
-        // assert !awtHasFocus;\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        if (frame == null)\r
-            return;\r
-\r
-        FocusTraversalPolicy policy = frame.getFocusTraversalPolicy();\r
-        Component component;\r
-        if (policy instanceof EmbeddedChildFocusTraversalPolicy) {\r
-            EmbeddedChildFocusTraversalPolicy embeddedPolicy = (EmbeddedChildFocusTraversalPolicy) policy; \r
-            component = embeddedPolicy.getCurrentComponent(frame);\r
-        } else {\r
-            // TODO: direction based?\r
-            component = policy.getDefaultComponent(frame);\r
-        }\r
-        if (component != null) {\r
-            // System.out.println("Requesting focus for component: " + component);\r
-            component.requestFocus();\r
-            // TODO: else case error? If not, consider moving flag setting below into this if\r
-        }\r
-        awtHasFocus = true;\r
-    }\r
-    \r
-    /**\r
-     * Moves focus back to the next SWT component\r
-     */\r
-    void transferFocusNext() {\r
-        assert swtHandler != null;\r
-        assert awtHasFocus;\r
-        \r
-        awtHasFocus = false;\r
-        swtHandler.gainFocusNext();\r
-    }\r
-    \r
-    /**\r
-     * Moves focus back to the previous SWT component\r
-     */\r
-    void transferFocusPrevious() {\r
-        assert swtHandler != null;\r
-        assert awtHasFocus;\r
-        \r
-        awtHasFocus = false;\r
-        swtHandler.gainFocusPrevious();\r
-    }\r
-    \r
-    boolean awtHasFocus() {\r
-        return awtHasFocus;\r
-    }\r
-\r
-    Component getCurrentComponent() {\r
-        return currentComponent;\r
-    }\r
-    \r
-    // ..................... Listener implementations\r
-\r
-    public void focusGained(FocusEvent e) {\r
-        assert e != null;\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        \r
-        // System.out.println("gained (awt). component = " + e.getComponent() + ", opposite = " + e.getOppositeComponent());\r
-        currentComponent  = e.getComponent();\r
-    }\r
-\r
-    public void focusLost(FocusEvent e) {\r
-        // System.out.println("component focus lost (awt). opposite = " + e.getOppositeComponent());\r
-        \r
-        // Intentionally leaving currentComponent set. When window focus is lost, \r
-        // it will be needed. \r
-    }\r
-\r
-    public void componentAdded(ContainerEvent e) {\r
-        assert e != null;\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        \r
-        e.getChild().addFocusListener(this);\r
-    }\r
-\r
-    public void componentRemoved(ContainerEvent e) {\r
-        assert e != null;\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        \r
-        e.getChild().removeFocusListener(this);\r
-    }\r
-    \r
-    public void windowGainedFocus(WindowEvent e) {\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        // System.out.println("WindowFocusListener.windowGainedFocus");\r
-        awtHasFocus = true;\r
-    }\r
-\r
-    public void windowLostFocus(WindowEvent e) {\r
-        assert e != null;\r
-        assert swtHandler != null;\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        \r
-        // System.out.println("WindowFocusListener.windowLostFocus");\r
-        \r
-        // Dismiss any popup menus that are\r
-        // open when losing focus. This prevents situations where\r
-        // multiple popup menus are visible at the same time. In JDK 1.4 and earlier, \r
-        // the dismissal is not done automatically. In JDK 1.5, this code is \r
-        // unnecessary, but it doesn't seem to hurt anything. \r
-        // TODO: verify this is OK on other windowing systems\r
-        // TODO: disable in post-1.4 environments\r
-        /* boolean popupShown = */hidePopups();\r
-        \r
-        // If focus is being lost to the parent SWT composite, then\r
-        // grab it back for AWT and return. Normally the parent SWT composite will\r
-        // do this for us, but it will not see a focus gained event when focus \r
-        // is transferred to it from its AWT frame child. \r
-        // This happens, for example, if an AWT control has focus and the \r
-        // tab of a containing (already active) view is clicked.\r
-        //\r
-        // However, don't grab back focus if a popup was hidden above. The popup\r
-        // area will not be properly redrawn (the popup, or part of it, will \r
-        // appear to be still there. \r
-        //if (!popupShown && swtHandler.hasFocus()) {\r
-            // System.out.println("**** Taking back focus: " + e);\r
-            // This seems to have side effects, so it's commented out for now. \r
-            // (Sometimes, it forces the workbench window to the foreground when another\r
-            // program's window is selected.)\r
-            // TODO: find an alternate approach to reassert focus\r
-            // gainFocus();\r
-            // return;\r
-        //}\r
-        \r
-        // On a normal change of focus, Swing will turn off any selection\r
-        // in a text field to help indicate focus is lost. This won't happen\r
-        // automatically when transferring to SWT, so turn off the selection\r
-        // manually.\r
-        if (currentComponent instanceof JTextComponent) {\r
-            Caret caret = ((JTextComponent)currentComponent).getCaret();\r
-            if (caret != null) {\r
-                caret.setSelectionVisible(false);\r
-            }\r
-        }\r
-        awtHasFocus = false;\r
-    }\r
-\r
-    // Returns true if any popup has been hidden\r
-    private boolean hidePopups() {\r
-        boolean result = false;\r
-        List popups = new ArrayList();\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        Window frame = this.frame;\r
-        if (frame == null)\r
-            return result;\r
-\r
-        // Look for popups inside the frame's component hierarchy. \r
-        // Lightweight popups will be found here. \r
-        findContainedPopups(frame, popups);\r
-        \r
-        // Also look for popups in the frame's window hierachy. \r
-        // Heavyweight popups will be found here.\r
-        findOwnedPopups(frame, popups);\r
-        \r
-        // System.out.println("Hiding popups, count=" + popups.size());\r
-        for (Iterator iter = popups.iterator(); iter.hasNext();) {\r
-            Component popup = (Component)iter.next();\r
-            if (popup.isVisible()) {\r
-                result = true;\r
-                popup.setVisible(false);\r
-            }\r
-        }\r
-        return result;\r
-    }\r
-\r
-    private void findOwnedPopups(Window window, List popups) {\r
-        assert window != null;\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        \r
-        Window[] ownedWindows = window.getOwnedWindows();\r
-        for (int i = 0; i < ownedWindows.length; i++) {\r
-            findContainedPopups(ownedWindows[i], popups);\r
-            findOwnedPopups(ownedWindows[i], popups);\r
-        }\r
-    }\r
-\r
-    private void findContainedPopups(Container container, List popups) {\r
-        assert container != null;\r
-        assert popups != null;\r
-        assert EventQueue.isDispatchThread();    // On AWT event thread\r
-        \r
-        Component[] components = container.getComponents();\r
-        for (int i = 0; i < components.length; i++) {\r
-            Component c = components[i];\r
-            // JPopupMenu is a container, so check for it first\r
-            if (c instanceof JPopupMenu) {\r
-                popups.add(c);\r
-            } else if (c instanceof Container) {\r
-                findContainedPopups((Container)c, popups);\r
-            }\r
-        }\r
-    }\r
-\r
-    public void postHidePopups() {\r
-        EventQueue.invokeLater(new Runnable() {\r
-            public void run() {\r
-                hidePopups();\r
-            }\r
-        });\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.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;
+
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class AwtFocusHandler implements FocusListener, ContainerListener, 
+                                      WindowFocusListener {
+
+    private Frame frame;
+    private SwtFocusHandler swtHandler;
+    private RecursiveContainerListener containerListener;
+    private boolean awtHasFocus = false;
+    private Component currentComponent = null;
+
+    public AwtFocusHandler(Frame frame) {
+        assert frame != null;
+
+        this.frame = frame;
+        this.containerListener = new RecursiveContainerListener(this);
+        frame.addContainerListener(this.containerListener);
+        frame.addWindowFocusListener(this);
+    }
+
+    public void setSwtHandler(SwtFocusHandler handler) {
+        assert handler != null;
+        assert swtHandler == null;  // this method is meant to be called once
+
+        swtHandler = handler;
+    }
+
+    /**
+     * Invoked from {@link SwtFocusHandler} DisposeListener.
+     * Only intended to be invoked once.
+     */
+    public void dispose() {
+        assert frame != null;
+        frame.removeWindowFocusListener(this);
+        frame.removeContainerListener(containerListener);
+        frame = null;
+        currentComponent = null;
+    }
+
+    void gainFocus() {
+        // assert frame != null;
+        // assert !awtHasFocus;
+        assert EventQueue.isDispatchThread();    // On AWT event thread
+        if (frame == null)
+            return;
+
+        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
+    private boolean hidePopups() {
+        boolean result = false;
+        List popups = new ArrayList();
+        assert EventQueue.isDispatchThread();    // On AWT event thread
+        Window frame = this.frame;
+        if (frame == null)
+            return result;
+
+        // 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);
+            }
+        }
+    }
+
+    public void postHidePopups() {
+        EventQueue.invokeLater(new Runnable() {
+            public void run() {
+                hidePopups();
+            }
+        });
+    }
+
+}