/* * DefaultInputHandler.java - Default implementation of an input handler * Copyright (C) 1999 Slava Pestov * Modified by IsmAvatar <IsmAvatar@gmail.com> * * You may use and modify this package for any purpose. Redistribution is * permitted, in both source and binary form, provided that this notice * remains intact in all source distributions of this package. */ package org.lateralgm.jedit; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.util.Hashtable; import javax.swing.KeyStroke; /** * The default input handler. It maps sequences of keystrokes into actions and * inserts key typed events into the text area. * @author Slava Pestov */ public class DefaultInputHandler extends InputHandler { private Hashtable<KeyStroke,ActionListener> bindings; /** Creates a new input handler with no key bindings defined. */ public DefaultInputHandler() { bindings = new Hashtable<KeyStroke,ActionListener>(); } /** Sets up the default key bindings. */ public void addDefaultKeyBindings() { addKeyBinding("BACK_SPACE",BACKSPACE); addKeyBinding("C+BACK_SPACE",BACKSPACE_WORD); addKeyBinding("DELETE",DELETE); addKeyBinding("C+DELETE",DELETE_WORD); addKeyBinding("ENTER",INSERT_BREAK); addKeyBinding("TAB",INSERT_TAB); addKeyBinding("INSERT",OVERWRITE); addKeyBinding("C+\\",TOGGLE_RECT); addKeyBinding("HOME",HOME); addKeyBinding("END",END); addKeyBinding("S+HOME",SELECT_HOME); addKeyBinding("S+END",SELECT_END); addKeyBinding("C+HOME",DOCUMENT_HOME); addKeyBinding("C+END",DOCUMENT_END); addKeyBinding("CS+HOME",SELECT_DOC_HOME); addKeyBinding("CS+END",SELECT_DOC_END); addKeyBinding("C+A",SELECT_ALL); addKeyBinding("PAGE_UP",PREV_PAGE); addKeyBinding("PAGE_DOWN",NEXT_PAGE); addKeyBinding("S+PAGE_UP",SELECT_PREV_PAGE); addKeyBinding("S+PAGE_DOWN",SELECT_NEXT_PAGE); addKeyBinding("LEFT",PREV_CHAR); addKeyBinding("S+LEFT",SELECT_PREV_CHAR); addKeyBinding("C+LEFT",PREV_WORD); addKeyBinding("CS+LEFT",SELECT_PREV_WORD); addKeyBinding("RIGHT",NEXT_CHAR); addKeyBinding("S+RIGHT",SELECT_NEXT_CHAR); addKeyBinding("C+RIGHT",NEXT_WORD); addKeyBinding("CS+RIGHT",SELECT_NEXT_WORD); addKeyBinding("UP",PREV_LINE); addKeyBinding("S+UP",SELECT_PREV_LINE); addKeyBinding("DOWN",NEXT_LINE); addKeyBinding("S+DOWN",SELECT_NEXT_LINE); addKeyBinding("C+ENTER",REPEAT); addKeyBinding("C+C",COPY); addKeyBinding("C+V",PASTE); addKeyBinding("C+X",CUT); } /** * Adds a key binding to this input handler. The key binding is of the * form <i>[modifiers+]key</i> where modifier is C for Control, A for Alt, * S for Shift, and M for Meta, and key is either a character (a-z) or * a field name in the KeyEvent class prefixed with VK_ (e.g., BACK_SPACE) * @param keyBinding The key binding * @param action The action */ public void addKeyBinding(String keyBinding, ActionListener action) { KeyStroke keyStroke = parseKeyStroke(keyBinding); if (keyStroke == null) return; bindings.put(keyStroke,action); } /** * Removes a key binding from this input handler. * @param keyBinding The key binding */ public void removeKeyBinding(String keyBinding) { KeyStroke keyStroke = parseKeyStroke(keyBinding); if (keyStroke == null) return; bindings.remove(keyStroke); } /** Removes all key bindings from this input handler. */ public void removeAllKeyBindings() { bindings.clear(); } /** Handle a key pressed event. This looks up the binding for the key stroke and executes it. */ public void keyPressed(KeyEvent evt) { int keyCode = evt.getKeyCode(); int modifiers = evt.getModifiers(); if (keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_SHIFT || keyCode == KeyEvent.VK_ALT || keyCode == KeyEvent.VK_META) return; if ((modifiers & ~KeyEvent.SHIFT_MASK) != 0 || evt.isActionKey() || keyCode == KeyEvent.VK_BACK_SPACE || keyCode == KeyEvent.VK_DELETE || keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_ESCAPE) { if (grabAction != null) { handleGrabAction(evt); return; } KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode,modifiers); ActionListener o = bindings.get(keyStroke); if (o == null) return; executeAction(o,evt.getSource(),null); evt.consume(); } } /** Handle a key typed event. This inserts the key into the text area. */ public void keyTyped(KeyEvent evt) { int modifiers = evt.getModifiers(); char c = evt.getKeyChar(); if (c != KeyEvent.CHAR_UNDEFINED && (modifiers & (KeyEvent.ALT_MASK | KeyEvent.CTRL_MASK)) == 0) { if (c >= 0x20 && c != 0x7f) { KeyStroke keyStroke = KeyStroke.getKeyStroke(Character.toUpperCase(c)); ActionListener o = bindings.get(keyStroke); if (o != null) { executeAction(o,evt.getSource(),String.valueOf(c)); return; } if (grabAction != null) { handleGrabAction(evt); return; } // 0-9 adds another 'digit' to the repeat number if (repeat && Character.isDigit(c)) { repeatCount *= 10; repeatCount += (c - '0'); return; } executeAction(INSERT_CHAR,evt.getSource(),String.valueOf(evt.getKeyChar())); repeatCount = 0; repeat = false; } } } /** * Converts a string to a keystroke. The string should be of the * form <i>modifiers</i>+<i>shortcut</i> where <i>modifiers</i> * is any combination of A for Alt, C for Control, S for Shift * or M for Meta, and <i>shortcut</i> is either a single character, * or a keycode name from the <code>KeyEvent</code> class, without * the <code>VK_</code> prefix. * @param keyStroke A string description of the key stroke */ public static KeyStroke parseKeyStroke(String keyStroke) { if (keyStroke == null) return null; int modifiers = 0; int index = keyStroke.indexOf('+'); if (index != -1) { for (int i = 0; i < index; i++) { switch (Character.toUpperCase(keyStroke.charAt(i))) { case 'A': modifiers |= InputEvent.ALT_MASK; break; case 'C': modifiers |= InputEvent.CTRL_MASK; break; case 'M': modifiers |= InputEvent.META_MASK; break; case 'S': modifiers |= InputEvent.SHIFT_MASK; break; } } } String key = keyStroke.substring(index + 1); if (key.length() == 1) { char ch = Character.toUpperCase(key.charAt(0)); if (modifiers == 0) return KeyStroke.getKeyStroke(ch); return KeyStroke.getKeyStroke(ch,modifiers); } else if (key.length() == 0) { System.err.println("Invalid key stroke: " + keyStroke); return null; } else { int ch; try { ch = KeyEvent.class.getField("VK_".concat(key)).getInt(null); } catch (Exception e) { System.err.println("Invalid key stroke: " + keyStroke); return null; } return KeyStroke.getKeyStroke(ch,modifiers); } } }