001: package net.xoetrope.builder.editor.syntaxhighlight;
002:
003: /*
004: * InputHandler.java - Manages key bindings and executes actions
005: * Copyright (C) 1999 Slava Pestov
006: *
007: * You may use and modify this package for any purpose. Redistribution is
008: * permitted, in both source and binary form, provided that this notice
009: * remains intact in all source distributions of this package.
010: */
011:
012: import java.util.Enumeration;
013: import java.util.EventObject;
014: import java.util.Hashtable;
015:
016: import java.awt.Component;
017: import java.awt.event.ActionEvent;
018: import java.awt.event.ActionListener;
019: import java.awt.event.KeyAdapter;
020: import java.awt.event.KeyEvent;
021: import javax.swing.JPopupMenu;
022: import javax.swing.text.BadLocationException;
023:
024: /**
025: * An input handler converts the user's key strokes into concrete actions.
026: * It also takes care of macro recording and action repetition.<p>
027: *
028: * This class provides all the necessary support code for an input
029: * handler, but doesn't actually do any key binding logic. It is up
030: * to the implementations of this class to do so.
031: *
032: * @author Slava Pestov
033: * @version $Id: InputHandler.java,v 1.22 2005/01/05 17:20:48 luano Exp $
034: * @see net.xoetrope.builder.editor.syntaxhighlight.DefaultInputHandler
035: */
036: public abstract class InputHandler extends KeyAdapter {
037: /**
038: * If this client property is set to Boolean.TRUE on the text area,
039: * the home/end keys will support 'smart' BRIEF-like behaviour
040: * (one press = start/end of line, two presses = start/end of
041: * viewscreen, three presses = start/end of document). By default,
042: * this property is not set.
043: */
044: public static final String SMART_HOME_END_PROPERTY = "InputHandler.homeEnd";
045:
046: public static final ActionListener BACKSPACE = new backspace();
047: public static final ActionListener BACKSPACE_WORD = new backspace_word();
048: public static final ActionListener DELETE = new delete();
049: public static final ActionListener DELETE_WORD = new delete_word();
050: public static final ActionListener END = new end(false);
051: public static final ActionListener DOCUMENT_END = new document_end(
052: false);
053: public static final ActionListener SELECT_END = new end(true);
054: public static final ActionListener SELECT_DOC_END = new document_end(
055: true);
056: public static final ActionListener INSERT_BREAK = new insert_break();
057: public static final ActionListener INSERT_TAB = new insert_tab();
058: public static final ActionListener HOME = new home(false);
059: public static final ActionListener DOCUMENT_HOME = new document_home(
060: false);
061: public static final ActionListener SELECT_HOME = new home(true);
062: public static final ActionListener SELECT_DOC_HOME = new document_home(
063: true);
064: public static final ActionListener NEXT_CHAR = new next_char(false);
065: public static final ActionListener NEXT_LINE = new next_line(false);
066: public static final ActionListener NEXT_PAGE = new next_page(false);
067: public static final ActionListener NEXT_WORD = new next_word(false);
068: public static final ActionListener SELECT_NEXT_CHAR = new next_char(
069: true);
070: public static final ActionListener SELECT_NEXT_LINE = new next_line(
071: true);
072: public static final ActionListener SELECT_NEXT_PAGE = new next_page(
073: true);
074: public static final ActionListener SELECT_NEXT_WORD = new next_word(
075: true);
076: public static final ActionListener OVERWRITE = new overwrite();
077: public static final ActionListener PREV_CHAR = new prev_char(false);
078: public static final ActionListener PREV_LINE = new prev_line(false);
079: public static final ActionListener PREV_PAGE = new prev_page(false);
080: public static final ActionListener PREV_WORD = new prev_word(false);
081: public static final ActionListener SELECT_PREV_CHAR = new prev_char(
082: true);
083: public static final ActionListener SELECT_PREV_LINE = new prev_line(
084: true);
085: public static final ActionListener SELECT_PREV_PAGE = new prev_page(
086: true);
087: public static final ActionListener SELECT_PREV_WORD = new prev_word(
088: true);
089: public static final ActionListener REPEAT = new repeat();
090: public static final ActionListener TOGGLE_RECT = new toggle_rect();
091:
092: // Default action
093: public static final ActionListener INSERT_CHAR = new insert_char();
094:
095: private static Hashtable actions;
096:
097: static {
098: actions = new Hashtable();
099: actions.put("backspace", BACKSPACE);
100: actions.put("backspace-word", BACKSPACE_WORD);
101: actions.put("delete", DELETE);
102: actions.put("delete-word", DELETE_WORD);
103: actions.put("end", END);
104: actions.put("select-end", SELECT_END);
105: actions.put("document-end", DOCUMENT_END);
106: actions.put("select-doc-end", SELECT_DOC_END);
107: actions.put("insert-break", INSERT_BREAK);
108: actions.put("insert-tab", INSERT_TAB);
109: actions.put("home", HOME);
110: actions.put("select-home", SELECT_HOME);
111: actions.put("document-home", DOCUMENT_HOME);
112: actions.put("select-doc-home", SELECT_DOC_HOME);
113: actions.put("next-char", NEXT_CHAR);
114: actions.put("next-line", NEXT_LINE);
115: actions.put("next-page", NEXT_PAGE);
116: actions.put("next-word", NEXT_WORD);
117: actions.put("select-next-char", SELECT_NEXT_CHAR);
118: actions.put("select-next-line", SELECT_NEXT_LINE);
119: actions.put("select-next-page", SELECT_NEXT_PAGE);
120: actions.put("select-next-word", SELECT_NEXT_WORD);
121: actions.put("overwrite", OVERWRITE);
122: actions.put("prev-char", PREV_CHAR);
123: actions.put("prev-line", PREV_LINE);
124: actions.put("prev-page", PREV_PAGE);
125: actions.put("prev-word", PREV_WORD);
126: actions.put("select-prev-char", SELECT_PREV_CHAR);
127: actions.put("select-prev-line", SELECT_PREV_LINE);
128: actions.put("select-prev-page", SELECT_PREV_PAGE);
129: actions.put("select-prev-word", SELECT_PREV_WORD);
130: actions.put("repeat", REPEAT);
131: actions.put("toggle-rect", TOGGLE_RECT);
132: actions.put("insert-char", INSERT_CHAR);
133: }
134:
135: /**
136: * Returns a named text area action.
137: * @param name The action name
138: */
139: public static ActionListener getAction(String name) {
140: return (ActionListener) actions.get(name);
141: }
142:
143: /**
144: * Returns the name of the specified text area action.
145: * @param listener The action
146: */
147: public static String getActionName(ActionListener listener)
148: {
149: Enumeration enum = getActions();
150: while(enum.hasMoreElements())
151: {
152: String name = (String)enum.nextElement();
153: ActionListener _listener = getAction(name);
154: if(_listener == listener)
155: return name;
156: }
157: return null;
158: }
159:
160: /**
161: * Returns an enumeration of all available actions.
162: */
163: public static Enumeration getActions() {
164: return actions.keys();
165: }
166:
167: /**
168: * Adds the default key bindings to this input handler.
169: * This should not be called in the constructor of this
170: * input handler, because applications might load the
171: * key bindings from a file, etc.
172: */
173: public abstract void addDefaultKeyBindings();
174:
175: /**
176: * Adds a key binding to this input handler.
177: * @param keyBinding The key binding (the format of this is
178: * input-handler specific)
179: * @param action The action
180: */
181: public abstract void addKeyBinding(String keyBinding,
182: ActionListener action);
183:
184: /**
185: * Removes a key binding from this input handler.
186: * @param keyBinding The key binding
187: */
188: public abstract void removeKeyBinding(String keyBinding);
189:
190: /**
191: * Removes all key bindings from this input handler.
192: */
193: public abstract void removeAllKeyBindings();
194:
195: /**
196: * Grabs the next key typed event and invokes the specified
197: * action with the key as a the action command.
198: * @param action The action
199: */
200: public void grabNextKeyStroke(ActionListener listener) {
201: grabAction = listener;
202: }
203:
204: /**
205: * Returns if repeating is enabled. When repeating is enabled,
206: * actions will be executed multiple times. This is usually
207: * invoked with a special key stroke in the input handler.
208: */
209: public boolean isRepeatEnabled() {
210: return repeat;
211: }
212:
213: /**
214: * Enables repeating. When repeating is enabled, actions will be
215: * executed multiple times. Once repeating is enabled, the input
216: * handler should read a number from the keyboard.
217: */
218: public void setRepeatEnabled(boolean repeat) {
219: this .repeat = repeat;
220: }
221:
222: /**
223: * Returns the number of times the next action will be repeated.
224: */
225: public int getRepeatCount() {
226: return (repeat ? Math.max(1, repeatCount) : 1);
227: }
228:
229: /**
230: * Sets the number of times the next action will be repeated.
231: * @param repeatCount The repeat count
232: */
233: public void setRepeatCount(int repeatCount) {
234: this .repeatCount = repeatCount;
235: }
236:
237: /**
238: * Returns the macro recorder. If this is non-null, all executed
239: * actions should be forwarded to the recorder.
240: */
241: public InputHandler.MacroRecorder getMacroRecorder() {
242: return recorder;
243: }
244:
245: /**
246: * Sets the macro recorder. If this is non-null, all executed
247: * actions should be forwarded to the recorder.
248: * @param recorder The macro recorder
249: */
250: public void setMacroRecorder(InputHandler.MacroRecorder recorder) {
251: this .recorder = recorder;
252: }
253:
254: /**
255: * Returns a copy of this input handler that shares the same
256: * key bindings. Setting key bindings in the copy will also
257: * set them in the original.
258: */
259: public abstract InputHandler copy();
260:
261: /**
262: * Executes the specified action, repeating and recording it as
263: * necessary.
264: * @param listener The action listener
265: * @param source The event source
266: * @param actionCommand The action command
267: */
268: public void executeAction(ActionListener listener, Object source,
269: String actionCommand) {
270: // create event
271: ActionEvent evt = new ActionEvent(source,
272: ActionEvent.ACTION_PERFORMED, actionCommand);
273:
274: // don't do anything if the action is a wrapper
275: // (like EditAction.Wrapper)
276: if (listener instanceof Wrapper) {
277: listener.actionPerformed(evt);
278: return;
279: }
280:
281: // remember old values, in case action changes them
282: boolean _repeat = repeat;
283: int _repeatCount = getRepeatCount();
284:
285: // execute the action
286: if (listener instanceof InputHandler.NonRepeatable)
287: listener.actionPerformed(evt);
288: else {
289: for (int i = 0; i < Math.max(1, repeatCount); i++)
290: listener.actionPerformed(evt);
291: }
292:
293: // do recording. Notice that we do no recording whatsoever
294: // for actions that grab keys
295: if (grabAction == null) {
296: if (recorder != null) {
297: if (!(listener instanceof InputHandler.NonRecordable)) {
298: if (_repeatCount != 1)
299: recorder.actionPerformed(REPEAT, String
300: .valueOf(_repeatCount));
301:
302: recorder.actionPerformed(listener, actionCommand);
303: }
304: }
305:
306: // If repeat was true originally, clear it
307: // Otherwise it might have been set by the action, etc
308: if (_repeat) {
309: repeat = false;
310: repeatCount = 0;
311: }
312: }
313: }
314:
315: /**
316: * Returns the text area that fired the specified event.
317: * @param evt The event
318: */
319: public static JEditTextArea getTextArea(EventObject evt) {
320: if (evt != null) {
321: Object o = evt.getSource();
322: if (o instanceof Component) {
323: // find the parent text area
324: Component c = (Component) o;
325: for (;;) {
326: if (c instanceof JEditTextArea)
327: return (JEditTextArea) c;
328: else if (c == null)
329: break;
330: if (c instanceof JPopupMenu)
331: c = ((JPopupMenu) c).getInvoker();
332: else
333: c = c.getParent();
334: }
335: }
336: }
337:
338: // this shouldn't happen
339: System.err.println("BUG: getTextArea() returning null");
340: System.err.println("Report this to Slava Pestov <sp@gjt.org>");
341: return null;
342: }
343:
344: // protected members
345:
346: /**
347: * If a key is being grabbed, this method should be called with
348: * the appropriate key event. It executes the grab action with
349: * the typed character as the parameter.
350: */
351: protected void handleGrabAction(KeyEvent evt) {
352: // Clear it *before* it is executed so that executeAction()
353: // resets the repeat count
354: ActionListener _grabAction = grabAction;
355: grabAction = null;
356: executeAction(_grabAction, evt.getSource(), String.valueOf(evt
357: .getKeyChar()));
358: }
359:
360: // protected members
361: protected ActionListener grabAction;
362: protected boolean repeat;
363: protected int repeatCount;
364: protected InputHandler.MacroRecorder recorder;
365:
366: /**
367: * If an action implements this interface, it should not be repeated.
368: * Instead, it will handle the repetition itself.
369: */
370: public interface NonRepeatable {
371: }
372:
373: /**
374: * If an action implements this interface, it should not be recorded
375: * by the macro recorder. Instead, it will do its own recording.
376: */
377: public interface NonRecordable {
378: }
379:
380: /**
381: * For use by EditAction.Wrapper only.
382: * @since jEdit 2.2final
383: */
384: public interface Wrapper {
385: }
386:
387: /**
388: * Macro recorder.
389: */
390: public interface MacroRecorder {
391: void actionPerformed(ActionListener listener,
392: String actionCommand);
393: }
394:
395: public static class backspace implements ActionListener {
396: public void actionPerformed(ActionEvent evt) {
397: JEditTextArea textArea = getTextArea(evt);
398:
399: if (!textArea.isEditable()) {
400: textArea.getToolkit().beep();
401: return;
402: }
403:
404: if (textArea.getSelectionStart() != textArea
405: .getSelectionEnd()) {
406: textArea.setSelectedText("");
407: } else {
408: int caret = textArea.getCaretPosition();
409: if (caret == 0) {
410: textArea.getToolkit().beep();
411: return;
412: }
413: try {
414: textArea.getDocument().remove(caret - 1, 1);
415: } catch (BadLocationException bl) {
416: bl.printStackTrace();
417: }
418: }
419: }
420: }
421:
422: public static class backspace_word implements ActionListener {
423: public void actionPerformed(ActionEvent evt) {
424: JEditTextArea textArea = getTextArea(evt);
425: int start = textArea.getSelectionStart();
426: if (start != textArea.getSelectionEnd()) {
427: textArea.setSelectedText("");
428: }
429:
430: int line = textArea.getCaretLine();
431: int lineStart = textArea.getLineStartOffset(line);
432: int caret = start - lineStart;
433:
434: String lineText = textArea.getLineText(textArea
435: .getCaretLine());
436:
437: if (caret == 0) {
438: if (lineStart == 0) {
439: textArea.getToolkit().beep();
440: return;
441: }
442: caret--;
443: } else {
444: String noWordSep = (String) textArea.getDocument()
445: .getProperty("noWordSep");
446: caret = TextUtilities.findWordStart(lineText, caret,
447: noWordSep);
448: }
449:
450: try {
451: textArea.getDocument().remove(caret + lineStart,
452: start - (caret + lineStart));
453: } catch (BadLocationException bl) {
454: bl.printStackTrace();
455: }
456: }
457: }
458:
459: public static class delete implements ActionListener {
460: public void actionPerformed(ActionEvent evt) {
461: JEditTextArea textArea = getTextArea(evt);
462:
463: if (!textArea.isEditable()) {
464: textArea.getToolkit().beep();
465: return;
466: }
467:
468: if (textArea.getSelectionStart() != textArea
469: .getSelectionEnd()) {
470: textArea.setSelectedText("");
471: } else {
472: int caret = textArea.getCaretPosition();
473: if (caret == textArea.getDocumentLength()) {
474: textArea.getToolkit().beep();
475: return;
476: }
477: try {
478: textArea.getDocument().remove(caret, 1);
479: } catch (BadLocationException bl) {
480: bl.printStackTrace();
481: }
482: }
483: }
484: }
485:
486: public static class delete_word implements ActionListener {
487: public void actionPerformed(ActionEvent evt) {
488: JEditTextArea textArea = getTextArea(evt);
489: int start = textArea.getSelectionStart();
490: if (start != textArea.getSelectionEnd()) {
491: textArea.setSelectedText("");
492: }
493:
494: int line = textArea.getCaretLine();
495: int lineStart = textArea.getLineStartOffset(line);
496: int caret = start - lineStart;
497:
498: String lineText = textArea.getLineText(textArea
499: .getCaretLine());
500:
501: if (caret == lineText.length()) {
502: if (lineStart + caret == textArea.getDocumentLength()) {
503: textArea.getToolkit().beep();
504: return;
505: }
506: caret++;
507: } else {
508: String noWordSep = (String) textArea.getDocument()
509: .getProperty("noWordSep");
510: caret = TextUtilities.findWordEnd(lineText, caret,
511: noWordSep);
512: }
513:
514: try {
515: textArea.getDocument().remove(start,
516: (caret + lineStart) - start);
517: } catch (BadLocationException bl) {
518: bl.printStackTrace();
519: }
520: }
521: }
522:
523: public static class end implements ActionListener {
524: private boolean select;
525:
526: public end(boolean select) {
527: this .select = select;
528: }
529:
530: public void actionPerformed(ActionEvent evt) {
531: JEditTextArea textArea = getTextArea(evt);
532:
533: int caret = textArea.getCaretPosition();
534:
535: int lastOfLine = textArea.getLineEndOffset(textArea
536: .getCaretLine()) - 1;
537: int lastVisibleLine = textArea.getFirstLine()
538: + textArea.getVisibleLines();
539: if (lastVisibleLine >= textArea.getLineCount()) {
540: lastVisibleLine = Math.min(textArea.getLineCount() - 1,
541: lastVisibleLine);
542: } else
543: lastVisibleLine -= (textArea.getElectricScroll() + 1);
544:
545: int lastVisible = textArea
546: .getLineEndOffset(lastVisibleLine) - 1;
547: int lastDocument = textArea.getDocumentLength();
548:
549: if (caret == lastDocument) {
550: textArea.getToolkit().beep();
551: return;
552: } else if (!Boolean.TRUE.equals(textArea
553: .getClientProperty(SMART_HOME_END_PROPERTY)))
554: caret = lastOfLine;
555: else if (caret == lastVisible)
556: caret = lastDocument;
557: else if (caret == lastOfLine)
558: caret = lastVisible;
559: else
560: caret = lastOfLine;
561:
562: if (select)
563: textArea.select(textArea.getMarkPosition(), caret);
564: else
565: textArea.setCaretPosition(caret);
566: }
567: }
568:
569: public static class document_end implements ActionListener {
570: private boolean select;
571:
572: public document_end(boolean select) {
573: this .select = select;
574: }
575:
576: public void actionPerformed(ActionEvent evt) {
577: JEditTextArea textArea = getTextArea(evt);
578: if (select)
579: textArea.select(textArea.getMarkPosition(), textArea
580: .getDocumentLength());
581: else
582: textArea.setCaretPosition(textArea.getDocumentLength());
583: }
584: }
585:
586: public static class home implements ActionListener {
587: private boolean select;
588:
589: public home(boolean select) {
590: this .select = select;
591: }
592:
593: public void actionPerformed(ActionEvent evt) {
594: JEditTextArea textArea = getTextArea(evt);
595:
596: int caret = textArea.getCaretPosition();
597:
598: int firstLine = textArea.getFirstLine();
599:
600: int firstOfLine = textArea.getLineStartOffset(textArea
601: .getCaretLine());
602: int firstVisibleLine = (firstLine == 0 ? 0 : firstLine
603: + textArea.getElectricScroll());
604: int firstVisible = textArea
605: .getLineStartOffset(firstVisibleLine);
606:
607: if (caret == 0) {
608: textArea.getToolkit().beep();
609: return;
610: } else if (!Boolean.TRUE.equals(textArea
611: .getClientProperty(SMART_HOME_END_PROPERTY)))
612: caret = firstOfLine;
613: else if (caret == firstVisible)
614: caret = 0;
615: else if (caret == firstOfLine)
616: caret = firstVisible;
617: else
618: caret = firstOfLine;
619:
620: if (select)
621: textArea.select(textArea.getMarkPosition(), caret);
622: else
623: textArea.setCaretPosition(caret);
624: }
625: }
626:
627: public static class document_home implements ActionListener {
628: private boolean select;
629:
630: public document_home(boolean select) {
631: this .select = select;
632: }
633:
634: public void actionPerformed(ActionEvent evt) {
635: JEditTextArea textArea = getTextArea(evt);
636: if (select)
637: textArea.select(textArea.getMarkPosition(), 0);
638: else
639: textArea.setCaretPosition(0);
640: }
641: }
642:
643: public static class insert_break implements ActionListener {
644: public void actionPerformed(ActionEvent evt) {
645: JEditTextArea textArea = getTextArea(evt);
646:
647: if (!textArea.isEditable()) {
648: textArea.getToolkit().beep();
649: return;
650: }
651:
652: textArea.setSelectedText("\n");
653: }
654: }
655:
656: public static class insert_tab implements ActionListener {
657: public void actionPerformed(ActionEvent evt) {
658: JEditTextArea textArea = getTextArea(evt);
659:
660: if (!textArea.isEditable()) {
661: textArea.getToolkit().beep();
662: return;
663: }
664:
665: textArea.overwriteSetSelectedText("\t");
666: }
667: }
668:
669: public static class next_char implements ActionListener {
670: private boolean select;
671:
672: public next_char(boolean select) {
673: this .select = select;
674: }
675:
676: public void actionPerformed(ActionEvent evt) {
677: JEditTextArea textArea = getTextArea(evt);
678: int caret = textArea.getCaretPosition();
679: if (caret == textArea.getDocumentLength()) {
680: textArea.getToolkit().beep();
681: return;
682: }
683:
684: if (select)
685: textArea.select(textArea.getMarkPosition(), caret + 1);
686: else
687: textArea.setCaretPosition(caret + 1);
688: }
689: }
690:
691: public static class next_line implements ActionListener {
692: private boolean select;
693:
694: public next_line(boolean select) {
695: this .select = select;
696: }
697:
698: public void actionPerformed(ActionEvent evt) {
699: JEditTextArea textArea = getTextArea(evt);
700: int caret = textArea.getCaretPosition();
701: int line = textArea.getCaretLine();
702:
703: if (line == textArea.getLineCount() - 1) {
704: textArea.getToolkit().beep();
705: return;
706: }
707:
708: int magic = textArea.getMagicCaretPosition();
709: if (magic == -1) {
710: magic = textArea.offsetToX(line, caret
711: - textArea.getLineStartOffset(line));
712: }
713:
714: caret = textArea.getLineStartOffset(line + 1)
715: + textArea.xToOffset(line + 1, magic);
716: if (select)
717: textArea.select(textArea.getMarkPosition(), caret);
718: else
719: textArea.setCaretPosition(caret);
720: textArea.setMagicCaretPosition(magic);
721: }
722: }
723:
724: public static class next_page implements ActionListener {
725: private boolean select;
726:
727: public next_page(boolean select) {
728: this .select = select;
729: }
730:
731: public void actionPerformed(ActionEvent evt) {
732: JEditTextArea textArea = getTextArea(evt);
733: int lineCount = textArea.getLineCount();
734: int firstLine = textArea.getFirstLine();
735: int visibleLines = textArea.getVisibleLines();
736: int line = textArea.getCaretLine();
737:
738: firstLine += visibleLines;
739:
740: if (firstLine + visibleLines >= lineCount - 1)
741: firstLine = lineCount - visibleLines;
742:
743: textArea.setFirstLine(firstLine);
744:
745: int caret = textArea.getLineStartOffset(Math.min(textArea
746: .getLineCount() - 1, line + visibleLines));
747: if (select)
748: textArea.select(textArea.getMarkPosition(), caret);
749: else
750: textArea.setCaretPosition(caret);
751: }
752: }
753:
754: public static class next_word implements ActionListener {
755: private boolean select;
756:
757: public next_word(boolean select) {
758: this .select = select;
759: }
760:
761: public void actionPerformed(ActionEvent evt) {
762: JEditTextArea textArea = getTextArea(evt);
763: int caret = textArea.getCaretPosition();
764: int line = textArea.getCaretLine();
765: int lineStart = textArea.getLineStartOffset(line);
766: caret -= lineStart;
767:
768: String lineText = textArea.getLineText(textArea
769: .getCaretLine());
770:
771: if (caret == lineText.length()) {
772: if (lineStart + caret == textArea.getDocumentLength()) {
773: textArea.getToolkit().beep();
774: return;
775: }
776: caret++;
777: } else {
778: String noWordSep = (String) textArea.getDocument()
779: .getProperty("noWordSep");
780: caret = TextUtilities.findWordEnd(lineText, caret,
781: noWordSep);
782: }
783:
784: if (select)
785: textArea.select(textArea.getMarkPosition(), lineStart
786: + caret);
787: else
788: textArea.setCaretPosition(lineStart + caret);
789: }
790: }
791:
792: public static class overwrite implements ActionListener {
793: public void actionPerformed(ActionEvent evt) {
794: JEditTextArea textArea = getTextArea(evt);
795: textArea
796: .setOverwriteEnabled(!textArea.isOverwriteEnabled());
797: }
798: }
799:
800: public static class prev_char implements ActionListener {
801: private boolean select;
802:
803: public prev_char(boolean select) {
804: this .select = select;
805: }
806:
807: public void actionPerformed(ActionEvent evt) {
808: JEditTextArea textArea = getTextArea(evt);
809: int caret = textArea.getCaretPosition();
810: if (caret == 0) {
811: textArea.getToolkit().beep();
812: return;
813: }
814:
815: if (select)
816: textArea.select(textArea.getMarkPosition(), caret - 1);
817: else
818: textArea.setCaretPosition(caret - 1);
819: }
820: }
821:
822: public static class prev_line implements ActionListener {
823: private boolean select;
824:
825: public prev_line(boolean select) {
826: this .select = select;
827: }
828:
829: public void actionPerformed(ActionEvent evt) {
830: JEditTextArea textArea = getTextArea(evt);
831: int caret = textArea.getCaretPosition();
832: int line = textArea.getCaretLine();
833:
834: if (line == 0) {
835: textArea.getToolkit().beep();
836: return;
837: }
838:
839: int magic = textArea.getMagicCaretPosition();
840: if (magic == -1) {
841: magic = textArea.offsetToX(line, caret
842: - textArea.getLineStartOffset(line));
843: }
844:
845: caret = textArea.getLineStartOffset(line - 1)
846: + textArea.xToOffset(line - 1, magic);
847: if (select)
848: textArea.select(textArea.getMarkPosition(), caret);
849: else
850: textArea.setCaretPosition(caret);
851: textArea.setMagicCaretPosition(magic);
852: }
853: }
854:
855: public static class prev_page implements ActionListener {
856: private boolean select;
857:
858: public prev_page(boolean select) {
859: this .select = select;
860: }
861:
862: public void actionPerformed(ActionEvent evt) {
863: JEditTextArea textArea = getTextArea(evt);
864: int firstLine = textArea.getFirstLine();
865: int visibleLines = textArea.getVisibleLines();
866: int line = textArea.getCaretLine();
867:
868: if (firstLine < visibleLines)
869: firstLine = visibleLines;
870:
871: textArea.setFirstLine(firstLine - visibleLines);
872:
873: int caret = textArea.getLineStartOffset(Math.max(0, line
874: - visibleLines));
875: if (select)
876: textArea.select(textArea.getMarkPosition(), caret);
877: else
878: textArea.setCaretPosition(caret);
879: }
880: }
881:
882: public static class prev_word implements ActionListener {
883: private boolean select;
884:
885: public prev_word(boolean select) {
886: this .select = select;
887: }
888:
889: public void actionPerformed(ActionEvent evt) {
890: JEditTextArea textArea = getTextArea(evt);
891: int caret = textArea.getCaretPosition();
892: int line = textArea.getCaretLine();
893: int lineStart = textArea.getLineStartOffset(line);
894: caret -= lineStart;
895:
896: String lineText = textArea.getLineText(textArea
897: .getCaretLine());
898:
899: if (caret == 0) {
900: if (lineStart == 0) {
901: textArea.getToolkit().beep();
902: return;
903: }
904: caret--;
905: } else {
906: String noWordSep = (String) textArea.getDocument()
907: .getProperty("noWordSep");
908: caret = TextUtilities.findWordStart(lineText, caret,
909: noWordSep);
910: }
911:
912: if (select)
913: textArea.select(textArea.getMarkPosition(), lineStart
914: + caret);
915: else
916: textArea.setCaretPosition(lineStart + caret);
917: }
918: }
919:
920: public static class repeat implements ActionListener,
921: InputHandler.NonRecordable {
922: public void actionPerformed(ActionEvent evt) {
923: JEditTextArea textArea = getTextArea(evt);
924: textArea.getInputHandler().setRepeatEnabled(true);
925: String actionCommand = evt.getActionCommand();
926: if (actionCommand != null) {
927: textArea.getInputHandler().setRepeatCount(
928: Integer.parseInt(actionCommand));
929: }
930: }
931: }
932:
933: public static class toggle_rect implements ActionListener {
934: public void actionPerformed(ActionEvent evt) {
935: JEditTextArea textArea = getTextArea(evt);
936: textArea.setSelectionRectangular(!textArea
937: .isSelectionRectangular());
938: }
939: }
940:
941: public static class insert_char implements ActionListener,
942: InputHandler.NonRepeatable {
943: public void actionPerformed(ActionEvent evt) {
944: JEditTextArea textArea = getTextArea(evt);
945: String str = evt.getActionCommand();
946: int repeatCount = textArea.getInputHandler()
947: .getRepeatCount();
948:
949: if (textArea.isEditable()) {
950: StringBuffer buf = new StringBuffer();
951: for (int i = 0; i < repeatCount; i++)
952: buf.append(str);
953: textArea.overwriteSetSelectedText(buf.toString());
954: } else {
955: textArea.getToolkit().beep();
956: }
957: }
958: }
959: }
|