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