package org.esa.snap.ui.tooladapter.actions; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * Convenience Action to dispose of a Swing Window by using the Escape key. * Before disposing of the window the Action will first attempt to hide * any popups. In this case the user will need to invoke the Escape key a * second time before the Window is disposed. */ public class EscapeAction extends AbstractAction { private static final String KEY_STROKE_AND_KEY = "ESCAPE"; private static final KeyStroke ESCAPE_KEY_STROKE = KeyStroke.getKeyStroke( KEY_STROKE_AND_KEY ); private static EscapeAction instance = new EscapeAction(); /** * Registers an EscapeAction on the specified JDialog * * @param dialog the JDialog the EscapeAction is registered with */ public static void register(JDialog dialog) { register(dialog.getRootPane()); } /** * Registers an EscapeAction on the specified JRootPane * * @param rootPane the JRootPane the EscapeAction is registered with */ public static void register(JRootPane rootPane) { rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ESCAPE_KEY_STROKE, KEY_STROKE_AND_KEY); rootPane.getActionMap().put(KEY_STROKE_AND_KEY, instance); } private EscapeAction() { super("Escape"); } /** * Implement the Escape Action. First attempt to hide a popup menu. * If no popups are found then dispose the window. */ @Override public void actionPerformed(ActionEvent e) { // When a popup is visible the root pane of the Window will // (generally) have focus Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); JComponent rootPane = (JComponent)component; // In some cases a component added to a popup menu may have focus, but // we need the root pane to check for popup menu key bindings if (!(rootPane instanceof JRootPane)) { rootPane = (JComponent)SwingUtilities.getAncestorOfClass(JRootPane.class, component); } // Hide the popup menu when an ESCAPE key binding is found, otherwise dispose the Window ActionListener escapeAction = getEscapeAction(rootPane); if (escapeAction != null) { escapeAction.actionPerformed(null); } else { Window window = SwingUtilities.windowForComponent(component); if (window != null) { window.dispose(); } } } private ActionListener getEscapeAction(JComponent rootPane) { // Search the operatorDescriptor InputMap to see if a binding for the ESCAPE key // exists. This binding is added when a popup menu is made visible // (and removed when the popup menu is hidden). InputMap im = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); if (im == null || (im = im.getParent()) == null) { return null; } Object[] keys = im.keys(); if (keys == null) { return null; } for (Object keyStroke : keys) { if (keyStroke.equals(ESCAPE_KEY_STROKE)) { Object key = im.get(ESCAPE_KEY_STROKE); return rootPane.getActionMap().get(key); } } return null; } }