source: josm/trunk/src/org/openstreetmap/josm/gui/util/AdvancedKeyPressDetector.java@ 7219

Last change on this file since 7219 was 7219, checked in by akks, 10 years ago

missing files for two last commits

File size: 5.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.util;
3
4import java.awt.AWTEvent;
5import java.awt.Component;
6import java.awt.KeyboardFocusManager;
7import java.awt.Toolkit;
8import java.awt.event.AWTEventListener;
9import java.awt.event.ActionEvent;
10import java.awt.event.ActionListener;
11import java.awt.event.KeyEvent;
12import java.util.ArrayList;
13import java.util.Set;
14import java.util.TreeSet;
15import javax.swing.JFrame;
16import javax.swing.SwingUtilities;
17import javax.swing.Timer;
18
19import org.openstreetmap.josm.Main;
20
21import static org.openstreetmap.josm.tools.I18n.tr;
22/**
23 * Helper object that allows cross-platform detection of key press and realease events
24 * instance is available globally as Main.map.keyDetector
25 * @since 7217
26 */
27public class AdvancedKeyPressDetector implements AWTEventListener {
28
29 // events for crossplatform key holding processing
30 // thanks to http://www.arco.in-berlin.de/keyevent.html
31 private final Set<Integer> set = new TreeSet<>();
32 private KeyEvent releaseEvent;
33 private Timer timer;
34
35 private final ArrayList<KeyPressReleaseListener> keyListeners = new ArrayList<>();
36 private final ArrayList<ModifierListener> modifierListeners = new ArrayList<>();
37 private int previousModifiers;
38
39 /**
40 * Adds an object that wants to receive key press and release events
41 */
42 public void addKeyListener(KeyPressReleaseListener l) {
43 keyListeners.add(l);
44 }
45
46 /**
47 * Adds an object that wants to receive key modifier changed events
48 */
49 public void addModifierListener(ModifierListener l) {
50 modifierListeners.add(l);
51 }
52
53 /**
54 * Removes the listener
55 */
56 public void removeKeyListener(KeyPressReleaseListener l) {
57 keyListeners.remove(l);
58 }
59
60 /**
61 * Removes the key modifier listener
62 */
63 public void removeModifierListener(ModifierListener l) {
64 modifierListeners.remove(l);
65 }
66
67
68 /**
69 * Register this object as AWTEventListener
70 */
71 public void register() {
72 try {
73 Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
74 } catch (SecurityException ex) {
75 Main.warn(ex);
76 }
77 timer = new Timer(0, new ActionListener() {
78 @Override
79 public void actionPerformed(ActionEvent e) {
80 timer.stop();
81 if (set.remove(releaseEvent.getKeyCode())) {
82 for (KeyPressReleaseListener q: keyListeners) {
83 q.doKeyReleased(releaseEvent);
84 }
85 }
86 }
87 });
88 }
89
90 /**
91 * Unregister this object as AWTEventListener
92 * lists of listeners are not cleared!
93 */
94 public void unregister() {
95 timer.stop(); set.clear();
96 if (!keyListeners.isEmpty()) {
97 Main.warn(tr("Some of the key listeners forgot to remove themselves: {0}"), keyListeners.toString());
98 }
99 if (!modifierListeners.isEmpty()) {
100 Main.warn(tr("Some of the key listeners forgot to remove themselves: {0}"), modifierListeners.toString());
101 }
102 try {
103 Toolkit.getDefaultToolkit().removeAWTEventListener(this);
104 } catch (SecurityException ex) {
105 Main.warn(ex);
106 }
107 }
108
109 private void processKeyEvent(KeyEvent e) {
110 if (e.getID() == KeyEvent.KEY_PRESSED) {
111 if (timer.isRunning()) {
112 timer.stop();
113 } else if (set.add((e.getKeyCode()))) {
114 for (KeyPressReleaseListener q: keyListeners) {
115 q.doKeyPressed(e);
116 }
117 }
118 } else if (e.getID() == KeyEvent.KEY_RELEASED) {
119 if (timer.isRunning()) {
120 timer.stop();
121 if (set.remove(e.getKeyCode())) {
122 for (KeyPressReleaseListener q: keyListeners) {
123 q.doKeyReleased(e);
124 }
125 }
126 } else {
127 releaseEvent = e;
128 timer.restart();
129 }
130 }
131 }
132
133 @Override
134 public void eventDispatched(AWTEvent e) {
135 if (!(e instanceof KeyEvent)) {
136 return;
137 }
138 KeyEvent ke = (KeyEvent) e;
139
140 // check if ctrl, alt, shift modifiers are changed
141 int modif = ke.getModifiers();
142 if (previousModifiers != modif) {
143 previousModifiers = modif;
144 for (ModifierListener m: modifierListeners) {
145 m.modifiersChanged(modif);
146 }
147 }
148
149 // check if key press is done in main window, not in dialogs
150 Component focused = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
151 if (SwingUtilities.getWindowAncestor(focused) instanceof JFrame) {
152 processKeyEvent(ke);
153 }
154 }
155
156 /**
157 * Allows to determine if the key with specific code is pressed now
158 * @param keyCode the key code, for example KeyEvent.VK_ENTER
159 * @return true if the key is pressed now
160 */
161 public boolean isKeyPressed(int keyCode) {
162 return set.contains(Integer.valueOf(keyCode));
163 }
164}
Note: See TracBrowser for help on using the repository browser.