processing.app.syntax.InputHandler Maven / Gradle / Ivy
Show all versions of pde Show documentation
/*
* 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.
*/
package processing.app.syntax;
import javax.swing.text.*;
import javax.swing.JPopupMenu;
import processing.app.Preferences;
import processing.data.StringDict;
import java.awt.event.*;
import java.awt.Component;
import java.util.*;
/**
* An input handler converts the user's key strokes into concrete actions.
* It also takes care of macro recording and action repetition.
*
* 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$
*/
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.
*/
public static final String SMART_HOME_END_PROPERTY = "InputHandler.homeEnd";
/**
* If this PDE property is set to Boolean.TRUE, the home/end keys will
* go to the first/last non-whitespace character of the line. If already at
* the that character, the keypress will move the cursor to the actual
* start/end of the line.
*
* SMART_HOME_END_PROPERTY takes precedence over this property.
*/
public static final String CONTEXT_AWARE_HOME_END =
"editor.keys.home_and_end_travel_smart";
public static final ActionListener BACKSPACE = new backspace();
public static final ActionListener BACKSPACE_WORD = new backspace_word();
public static final ActionListener DELETE = new delete();
public static final ActionListener DELETE_WORD = new delete_word();
public static final ActionListener END = new end(false);
public static final ActionListener DOCUMENT_END = new document_end(false);
public static final ActionListener SELECT_END = new end(true);
public static final ActionListener SELECT_DOC_END = new document_end(true);
public static final ActionListener INSERT_BREAK = new insert_break();
public static final ActionListener INSERT_TAB = new insert_tab();
public static final ActionListener HOME = new home(false);
public static final ActionListener DOCUMENT_HOME = new document_home(false);
public static final ActionListener SELECT_HOME = new home(true);
public static final ActionListener SELECT_DOC_HOME = new document_home(true);
public static final ActionListener NEXT_CHAR = new next_char(false);
public static final ActionListener NEXT_LINE = new next_line(false);
public static final ActionListener NEXT_PAGE = new next_page(false);
public static final ActionListener NEXT_WORD = new next_word(false);
public static final ActionListener SELECT_NEXT_CHAR = new next_char(true);
public static final ActionListener SELECT_NEXT_LINE = new next_line(true);
public static final ActionListener SELECT_NEXT_PAGE = new next_page(true);
public static final ActionListener SELECT_NEXT_WORD = new next_word(true);
public static final ActionListener OVERWRITE = new overwrite();
public static final ActionListener PREV_CHAR = new prev_char(false);
public static final ActionListener PREV_LINE = new prev_line(false);
public static final ActionListener PREV_PAGE = new prev_page(false);
public static final ActionListener PREV_WORD = new prev_word(false);
public static final ActionListener SELECT_PREV_CHAR = new prev_char(true);
public static final ActionListener SELECT_PREV_LINE = new prev_line(true);
public static final ActionListener SELECT_PREV_PAGE = new prev_page(true);
public static final ActionListener SELECT_PREV_WORD = new prev_word(true);
public static final ActionListener REPEAT = new repeat();
public static final ActionListener TOGGLE_RECT = new toggle_rect();
public static final ActionListener CLIPBOARD_CUT = new clipboard_cut(); // [fry]
public static final ActionListener CLIPBOARD_COPY = new clipboard_copy();
public static final ActionListener CLIPBOARD_PASTE = new clipboard_paste();
// Default action
public static final ActionListener INSERT_CHAR = new insert_char();
private static Map actions;
private static final StringDict bracketsAndQuotesMap =
new StringDict(new String[][] {
{ "(", ")" }, { "{", "}" }, { "[", "]" }, { "\"", "\"" }, { "\'", "\'" }
});
static {
actions = new HashMap();
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);
actions.put("clipboard-cut",CLIPBOARD_CUT);
actions.put("clipboard-copy",CLIPBOARD_COPY);
actions.put("clipboard-paste",CLIPBOARD_PASTE);
}
/**
* Returns a named text area action.
* @param name The action name
*/
public static ActionListener getAction(String name) {
return actions.get(name);
}
/**
* Returns the name of the specified text area action.
* @param listener The action
*/
public static String getActionName(ActionListener listener) {
Set set = getActions();
for (String name : set) {
ActionListener _listener = getAction(name);
if (_listener == listener) {
return name;
}
}
return null;
}
/**
* Returns an enumeration of all available actions.
*/
public static Set getActions() {
return actions.keySet();
}
/**
* 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.
*/
public void grabNextKeyStroke(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 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.
*/
public void setRepeatEnabled(boolean repeat) {
this.repeat = repeat;
}
/**
* Returns the number of times the next action will be repeated.
*/
public 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
*/
public void setRepeatCount(int repeatCount) {
this.repeatCount = repeatCount;
}
/**
* Returns the macro recorder. If this is non-null, all executed
* actions should be forwarded to the recorder.
*/
public InputHandler.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 void setMacroRecorder(InputHandler.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
*/
public void executeAction(ActionListener listener, Object source,
String actionCommand) {
// create event
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
boolean _repeat = repeat;
int _repeatCount = getRepeatCount();
// execute the action
if (listener instanceof InputHandler.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 InputHandler.NonRecordable)) {
if (_repeatCount != 1) {
recorder.actionPerformed(REPEAT,String.valueOf(_repeatCount));
}
recorder.actionPerformed(listener,actionCommand);
}
}
// If repeat was true originally, clear it
// Otherwise it might have been set by the action, etc
if (_repeat) {
repeat = false;
repeatCount = 0;
}
}
}
/**
* Returns the text area that fired the specified event.
* @param evt The event
*/
public static JEditTextArea getTextArea(EventObject evt) {
if (evt != null) {
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 ");
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 void handleGrabAction(KeyEvent evt) {
// Clear it *before* it is executed so that executeAction()
// resets the repeat count
ActionListener _grabAction = grabAction;
grabAction = null;
executeAction(_grabAction,evt.getSource(),
String.valueOf(evt.getKeyChar()));
}
// protected members
protected ActionListener grabAction;
protected boolean repeat;
protected int repeatCount;
protected InputHandler.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 recorder. Instead, it will do its own recording.
*/
public interface NonRecordable { }
/**
* For use by EditAction.Wrapper only.
* @since jEdit 2.2final
*/
public interface Wrapper { }
public interface MacroRecorder {
void actionPerformed(ActionListener listener, String actionCommand);
}
static public class backspace implements ActionListener {
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (!textArea.isEditable()) {
textArea.getToolkit().beep();
return;
}
if (textArea.getSelectionStart() != textArea.getSelectionStop()) {
textArea.setSelectedText("");
} else {
int caret = textArea.getCaretPosition();
if (caret == 0) {
textArea.getToolkit().beep();
return;
}
try {
textArea.getDocument().remove(caret - 1,1);
} catch(BadLocationException bl) {
bl.printStackTrace();
}
}
}
}
public static class backspace_word implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int start = textArea.getSelectionStart();
if (start != textArea.getSelectionStop())
{
textArea.setSelectedText("");
}
int line = textArea.getCaretLine();
int lineStart = textArea.getLineStartOffset(line);
int caret = start - lineStart;
String lineText = textArea.getLineText(textArea
.getCaretLine());
if (caret == 0)
{
if (lineStart == 0)
{
textArea.getToolkit().beep();
return;
}
caret--;
}
else
{
String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
caret = findWordStart(lineText,caret,noWordSep);
}
try
{
textArea.getDocument().remove(
caret + lineStart,
start - (caret + lineStart));
}
catch(BadLocationException bl)
{
bl.printStackTrace();
}
}
}
public static class delete implements ActionListener {
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (!textArea.isEditable()) {
textArea.getToolkit().beep();
return;
}
if (textArea.getSelectionStart() != textArea.getSelectionStop()) {
textArea.setSelectedText("");
} else {
int caret = textArea.getCaretPosition();
if (caret == textArea.getDocumentLength()) {
textArea.getToolkit().beep();
return;
}
try {
textArea.getDocument().remove(caret,1);
} catch(BadLocationException bl) {
bl.printStackTrace();
}
}
}
}
public static class delete_word implements ActionListener {
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int start = textArea.getSelectionStart();
if (start != textArea.getSelectionStop()) {
textArea.setSelectedText("");
}
int line = textArea.getCaretLine();
int lineStart = textArea.getLineStartOffset(line);
int caret = start - lineStart;
String lineText =
textArea.getLineText(textArea.getCaretLine());
if (caret == lineText.length()) {
if (lineStart + caret == textArea.getDocumentLength()) {
textArea.getToolkit().beep();
return;
}
caret++;
} else {
String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
caret = findWordEnd(lineText,caret,noWordSep);
}
try {
textArea.getDocument().remove(start, (caret + lineStart) - start);
} catch(BadLocationException bl) {
bl.printStackTrace();
}
}
}
public static class end implements ActionListener {
private boolean select;
public end(boolean select) {
this.select = select;
}
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int caretLine = textArea.getCaretLine();
int lastOfLine = textArea.getLineStopOffset(caretLine) - 1;
int lastNonWhiteSpaceOfLine =
textArea.getLineStopNonWhiteSpaceOffset(caretLine) - 1;
int lastVisibleLine =
textArea.getFirstLine() + textArea.getVisibleLines();
if (lastVisibleLine >= textArea.getLineCount()) {
lastVisibleLine = Math.min(textArea.getLineCount() - 1,
lastVisibleLine);
} else {
lastVisibleLine -= (textArea.getElectricScroll() + 1);
}
int lastVisible = textArea.getLineStopOffset(lastVisibleLine) - 1;
int lastDocument = textArea.getDocumentLength();
if (caret == lastDocument &&
!Preferences.getBoolean(CONTEXT_AWARE_HOME_END)) {
textArea.getToolkit().beep();
return;
} else if (!Boolean.TRUE.equals(textArea.getClientProperty(SMART_HOME_END_PROPERTY))) {
if (!Preferences.getBoolean(CONTEXT_AWARE_HOME_END) || caret == lastNonWhiteSpaceOfLine) {
caret = lastOfLine;
} else {
caret = lastNonWhiteSpaceOfLine;
}
} else if (caret == lastVisible) {
caret = lastDocument;
} else if (caret == lastOfLine) {
caret = lastVisible;
} else {
caret = lastOfLine;
}
if (select) {
textArea.select(textArea.getMarkPosition(),caret);
} else {
textArea.setCaretPosition(caret);
}
}
}
public static class document_end implements ActionListener {
private boolean select;
public document_end(boolean select) {
this.select = select;
}
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (select) {
textArea.select(textArea.getMarkPosition(),
textArea.getDocumentLength());
} else {
textArea.setCaretPosition(textArea.getDocumentLength());
}
}
}
public static class home implements ActionListener {
private boolean select;
public home(boolean select) {
this.select = select;
}
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int firstLine = textArea.getFirstLine();
int caretLine = textArea.getCaretLine();
int firstOfLine = textArea.getLineStartOffset(caretLine);
int firstNonWhiteSpaceOfLine =
textArea.getLineStartNonWhiteSpaceOffset(caretLine);
int firstVisibleLine =
(firstLine == 0 ? 0 : firstLine + textArea.getElectricScroll());
int firstVisible = textArea.getLineStartOffset(firstVisibleLine);
if (caret == 0 && !Preferences.getBoolean(CONTEXT_AWARE_HOME_END)) {
textArea.getToolkit().beep();
return;
} else if (!Boolean.TRUE.equals(textArea.getClientProperty(SMART_HOME_END_PROPERTY))) {
if (!Preferences.getBoolean(CONTEXT_AWARE_HOME_END) || caret == firstNonWhiteSpaceOfLine) {
caret = firstOfLine;
} else {
caret = firstNonWhiteSpaceOfLine;
}
} else if (caret == firstVisible) {
caret = 0;
} else if (caret == firstOfLine) {
caret = firstVisible;
} else {
caret = firstOfLine;
}
if (select) {
textArea.select(textArea.getMarkPosition(),caret);
} else {
textArea.setCaretPosition(caret);
}
}
}
public static class document_home implements ActionListener {
private boolean select;
public document_home(boolean select) {
this.select = select;
}
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (select) {
textArea.select(textArea.getMarkPosition(),0);
} else {
textArea.setCaretPosition(0);
}
}
}
public static class insert_break implements ActionListener {
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (!textArea.isEditable())
{
textArea.getToolkit().beep();
return;
}
textArea.setSelectedText("\n");
}
}
public static class insert_tab implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
if (!textArea.isEditable())
{
textArea.getToolkit().beep();
return;
}
textArea.overwriteSetSelectedText("\t");
}
}
public static class next_char implements ActionListener
{
private boolean select;
public next_char(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
if (caret == textArea.getDocumentLength())
{
if (textArea.getSelectionStart() !=
textArea.getSelectionStop()) {
// just move to the end of the selection
textArea.select(caret, caret);
} else {
// beep at the user for being annoying
textArea.getToolkit().beep();
}
} else if (select) {
textArea.select(textArea.getMarkPosition(), caret+1);
} else {
int start = textArea.getSelectionStart();
int end = textArea.getSelectionStop();
if (start != end) {
textArea.select(end, end);
} else {
textArea.setCaretPosition(caret + 1);
}
}
}
}
public static class next_line implements ActionListener
{
private boolean select;
public next_line(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
if (line == textArea.getLineCount() - 1)
{
//textArea.getToolkit().beep();
int doc = textArea.getDocumentLength();
if (select) {
textArea.select(textArea.getMarkPosition(), doc);
} else {
textArea.setCaretPosition(doc);
}
return;
}
int magic = textArea.getMagicCaretPosition();
if (magic == -1)
{
magic = textArea.offsetToX(line,
caret - textArea.getLineStartOffset(line));
}
caret = textArea.getLineStartOffset(line + 1)
+ textArea.xToOffset(line + 1,magic);
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
textArea.setMagicCaretPosition(magic);
}
}
public static class next_page implements ActionListener
{
private boolean select;
public next_page(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int lineCount = textArea.getLineCount();
int firstLine = textArea.getFirstLine();
int visibleLines = textArea.getVisibleLines();
int line = textArea.getCaretLine();
// Can't page down if there's nothing to visit
// https://github.com/processing/processing/issues/2990
if (lineCount > visibleLines) {
firstLine += visibleLines; // page down
if (firstLine + visibleLines >= lineCount - 1) {
// back up to the latest line we can go to
firstLine = lineCount - visibleLines;
}
textArea.setFirstLine(firstLine);
int caret = textArea.getLineStartOffset(Math.min(textArea.getLineCount() - 1, line + visibleLines));
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
}
}
}
public static class next_word implements ActionListener
{
private boolean select;
public next_word(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
int lineStart = textArea.getLineStartOffset(line);
caret -= lineStart;
String lineText = textArea.getLineText(textArea
.getCaretLine());
if (caret == lineText.length())
{
if (lineStart + caret == textArea.getDocumentLength())
{
textArea.getToolkit().beep();
return;
}
caret++;
}
else
{
String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
caret = findWordEnd(lineText,caret,noWordSep);
}
if (select)
textArea.select(textArea.getMarkPosition(),
lineStart + caret);
else
textArea.setCaretPosition(lineStart + caret);
}
}
public static class overwrite implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
textArea.setOverwriteEnabled(
!textArea.isOverwriteEnabled());
}
}
public static class prev_char implements ActionListener
{
private boolean select;
public prev_char(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
if (caret == 0)
{
textArea.getToolkit().beep();
return;
}
if (select) {
textArea.select(textArea.getMarkPosition(), caret-1);
} else {
int start = textArea.getSelectionStart();
int end = textArea.getSelectionStop();
if (start != end) {
textArea.select(start, start);
} else {
textArea.setCaretPosition(caret - 1);
}
}
}
}
public static class prev_line implements ActionListener
{
private boolean select;
public prev_line(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
if (line == 0)
{
if (select) {
if (textArea.getSelectionStart() != 0) {
textArea.select(textArea.getMarkPosition(), 0);
}
} else {
textArea.setCaretPosition(0);
}
//textArea.getToolkit().beep();
return;
}
int magic = textArea.getMagicCaretPosition();
if (magic == -1)
{
magic = textArea.offsetToX(line,
caret - textArea.getLineStartOffset(line));
}
caret = textArea.getLineStartOffset(line - 1)
+ textArea.xToOffset(line - 1,magic);
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
textArea.setMagicCaretPosition(magic);
}
}
public static class prev_page implements ActionListener
{
private boolean select;
public prev_page(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int firstLine = textArea.getFirstLine();
int visibleLines = textArea.getVisibleLines();
int line = textArea.getCaretLine();
if (firstLine < visibleLines)
firstLine = visibleLines;
textArea.setFirstLine(firstLine - visibleLines);
int caret = textArea.getLineStartOffset(
Math.max(0,line - visibleLines));
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
}
}
public static class prev_word implements ActionListener
{
private boolean select;
public prev_word(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
int lineStart = textArea.getLineStartOffset(line);
caret -= lineStart;
String lineText = textArea.getLineText(textArea
.getCaretLine());
if (caret == 0)
{
if (lineStart == 0)
{
textArea.getToolkit().beep();
return;
}
caret--;
}
else
{
String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
caret = findWordStart(lineText,caret,noWordSep);
}
if (select)
textArea.select(textArea.getMarkPosition(),
lineStart + caret);
else
textArea.setCaretPosition(lineStart + caret);
}
}
public static class repeat implements ActionListener,
InputHandler.NonRecordable {
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
textArea.getInputHandler().setRepeatEnabled(true);
String actionCommand = evt.getActionCommand();
if (actionCommand != null) {
textArea.getInputHandler().setRepeatCount(Integer.parseInt(actionCommand));
}
}
}
public static class toggle_rect implements ActionListener {
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
textArea.setSelectionRectangular(!textArea.isSelectionRectangular());
}
}
public static class clipboard_cut implements ActionListener {
public void actionPerformed(ActionEvent evt) {
getTextArea(evt).cut();
}
}
public static class clipboard_copy implements ActionListener {
public void actionPerformed(ActionEvent evt) {
getTextArea(evt).copy();
}
}
public static class clipboard_paste implements ActionListener {
public void actionPerformed(ActionEvent evt) {
getTextArea(evt).paste();
}
}
public static class insert_char implements ActionListener,
InputHandler.NonRepeatable {
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
String str = evt.getActionCommand();
int repeatCount = textArea.getInputHandler().getRepeatCount();
if (textArea.isEditable()) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < repeatCount; i++)
sb.append(str);
if (Preferences.getBoolean("editor.completion.auto_close") &&
hasBracketsAndQuotes(str)) {
matchBracketsAndQuotes(str, evt, textArea, sb);
} else {
textArea.overwriteSetSelectedText(sb.toString());
}
} else {
textArea.getToolkit().beep();
}
}
private void matchBracketsAndQuotes(String str, ActionEvent evt,
JEditTextArea ta, StringBuilder sb) {
sb.append(bracketsAndQuotesMap.get(str));
ta.overwriteSetSelectedText(sb.toString());
InputHandler.PREV_CHAR.actionPerformed(evt);
}
private boolean hasBracketsAndQuotes(String str) {
for (String item : bracketsAndQuotesMap.keys()) {
if (str.equals(item)) {
return true;
}
}
return false;
}
}
/**
* Locates the start of the word at the specified position.
* Moved from TextUtilities.java [fry 121210].
* @param line The text
* @param pos The position
*/
public static int findWordStart(String line, int pos, String noWordSep) {
char ch = line.charAt(pos - 1);
if (noWordSep == null) {
noWordSep = "";
}
boolean selectNoLetter =
!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1;
int wordStart = 0;
for (int i = pos - 1; i >= 0; i--) {
ch = line.charAt(i);
if (selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
noWordSep.indexOf(ch) == -1)) {
wordStart = i + 1;
break;
}
}
return wordStart;
}
/**
* Locates the end of the word at the specified position.
* Moved from TextUtilities.java [fry 121210].
* @param line The text
* @param pos The position
*/
public static int findWordEnd(String line, int pos, String noWordSep) {
char ch = line.charAt(pos);
if (noWordSep == null) {
noWordSep = "";
}
boolean selectNoLetter =
!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1;
int wordEnd = line.length();
for (int i = pos; i < line.length(); i++) {
ch = line.charAt(i);
if (selectNoLetter ^
(!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1)) {
wordEnd = i;
break;
}
}
return wordEnd;
}
}