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;
}
}