001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.util;
003
004import javax.swing.ComponentInputMap;
005import javax.swing.InputMap;
006import javax.swing.JComponent;
007import javax.swing.KeyStroke;
008
009/**
010 * Make shortcuts from main window work in dialog windows.
011 *
012 * It's not possible to simply set component input map parent to be Main.contentPane.getInputMap
013 * because there is check in setParent that InputMap is for the same component.
014 * Yes, this is a hack.
015 * Another possibility would be simply copy InputMap, but that would require to
016 * keep copies synchronized when some shortcuts are changed later.
017 */
018public class RedirectInputMap extends ComponentInputMap {
019
020    private final InputMap target;
021
022    /**
023     * Create a new {@link RedirectInputMap}
024     * @param component The component the input map will be added to
025     * @param target The target input map that should be mirrored.
026     */
027    public RedirectInputMap(JComponent component, InputMap target) {
028        super(component);
029        this.target = target;
030    }
031
032    @Override
033    public Object get(KeyStroke keyStroke) {
034        return target.get(keyStroke);
035    }
036
037    @Override
038    public KeyStroke[] keys() {
039        return target.keys();
040    }
041
042    @Override
043    public int size() {
044        return target.size();
045    }
046
047    @Override
048    public KeyStroke[] allKeys() {
049        return target.allKeys();
050    }
051
052    @Override
053    public void put(KeyStroke keyStroke, Object actionMapKey) {
054        throw new UnsupportedOperationException();
055    }
056
057    @Override
058    public void remove(KeyStroke key) {
059        throw new UnsupportedOperationException();
060    }
061
062    @Override
063    public void clear() {
064        throw new UnsupportedOperationException();
065    }
066
067    /**
068     * Redirects the key inputs from one component to an other component
069     * @param source The source component
070     * @param target The target component to send the keystrokes to.
071     */
072    public static void redirect(JComponent source, JComponent target) {
073        InputMap lastParent = source.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
074        while (lastParent.getParent() != null) {
075            lastParent = lastParent.getParent();
076        }
077        lastParent.setParent(new RedirectInputMap(source, target.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)));
078        source.getActionMap().setParent(target.getActionMap());
079    }
080}