/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.gui.tools.syntax;
/*
* 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.InputEvent;
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.AbstractAction;
import javax.swing.Action;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;
import com.rapidminer.gui.dialog.SearchDialog;
import com.rapidminer.gui.dialog.SearchableJEditTextArea;
import com.rapidminer.gui.tools.IconSize;
import com.rapidminer.tools.Tools;
/**
* An input handler converts the user's key strokes into concrete actions. It also takes care of
* macro recording and action repetition.
* <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, Ingo Mierswa
*/
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";
public static final ActionListener BACKSPACE = new Backspace();
public static final ActionListener BACKSPACE_WORD = new BackspaceWord();
public static final ActionListener DELETE = new Delete();
public static final ActionListener DELETE_WORD = new DeleteWord();
public static final ActionListener END = new End(false);
public static final ActionListener DOCUMENT_END = new DocumentEnd(false);
public static final ActionListener SELECT_END = new End(true);
public static final ActionListener SELECT_DOC_END = new DocumentEnd(true);
public static final ActionListener INSERT_BREAK = new InsertBreak();
public static final ActionListener INSERT_TAB = new InsertTab();
public static final ActionListener HOME = new Home(false);
public static final ActionListener DOCUMENT_HOME = new DocumentHome(false);
public static final ActionListener SELECT_HOME = new Home(true);
public static final ActionListener SELECT_DOC_HOME = new DocumentHome(true);
public static final ActionListener NEXT_CHAR = new NextChar(false);
public static final ActionListener NEXT_LINE = new NextLine(false);
public static final ActionListener NEXT_PAGE = new NextPage(false);
public static final ActionListener NEXT_WORD = new NextWord(false);
public static final ActionListener SELECT_NEXT_CHAR = new NextChar(true);
public static final ActionListener SELECT_NEXT_LINE = new NextLine(true);
public static final ActionListener SELECT_NEXT_PAGE = new NextPage(true);
public static final ActionListener SELECT_NEXT_WORD = new NextWord(true);
public static final ActionListener OVERWRITE = new Overwrite();
public static final ActionListener PREV_CHAR = new PrevChar(false);
public static final ActionListener PREV_LINE = new PrevLine(false);
public static final ActionListener PREV_PAGE = new PrevPage(false);
public static final ActionListener PREV_WORD = new PrevWord(false);
public static final ActionListener SELECT_PREV_CHAR = new PrevChar(true);
public static final ActionListener SELECT_PREV_LINE = new PrevLine(true);
public static final ActionListener SELECT_PREV_PAGE = new PrevPage(true);
public static final ActionListener SELECT_PREV_WORD = new PrevWord(true);
public static final ActionListener REPEAT = new Repeat();
public static final ActionListener TOGGLE_RECT = new ToggleRect();
// Default action
public static final ActionListener INSERT_CHAR = new insert_char();
// Clipboard
public static final Action CLIP_COPY = new ClipCopy();
public static final Action CLIP_PASTE = new ClipPaste();
public static final Action CLIP_CUT = new ClipCut();
public static final Action SELECT_ALL = new SelectAll();
public static final Action SEARCH_AND_REPLACE = new SearchAction(IconSize.SMALL);
private static Hashtable<String, ActionListener> actions;
static {
actions = new Hashtable<>();
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-copy", CLIP_COPY);
actions.put("clipboard-paste", CLIP_PASTE);
actions.put("clipboard-cut", CLIP_CUT);
actions.put("select-all", SELECT_ALL);
}
/**
* 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) {
Enumeration<String> enumeration = getActions();
while (enumeration.hasMoreElements()) {
String name = enumeration.nextElement();
ActionListener _listener = getAction(name);
if (_listener == listener) {
return name;
}
}
return null;
}
/**
* Returns an enumeration of all available actions.
*/
public static Enumeration<String> 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.
*/
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 <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 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 {
}
/**
* Macro recorder.
*/
public interface MacroRecorder {
void actionPerformed(ActionListener listener, String actionCommand);
}
public static class Backspace implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (!textArea.isEditable()) {
textArea.getToolkit().beep();
return;
}
if (textArea.getSelectionStart() != textArea.getSelectionEnd()) {
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 BackspaceWord implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int start = textArea.getSelectionStart();
if (start != textArea.getSelectionEnd()) {
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 = TextUtilities.findWordStart(lineText, caret, noWordSep);
}
try {
textArea.getDocument().remove(caret + lineStart, start - (caret + lineStart));
} catch (BadLocationException bl) {
bl.printStackTrace();
}
}
}
public static class Delete implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (!textArea.isEditable()) {
textArea.getToolkit().beep();
return;
}
if (textArea.getSelectionStart() != textArea.getSelectionEnd()) {
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 DeleteWord implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int start = textArea.getSelectionStart();
if (start != textArea.getSelectionEnd()) {
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 = TextUtilities.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;
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int lastOfLine = textArea.getLineEndOffset(textArea.getCaretLine()) - 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.getLineEndOffset(lastVisibleLine) - 1;
int lastDocument = textArea.getDocumentLength();
if (caret == lastDocument) {
textArea.getToolkit().beep();
return;
} else if (!Boolean.TRUE.equals(textArea.getClientProperty(SMART_HOME_END_PROPERTY))) {
caret = lastOfLine;
} 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 DocumentEnd implements ActionListener {
private boolean select;
public DocumentEnd(boolean select) {
this.select = select;
}
@Override
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;
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int firstLine = textArea.getFirstLine();
int firstOfLine = textArea.getLineStartOffset(textArea.getCaretLine());
int firstVisibleLine = firstLine == 0 ? 0 : firstLine + textArea.getElectricScroll();
int firstVisible = textArea.getLineStartOffset(firstVisibleLine);
if (caret == 0) {
textArea.getToolkit().beep();
return;
} else if (!Boolean.TRUE.equals(textArea.getClientProperty(SMART_HOME_END_PROPERTY))) {
caret = firstOfLine;
} 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 DocumentHome implements ActionListener {
private boolean select;
public DocumentHome(boolean select) {
this.select = select;
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (select) {
textArea.select(textArea.getMarkPosition(), 0);
} else {
textArea.setCaretPosition(0);
}
}
}
public static class InsertBreak implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (!textArea.isEditable()) {
textArea.getToolkit().beep();
return;
}
textArea.setSelectedText(Tools.getLineSeparator());
}
}
public static class InsertTab implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
if (!textArea.isEditable()) {
textArea.getToolkit().beep();
return;
}
textArea.overwriteSetSelectedText("\t");
}
}
public static class NextChar implements ActionListener {
private boolean select;
public NextChar(boolean select) {
this.select = select;
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
if (caret == textArea.getDocumentLength()) {
textArea.getToolkit().beep();
return;
}
if (select) {
textArea.select(textArea.getMarkPosition(), caret + 1);
} else {
textArea.setCaretPosition(caret + 1);
}
}
}
public static class NextLine implements ActionListener {
private boolean select;
public NextLine(boolean select) {
this.select = select;
}
@Override
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();
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 NextPage implements ActionListener {
private boolean select;
public NextPage(boolean select) {
this.select = select;
}
@Override
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();
firstLine += visibleLines;
if (firstLine + visibleLines >= lineCount - 1) {
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 NextWord implements ActionListener {
private boolean select;
public NextWord(boolean select) {
this.select = select;
}
@Override
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 = TextUtilities.findWordEnd(lineText, caret, noWordSep);
}
if (select) {
textArea.select(textArea.getMarkPosition(), lineStart + caret);
} else {
textArea.setCaretPosition(lineStart + caret);
}
}
}
public static class Overwrite implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
textArea.setOverwriteEnabled(!textArea.isOverwriteEnabled());
}
}
public static class PrevChar implements ActionListener {
private boolean select;
public PrevChar(boolean select) {
this.select = select;
}
@Override
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 {
textArea.setCaretPosition(caret - 1);
}
}
}
public static class PrevLine implements ActionListener {
private boolean select;
public PrevLine(boolean select) {
this.select = select;
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
if (line == 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 PrevPage implements ActionListener {
private boolean select;
public PrevPage(boolean select) {
this.select = select;
}
@Override
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 PrevWord implements ActionListener {
private boolean select;
public PrevWord(boolean select) {
this.select = select;
}
@Override
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 = TextUtilities.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 {
@Override
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 ToggleRect implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
textArea.setSelectionRectangular(!textArea.isSelectionRectangular());
}
}
public static class insert_char implements ActionListener, InputHandler.NonRepeatable {
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
String str = evt.getActionCommand();
int repeatCount = textArea.getInputHandler().getRepeatCount();
if (textArea.isEditable()) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < repeatCount; i++) {
buf.append(str);
}
textArea.overwriteSetSelectedText(buf.toString());
} else {
textArea.getToolkit().beep();
}
}
}
public static class ClipCopy extends AbstractAction {
private static final long serialVersionUID = 2942143617686299824L;
public ClipCopy() {
super("Copy");
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
textArea.copy();
}
}
public static class ClipPaste extends AbstractAction {
private static final long serialVersionUID = 1961399179178333327L;
public ClipPaste() {
super("Paste");
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
textArea.paste();
}
}
public static class ClipCut extends AbstractAction {
private static final long serialVersionUID = 8199702559544536825L;
public ClipCut() {
super("Cut");
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
textArea.cut();
}
}
public static class SelectAll extends AbstractAction {
private static final long serialVersionUID = -5706102409245450060L;
public SelectAll() {
super("Select All");
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK));
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
textArea.selectAll();
}
}
private static class SearchAction extends AbstractAction {
private static final long serialVersionUID = -8380073257252178693L;
private SearchAction(IconSize size) {
super("Search and Replace...");
putValue(SHORT_DESCRIPTION, "Searches and replaces text occurances.");
putValue(MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_F));
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK));
}
@Override
public void actionPerformed(ActionEvent evt) {
JEditTextArea textArea = getTextArea(evt);
new SearchDialog(textArea, new SearchableJEditTextArea(textArea), true).setVisible(true);
}
}
}