-/*******************************************************************************\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.EventQueue;\r
-\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.events.ControlAdapter;\r
-import org.eclipse.swt.events.ControlEvent;\r
-import org.eclipse.swt.events.DisposeEvent;\r
-import org.eclipse.swt.events.DisposeListener;\r
-import org.eclipse.swt.events.FocusEvent;\r
-import org.eclipse.swt.events.FocusListener;\r
-import org.eclipse.swt.events.KeyEvent;\r
-import org.eclipse.swt.events.KeyListener;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.eclipse.swt.widgets.Shell;\r
-\r
-public class SwtFocusHandler implements FocusListener, KeyListener {\r
-\r
- private Composite composite;\r
- private final Display display;\r
- private AwtFocusHandler awtHandler;\r
-\r
- public SwtFocusHandler(Composite composite) {\r
- assert composite != null;\r
- assert Display.getCurrent() != null; // On SWT event thread\r
- \r
- this.composite = composite;\r
- display = composite.getDisplay();\r
- composite.addFocusListener(this);\r
- composite.addKeyListener(this);\r
- }\r
-\r
- public void setAwtHandler(AwtFocusHandler handler) {\r
- assert handler != null;\r
- assert awtHandler == null; // this method is meant to be called once\r
- assert composite != null;\r
- assert Display.getCurrent() != null; // On SWT event thread \r
- \r
- awtHandler = handler;\r
- \r
- // Dismiss Swing popups when the main window is moved. (It would be \r
- // better to dismiss popups whenever the titlebar is clicked, but \r
- // there does not seem to be a way.)\r
- final ControlAdapter controlAdapter = new ControlAdapter() {\r
- public void controlMoved(ControlEvent e) {\r
- assert awtHandler != null;\r
- awtHandler.postHidePopups();\r
- }\r
- };\r
- final Shell shell = composite.getShell();\r
- shell.addControlListener(controlAdapter);\r
- \r
- // Cleanup listeners on dispose\r
- composite.addDisposeListener(new DisposeListener() {\r
- public void widgetDisposed(DisposeEvent e) {\r
- // Remove listener from shell before nullifying awtHandler\r
- shell.removeControlListener(controlAdapter);\r
- awtHandler.dispose();\r
- awtHandler = null;\r
- composite = null;\r
- }\r
- });\r
- }\r
- \r
- void gainFocusNext() {\r
- traverse(SWT.TRAVERSE_TAB_NEXT);\r
- }\r
- \r
- void gainFocusPrevious() {\r
- traverse(SWT.TRAVERSE_TAB_PREVIOUS);\r
- }\r
- \r
- private void traverse(final int traversal) {\r
- //assert composite != null;\r
- if (composite == null)\r
- return;\r
-\r
- // Tab from the containing SWT component while \r
- // running on the SWT thread\r
- Runnable r = new Runnable() {\r
- public void run() {\r
- composite.traverse(traversal);\r
- }\r
- };\r
- display.asyncExec(r);\r
- }\r
-\r
-// boolean hasFocus() {\r
-// assert composite != null;\r
-// \r
-// // This will return true if the composite has focus, or if any\r
-// // foreign (e.g. AWT) child of the composite has focus.\r
-// if (display.isDisposed()) {\r
-// return false;\r
-// }\r
-// final boolean[] result = new boolean[1];\r
-// display.syncExec(new Runnable() {\r
-// public void run() {\r
-// result[0] = (!composite.isDisposed() &&\r
-// (display.getFocusControl() == composite));\r
-// }\r
-// });\r
-// return result[0];\r
-// }\r
-\r
- // ..................... Listener implementations\r
- \r
- public void focusGained(FocusEvent e) {\r
- assert awtHandler != null;\r
- assert Display.getCurrent() != null; // On SWT event thread\r
-\r
- // System.out.println("Gained: " + e.toString() + " (" + e.widget.getClass().getName() + ")");\r
- EventQueue.invokeLater(new Runnable() {\r
- public void run() {\r
- // composite DisposeListener may have nullified this meanwhile!\r
- // Not a bug.\r
- if (awtHandler != null)\r
- awtHandler.gainFocus();\r
- }\r
- });\r
- }\r
- \r
- public void focusLost(FocusEvent e) {\r
- // System.out.println("Lost: " + e.toString() + " (" + e.widget.getClass().getName() + ")");\r
- }\r
-\r
- public void keyPressed(KeyEvent e) {\r
- assert Display.getCurrent() != null; // On SWT event thread\r
-\r
- // If the embedded swing root pane has no components to receive focus, \r
- // then there will be cases where the parent SWT composite will keep \r
- // focus. (For example, when tabbing into the root pane container). \r
- // By default, in these cases, the focus is swallowed by the Composite\r
- // and never escapes. This code allows tab and back-tab to do the \r
- // proper traversal to other SWT components from the composite.\r
- // TODO: other keys?\r
- if (e.keyCode == SWT.TAB) {\r
- // TODO: In some cases, this gobbles up all the tabs, even from AWT children. Find a more selective way. \r
- /*if (e.stateMask == SWT.NONE) {\r
- traverse(SWT.TRAVERSE_TAB_NEXT);\r
- } else if (e.stateMask == SWT.SHIFT) {\r
- traverse(SWT.TRAVERSE_TAB_PREVIOUS);\r
- }*/\r
- }\r
- }\r
-\r
- public void keyReleased(KeyEvent e) {\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.EventQueue;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+public class SwtFocusHandler implements FocusListener, KeyListener {
+
+ private Composite composite;
+ private final Display display;
+ private AwtFocusHandler awtHandler;
+
+ public SwtFocusHandler(Composite composite) {
+ assert composite != null;
+ assert Display.getCurrent() != null; // On SWT event thread
+
+ this.composite = composite;
+ display = composite.getDisplay();
+ composite.addFocusListener(this);
+ composite.addKeyListener(this);
+ }
+
+ public void setAwtHandler(AwtFocusHandler handler) {
+ assert handler != null;
+ assert awtHandler == null; // this method is meant to be called once
+ assert composite != null;
+ assert Display.getCurrent() != null; // On SWT event thread
+
+ awtHandler = handler;
+
+ // Dismiss Swing popups when the main window is moved. (It would be
+ // better to dismiss popups whenever the titlebar is clicked, but
+ // there does not seem to be a way.)
+ final ControlAdapter controlAdapter = new ControlAdapter() {
+ public void controlMoved(ControlEvent e) {
+ assert awtHandler != null;
+ awtHandler.postHidePopups();
+ }
+ };
+ final Shell shell = composite.getShell();
+ shell.addControlListener(controlAdapter);
+
+ // Cleanup listeners on dispose
+ composite.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ // Remove listener from shell before nullifying awtHandler
+ shell.removeControlListener(controlAdapter);
+ awtHandler.dispose();
+ awtHandler = null;
+ composite = null;
+ }
+ });
+ }
+
+ void gainFocusNext() {
+ traverse(SWT.TRAVERSE_TAB_NEXT);
+ }
+
+ void gainFocusPrevious() {
+ traverse(SWT.TRAVERSE_TAB_PREVIOUS);
+ }
+
+ private void traverse(final int traversal) {
+ //assert composite != null;
+ if (composite == null)
+ return;
+
+ // Tab from the containing SWT component while
+ // running on the SWT thread
+ Runnable r = new Runnable() {
+ public void run() {
+ composite.traverse(traversal);
+ }
+ };
+ display.asyncExec(r);
+ }
+
+// boolean hasFocus() {
+// assert composite != null;
+//
+// // This will return true if the composite has focus, or if any
+// // foreign (e.g. AWT) child of the composite has focus.
+// if (display.isDisposed()) {
+// return false;
+// }
+// final boolean[] result = new boolean[1];
+// display.syncExec(new Runnable() {
+// public void run() {
+// result[0] = (!composite.isDisposed() &&
+// (display.getFocusControl() == composite));
+// }
+// });
+// return result[0];
+// }
+
+ // ..................... Listener implementations
+
+ public void focusGained(FocusEvent e) {
+ assert awtHandler != null;
+ assert Display.getCurrent() != null; // On SWT event thread
+
+ // System.out.println("Gained: " + e.toString() + " (" + e.widget.getClass().getName() + ")");
+ EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ // composite DisposeListener may have nullified this meanwhile!
+ // Not a bug.
+ if (awtHandler != null)
+ awtHandler.gainFocus();
+ }
+ });
+ }
+
+ public void focusLost(FocusEvent e) {
+ // System.out.println("Lost: " + e.toString() + " (" + e.widget.getClass().getName() + ")");
+ }
+
+ public void keyPressed(KeyEvent e) {
+ assert Display.getCurrent() != null; // On SWT event thread
+
+ // If the embedded swing root pane has no components to receive focus,
+ // then there will be cases where the parent SWT composite will keep
+ // focus. (For example, when tabbing into the root pane container).
+ // By default, in these cases, the focus is swallowed by the Composite
+ // and never escapes. This code allows tab and back-tab to do the
+ // proper traversal to other SWT components from the composite.
+ // TODO: other keys?
+ if (e.keyCode == SWT.TAB) {
+ // TODO: In some cases, this gobbles up all the tabs, even from AWT children. Find a more selective way.
+ /*if (e.stateMask == SWT.NONE) {
+ traverse(SWT.TRAVERSE_TAB_NEXT);
+ } else if (e.stateMask == SWT.SHIFT) {
+ traverse(SWT.TRAVERSE_TAB_PREVIOUS);
+ }*/
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+ }
+
+
+}