Statistics
| Revision:

svn-gvsig-desktop / tags / v1_0_2_Build_906 / libraries / libIverUtiles / src / com / iver / utiles / console / jedit / DefaultInputHandler.java @ 10972

History | View | Annotate | Download (8.34 KB)

1
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
import java.awt.event.ActionListener;
13
import java.awt.event.InputEvent;
14
import java.awt.event.KeyEvent;
15
import java.util.Hashtable;
16
import java.util.StringTokenizer;
17

    
18
import javax.swing.KeyStroke;
19

    
20
/**
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
}