0001: /*
0002: * Copyright (C) 2005 - 2008 JasperSoft Corporation. All rights reserved.
0003: * http://www.jaspersoft.com.
0004: *
0005: * Unless you have purchased a commercial license agreement from JasperSoft,
0006: * the following license terms apply:
0007: *
0008: * This program is free software; you can redistribute it and/or modify
0009: * it under the terms of the GNU General Public License version 2 as published by
0010: * the Free Software Foundation.
0011: *
0012: * This program is distributed WITHOUT ANY WARRANTY; and without the
0013: * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0014: * See the GNU General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU General Public License
0017: * along with this program; if not, see http://www.gnu.org/licenses/gpl.txt
0018: * or write to:
0019: *
0020: * Free Software Foundation, Inc.,
0021: * 59 Temple Place - Suite 330,
0022: * Boston, MA USA 02111-1307
0023: *
0024: *
0025: *
0026: *
0027: * InputHandler.java
0028: *
0029: */
0030:
0031: package org.syntax.jedit;
0032:
0033: import javax.swing.text.*;
0034: import javax.swing.JPopupMenu;
0035: import java.awt.event.*;
0036: import java.awt.Component;
0037: import java.util.*;
0038:
0039: /**
0040: * An input handler converts the user's key strokes into concrete actions.
0041: * It also takes care of macro recording and action repetition.<p>
0042: *
0043: * This class provides all the necessary support code for an input
0044: * handler, but doesn't actually do any key binding logic. It is up
0045: * to the implementations of this class to do so.
0046: *
0047: * @author Slava Pestov
0048: * @version $Id: InputHandler.java 1167 2008-01-15 18:49:05Z gtoffoli $
0049: * @see org.syntax.jedit.DefaultInputHandler
0050: *
0051: * 08/12/2002 Clipboard actions (Oliver Henning)
0052: */
0053: public abstract class InputHandler extends KeyAdapter {
0054: /**
0055: * If this client property is set to Boolean.TRUE on the text area,
0056: * the home/end keys will support 'smart' BRIEF-like behaviour
0057: * (one press = start/end of line, two presses = start/end of
0058: * viewscreen, three presses = start/end of document). By default,
0059: * this property is not set.
0060: */
0061: public static final String SMART_HOME_END_PROPERTY = "InputHandler.homeEnd";
0062:
0063: public static final ActionListener BACKSPACE = new backspace();
0064: public static final ActionListener BACKSPACE_WORD = new backspace_word();
0065: public static final ActionListener DELETE = new delete();
0066: public static final ActionListener DELETE_WORD = new delete_word();
0067: public static final ActionListener END = new end(false);
0068: public static final ActionListener DOCUMENT_END = new document_end(
0069: false);
0070: public static final ActionListener SELECT_ALL = new select_all();
0071: public static final ActionListener SELECT_END = new end(true);
0072: public static final ActionListener SELECT_DOC_END = new document_end(
0073: true);
0074: public static final ActionListener INSERT_BREAK = new insert_break();
0075: public static final ActionListener INSERT_TAB = new insert_tab();
0076: public static final ActionListener HOME = new home(false);
0077: public static final ActionListener DOCUMENT_HOME = new document_home(
0078: false);
0079: public static final ActionListener SELECT_HOME = new home(true);
0080: public static final ActionListener SELECT_DOC_HOME = new document_home(
0081: true);
0082: public static final ActionListener NEXT_CHAR = new next_char(false);
0083: public static final ActionListener NEXT_LINE = new next_line(false);
0084: public static final ActionListener NEXT_PAGE = new next_page(false);
0085: public static final ActionListener NEXT_WORD = new next_word(false);
0086: public static final ActionListener SELECT_NEXT_CHAR = new next_char(
0087: true);
0088: public static final ActionListener SELECT_NEXT_LINE = new next_line(
0089: true);
0090: public static final ActionListener SELECT_NEXT_PAGE = new next_page(
0091: true);
0092: public static final ActionListener SELECT_NEXT_WORD = new next_word(
0093: true);
0094: public static final ActionListener OVERWRITE = new overwrite();
0095: public static final ActionListener PREV_CHAR = new prev_char(false);
0096: public static final ActionListener PREV_LINE = new prev_line(false);
0097: public static final ActionListener PREV_PAGE = new prev_page(false);
0098: public static final ActionListener PREV_WORD = new prev_word(false);
0099: public static final ActionListener SELECT_PREV_CHAR = new prev_char(
0100: true);
0101: public static final ActionListener SELECT_PREV_LINE = new prev_line(
0102: true);
0103: public static final ActionListener SELECT_PREV_PAGE = new prev_page(
0104: true);
0105: public static final ActionListener SELECT_PREV_WORD = new prev_word(
0106: true);
0107: public static final ActionListener REPEAT = new repeat();
0108: public static final ActionListener TOGGLE_RECT = new toggle_rect();
0109: // Clipboard
0110: public static final ActionListener CLIP_COPY = new clip_copy();
0111: public static final ActionListener CLIP_PASTE = new clip_paste();
0112: public static final ActionListener CLIP_CUT = new clip_cut();
0113: public static final ActionListener UNDO = new undo();
0114: public static final ActionListener REDO = new redo();
0115:
0116: // Default action
0117: public static final ActionListener INSERT_CHAR = new insert_char();
0118:
0119: private static Hashtable actions;
0120:
0121: static {
0122: actions = new Hashtable();
0123: actions.put("backspace", BACKSPACE);
0124: actions.put("backspace-word", BACKSPACE_WORD);
0125: actions.put("delete", DELETE);
0126: actions.put("delete-word", DELETE_WORD);
0127: actions.put("end", END);
0128: actions.put("select-all", SELECT_ALL);
0129: actions.put("select-end", SELECT_END);
0130: actions.put("document-end", DOCUMENT_END);
0131: actions.put("select-doc-end", SELECT_DOC_END);
0132: actions.put("insert-break", INSERT_BREAK);
0133: actions.put("insert-tab", INSERT_TAB);
0134: actions.put("home", HOME);
0135: actions.put("select-home", SELECT_HOME);
0136: actions.put("document-home", DOCUMENT_HOME);
0137: actions.put("select-doc-home", SELECT_DOC_HOME);
0138: actions.put("next-char", NEXT_CHAR);
0139: actions.put("next-line", NEXT_LINE);
0140: actions.put("next-page", NEXT_PAGE);
0141: actions.put("next-word", NEXT_WORD);
0142: actions.put("select-next-char", SELECT_NEXT_CHAR);
0143: actions.put("select-next-line", SELECT_NEXT_LINE);
0144: actions.put("select-next-page", SELECT_NEXT_PAGE);
0145: actions.put("select-next-word", SELECT_NEXT_WORD);
0146: actions.put("overwrite", OVERWRITE);
0147: actions.put("prev-char", PREV_CHAR);
0148: actions.put("prev-line", PREV_LINE);
0149: actions.put("prev-page", PREV_PAGE);
0150: actions.put("prev-word", PREV_WORD);
0151: actions.put("select-prev-char", SELECT_PREV_CHAR);
0152: actions.put("select-prev-line", SELECT_PREV_LINE);
0153: actions.put("select-prev-page", SELECT_PREV_PAGE);
0154: actions.put("select-prev-word", SELECT_PREV_WORD);
0155: actions.put("repeat", REPEAT);
0156: actions.put("toggle-rect", TOGGLE_RECT);
0157: actions.put("insert-char", INSERT_CHAR);
0158: actions.put("clipboard-copy", CLIP_COPY);
0159: actions.put("clipboard-paste", CLIP_PASTE);
0160: actions.put("clipboard-cut", CLIP_CUT);
0161: actions.put("undo", UNDO);
0162: actions.put("redo", REDO);
0163: }
0164:
0165: /**
0166: * Returns a named text area action.
0167: * @param name The action name
0168: */
0169: public static ActionListener getAction(String name) {
0170: return (ActionListener) actions.get(name);
0171: }
0172:
0173: /**
0174: * Returns the name of the specified text area action.
0175: * @param listener The action
0176: */
0177: public static String getActionName(ActionListener listener) {
0178: Enumeration e = getActions();
0179: while (e.hasMoreElements()) {
0180: String name = (String) e.nextElement();
0181: ActionListener _listener = getAction(name);
0182: if (_listener == listener)
0183: return name;
0184: }
0185: return null;
0186: }
0187:
0188: /**
0189: * Returns an enumeration of all available actions.
0190: */
0191: public static Enumeration getActions() {
0192: return actions.keys();
0193: }
0194:
0195: /**
0196: * Adds the default key bindings to this input handler.
0197: * This should not be called in the constructor of this
0198: * input handler, because applications might load the
0199: * key bindings from a file, etc.
0200: */
0201: public abstract void addDefaultKeyBindings();
0202:
0203: /**
0204: * Adds a key binding to this input handler.
0205: * @param keyBinding The key binding (the format of this is
0206: * input-handler specific)
0207: * @param action The action
0208: */
0209: public abstract void addKeyBinding(String keyBinding,
0210: ActionListener action);
0211:
0212: /**
0213: * Removes a key binding from this input handler.
0214: * @param keyBinding The key binding
0215: */
0216: public abstract void removeKeyBinding(String keyBinding);
0217:
0218: /**
0219: * Removes all key bindings from this input handler.
0220: */
0221: public abstract void removeAllKeyBindings();
0222:
0223: /**
0224: * Grabs the next key typed event and invokes the specified
0225: * action with the key as a the action command.
0226: * @param action The action
0227: */
0228: public void grabNextKeyStroke(ActionListener listener) {
0229: grabAction = listener;
0230: }
0231:
0232: /**
0233: * Returns if repeating is enabled. When repeating is enabled,
0234: * actions will be executed multiple times. This is usually
0235: * invoked with a special key stroke in the input handler.
0236: */
0237: public boolean isRepeatEnabled() {
0238: return repeat;
0239: }
0240:
0241: /**
0242: * Enables repeating. When repeating is enabled, actions will be
0243: * executed multiple times. Once repeating is enabled, the input
0244: * handler should read a number from the keyboard.
0245: */
0246: public void setRepeatEnabled(boolean repeat) {
0247: this .repeat = repeat;
0248: }
0249:
0250: /**
0251: * Returns the number of times the next action will be repeated.
0252: */
0253: public int getRepeatCount() {
0254: return (repeat ? Math.max(1, repeatCount) : 1);
0255: }
0256:
0257: /**
0258: * Sets the number of times the next action will be repeated.
0259: * @param repeatCount The repeat count
0260: */
0261: public void setRepeatCount(int repeatCount) {
0262: this .repeatCount = repeatCount;
0263: }
0264:
0265: /**
0266: * Returns the macro recorder. If this is non-null, all executed
0267: * actions should be forwarded to the recorder.
0268: */
0269: public InputHandler.MacroRecorder getMacroRecorder() {
0270: return recorder;
0271: }
0272:
0273: /**
0274: * Sets the macro recorder. If this is non-null, all executed
0275: * actions should be forwarded to the recorder.
0276: * @param recorder The macro recorder
0277: */
0278: public void setMacroRecorder(InputHandler.MacroRecorder recorder) {
0279: this .recorder = recorder;
0280: }
0281:
0282: /**
0283: * Returns a copy of this input handler that shares the same
0284: * key bindings. Setting key bindings in the copy will also
0285: * set them in the original.
0286: */
0287: public abstract InputHandler copy();
0288:
0289: /**
0290: * Executes the specified action, repeating and recording it as
0291: * necessary.
0292: * @param listener The action listener
0293: * @param source The event source
0294: * @param actionCommand The action command
0295: */
0296: public void executeAction(ActionListener listener, Object source,
0297: String actionCommand) {
0298: // create event
0299: ActionEvent evt = new ActionEvent(source,
0300: ActionEvent.ACTION_PERFORMED, actionCommand);
0301:
0302: // don't do anything if the action is a wrapper
0303: // (like EditAction.Wrapper)
0304: if (listener instanceof Wrapper) {
0305: listener.actionPerformed(evt);
0306: return;
0307: }
0308:
0309: // remember old values, in case action changes them
0310: boolean _repeat = repeat;
0311: int _repeatCount = getRepeatCount();
0312:
0313: // execute the action
0314: if (listener instanceof InputHandler.NonRepeatable)
0315: listener.actionPerformed(evt);
0316: else {
0317: for (int i = 0; i < Math.max(1, repeatCount); i++)
0318: listener.actionPerformed(evt);
0319: }
0320:
0321: // do recording. Notice that we do no recording whatsoever
0322: // for actions that grab keys
0323: if (grabAction == null) {
0324: if (recorder != null) {
0325: if (!(listener instanceof InputHandler.NonRecordable)) {
0326: if (_repeatCount != 1)
0327: recorder.actionPerformed(REPEAT, String
0328: .valueOf(_repeatCount));
0329:
0330: recorder.actionPerformed(listener, actionCommand);
0331: }
0332: }
0333:
0334: // If repeat was true originally, clear it
0335: // Otherwise it might have been set by the action, etc
0336: if (_repeat) {
0337: repeat = false;
0338: repeatCount = 0;
0339: }
0340: }
0341: }
0342:
0343: /**
0344: * Returns the text area that fired the specified event.
0345: * @param evt The event
0346: */
0347: public static JEditTextArea getTextArea(EventObject evt) {
0348: if (evt != null) {
0349: Object o = evt.getSource();
0350: if (o instanceof Component) {
0351: // find the parent text area
0352: Component c = (Component) o;
0353: for (;;) {
0354: if (c instanceof JEditTextArea)
0355: return (JEditTextArea) c;
0356: else if (c == null)
0357: break;
0358: if (c instanceof JPopupMenu)
0359: c = ((JPopupMenu) c).getInvoker();
0360: else
0361: c = c.getParent();
0362: }
0363: }
0364: }
0365:
0366: // this shouldn't happen
0367: System.err.println("BUG: getTextArea() returning null");
0368: System.err.println("Report this to Slava Pestov <sp@gjt.org>");
0369: return null;
0370: }
0371:
0372: // protected members
0373:
0374: /**
0375: * If a key is being grabbed, this method should be called with
0376: * the appropriate key event. It executes the grab action with
0377: * the typed character as the parameter.
0378: */
0379: protected void handleGrabAction(KeyEvent evt) {
0380: // Clear it *before* it is executed so that executeAction()
0381: // resets the repeat count
0382: ActionListener _grabAction = grabAction;
0383: grabAction = null;
0384: executeAction(_grabAction, evt.getSource(), String.valueOf(evt
0385: .getKeyChar()));
0386: }
0387:
0388: // protected members
0389: protected ActionListener grabAction;
0390: protected boolean repeat;
0391: protected int repeatCount;
0392: protected InputHandler.MacroRecorder recorder;
0393:
0394: /**
0395: * If an action implements this interface, it should not be repeated.
0396: * Instead, it will handle the repetition itself.
0397: */
0398: public interface NonRepeatable {
0399: }
0400:
0401: /**
0402: * If an action implements this interface, it should not be recorded
0403: * by the macro recorder. Instead, it will do its own recording.
0404: */
0405: public interface NonRecordable {
0406: }
0407:
0408: /**
0409: * For use by EditAction.Wrapper only.
0410: * @since jEdit 2.2final
0411: */
0412: public interface Wrapper {
0413: }
0414:
0415: /**
0416: * Macro recorder.
0417: */
0418: public interface MacroRecorder {
0419: void actionPerformed(ActionListener listener,
0420: String actionCommand);
0421: }
0422:
0423: public static class backspace implements ActionListener {
0424: public void actionPerformed(ActionEvent evt) {
0425: JEditTextArea textArea = getTextArea(evt);
0426:
0427: if (!textArea.isEditable()) {
0428: textArea.getToolkit().beep();
0429: return;
0430: }
0431:
0432: if (textArea.getSelectionStart() != textArea
0433: .getSelectionEnd()) {
0434: textArea.setSelectedText("");
0435: } else {
0436: int caret = textArea.getCaretPosition();
0437: if (caret == 0) {
0438: textArea.getToolkit().beep();
0439: return;
0440: }
0441: try {
0442: textArea.getDocument().remove(caret - 1, 1);
0443: } catch (BadLocationException bl) {
0444: bl.printStackTrace();
0445: }
0446: }
0447: }
0448: }
0449:
0450: public static class backspace_word implements ActionListener {
0451: public void actionPerformed(ActionEvent evt) {
0452: JEditTextArea textArea = getTextArea(evt);
0453: int start = textArea.getSelectionStart();
0454: if (start != textArea.getSelectionEnd()) {
0455: textArea.setSelectedText("");
0456: }
0457:
0458: int line = textArea.getCaretLine();
0459: int lineStart = textArea.getLineStartOffset(line);
0460: int caret = start - lineStart;
0461:
0462: String lineText = textArea.getLineText(textArea
0463: .getCaretLine());
0464:
0465: if (caret == 0) {
0466: if (lineStart == 0) {
0467: textArea.getToolkit().beep();
0468: return;
0469: }
0470: caret--;
0471: } else {
0472: String noWordSep = (String) textArea.getDocument()
0473: .getProperty("noWordSep");
0474: caret = TextUtilities.findWordStart(lineText, caret,
0475: noWordSep);
0476: }
0477:
0478: try {
0479: textArea.getDocument().remove(caret + lineStart,
0480: start - (caret + lineStart));
0481: } catch (BadLocationException bl) {
0482: bl.printStackTrace();
0483: }
0484: }
0485: }
0486:
0487: public static class delete implements ActionListener {
0488: public void actionPerformed(ActionEvent evt) {
0489: JEditTextArea textArea = getTextArea(evt);
0490:
0491: if (!textArea.isEditable()) {
0492: textArea.getToolkit().beep();
0493: return;
0494: }
0495:
0496: if (textArea.getSelectionStart() != textArea
0497: .getSelectionEnd()) {
0498: textArea.setSelectedText("");
0499: } else {
0500: int caret = textArea.getCaretPosition();
0501: if (caret == textArea.getDocumentLength()) {
0502: textArea.getToolkit().beep();
0503: return;
0504: }
0505: try {
0506: textArea.getDocument().remove(caret, 1);
0507: } catch (BadLocationException bl) {
0508: bl.printStackTrace();
0509: }
0510: }
0511: }
0512: }
0513:
0514: public static class delete_word implements ActionListener {
0515: public void actionPerformed(ActionEvent evt) {
0516: JEditTextArea textArea = getTextArea(evt);
0517: int start = textArea.getSelectionStart();
0518: if (start != textArea.getSelectionEnd()) {
0519: textArea.setSelectedText("");
0520: }
0521:
0522: int line = textArea.getCaretLine();
0523: int lineStart = textArea.getLineStartOffset(line);
0524: int caret = start - lineStart;
0525:
0526: String lineText = textArea.getLineText(textArea
0527: .getCaretLine());
0528:
0529: if (caret == lineText.length()) {
0530: if (lineStart + caret == textArea.getDocumentLength()) {
0531: textArea.getToolkit().beep();
0532: return;
0533: }
0534: caret++;
0535: } else {
0536: String noWordSep = (String) textArea.getDocument()
0537: .getProperty("noWordSep");
0538: caret = TextUtilities.findWordEnd(lineText, caret,
0539: noWordSep);
0540: }
0541:
0542: try {
0543: textArea.getDocument().remove(start,
0544: (caret + lineStart) - start);
0545: } catch (BadLocationException bl) {
0546: bl.printStackTrace();
0547: }
0548: }
0549: }
0550:
0551: public static class end implements ActionListener {
0552: private boolean select;
0553:
0554: public end(boolean select) {
0555: this .select = select;
0556: }
0557:
0558: public void actionPerformed(ActionEvent evt) {
0559: JEditTextArea textArea = getTextArea(evt);
0560:
0561: int caret = textArea.getCaretPosition();
0562:
0563: int lastOfLine = textArea.getLineEndOffset(textArea
0564: .getCaretLine()) - 1;
0565: int lastVisibleLine = textArea.getFirstLine()
0566: + textArea.getVisibleLines();
0567: if (lastVisibleLine >= textArea.getLineCount()) {
0568: lastVisibleLine = Math.min(textArea.getLineCount() - 1,
0569: lastVisibleLine);
0570: } else
0571: lastVisibleLine -= (textArea.getElectricScroll() + 1);
0572:
0573: int lastVisible = textArea
0574: .getLineEndOffset(lastVisibleLine) - 1;
0575: int lastDocument = textArea.getDocumentLength();
0576:
0577: if (caret == lastDocument) {
0578: textArea.getToolkit().beep();
0579: return;
0580: } else if (!Boolean.TRUE.equals(textArea
0581: .getClientProperty(SMART_HOME_END_PROPERTY)))
0582: caret = lastOfLine;
0583: else if (caret == lastVisible)
0584: caret = lastDocument;
0585: else if (caret == lastOfLine)
0586: caret = lastVisible;
0587: else
0588: caret = lastOfLine;
0589:
0590: if (select)
0591: textArea.select(textArea.getMarkPosition(), caret);
0592: else
0593: textArea.setCaretPosition(caret);
0594: }
0595: }
0596:
0597: public static class select_all implements ActionListener {
0598: public void actionPerformed(ActionEvent evt) {
0599: JEditTextArea textArea = getTextArea(evt);
0600: textArea.selectAll();
0601: }
0602: }
0603:
0604: public static class document_end implements ActionListener {
0605: private boolean select;
0606:
0607: public document_end(boolean select) {
0608: this .select = select;
0609: }
0610:
0611: public void actionPerformed(ActionEvent evt) {
0612: JEditTextArea textArea = getTextArea(evt);
0613: if (select)
0614: textArea.select(textArea.getMarkPosition(), textArea
0615: .getDocumentLength());
0616: else
0617: textArea.setCaretPosition(textArea.getDocumentLength());
0618: }
0619: }
0620:
0621: public static class home implements ActionListener {
0622: private boolean select;
0623:
0624: public home(boolean select) {
0625: this .select = select;
0626: }
0627:
0628: public void actionPerformed(ActionEvent evt) {
0629: JEditTextArea textArea = getTextArea(evt);
0630:
0631: int caret = textArea.getCaretPosition();
0632:
0633: int firstLine = textArea.getFirstLine();
0634:
0635: int firstOfLine = textArea.getLineStartOffset(textArea
0636: .getCaretLine());
0637: int firstVisibleLine = (firstLine == 0 ? 0 : firstLine
0638: + textArea.getElectricScroll());
0639: int firstVisible = textArea
0640: .getLineStartOffset(firstVisibleLine);
0641:
0642: if (caret == 0) {
0643: textArea.getToolkit().beep();
0644: return;
0645: } else if (!Boolean.TRUE.equals(textArea
0646: .getClientProperty(SMART_HOME_END_PROPERTY)))
0647: caret = firstOfLine;
0648: else if (caret == firstVisible)
0649: caret = 0;
0650: else if (caret == firstOfLine)
0651: caret = firstVisible;
0652: else
0653: caret = firstOfLine;
0654:
0655: if (select)
0656: textArea.select(textArea.getMarkPosition(), caret);
0657: else
0658: textArea.setCaretPosition(caret);
0659: }
0660: }
0661:
0662: public static class document_home implements ActionListener {
0663: private boolean select;
0664:
0665: public document_home(boolean select) {
0666: this .select = select;
0667: }
0668:
0669: public void actionPerformed(ActionEvent evt) {
0670: JEditTextArea textArea = getTextArea(evt);
0671: if (select)
0672: textArea.select(textArea.getMarkPosition(), 0);
0673: else
0674: textArea.setCaretPosition(0);
0675: }
0676: }
0677:
0678: public static class insert_break implements ActionListener {
0679: public void actionPerformed(ActionEvent evt) {
0680: JEditTextArea textArea = getTextArea(evt);
0681:
0682: if (!textArea.isEditable()) {
0683: textArea.getToolkit().beep();
0684: return;
0685: }
0686:
0687: textArea.setSelectedText("\n");
0688: }
0689: }
0690:
0691: public static class insert_tab implements ActionListener {
0692: public void actionPerformed(ActionEvent evt) {
0693: JEditTextArea textArea = getTextArea(evt);
0694:
0695: if (!textArea.isEditable()) {
0696: textArea.getToolkit().beep();
0697: return;
0698: }
0699:
0700: textArea.overwriteSetSelectedText("\t");
0701: }
0702: }
0703:
0704: public static class next_char implements ActionListener {
0705: private boolean select;
0706:
0707: public next_char(boolean select) {
0708: this .select = select;
0709: }
0710:
0711: public void actionPerformed(ActionEvent evt) {
0712: JEditTextArea textArea = getTextArea(evt);
0713: int caret = textArea.getCaretPosition();
0714: if (caret == textArea.getDocumentLength()) {
0715: textArea.getToolkit().beep();
0716: return;
0717: }
0718:
0719: if (select)
0720: textArea.select(textArea.getMarkPosition(), caret + 1);
0721: else
0722: textArea.setCaretPosition(caret + 1);
0723: }
0724: }
0725:
0726: public static class next_line implements ActionListener {
0727: private boolean select;
0728:
0729: public next_line(boolean select) {
0730: this .select = select;
0731: }
0732:
0733: public void actionPerformed(ActionEvent evt) {
0734: JEditTextArea textArea = getTextArea(evt);
0735: int caret = textArea.getCaretPosition();
0736: int line = textArea.getCaretLine();
0737:
0738: if (line == textArea.getLineCount() - 1) {
0739: textArea.getToolkit().beep();
0740: return;
0741: }
0742:
0743: int magic = textArea.getMagicCaretPosition();
0744: if (magic == -1) {
0745: magic = textArea.offsetToX(line, caret
0746: - textArea.getLineStartOffset(line));
0747: }
0748:
0749: caret = textArea.getLineStartOffset(line + 1)
0750: + textArea.xToOffset(line + 1, magic);
0751: if (select)
0752: textArea.select(textArea.getMarkPosition(), caret);
0753: else
0754: textArea.setCaretPosition(caret);
0755: textArea.setMagicCaretPosition(magic);
0756: }
0757: }
0758:
0759: public static class next_page implements ActionListener {
0760: private boolean select;
0761:
0762: public next_page(boolean select) {
0763: this .select = select;
0764: }
0765:
0766: public void actionPerformed(ActionEvent evt) {
0767: JEditTextArea textArea = getTextArea(evt);
0768: int lineCount = textArea.getLineCount();
0769: int firstLine = textArea.getFirstLine();
0770: int visibleLines = textArea.getVisibleLines();
0771: int line = textArea.getCaretLine();
0772:
0773: firstLine += visibleLines;
0774:
0775: if (firstLine + visibleLines >= lineCount - 1)
0776: firstLine = lineCount - visibleLines;
0777:
0778: textArea.setFirstLine(firstLine);
0779:
0780: int caret = textArea.getLineStartOffset(Math.min(textArea
0781: .getLineCount() - 1, line + visibleLines));
0782: if (select)
0783: textArea.select(textArea.getMarkPosition(), caret);
0784: else
0785: textArea.setCaretPosition(caret);
0786: }
0787: }
0788:
0789: public static class next_word implements ActionListener {
0790: private boolean select;
0791:
0792: public next_word(boolean select) {
0793: this .select = select;
0794: }
0795:
0796: public void actionPerformed(ActionEvent evt) {
0797: JEditTextArea textArea = getTextArea(evt);
0798: int caret = textArea.getCaretPosition();
0799: int line = textArea.getCaretLine();
0800: int lineStart = textArea.getLineStartOffset(line);
0801: caret -= lineStart;
0802:
0803: String lineText = textArea.getLineText(textArea
0804: .getCaretLine());
0805:
0806: if (caret == lineText.length()) {
0807: if (lineStart + caret == textArea.getDocumentLength()) {
0808: textArea.getToolkit().beep();
0809: return;
0810: }
0811: caret++;
0812: } else {
0813: String noWordSep = (String) textArea.getDocument()
0814: .getProperty("noWordSep");
0815: caret = TextUtilities.findWordEnd(lineText, caret,
0816: noWordSep);
0817: }
0818:
0819: if (select)
0820: textArea.select(textArea.getMarkPosition(), lineStart
0821: + caret);
0822: else
0823: textArea.setCaretPosition(lineStart + caret);
0824: }
0825: }
0826:
0827: public static class overwrite implements ActionListener {
0828: public void actionPerformed(ActionEvent evt) {
0829: JEditTextArea textArea = getTextArea(evt);
0830: textArea
0831: .setOverwriteEnabled(!textArea.isOverwriteEnabled());
0832: }
0833: }
0834:
0835: public static class prev_char implements ActionListener {
0836: private boolean select;
0837:
0838: public prev_char(boolean select) {
0839: this .select = select;
0840: }
0841:
0842: public void actionPerformed(ActionEvent evt) {
0843: JEditTextArea textArea = getTextArea(evt);
0844: int caret = textArea.getCaretPosition();
0845: if (caret == 0) {
0846: textArea.getToolkit().beep();
0847: return;
0848: }
0849:
0850: if (select)
0851: textArea.select(textArea.getMarkPosition(), caret - 1);
0852: else
0853: textArea.setCaretPosition(caret - 1);
0854: }
0855: }
0856:
0857: public static class prev_line implements ActionListener {
0858: private boolean select;
0859:
0860: public prev_line(boolean select) {
0861: this .select = select;
0862: }
0863:
0864: public void actionPerformed(ActionEvent evt) {
0865: JEditTextArea textArea = getTextArea(evt);
0866: int caret = textArea.getCaretPosition();
0867: int line = textArea.getCaretLine();
0868:
0869: if (line == 0) {
0870: textArea.getToolkit().beep();
0871: return;
0872: }
0873:
0874: int magic = textArea.getMagicCaretPosition();
0875: if (magic == -1) {
0876: magic = textArea.offsetToX(line, caret
0877: - textArea.getLineStartOffset(line));
0878: }
0879:
0880: caret = textArea.getLineStartOffset(line - 1)
0881: + textArea.xToOffset(line - 1, magic);
0882: if (select)
0883: textArea.select(textArea.getMarkPosition(), caret);
0884: else
0885: textArea.setCaretPosition(caret);
0886: textArea.setMagicCaretPosition(magic);
0887: }
0888: }
0889:
0890: public static class prev_page implements ActionListener {
0891: private boolean select;
0892:
0893: public prev_page(boolean select) {
0894: this .select = select;
0895: }
0896:
0897: public void actionPerformed(ActionEvent evt) {
0898: JEditTextArea textArea = getTextArea(evt);
0899: int firstLine = textArea.getFirstLine();
0900: int visibleLines = textArea.getVisibleLines();
0901: int line = textArea.getCaretLine();
0902:
0903: if (firstLine < visibleLines)
0904: firstLine = visibleLines;
0905:
0906: textArea.setFirstLine(firstLine - visibleLines);
0907:
0908: int caret = textArea.getLineStartOffset(Math.max(0, line
0909: - visibleLines));
0910: if (select)
0911: textArea.select(textArea.getMarkPosition(), caret);
0912: else
0913: textArea.setCaretPosition(caret);
0914: }
0915: }
0916:
0917: public static class prev_word implements ActionListener {
0918: private boolean select;
0919:
0920: public prev_word(boolean select) {
0921: this .select = select;
0922: }
0923:
0924: public void actionPerformed(ActionEvent evt) {
0925: JEditTextArea textArea = getTextArea(evt);
0926: int caret = textArea.getCaretPosition();
0927: int line = textArea.getCaretLine();
0928: int lineStart = textArea.getLineStartOffset(line);
0929: caret -= lineStart;
0930:
0931: String lineText = textArea.getLineText(textArea
0932: .getCaretLine());
0933:
0934: if (caret == 0) {
0935: if (lineStart == 0) {
0936: textArea.getToolkit().beep();
0937: return;
0938: }
0939: caret--;
0940: } else {
0941: String noWordSep = (String) textArea.getDocument()
0942: .getProperty("noWordSep");
0943: caret = TextUtilities.findWordStart(lineText, caret,
0944: noWordSep);
0945: }
0946:
0947: if (select)
0948: textArea.select(textArea.getMarkPosition(), lineStart
0949: + caret);
0950: else
0951: textArea.setCaretPosition(lineStart + caret);
0952: }
0953: }
0954:
0955: public static class repeat implements ActionListener,
0956: InputHandler.NonRecordable {
0957: public void actionPerformed(ActionEvent evt) {
0958: JEditTextArea textArea = getTextArea(evt);
0959: textArea.getInputHandler().setRepeatEnabled(true);
0960: String actionCommand = evt.getActionCommand();
0961: if (actionCommand != null) {
0962: textArea.getInputHandler().setRepeatCount(
0963: Integer.parseInt(actionCommand));
0964: }
0965: }
0966: }
0967:
0968: public static class toggle_rect implements ActionListener {
0969: public void actionPerformed(ActionEvent evt) {
0970: JEditTextArea textArea = getTextArea(evt);
0971: textArea.setSelectionRectangular(!textArea
0972: .isSelectionRectangular());
0973: }
0974: }
0975:
0976: public static class insert_char implements ActionListener,
0977: InputHandler.NonRepeatable {
0978: public void actionPerformed(ActionEvent evt) {
0979: JEditTextArea textArea = getTextArea(evt);
0980: String str = evt.getActionCommand();
0981: int repeatCount = textArea.getInputHandler()
0982: .getRepeatCount();
0983:
0984: if (textArea.isEditable()) {
0985: StringBuffer buf = new StringBuffer();
0986: for (int i = 0; i < repeatCount; i++)
0987: buf.append(str);
0988: textArea.overwriteSetSelectedText(buf.toString());
0989: } else {
0990: textArea.getToolkit().beep();
0991: }
0992: }
0993: }
0994:
0995: public static class clip_copy implements ActionListener {
0996: public void actionPerformed(ActionEvent evt) {
0997: JEditTextArea textArea = getTextArea(evt);
0998: textArea.copy();
0999: }
1000: }
1001:
1002: public static class clip_paste implements ActionListener {
1003: public void actionPerformed(ActionEvent evt) {
1004: JEditTextArea textArea = getTextArea(evt);
1005: textArea.paste();
1006: }
1007: }
1008:
1009: public static class clip_cut implements ActionListener {
1010: public void actionPerformed(ActionEvent evt) {
1011: JEditTextArea textArea = getTextArea(evt);
1012: textArea.cut();
1013: }
1014: }
1015:
1016: public static class undo implements ActionListener {
1017: public void actionPerformed(ActionEvent evt) {
1018: JEditTextArea textArea = getTextArea(evt);
1019: if (textArea.getDocument().getUM().canUndo()) {
1020: textArea.getDocument().getUM().undo();
1021: }
1022: }
1023: }
1024:
1025: public static class redo implements ActionListener {
1026: public void actionPerformed(ActionEvent evt) {
1027: JEditTextArea textArea = getTextArea(evt);
1028: if (textArea.getDocument().getUM().canRedo()) {
1029: textArea.getDocument().getUM().redo();
1030: }
1031: }
1032: }
1033: }
|