Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libIverUtiles / src / com / iver / utiles / console / jedit / DefaultInputHandler.java @ 4890

History | View | Annotate | Download (8.26 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 javax.swing.KeyStroke;
12
import java.awt.event.*;
13
import java.awt.Toolkit;
14
import java.util.Hashtable;
15
import java.util.StringTokenizer;
16

    
17
/**
18
 * The default input handler. It maps sequences of keystrokes into actions
19
 * and inserts key typed events into the text area.
20
 * @author Slava Pestov
21
 * @version $Id$
22
 */
23
public class DefaultInputHandler extends InputHandler
24
{
25
        /**
26
         * Creates a new input handler with no key bindings defined.
27
         */
28
        public DefaultInputHandler()
29
        {
30
                bindings = currentBindings = new Hashtable();
31
        }
32

    
33
        /**
34
         * Sets up the default key bindings.
35
         */
36
        public void addDefaultKeyBindings()
37
        {
38
                addKeyBinding("BACK_SPACE",BACKSPACE);
39
                addKeyBinding("C+BACK_SPACE",BACKSPACE_WORD);
40
                addKeyBinding("DELETE",DELETE);
41
                addKeyBinding("C+DELETE",DELETE_WORD);
42

    
43
                addKeyBinding("ENTER",INSERT_BREAK);
44
                addKeyBinding("TAB",INSERT_TAB);
45

    
46
                addKeyBinding("INSERT",OVERWRITE);
47
                addKeyBinding("C+\\",TOGGLE_RECT);
48

    
49
                addKeyBinding("HOME",HOME);
50
                addKeyBinding("END",END);
51
                addKeyBinding("S+HOME",SELECT_HOME);
52
                addKeyBinding("S+END",SELECT_END);
53
                addKeyBinding("C+HOME",DOCUMENT_HOME);
54
                addKeyBinding("C+END",DOCUMENT_END);
55
                addKeyBinding("CS+HOME",SELECT_DOC_HOME);
56
                addKeyBinding("CS+END",SELECT_DOC_END);
57

    
58
                addKeyBinding("PAGE_UP",PREV_PAGE);
59
                addKeyBinding("PAGE_DOWN",NEXT_PAGE);
60
                addKeyBinding("S+PAGE_UP",SELECT_PREV_PAGE);
61
                addKeyBinding("S+PAGE_DOWN",SELECT_NEXT_PAGE);
62

    
63
                addKeyBinding("LEFT",PREV_CHAR);
64
                addKeyBinding("S+LEFT",SELECT_PREV_CHAR);
65
                addKeyBinding("C+LEFT",PREV_WORD);
66
                addKeyBinding("CS+LEFT",SELECT_PREV_WORD);
67
                addKeyBinding("RIGHT",NEXT_CHAR);
68
                addKeyBinding("S+RIGHT",SELECT_NEXT_CHAR);
69
                addKeyBinding("C+RIGHT",NEXT_WORD);
70
                addKeyBinding("CS+RIGHT",SELECT_NEXT_WORD);
71
                addKeyBinding("UP",PREV_LINE);
72
                addKeyBinding("S+UP",SELECT_PREV_LINE);
73
                addKeyBinding("DOWN",NEXT_LINE);
74
                addKeyBinding("S+DOWN",SELECT_NEXT_LINE);
75

    
76
                addKeyBinding("C+ENTER",REPEAT);
77
        }
78

    
79
        /**
80
         * Adds a key binding to this input handler. The key binding is
81
         * a list of white space separated key strokes of the form
82
         * <i>[modifiers+]key</i> where modifier is C for Control, A for Alt,
83
         * or S for Shift, and key is either a character (a-z) or a field
84
         * name in the KeyEvent class prefixed with VK_ (e.g., BACK_SPACE)
85
         * @param keyBinding The key binding
86
         * @param action The action
87
         */
88
        public void addKeyBinding(String keyBinding, ActionListener action)
89
        {
90
                Hashtable current = bindings;
91

    
92
                StringTokenizer st = new StringTokenizer(keyBinding);
93
                while(st.hasMoreTokens())
94
                {
95
                        KeyStroke keyStroke = parseKeyStroke(st.nextToken());
96
                        if(keyStroke == null)
97
                                return;
98

    
99
                        if(st.hasMoreTokens())
100
                        {
101
                                Object o = current.get(keyStroke);
102
                                if(o instanceof Hashtable)
103
                                        current = (Hashtable)o;
104
                                else
105
                                {
106
                                        o = new Hashtable();
107
                                        current.put(keyStroke,o);
108
                                        current = (Hashtable)o;
109
                                }
110
                        }
111
                        else
112
                                current.put(keyStroke,action);
113
                }
114
        }
115

    
116
        /**
117
         * Removes a key binding from this input handler. This is not yet
118
         * implemented.
119
         * @param keyBinding The key binding
120
         */
121
        public void removeKeyBinding(String keyBinding)
122
        {
123
                throw new InternalError("Not yet implemented");
124
        }
125

    
126
        /**
127
         * Removes all key bindings from this input handler.
128
         */
129
        public void removeAllKeyBindings()
130
        {
131
                bindings.clear();
132
        }
133

    
134
        /**
135
         * Returns a copy of this input handler that shares the same
136
         * key bindings. Setting key bindings in the copy will also
137
         * set them in the original.
138
         */
139
        public InputHandler copy()
140
        {
141
                return new DefaultInputHandler(this);
142
        }
143

    
144
        /**
145
         * Handle a key pressed event. This will look up the binding for
146
         * the key stroke and execute it.
147
         */
148
        public void keyPressed(KeyEvent evt)
149
        {
150
                int keyCode = evt.getKeyCode();
151
                int modifiers = evt.getModifiers();
152

    
153
                if(keyCode == KeyEvent.VK_CONTROL ||
154
                        keyCode == KeyEvent.VK_SHIFT ||
155
                        keyCode == KeyEvent.VK_ALT ||
156
                        keyCode == KeyEvent.VK_META)
157
                        return;
158

    
159
                if((modifiers & ~KeyEvent.SHIFT_MASK) != 0
160
                        || evt.isActionKey()
161
                        || keyCode == KeyEvent.VK_BACK_SPACE
162
                        || keyCode == KeyEvent.VK_DELETE
163
                        || keyCode == KeyEvent.VK_ENTER
164
                        || keyCode == KeyEvent.VK_TAB
165
                        || keyCode == KeyEvent.VK_ESCAPE)
166
                {
167
                        if(grabAction != null)
168
                        {
169
                                handleGrabAction(evt);
170
                                return;
171
                        }
172

    
173
                        KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode,
174
                                modifiers);
175
                        Object o = currentBindings.get(keyStroke);
176
                        if(o == null)
177
                        {
178
                                // Don't beep if the user presses some
179
                                // key we don't know about unless a
180
                                // prefix is active. Otherwise it will
181
                                // beep when caps lock is pressed, etc.
182
                                if(currentBindings != bindings)
183
                                {
184
                                        Toolkit.getDefaultToolkit().beep();
185
                                        // F10 should be passed on, but C+e F10
186
                                        // shouldn't
187
                                        repeatCount = 0;
188
                                        repeat = false;
189
                                        evt.consume();
190
                                }
191
                                currentBindings = bindings;
192
                                return;
193
                        }
194
                        else if(o instanceof ActionListener)
195
                        {
196
                                currentBindings = bindings;
197

    
198
                                executeAction(((ActionListener)o),
199
                                        evt.getSource(),null);
200

    
201
                                evt.consume();
202
                                return;
203
                        }
204
                        else if(o instanceof Hashtable)
205
                        {
206
                                currentBindings = (Hashtable)o;
207
                                evt.consume();
208
                                return;
209
                        }
210
                }
211
        }
212

    
213
        /**
214
         * Handle a key typed event. This inserts the key into the text area.
215
         */
216
        public void keyTyped(KeyEvent evt)
217
        {
218
                int modifiers = evt.getModifiers();
219
                char c = evt.getKeyChar();
220
                if(c != KeyEvent.CHAR_UNDEFINED &&
221
                        (modifiers & KeyEvent.ALT_MASK) == 0)
222
                {
223
                        if(c >= 0x20 && c != 0x7f)
224
                        {
225
                                KeyStroke keyStroke = KeyStroke.getKeyStroke(
226
                                        Character.toUpperCase(c));
227
                                Object o = currentBindings.get(keyStroke);
228

    
229
                                if(o instanceof Hashtable)
230
                                {
231
                                        currentBindings = (Hashtable)o;
232
                                        return;
233
                                }
234
                                else if(o instanceof ActionListener)
235
                                {
236
                                        currentBindings = bindings;
237
                                        executeAction((ActionListener)o,
238
                                                evt.getSource(),
239
                                                String.valueOf(c));
240
                                        return;
241
                                }
242

    
243
                                currentBindings = bindings;
244

    
245
                                if(grabAction != null)
246
                                {
247
                                        handleGrabAction(evt);
248
                                        return;
249
                                }
250

    
251
                                // 0-9 adds another 'digit' to the repeat number
252
                                if(repeat && Character.isDigit(c))
253
                                {
254
                                        repeatCount *= 10;
255
                                        repeatCount += (c - '0');
256
                                        return;
257
                                }
258

    
259
                                executeAction(INSERT_CHAR,evt.getSource(),
260
                                        String.valueOf(evt.getKeyChar()));
261

    
262
                                repeatCount = 0;
263
                                repeat = false;
264
                        }
265
                }
266
        }
267

    
268
        /**
269
         * Converts a string to a keystroke. The string should be of the
270
         * form <i>modifiers</i>+<i>shortcut</i> where <i>modifiers</i>
271
         * is any combination of A for Alt, C for Control, S for Shift
272
         * or M for Meta, and <i>shortcut</i> is either a single character,
273
         * or a keycode name from the <code>KeyEvent</code> class, without
274
         * the <code>VK_</code> prefix.
275
         * @param keyStroke A string description of the key stroke
276
         */
277
        public static KeyStroke parseKeyStroke(String keyStroke)
278
        {
279
                if(keyStroke == null)
280
                        return null;
281
                int modifiers = 0;
282
                int index = keyStroke.indexOf('+');
283
                if(index != -1)
284
                {
285
                        for(int i = 0; i < index; i++)
286
                        {
287
                                switch(Character.toUpperCase(keyStroke
288
                                        .charAt(i)))
289
                                {
290
                                case 'A':
291
                                        modifiers |= InputEvent.ALT_MASK;
292
                                        break;
293
                                case 'C':
294
                                        modifiers |= InputEvent.CTRL_MASK;
295
                                        break;
296
                                case 'M':
297
                                        modifiers |= InputEvent.META_MASK;
298
                                        break;
299
                                case 'S':
300
                                        modifiers |= InputEvent.SHIFT_MASK;
301
                                        break;
302
                                }
303
                        }
304
                }
305
                String key = keyStroke.substring(index + 1);
306
                if(key.length() == 1)
307
                {
308
                        char ch = Character.toUpperCase(key.charAt(0));
309
                        if(modifiers == 0)
310
                                return KeyStroke.getKeyStroke(ch);
311
                        else
312
                                return KeyStroke.getKeyStroke(ch,modifiers);
313
                }
314
                else if(key.length() == 0)
315
                {
316
                        System.err.println("Invalid key stroke: " + keyStroke);
317
                        return null;
318
                }
319
                else
320
                {
321
                        int ch;
322

    
323
                        try
324
                        {
325
                                ch = KeyEvent.class.getField("VK_".concat(key))
326
                                        .getInt(null);
327
                        }
328
                        catch(Exception e)
329
                        {
330
                                System.err.println("Invalid key stroke: "
331
                                        + keyStroke);
332
                                return null;
333
                        }
334

    
335
                        return KeyStroke.getKeyStroke(ch,modifiers);
336
                }
337
        }
338

    
339
        // private members
340
        private Hashtable bindings;
341
        private Hashtable currentBindings;
342

    
343
        private DefaultInputHandler(DefaultInputHandler copy)
344
        {
345
                bindings = currentBindings = copy.bindings;
346
        }
347
}