📄 inputhandler.java
字号:
package org.jfree.designer.text.jedit;
/*
* InputHandler.java - Manages key bindings and executes actions
* Copyright (C) 1999 Slava Pestov
*
* 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.
*/
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Enumeration;
import java.util.EventObject;
import java.util.Hashtable;
import javax.swing.JPopupMenu;
import javax.swing.text.BadLocationException;
/**
* An input handler converts the user's key strokes into concrete actions. It also takes
* care of macro recording and action repetition.<p>
* <p/>
* This class provides all the necessary support code for an input handler, but doesn't
* actually do any key binding logic. It is up to the implementations of this class to do
* so.
*
* @author Slava Pestov
* @version $Id: InputHandler.java,v 1.3 2004/04/20 18:54:42 taqua Exp $ //@see
* com.efs.transfix.gui.components.jEditTextArea.DefaultInputHandler
*/
public abstract class InputHandler
extends KeyAdapter
{
/**
* If this client property is set to Boolean.TRUE on the text area, the home/end keys
* will support 'smart' BRIEF-like behaviour (one press = start/end of line, two presses
* = start/end of viewscreen, three presses = start/end of document). By default, this
* property is not set.
*/
private static final String SMART_HOME_END_PROPERTY = "InputHandler.homeEnd";
protected static final ActionListener BACKSPACE = new BackspaceAction();
protected static final ActionListener BACKSPACE_WORD = new BackspaceWordAction();
protected static final ActionListener DELETE = new DeleteAction();
protected static final ActionListener DELETE_WORD = new DeleteWordAction();
protected static final ActionListener END = new EndAction(false);
protected static final ActionListener DOCUMENT_END = new DocumentEndAction(false);
protected static final ActionListener SELECT_END = new EndAction(true);
protected static final ActionListener SELECT_DOC_END = new DocumentEndAction(true);
protected static final ActionListener INSERT_BREAK = new InsertBreakAction();
protected static final ActionListener INSERT_TAB = new InsertTabAction();
protected static final ActionListener HOME = new HomeAction(false);
protected static final ActionListener DOCUMENT_HOME = new DocumentHomeAction(false);
protected static final ActionListener SELECT_HOME = new HomeAction(true);
protected static final ActionListener SELECT_DOC_HOME = new DocumentHomeAction(true);
protected static final ActionListener NEXT_CHAR = new NextCharAction(false);
protected static final ActionListener NEXT_LINE = new NextLineAction(false);
protected static final ActionListener NEXT_PAGE = new NextPageAction(false);
protected static final ActionListener NEXT_WORD = new NextWordAction(false);
protected static final ActionListener SELECT_NEXT_CHAR = new NextCharAction(true);
protected static final ActionListener SELECT_NEXT_LINE = new NextLineAction(true);
protected static final ActionListener SELECT_NEXT_PAGE = new NextPageAction(true);
protected static final ActionListener SELECT_NEXT_WORD = new NextWordAction(true);
protected static final ActionListener OVERWRITE = new OverwriteAction();
protected static final ActionListener PREV_CHAR = new PrevCharAction(false);
protected static final ActionListener PREV_LINE = new PrevLineAction(false);
protected static final ActionListener PREV_PAGE = new PrevPageAction(false);
protected static final ActionListener PREV_WORD = new PrevWordAction(false);
protected static final ActionListener SELECT_PREV_CHAR = new PrevCharAction(true);
protected static final ActionListener SELECT_PREV_LINE = new PrevLineAction(true);
protected static final ActionListener SELECT_PREV_PAGE = new PrevPageAction(true);
protected static final ActionListener SELECT_PREV_WORD = new PrevWordAction(true);
protected static final ActionListener REPEAT = new RepeatAction();
protected static final ActionListener TOGGLE_RECT = new ToogleRectAction();
//
protected static final ActionListener COPY = new CopyAction();
protected static final ActionListener PASTE = new PasteAction();
protected static final ActionListener CUT = new CutAction();
// Default action
protected static final ActionListener INSERT_CHAR = new InsertCharAction();
private static final Hashtable actions = new Hashtable();
static
{
actions.put("backspace", BACKSPACE);
actions.put("backspace-word", BACKSPACE_WORD);
actions.put("delete", DELETE);
actions.put("delete-word", DELETE_WORD);
actions.put("end", END);
actions.put("select-end", SELECT_END);
actions.put("document-end", DOCUMENT_END);
actions.put("select-doc-end", SELECT_DOC_END);
actions.put("insert-break", INSERT_BREAK);
actions.put("insert-tab", INSERT_TAB);
actions.put("home", HOME);
actions.put("select-home", SELECT_HOME);
actions.put("document-home", DOCUMENT_HOME);
actions.put("select-doc-home", SELECT_DOC_HOME);
actions.put("next-char", NEXT_CHAR);
actions.put("next-line", NEXT_LINE);
actions.put("next-page", NEXT_PAGE);
actions.put("next-word", NEXT_WORD);
actions.put("select-next-char", SELECT_NEXT_CHAR);
actions.put("select-next-line", SELECT_NEXT_LINE);
actions.put("select-next-page", SELECT_NEXT_PAGE);
actions.put("select-next-word", SELECT_NEXT_WORD);
actions.put("overwrite", OVERWRITE);
actions.put("prev-char", PREV_CHAR);
actions.put("prev-line", PREV_LINE);
actions.put("prev-page", PREV_PAGE);
actions.put("prev-word", PREV_WORD);
actions.put("select-prev-char", SELECT_PREV_CHAR);
actions.put("select-prev-line", SELECT_PREV_LINE);
actions.put("select-prev-page", SELECT_PREV_PAGE);
actions.put("select-prev-word", SELECT_PREV_WORD);
actions.put("repeat", REPEAT);
actions.put("toggle-rect", TOGGLE_RECT);
actions.put("insert-char", INSERT_CHAR);
}
/**
* Returns a named text area action.
*
* @param name The action name
*/
private static ActionListener getAction (final String name)
{
return (ActionListener) actions.get(name);
}
/**
* Returns the name of the specified text area action.
*
* @param listener The action
*/
public static String getActionName (final ActionListener listener)
{
final Enumeration enum = getActions();
while (enum.hasMoreElements())
{
final String name = (String) enum.nextElement();
final ActionListener localAction = getAction(name);
if (localAction == listener)
{
return name;
}
}
return null;
}
/**
* Returns an enumeration of all available actions.
*/
private static Enumeration getActions ()
{
return actions.keys();
}
/**
* Adds the default key bindings to this input handler. This should not be called in the
* constructor of this input handler, because applications might load the key bindings
* from a file, etc.
*/
public abstract void addDefaultKeyBindings ();
/**
* Adds a key binding to this input handler.
*
* @param keyBinding The key binding (the format of this is input-handler specific)
* @param action The action
*/
public abstract void addKeyBinding (String keyBinding, ActionListener action);
/**
* Removes a key binding from this input handler.
*
* @param keyBinding The key binding
*/
public abstract void removeKeyBinding (String keyBinding);
/**
* Removes all key bindings from this input handler.
*/
public abstract void removeAllKeyBindings ();
/**
* Grabs the next key typed event and invokes the specified action with the key as a the
* action command.
*
* @param listener The action
*/
public final void grabNextKeyStroke (final ActionListener listener)
{
grabAction = listener;
}
/**
* Returns if repeating is enabled. When repeating is enabled, actions will be executed
* multiple times. This is usually invoked with a special key stroke in the input
* handler.
*/
public final boolean isRepeatEnabled ()
{
return repeat;
}
/**
* Enables repeating. When repeating is enabled, actions will be executed multiple
* times. Once repeating is enabled, the input handler should read a number from the
* keyboard.
*/
private void setRepeatEnabled (final boolean repeat)
{
this.repeat = repeat;
}
/**
* Returns the number of times the next action will be repeated.
*/
public final int getRepeatCount ()
{
return (repeat ? Math.max(1, repeatCount) : 1);
}
/**
* Sets the number of times the next action will be repeated.
*
* @param repeatCount The repeat count
*/
private void setRepeatCount (final int repeatCount)
{
this.repeatCount = repeatCount;
}
/**
* Returns the macro recorder. If this is non-null, all executed actions should be
* forwarded to the recorder.
*/
public final MacroRecorder getMacroRecorder ()
{
return recorder;
}
/**
* Sets the macro recorder. If this is non-null, all executed actions should be
* forwarded to the recorder.
*
* @param recorder The macro recorder
*/
public final void setMacroRecorder (final MacroRecorder recorder)
{
this.recorder = recorder;
}
/**
* Returns a copy of this input handler that shares the same key bindings. Setting key
* bindings in the copy will also set them in the original.
*/
public abstract InputHandler copy ();
/**
* Executes the specified action, repeating and recording it as necessary.
*
* @param listener The action listener
* @param source The event source
* @param actionCommand The action command
*/
protected final void executeAction (final ActionListener listener, final Object source,
final String actionCommand)
{
// create event
final ActionEvent evt = new ActionEvent(source,
ActionEvent.ACTION_PERFORMED,
actionCommand);
// don't do anything if the action is a wrapper
// (like EditAction.Wrapper)
if (listener instanceof Wrapper)
{
listener.actionPerformed(evt);
return;
}
// remember old values, in case action changes them
final boolean oldRepeat = repeat;
final int oldRepeatCount = getRepeatCount();
// execute the action
if (listener instanceof NonRepeatable)
{
listener.actionPerformed(evt);
}
else
{
for (int i = 0; i < Math.max(1, repeatCount); i++)
{
listener.actionPerformed(evt);
}
}
// do recording. Notice that we do no recording whatsoever
// for actions that grab keys
if (grabAction == null)
{
if (recorder != null)
{
if (!(listener instanceof NonRecordable))
{
if (oldRepeatCount != 1)
{
recorder.actionPerformed(REPEAT, String.valueOf(oldRepeatCount));
}
recorder.actionPerformed(listener, actionCommand);
}
}
// If repeat was true originally, clear it
// Otherwise it might have been set by the action, etc
if (oldRepeat)
{
repeat = false;
repeatCount = 0;
}
}
}
/**
* Returns the text area that fired the specified event.
*
* @param evt The event
*/
private static JEditTextArea getTextArea (final EventObject evt)
{
if (evt != null)
{
final Object o = evt.getSource();
if (o instanceof Component)
{
// find the parent text area
Component c = (Component) o;
for (; ;)
{
if (c instanceof JEditTextArea)
{
return (JEditTextArea) c;
}
else if (c == null)
{
break;
}
if (c instanceof JPopupMenu)
{
c = ((JPopupMenu) c).getInvoker();
}
else
{
c = c.getParent();
}
}
}
}
// this shouldn't happen
System.err.println("BUG: getTextArea() returning null");
System.err.println("Report this to Slava Pestov <sp@gjt.org>");
return null;
}
// protected members
/**
* If a key is being grabbed, this method should be called with the appropriate key
* event. It executes the grab action with the typed character as the parameter.
*/
protected final void handleGrabAction (final KeyEvent evt)
{
// Clear it *before* it is executed so that executeAction()
// resets the repeat count
final ActionListener orgGrabAction = grabAction;
grabAction = null;
executeAction(orgGrabAction, evt.getSource(),
String.valueOf(evt.getKeyChar()));
}
// protected members
protected ActionListener grabAction;
protected boolean repeat;
protected int repeatCount;
private MacroRecorder recorder;
/**
* If an action implements this interface, it should not be repeated. Instead, it will
* handle the repetition itself.
*/
public interface NonRepeatable
{
}
/**
* If an action implements this interface, it should not be recorded by the macro
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -