|
1 | 1 | package processing.app.helpers;
|
2 | 2 |
|
| 3 | +import java.awt.AWTKeyStroke; |
| 4 | +import java.awt.Component; |
| 5 | +import java.awt.KeyboardFocusManager; |
3 | 6 | import java.awt.Toolkit;
|
4 | 7 | import java.awt.event.InputEvent;
|
5 | 8 | import java.beans.PropertyChangeEvent;
|
| 9 | +import java.util.HashSet; |
| 10 | +import java.util.Set; |
6 | 11 |
|
7 | 12 | import javax.swing.Action;
|
| 13 | +import javax.swing.InputMap; |
8 | 14 | import javax.swing.JComponent;
|
9 | 15 | import javax.swing.KeyStroke;
|
10 | 16 |
|
@@ -86,6 +92,65 @@ public static void bind(final JComponent component, final Action action,
|
86 | 92 | });
|
87 | 93 | }
|
88 | 94 |
|
| 95 | + /** |
| 96 | + * Kill an existing binding from the given condition. If the binding is |
| 97 | + * defined on the given component, it is removed, but if it is defined through |
| 98 | + * a parent inputmap (typically shared by multiple components, so best not |
| 99 | + * touched), this adds a dummy binding for this component, that will never |
| 100 | + * match an action in the component's action map, effectively disabling the |
| 101 | + * binding. |
| 102 | + * |
| 103 | + * This method is not intended to unbind a binding created by bind(), since |
| 104 | + * such a binding would get re-enabled when the action is re-enabled. |
| 105 | + */ |
| 106 | + public static void killBinding(final JComponent component, |
| 107 | + final KeyStroke keystroke, int condition) { |
| 108 | + InputMap map = component.getInputMap(condition); |
| 109 | + // First, try removing it |
| 110 | + map.remove(keystroke); |
| 111 | + // If the binding is defined in a parent map, defining it will not work, so |
| 112 | + // instead add an override that will never appear in the action map. |
| 113 | + if (map.get(keystroke) != null) |
| 114 | + map.put(keystroke, new Object()); |
| 115 | + } |
| 116 | + |
| 117 | + /** |
| 118 | + * Kill an existing binding like above, but from all three conditions |
| 119 | + * (WHEN_FOCUSED, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, WHEN_IN_FOCUSED_WINDOW). |
| 120 | + */ |
| 121 | + public static void killBinding(final JComponent component, |
| 122 | + final KeyStroke key) { |
| 123 | + killBinding(component, key, JComponent.WHEN_FOCUSED); |
| 124 | + killBinding(component, key, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); |
| 125 | + killBinding(component, key, JComponent.WHEN_IN_FOCUSED_WINDOW); |
| 126 | + } |
| 127 | + |
| 128 | + /** |
| 129 | + * Remove a keystroke from the keys used to shift focus in or below the given |
| 130 | + * component. This modifies all sets of focus traversal keys on the given |
| 131 | + * component to remove the given keystroke. These sets are inherited down the |
| 132 | + * component hierarchy (until a component that has a custom set itself). |
| 133 | + */ |
| 134 | + public static void killFocusTraversalBinding(final Component component, |
| 135 | + final KeyStroke keystroke) { |
| 136 | + int[] sets = { KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, |
| 137 | + KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, |
| 138 | + KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, |
| 139 | + KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS }; |
| 140 | + for (int set : sets) { |
| 141 | + Set<AWTKeyStroke> keys = component.getFocusTraversalKeys(set); |
| 142 | + // keys is immutable, so create a new set to allow changes |
| 143 | + keys = new HashSet<>(keys); |
| 144 | + if (set == 0) |
| 145 | + keys.add(ctrlAlt('Z')); |
| 146 | + |
| 147 | + // If the given keystroke was present in the set, replace it with the |
| 148 | + // updated set with the keystroke removed. |
| 149 | + if (keys.remove(keystroke)) |
| 150 | + component.setFocusTraversalKeys(set, keys); |
| 151 | + } |
| 152 | + } |
| 153 | + |
89 | 154 | private static void enableBind(final JComponent component,
|
90 | 155 | final Action action, final KeyStroke keystroke,
|
91 | 156 | int condition) {
|
|
0 commit comments