svn-gvsig-desktop / tags / v1_0_2_Build_916 / libraries / libIverUtiles / src / com / iver / utiles / console / jedit / DefaultInputHandler.java @ 12327
History | View | Annotate | Download (8.34 KB)
1 | 4890 | caballero | package com.iver.utiles.console.jedit; |
---|---|---|---|
2 | /*
|
||
3 | * DefaultInputHandler.java - Default implementation of an input handler
|
||
4 | * Copyright (C) 1999 Slava Pestov
|
||
5 | *
|
||
6 | * You may use and modify this package for any purpose. Redistribution is
|
||
7 | * permitted, in both source and binary form, provided that this notice
|
||
8 | * remains intact in all source distributions of this package.
|
||
9 | */
|
||
10 | |||
11 | import java.awt.Toolkit; |
||
12 | 8765 | jjdelcerro | import java.awt.event.ActionListener; |
13 | import java.awt.event.InputEvent; |
||
14 | import java.awt.event.KeyEvent; |
||
15 | 4890 | caballero | import java.util.Hashtable; |
16 | import java.util.StringTokenizer; |
||
17 | |||
18 | 8765 | jjdelcerro | import javax.swing.KeyStroke; |
19 | |||
20 | 4890 | caballero | /**
|
21 | * The default input handler. It maps sequences of keystrokes into actions
|
||
22 | * and inserts key typed events into the text area.
|
||
23 | * @author Slava Pestov
|
||
24 | * @version $Id$
|
||
25 | */
|
||
26 | public class DefaultInputHandler extends InputHandler |
||
27 | { |
||
28 | /**
|
||
29 | * Creates a new input handler with no key bindings defined.
|
||
30 | */
|
||
31 | public DefaultInputHandler()
|
||
32 | { |
||
33 | bindings = currentBindings = new Hashtable(); |
||
34 | } |
||
35 | |||
36 | /**
|
||
37 | * Sets up the default key bindings.
|
||
38 | */
|
||
39 | public void addDefaultKeyBindings() |
||
40 | { |
||
41 | addKeyBinding("BACK_SPACE",BACKSPACE);
|
||
42 | addKeyBinding("C+BACK_SPACE",BACKSPACE_WORD);
|
||
43 | addKeyBinding("DELETE",DELETE);
|
||
44 | addKeyBinding("C+DELETE",DELETE_WORD);
|
||
45 | |||
46 | addKeyBinding("ENTER",INSERT_BREAK);
|
||
47 | addKeyBinding("TAB",INSERT_TAB);
|
||
48 | |||
49 | addKeyBinding("INSERT",OVERWRITE);
|
||
50 | addKeyBinding("C+\\",TOGGLE_RECT);
|
||
51 | |||
52 | addKeyBinding("HOME",HOME);
|
||
53 | addKeyBinding("END",END);
|
||
54 | addKeyBinding("S+HOME",SELECT_HOME);
|
||
55 | addKeyBinding("S+END",SELECT_END);
|
||
56 | addKeyBinding("C+HOME",DOCUMENT_HOME);
|
||
57 | addKeyBinding("C+END",DOCUMENT_END);
|
||
58 | addKeyBinding("CS+HOME",SELECT_DOC_HOME);
|
||
59 | addKeyBinding("CS+END",SELECT_DOC_END);
|
||
60 | |||
61 | addKeyBinding("PAGE_UP",PREV_PAGE);
|
||
62 | addKeyBinding("PAGE_DOWN",NEXT_PAGE);
|
||
63 | addKeyBinding("S+PAGE_UP",SELECT_PREV_PAGE);
|
||
64 | addKeyBinding("S+PAGE_DOWN",SELECT_NEXT_PAGE);
|
||
65 | |||
66 | addKeyBinding("LEFT",PREV_CHAR);
|
||
67 | addKeyBinding("S+LEFT",SELECT_PREV_CHAR);
|
||
68 | addKeyBinding("C+LEFT",PREV_WORD);
|
||
69 | addKeyBinding("CS+LEFT",SELECT_PREV_WORD);
|
||
70 | addKeyBinding("RIGHT",NEXT_CHAR);
|
||
71 | addKeyBinding("S+RIGHT",SELECT_NEXT_CHAR);
|
||
72 | addKeyBinding("C+RIGHT",NEXT_WORD);
|
||
73 | addKeyBinding("CS+RIGHT",SELECT_NEXT_WORD);
|
||
74 | addKeyBinding("UP",PREV_LINE);
|
||
75 | addKeyBinding("S+UP",SELECT_PREV_LINE);
|
||
76 | addKeyBinding("DOWN",NEXT_LINE);
|
||
77 | addKeyBinding("S+DOWN",SELECT_NEXT_LINE);
|
||
78 | |||
79 | addKeyBinding("C+ENTER",REPEAT);
|
||
80 | } |
||
81 | |||
82 | /**
|
||
83 | * Adds a key binding to this input handler. The key binding is
|
||
84 | * a list of white space separated key strokes of the form
|
||
85 | * <i>[modifiers+]key</i> where modifier is C for Control, A for Alt,
|
||
86 | * or S for Shift, and key is either a character (a-z) or a field
|
||
87 | * name in the KeyEvent class prefixed with VK_ (e.g., BACK_SPACE)
|
||
88 | * @param keyBinding The key binding
|
||
89 | * @param action The action
|
||
90 | */
|
||
91 | public void addKeyBinding(String keyBinding, ActionListener action) |
||
92 | { |
||
93 | Hashtable current = bindings;
|
||
94 | |||
95 | StringTokenizer st = new StringTokenizer(keyBinding); |
||
96 | while(st.hasMoreTokens())
|
||
97 | { |
||
98 | KeyStroke keyStroke = parseKeyStroke(st.nextToken());
|
||
99 | if(keyStroke == null) |
||
100 | return;
|
||
101 | |||
102 | if(st.hasMoreTokens())
|
||
103 | { |
||
104 | Object o = current.get(keyStroke);
|
||
105 | if(o instanceof Hashtable) |
||
106 | current = (Hashtable)o;
|
||
107 | else
|
||
108 | { |
||
109 | o = new Hashtable(); |
||
110 | current.put(keyStroke,o); |
||
111 | current = (Hashtable)o;
|
||
112 | } |
||
113 | } |
||
114 | else
|
||
115 | current.put(keyStroke,action); |
||
116 | } |
||
117 | } |
||
118 | |||
119 | /**
|
||
120 | * Removes a key binding from this input handler. This is not yet
|
||
121 | * implemented.
|
||
122 | * @param keyBinding The key binding
|
||
123 | */
|
||
124 | public void removeKeyBinding(String keyBinding) |
||
125 | { |
||
126 | throw new InternalError("Not yet implemented"); |
||
127 | } |
||
128 | |||
129 | /**
|
||
130 | * Removes all key bindings from this input handler.
|
||
131 | */
|
||
132 | public void removeAllKeyBindings() |
||
133 | { |
||
134 | bindings.clear(); |
||
135 | } |
||
136 | |||
137 | /**
|
||
138 | * Returns a copy of this input handler that shares the same
|
||
139 | * key bindings. Setting key bindings in the copy will also
|
||
140 | * set them in the original.
|
||
141 | */
|
||
142 | public InputHandler copy()
|
||
143 | { |
||
144 | return new DefaultInputHandler(this); |
||
145 | } |
||
146 | |||
147 | /**
|
||
148 | * Handle a key pressed event. This will look up the binding for
|
||
149 | * the key stroke and execute it.
|
||
150 | */
|
||
151 | public void keyPressed(KeyEvent evt) |
||
152 | { |
||
153 | int keyCode = evt.getKeyCode();
|
||
154 | int modifiers = evt.getModifiers();
|
||
155 | |||
156 | if(keyCode == KeyEvent.VK_CONTROL || |
||
157 | keyCode == KeyEvent.VK_SHIFT ||
|
||
158 | keyCode == KeyEvent.VK_ALT ||
|
||
159 | keyCode == KeyEvent.VK_META)
|
||
160 | return;
|
||
161 | |||
162 | if((modifiers & ~KeyEvent.SHIFT_MASK) != 0 |
||
163 | || evt.isActionKey() |
||
164 | || keyCode == KeyEvent.VK_BACK_SPACE
|
||
165 | || keyCode == KeyEvent.VK_DELETE
|
||
166 | || keyCode == KeyEvent.VK_ENTER
|
||
167 | || keyCode == KeyEvent.VK_TAB
|
||
168 | || keyCode == KeyEvent.VK_ESCAPE)
|
||
169 | { |
||
170 | if(grabAction != null) |
||
171 | { |
||
172 | handleGrabAction(evt); |
||
173 | return;
|
||
174 | } |
||
175 | |||
176 | KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, |
||
177 | modifiers); |
||
178 | Object o = currentBindings.get(keyStroke);
|
||
179 | if(o == null) |
||
180 | { |
||
181 | // Don't beep if the user presses some
|
||
182 | // key we don't know about unless a
|
||
183 | // prefix is active. Otherwise it will
|
||
184 | // beep when caps lock is pressed, etc.
|
||
185 | if(currentBindings != bindings)
|
||
186 | { |
||
187 | Toolkit.getDefaultToolkit().beep();
|
||
188 | // F10 should be passed on, but C+e F10
|
||
189 | // shouldn't
|
||
190 | repeatCount = 0;
|
||
191 | repeat = false;
|
||
192 | evt.consume(); |
||
193 | } |
||
194 | currentBindings = bindings; |
||
195 | return;
|
||
196 | } |
||
197 | else if(o instanceof ActionListener) |
||
198 | { |
||
199 | currentBindings = bindings; |
||
200 | |||
201 | executeAction(((ActionListener)o),
|
||
202 | evt.getSource(),null);
|
||
203 | |||
204 | evt.consume(); |
||
205 | return;
|
||
206 | } |
||
207 | else if(o instanceof Hashtable) |
||
208 | { |
||
209 | currentBindings = (Hashtable)o;
|
||
210 | evt.consume(); |
||
211 | return;
|
||
212 | } |
||
213 | } |
||
214 | } |
||
215 | |||
216 | /**
|
||
217 | * Handle a key typed event. This inserts the key into the text area.
|
||
218 | */
|
||
219 | public void keyTyped(KeyEvent evt) |
||
220 | { |
||
221 | int modifiers = evt.getModifiers();
|
||
222 | char c = evt.getKeyChar();
|
||
223 | if(c != KeyEvent.CHAR_UNDEFINED && |
||
224 | (modifiers & KeyEvent.ALT_MASK) == 0) |
||
225 | { |
||
226 | if(c >= 0x20 && c != 0x7f) |
||
227 | { |
||
228 | KeyStroke keyStroke = KeyStroke.getKeyStroke( |
||
229 | Character.toUpperCase(c));
|
||
230 | Object o = currentBindings.get(keyStroke);
|
||
231 | |||
232 | if(o instanceof Hashtable) |
||
233 | { |
||
234 | currentBindings = (Hashtable)o;
|
||
235 | return;
|
||
236 | } |
||
237 | else if(o instanceof ActionListener) |
||
238 | { |
||
239 | currentBindings = bindings; |
||
240 | executeAction((ActionListener)o,
|
||
241 | evt.getSource(), |
||
242 | String.valueOf(c));
|
||
243 | return;
|
||
244 | } |
||
245 | |||
246 | currentBindings = bindings; |
||
247 | |||
248 | if(grabAction != null) |
||
249 | { |
||
250 | handleGrabAction(evt); |
||
251 | return;
|
||
252 | } |
||
253 | |||
254 | // 0-9 adds another 'digit' to the repeat number
|
||
255 | if(repeat && Character.isDigit(c)) |
||
256 | { |
||
257 | repeatCount *= 10;
|
||
258 | repeatCount += (c - '0');
|
||
259 | return;
|
||
260 | } |
||
261 | |||
262 | executeAction(INSERT_CHAR,evt.getSource(), |
||
263 | String.valueOf(evt.getKeyChar()));
|
||
264 | |||
265 | repeatCount = 0;
|
||
266 | repeat = false;
|
||
267 | } |
||
268 | } |
||
269 | } |
||
270 | |||
271 | /**
|
||
272 | * Converts a string to a keystroke. The string should be of the
|
||
273 | * form <i>modifiers</i>+<i>shortcut</i> where <i>modifiers</i>
|
||
274 | * is any combination of A for Alt, C for Control, S for Shift
|
||
275 | * or M for Meta, and <i>shortcut</i> is either a single character,
|
||
276 | * or a keycode name from the <code>KeyEvent</code> class, without
|
||
277 | * the <code>VK_</code> prefix.
|
||
278 | * @param keyStroke A string description of the key stroke
|
||
279 | */
|
||
280 | public static KeyStroke parseKeyStroke(String keyStroke) |
||
281 | { |
||
282 | if(keyStroke == null) |
||
283 | return null; |
||
284 | int modifiers = 0; |
||
285 | int index = keyStroke.indexOf('+'); |
||
286 | if(index != -1) |
||
287 | { |
||
288 | for(int i = 0; i < index; i++) |
||
289 | { |
||
290 | switch(Character.toUpperCase(keyStroke |
||
291 | .charAt(i))) |
||
292 | { |
||
293 | case 'A': |
||
294 | modifiers |= InputEvent.ALT_MASK;
|
||
295 | break;
|
||
296 | case 'C': |
||
297 | modifiers |= InputEvent.CTRL_MASK;
|
||
298 | break;
|
||
299 | case 'M': |
||
300 | modifiers |= InputEvent.META_MASK;
|
||
301 | break;
|
||
302 | case 'S': |
||
303 | modifiers |= InputEvent.SHIFT_MASK;
|
||
304 | break;
|
||
305 | } |
||
306 | } |
||
307 | } |
||
308 | String key = keyStroke.substring(index + 1); |
||
309 | if(key.length() == 1) |
||
310 | { |
||
311 | char ch = Character.toUpperCase(key.charAt(0)); |
||
312 | if(modifiers == 0) |
||
313 | return KeyStroke.getKeyStroke(ch); |
||
314 | else
|
||
315 | return KeyStroke.getKeyStroke(ch,modifiers); |
||
316 | } |
||
317 | else if(key.length() == 0) |
||
318 | { |
||
319 | System.err.println("Invalid key stroke: " + keyStroke); |
||
320 | return null; |
||
321 | } |
||
322 | else
|
||
323 | { |
||
324 | int ch;
|
||
325 | |||
326 | try
|
||
327 | { |
||
328 | ch = KeyEvent.class.getField("VK_".concat(key)) |
||
329 | .getInt(null);
|
||
330 | } |
||
331 | catch(Exception e) |
||
332 | { |
||
333 | System.err.println("Invalid key stroke: " |
||
334 | + keyStroke); |
||
335 | return null; |
||
336 | } |
||
337 | |||
338 | return KeyStroke.getKeyStroke(ch,modifiers); |
||
339 | } |
||
340 | } |
||
341 | |||
342 | // private members
|
||
343 | private Hashtable bindings; |
||
344 | private Hashtable currentBindings; |
||
345 | |||
346 | private DefaultInputHandler(DefaultInputHandler copy)
|
||
347 | { |
||
348 | bindings = currentBindings = copy.bindings; |
||
349 | } |
||
350 | } |