|
29 | 29 |
|
30 | 30 | package processing.app.helpers;
|
31 | 31 |
|
| 32 | +import java.awt.AWTKeyStroke; |
| 33 | +import java.awt.Component; |
| 34 | +import java.awt.KeyboardFocusManager; |
32 | 35 | import java.awt.Toolkit;
|
33 | 36 | import java.awt.event.InputEvent;
|
34 | 37 | import java.beans.PropertyChangeEvent;
|
| 38 | +import java.util.HashSet; |
| 39 | +import java.util.Set; |
35 | 40 |
|
36 | 41 | import javax.swing.Action;
|
| 42 | +import javax.swing.InputMap; |
37 | 43 | import javax.swing.JComponent;
|
38 | 44 | import javax.swing.KeyStroke;
|
39 | 45 |
|
@@ -115,6 +121,65 @@ public static void bind(final JComponent component, final Action action,
|
115 | 121 | });
|
116 | 122 | }
|
117 | 123 |
|
| 124 | + /** |
| 125 | + * Kill an existing binding from the given condition. If the binding is |
| 126 | + * defined on the given component, it is removed, but if it is defined through |
| 127 | + * a parent inputmap (typically shared by multiple components, so best not |
| 128 | + * touched), this adds a dummy binding for this component, that will never |
| 129 | + * match an action in the component's action map, effectively disabling the |
| 130 | + * binding. |
| 131 | + * |
| 132 | + * This method is not intended to unbind a binding created by bind(), since |
| 133 | + * such a binding would get re-enabled when the action is re-enabled. |
| 134 | + */ |
| 135 | + public static void killBinding(final JComponent component, |
| 136 | + final KeyStroke keystroke, int condition) { |
| 137 | + InputMap map = component.getInputMap(condition); |
| 138 | + // First, try removing it |
| 139 | + map.remove(keystroke); |
| 140 | + // If the binding is defined in a parent map, defining it will not work, so |
| 141 | + // instead add an override that will never appear in the action map. |
| 142 | + if (map.get(keystroke) != null) |
| 143 | + map.put(keystroke, new Object()); |
| 144 | + } |
| 145 | + |
| 146 | + /** |
| 147 | + * Kill an existing binding like above, but from all three conditions |
| 148 | + * (WHEN_FOCUSED, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, WHEN_IN_FOCUSED_WINDOW). |
| 149 | + */ |
| 150 | + public static void killBinding(final JComponent component, |
| 151 | + final KeyStroke key) { |
| 152 | + killBinding(component, key, JComponent.WHEN_FOCUSED); |
| 153 | + killBinding(component, key, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); |
| 154 | + killBinding(component, key, JComponent.WHEN_IN_FOCUSED_WINDOW); |
| 155 | + } |
| 156 | + |
| 157 | + /** |
| 158 | + * Remove a keystroke from the keys used to shift focus in or below the given |
| 159 | + * component. This modifies all sets of focus traversal keys on the given |
| 160 | + * component to remove the given keystroke. These sets are inherited down the |
| 161 | + * component hierarchy (until a component that has a custom set itself). |
| 162 | + */ |
| 163 | + public static void killFocusTraversalBinding(final Component component, |
| 164 | + final KeyStroke keystroke) { |
| 165 | + int[] sets = { KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, |
| 166 | + KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, |
| 167 | + KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, |
| 168 | + KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS }; |
| 169 | + for (int set : sets) { |
| 170 | + Set<AWTKeyStroke> keys = component.getFocusTraversalKeys(set); |
| 171 | + // keys is immutable, so create a new set to allow changes |
| 172 | + keys = new HashSet<>(keys); |
| 173 | + if (set == 0) |
| 174 | + keys.add(ctrlAlt('Z')); |
| 175 | + |
| 176 | + // If the given keystroke was present in the set, replace it with the |
| 177 | + // updated set with the keystroke removed. |
| 178 | + if (keys.remove(keystroke)) |
| 179 | + component.setFocusTraversalKeys(set, keys); |
| 180 | + } |
| 181 | + } |
| 182 | + |
118 | 183 | private static void enableBind(final JComponent component,
|
119 | 184 | final Action action, final KeyStroke keystroke,
|
120 | 185 | int condition) {
|
|
0 commit comments