Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.utils / src / main / java / org / gvsig / utils / console / jedit / DefaultInputHandler.java @ 40561

History | View | Annotate | Download (9.28 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.utils.console.jedit;
25
/*
26
 * DefaultInputHandler.java - Default implementation of an input handler
27
 * Copyright (C) 1999 Slava Pestov
28
 *
29
 * You may use and modify this package for any purpose. Redistribution is
30
 * permitted, in both source and binary form, provided that this notice
31
 * remains intact in all source distributions of this package.
32
 */
33

    
34
import java.awt.Toolkit;
35
import java.awt.event.ActionListener;
36
import java.awt.event.InputEvent;
37
import java.awt.event.KeyEvent;
38
import java.util.Hashtable;
39
import java.util.StringTokenizer;
40

    
41
import javax.swing.KeyStroke;
42

    
43
/**
44
 * The default input handler. It maps sequences of keystrokes into actions
45
 * and inserts key typed events into the text area.
46
 * @author Slava Pestov
47
 * @version $Id$
48
 */
49
public class DefaultInputHandler extends InputHandler
50
{
51
        /**
52
         * Creates a new input handler with no key bindings defined.
53
         */
54
        public DefaultInputHandler()
55
        {
56
                bindings = currentBindings = new Hashtable();
57
        }
58

    
59
        /**
60
         * Sets up the default key bindings.
61
         */
62
        public void addDefaultKeyBindings()
63
        {
64
                addKeyBinding("BACK_SPACE",BACKSPACE);
65
                addKeyBinding("C+BACK_SPACE",BACKSPACE_WORD);
66
                addKeyBinding("DELETE",DELETE);
67
                addKeyBinding("C+DELETE",DELETE_WORD);
68

    
69
                addKeyBinding("ENTER",INSERT_BREAK);
70
                addKeyBinding("TAB",INSERT_TAB);
71

    
72
                addKeyBinding("INSERT",OVERWRITE);
73
                addKeyBinding("C+\\",TOGGLE_RECT);
74

    
75
                addKeyBinding("HOME",HOME);
76
                addKeyBinding("END",END);
77
                addKeyBinding("S+HOME",SELECT_HOME);
78
                addKeyBinding("S+END",SELECT_END);
79
                addKeyBinding("C+HOME",DOCUMENT_HOME);
80
                addKeyBinding("C+END",DOCUMENT_END);
81
                addKeyBinding("CS+HOME",SELECT_DOC_HOME);
82
                addKeyBinding("CS+END",SELECT_DOC_END);
83

    
84
                addKeyBinding("PAGE_UP",PREV_PAGE);
85
                addKeyBinding("PAGE_DOWN",NEXT_PAGE);
86
                addKeyBinding("S+PAGE_UP",SELECT_PREV_PAGE);
87
                addKeyBinding("S+PAGE_DOWN",SELECT_NEXT_PAGE);
88

    
89
                addKeyBinding("LEFT",PREV_CHAR);
90
                addKeyBinding("S+LEFT",SELECT_PREV_CHAR);
91
                addKeyBinding("C+LEFT",PREV_WORD);
92
                addKeyBinding("CS+LEFT",SELECT_PREV_WORD);
93
                addKeyBinding("RIGHT",NEXT_CHAR);
94
                addKeyBinding("S+RIGHT",SELECT_NEXT_CHAR);
95
                addKeyBinding("C+RIGHT",NEXT_WORD);
96
                addKeyBinding("CS+RIGHT",SELECT_NEXT_WORD);
97
                addKeyBinding("UP",PREV_LINE);
98
                addKeyBinding("S+UP",SELECT_PREV_LINE);
99
                addKeyBinding("DOWN",NEXT_LINE);
100
                addKeyBinding("S+DOWN",SELECT_NEXT_LINE);
101

    
102
                addKeyBinding("C+ENTER",REPEAT);
103
        }
104

    
105
        /**
106
         * Adds a key binding to this input handler. The key binding is
107
         * a list of white space separated key strokes of the form
108
         * <i>[modifiers+]key</i> where modifier is C for Control, A for Alt,
109
         * or S for Shift, and key is either a character (a-z) or a field
110
         * name in the KeyEvent class prefixed with VK_ (e.g., BACK_SPACE)
111
         * @param keyBinding The key binding
112
         * @param action The action
113
         */
114
        public void addKeyBinding(String keyBinding, ActionListener action)
115
        {
116
                Hashtable current = bindings;
117

    
118
                StringTokenizer st = new StringTokenizer(keyBinding);
119
                while(st.hasMoreTokens())
120
                {
121
                        KeyStroke keyStroke = parseKeyStroke(st.nextToken());
122
                        if(keyStroke == null)
123
                                return;
124

    
125
                        if(st.hasMoreTokens())
126
                        {
127
                                Object o = current.get(keyStroke);
128
                                if(o instanceof Hashtable)
129
                                        current = (Hashtable)o;
130
                                else
131
                                {
132
                                        o = new Hashtable();
133
                                        current.put(keyStroke,o);
134
                                        current = (Hashtable)o;
135
                                }
136
                        }
137
                        else
138
                                current.put(keyStroke,action);
139
                }
140
        }
141

    
142
        /**
143
         * Removes a key binding from this input handler. This is not yet
144
         * implemented.
145
         * @param keyBinding The key binding
146
         */
147
        public void removeKeyBinding(String keyBinding)
148
        {
149
                throw new InternalError("Not yet implemented");
150
        }
151

    
152
        /**
153
         * Removes all key bindings from this input handler.
154
         */
155
        public void removeAllKeyBindings()
156
        {
157
                bindings.clear();
158
        }
159

    
160
        /**
161
         * Returns a copy of this input handler that shares the same
162
         * key bindings. Setting key bindings in the copy will also
163
         * set them in the original.
164
         */
165
        public InputHandler copy()
166
        {
167
                return new DefaultInputHandler(this);
168
        }
169

    
170
        /**
171
         * Handle a key pressed event. This will look up the binding for
172
         * the key stroke and execute it.
173
         */
174
        public void keyPressed(KeyEvent evt)
175
        {
176
                int keyCode = evt.getKeyCode();
177
                int modifiers = evt.getModifiers();
178

    
179
                if(keyCode == KeyEvent.VK_CONTROL ||
180
                        keyCode == KeyEvent.VK_SHIFT ||
181
                        keyCode == KeyEvent.VK_ALT ||
182
                        keyCode == KeyEvent.VK_META)
183
                        return;
184

    
185
                if((modifiers & ~KeyEvent.SHIFT_MASK) != 0
186
                        || evt.isActionKey()
187
                        || keyCode == KeyEvent.VK_BACK_SPACE
188
                        || keyCode == KeyEvent.VK_DELETE
189
                        || keyCode == KeyEvent.VK_ENTER
190
                        || keyCode == KeyEvent.VK_TAB
191
                        || keyCode == KeyEvent.VK_ESCAPE)
192
                {
193
                        if(grabAction != null)
194
                        {
195
                                handleGrabAction(evt);
196
                                return;
197
                        }
198

    
199
                        KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode,
200
                                modifiers);
201
                        Object o = currentBindings.get(keyStroke);
202
                        if(o == null)
203
                        {
204
                                // Don't beep if the user presses some
205
                                // key we don't know about unless a
206
                                // prefix is active. Otherwise it will
207
                                // beep when caps lock is pressed, etc.
208
                                if(currentBindings != bindings)
209
                                {
210
                                        Toolkit.getDefaultToolkit().beep();
211
                                        // F10 should be passed on, but C+e F10
212
                                        // shouldn't
213
                                        repeatCount = 0;
214
                                        repeat = false;
215
                                        evt.consume();
216
                                }
217
                                currentBindings = bindings;
218
                                return;
219
                        }
220
                        else if(o instanceof ActionListener)
221
                        {
222
                                currentBindings = bindings;
223

    
224
                                executeAction(((ActionListener)o),
225
                                        evt.getSource(),null);
226

    
227
                                evt.consume();
228
                                return;
229
                        }
230
                        else if(o instanceof Hashtable)
231
                        {
232
                                currentBindings = (Hashtable)o;
233
                                evt.consume();
234
                                return;
235
                        }
236
                }
237
        }
238

    
239
        /**
240
         * Handle a key typed event. This inserts the key into the text area.
241
         */
242
        public void keyTyped(KeyEvent evt)
243
        {
244
                int modifiers = evt.getModifiers();
245
                char c = evt.getKeyChar();
246
                if(c != KeyEvent.CHAR_UNDEFINED &&
247
                        (modifiers & KeyEvent.ALT_MASK) == 0)
248
                {
249
                        if(c >= 0x20 && c != 0x7f)
250
                        {
251
                                KeyStroke keyStroke = KeyStroke.getKeyStroke(
252
                                        Character.toUpperCase(c));
253
                                Object o = currentBindings.get(keyStroke);
254

    
255
                                if(o instanceof Hashtable)
256
                                {
257
                                        currentBindings = (Hashtable)o;
258
                                        return;
259
                                }
260
                                else if(o instanceof ActionListener)
261
                                {
262
                                        currentBindings = bindings;
263
                                        executeAction((ActionListener)o,
264
                                                evt.getSource(),
265
                                                String.valueOf(c));
266
                                        return;
267
                                }
268

    
269
                                currentBindings = bindings;
270

    
271
                                if(grabAction != null)
272
                                {
273
                                        handleGrabAction(evt);
274
                                        return;
275
                                }
276

    
277
                                // 0-9 adds another 'digit' to the repeat number
278
                                if(repeat && Character.isDigit(c))
279
                                {
280
                                        repeatCount *= 10;
281
                                        repeatCount += (c - '0');
282
                                        return;
283
                                }
284

    
285
                                executeAction(INSERT_CHAR,evt.getSource(),
286
                                        String.valueOf(evt.getKeyChar()));
287

    
288
                                repeatCount = 0;
289
                                repeat = false;
290
                        }
291
                }
292
        }
293

    
294
        /**
295
         * Converts a string to a keystroke. The string should be of the
296
         * form <i>modifiers</i>+<i>shortcut</i> where <i>modifiers</i>
297
         * is any combination of A for Alt, C for Control, S for Shift
298
         * or M for Meta, and <i>shortcut</i> is either a single character,
299
         * or a keycode name from the <code>KeyEvent</code> class, without
300
         * the <code>VK_</code> prefix.
301
         * @param keyStroke A string description of the key stroke
302
         */
303
        public static KeyStroke parseKeyStroke(String keyStroke)
304
        {
305
                if(keyStroke == null)
306
                        return null;
307
                int modifiers = 0;
308
                int index = keyStroke.indexOf('+');
309
                if(index != -1)
310
                {
311
                        for(int i = 0; i < index; i++)
312
                        {
313
                                switch(Character.toUpperCase(keyStroke
314
                                        .charAt(i)))
315
                                {
316
                                case 'A':
317
                                        modifiers |= InputEvent.ALT_MASK;
318
                                        break;
319
                                case 'C':
320
                                        modifiers |= InputEvent.CTRL_MASK;
321
                                        break;
322
                                case 'M':
323
                                        modifiers |= InputEvent.META_MASK;
324
                                        break;
325
                                case 'S':
326
                                        modifiers |= InputEvent.SHIFT_MASK;
327
                                        break;
328
                                }
329
                        }
330
                }
331
                String key = keyStroke.substring(index + 1);
332
                if(key.length() == 1)
333
                {
334
                        char ch = Character.toUpperCase(key.charAt(0));
335
                        if(modifiers == 0)
336
                                return KeyStroke.getKeyStroke(ch);
337
                        else
338
                                return KeyStroke.getKeyStroke(ch,modifiers);
339
                }
340
                else if(key.length() == 0)
341
                {
342
                        System.err.println("Invalid key stroke: " + keyStroke);
343
                        return null;
344
                }
345
                else
346
                {
347
                        int ch;
348

    
349
                        try
350
                        {
351
                                ch = KeyEvent.class.getField("VK_".concat(key))
352
                                        .getInt(null);
353
                        }
354
                        catch(Exception e)
355
                        {
356
                                System.err.println("Invalid key stroke: "
357
                                        + keyStroke);
358
                                return null;
359
                        }
360

    
361
                        return KeyStroke.getKeyStroke(ch,modifiers);
362
                }
363
        }
364

    
365
        // private members
366
        private Hashtable bindings;
367
        private Hashtable currentBindings;
368

    
369
        private DefaultInputHandler(DefaultInputHandler copy)
370
        {
371
                bindings = currentBindings = copy.bindings;
372
        }
373
}