1
2
3
4
5
6
7
8
9
10 package org.syntax.jedit;
11
12 import java.awt.Component;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.ActionListener;
15 import java.awt.event.KeyAdapter;
16 import java.awt.event.KeyEvent;
17 import java.util.Enumeration;
18 import java.util.EventObject;
19 import java.util.Hashtable;
20
21 import javax.swing.AbstractAction;
22 import javax.swing.Action;
23 import javax.swing.JPopupMenu;
24 import javax.swing.text.BadLocationException;
25
26 import com.eviware.soapui.SoapUI;
27 import com.eviware.soapui.support.UISupport;
28
29 /***
30 * An input handler converts the user's key strokes into concrete actions. It
31 * also takes care of macro recording and action repetition.
32 * <p>
33 *
34 * This class provides all the necessary support code for an input handler, but
35 * doesn't actually do any key binding logic. It is up to the implementations of
36 * this class to do so.
37 *
38 * @author Slava Pestov
39 * @version $Id$
40 * @see org.syntax.jedit.DefaultInputHandler 08/12/2002 Clipboard actions
41 * (Oliver Henning)
42 */
43 public abstract class InputHandler extends KeyAdapter
44 {
45 /***
46 * If this client property is set to Boolean.TRUE on the text area, the
47 * home/end keys will support 'smart' BRIEF-like behaviour (one press =
48 * start/end of line, two presses = start/end of viewscreen, three presses =
49 * start/end of document). By default, this property is not set.
50 */
51 public static final String SMART_HOME_END_PROPERTY = "InputHandler.homeEnd";
52
53 public static final ActionListener BACKSPACE = new backspace();
54 public static final ActionListener BACKSPACE_WORD = new backspace_word();
55 public static final ActionListener DELETE = new delete();
56 public static final ActionListener DELETE_WORD = new delete_word();
57 public static final ActionListener END = new end( false );
58 public static final ActionListener DOCUMENT_END = new document_end( false );
59 public static final ActionListener SELECT_ALL = new select_all();
60 public static final ActionListener SELECT_END = new end( true );
61 public static final ActionListener SELECT_DOC_END = new document_end( true );
62 public static final ActionListener INSERT_BREAK = new insert_break();
63 public static final ActionListener INSERT_TAB = new insert_tab();
64 public static final ActionListener HOME = new home( false );
65 public static final ActionListener DOCUMENT_HOME = new document_home( false );
66 public static final ActionListener SELECT_HOME = new home( true );
67 public static final ActionListener SELECT_DOC_HOME = new document_home( true );
68 public static final ActionListener NEXT_CHAR = new next_char( false );
69 public static final ActionListener NEXT_LINE = new next_line( false );
70 public static final ActionListener NEXT_PAGE = new next_page( false );
71 public static final ActionListener NEXT_WORD = new next_word( false );
72 public static final ActionListener SELECT_NEXT_CHAR = new next_char( true );
73 public static final ActionListener SELECT_NEXT_LINE = new next_line( true );
74 public static final ActionListener SELECT_NEXT_PAGE = new next_page( true );
75 public static final ActionListener SELECT_NEXT_WORD = new next_word( true );
76 public static final ActionListener OVERWRITE = new overwrite();
77 public static final ActionListener PREV_CHAR = new prev_char( false );
78 public static final ActionListener PREV_LINE = new prev_line( false );
79 public static final ActionListener PREV_PAGE = new prev_page( false );
80 public static final ActionListener PREV_WORD = new prev_word( false );
81 public static final ActionListener SELECT_PREV_CHAR = new prev_char( true );
82 public static final ActionListener SELECT_PREV_LINE = new prev_line( true );
83 public static final ActionListener SELECT_PREV_PAGE = new prev_page( true );
84 public static final ActionListener SELECT_PREV_WORD = new prev_word( true );
85 public static final ActionListener REPEAT = new repeat();
86 public static final ActionListener TOGGLE_RECT = new toggle_rect();
87
88 public static final Action CLIP_COPY = new clip_copy();
89 public static final Action CLIP_PASTE = new clip_paste();
90 public static final Action CLIP_CUT = new clip_cut();
91
92
93 public static final ActionListener INSERT_CHAR = new insert_char();
94
95 private static Hashtable<String, ActionListener> actions;
96
97 static
98 {
99 actions = new Hashtable<String, ActionListener>();
100 actions.put( "backspace", BACKSPACE );
101 actions.put( "backspace-word", BACKSPACE_WORD );
102 actions.put( "delete", DELETE );
103 actions.put( "delete-word", DELETE_WORD );
104 actions.put( "end", END );
105 actions.put( "select-all", SELECT_ALL );
106 actions.put( "select-end", SELECT_END );
107 actions.put( "document-end", DOCUMENT_END );
108 actions.put( "select-doc-end", SELECT_DOC_END );
109 actions.put( "insert-break", INSERT_BREAK );
110 actions.put( "insert-tab", INSERT_TAB );
111 actions.put( "home", HOME );
112 actions.put( "select-home", SELECT_HOME );
113 actions.put( "document-home", DOCUMENT_HOME );
114 actions.put( "select-doc-home", SELECT_DOC_HOME );
115 actions.put( "next-char", NEXT_CHAR );
116 actions.put( "next-line", NEXT_LINE );
117 actions.put( "next-page", NEXT_PAGE );
118 actions.put( "next-word", NEXT_WORD );
119 actions.put( "select-next-char", SELECT_NEXT_CHAR );
120 actions.put( "select-next-line", SELECT_NEXT_LINE );
121 actions.put( "select-next-page", SELECT_NEXT_PAGE );
122 actions.put( "select-next-word", SELECT_NEXT_WORD );
123 actions.put( "overwrite", OVERWRITE );
124 actions.put( "prev-char", PREV_CHAR );
125 actions.put( "prev-line", PREV_LINE );
126 actions.put( "prev-page", PREV_PAGE );
127 actions.put( "prev-word", PREV_WORD );
128 actions.put( "select-prev-char", SELECT_PREV_CHAR );
129 actions.put( "select-prev-line", SELECT_PREV_LINE );
130 actions.put( "select-prev-page", SELECT_PREV_PAGE );
131 actions.put( "select-prev-word", SELECT_PREV_WORD );
132 actions.put( "repeat", REPEAT );
133 actions.put( "toggle-rect", TOGGLE_RECT );
134 actions.put( "insert-char", INSERT_CHAR );
135 actions.put( "clipboard-copy", CLIP_COPY );
136 actions.put( "clipboard-paste", CLIP_PASTE );
137 actions.put( "clipboard-cut", CLIP_CUT );
138 }
139
140 /***
141 * Returns a named text area action.
142 *
143 * @param name
144 * The action name
145 */
146 public static ActionListener getAction( String name )
147 {
148 return ( ActionListener )actions.get( name );
149 }
150
151 /***
152 * Returns the name of the specified text area action.
153 *
154 * @param listener
155 * The action
156 */
157 public static String getActionName( ActionListener listener )
158 {
159 Enumeration _enum = getActions();
160 while( _enum.hasMoreElements() )
161 {
162 String name = ( String )_enum.nextElement();
163 ActionListener _listener = getAction( name );
164 if( _listener == listener )
165 return name;
166 }
167 return null;
168 }
169
170 /***
171 * Returns an enumeration of all available actions.
172 */
173 public static Enumeration getActions()
174 {
175 return actions.keys();
176 }
177
178 /***
179 * Adds the default key bindings to this input handler. This should not be
180 * called in the constructor of this input handler, because applications
181 * might load the key bindings from a file, etc.
182 */
183 public abstract void addDefaultKeyBindings();
184
185 /***
186 * Adds a key binding to this input handler.
187 *
188 * @param keyBinding
189 * The key binding (the format of this is input-handler specific)
190 * @param action
191 * The action
192 */
193 public abstract void addKeyBinding( String keyBinding, ActionListener action );
194
195 /***
196 * Removes a key binding from this input handler.
197 *
198 * @param keyBinding
199 * The key binding
200 */
201 public abstract void removeKeyBinding( String keyBinding );
202
203 /***
204 * Removes all key bindings from this input handler.
205 */
206 public abstract void removeAllKeyBindings();
207
208 /***
209 * Grabs the next key typed event and invokes the specified action with the
210 * key as a the action command.
211 *
212 * @param action
213 * The action
214 */
215 public void grabNextKeyStroke( ActionListener listener )
216 {
217 grabAction = listener;
218 }
219
220 /***
221 * Returns if repeating is enabled. When repeating is enabled, actions will
222 * be executed multiple times. This is usually invoked with a special key
223 * stroke in the input handler.
224 */
225 public boolean isRepeatEnabled()
226 {
227 return repeat;
228 }
229
230 /***
231 * Enables repeating. When repeating is enabled, actions will be executed
232 * multiple times. Once repeating is enabled, the input handler should read a
233 * number from the keyboard.
234 */
235 public void setRepeatEnabled( boolean repeat )
236 {
237 this.repeat = repeat;
238 }
239
240 /***
241 * Returns the number of times the next action will be repeated.
242 */
243 public int getRepeatCount()
244 {
245 return( repeat ? Math.max( 1, repeatCount ) : 1 );
246 }
247
248 /***
249 * Sets the number of times the next action will be repeated.
250 *
251 * @param repeatCount
252 * The repeat count
253 */
254 public void setRepeatCount( int repeatCount )
255 {
256 this.repeatCount = repeatCount;
257 }
258
259 /***
260 * Returns the macro recorder. If this is non-null, all executed actions
261 * should be forwarded to the recorder.
262 */
263 public InputHandler.MacroRecorder getMacroRecorder()
264 {
265 return recorder;
266 }
267
268 /***
269 * Sets the macro recorder. If this is non-null, all executed actions should
270 * be forwarded to the recorder.
271 *
272 * @param recorder
273 * The macro recorder
274 */
275 public void setMacroRecorder( InputHandler.MacroRecorder recorder )
276 {
277 this.recorder = recorder;
278 }
279
280 /***
281 * Returns a copy of this input handler that shares the same key bindings.
282 * Setting key bindings in the copy will also set them in the original.
283 */
284 public abstract InputHandler copy();
285
286 /***
287 * Executes the specified action, repeating and recording it as necessary.
288 *
289 * @param listener
290 * The action listener
291 * @param source
292 * The event source
293 * @param actionCommand
294 * The action command
295 */
296 public void executeAction( ActionListener listener, Object source, String actionCommand )
297 {
298
299 ActionEvent evt = new ActionEvent( source, ActionEvent.ACTION_PERFORMED, actionCommand );
300
301
302
303 if( listener instanceof Wrapper )
304 {
305 listener.actionPerformed( evt );
306 return;
307 }
308
309
310 boolean _repeat = repeat;
311 int _repeatCount = getRepeatCount();
312
313
314 if( listener instanceof InputHandler.NonRepeatable )
315 listener.actionPerformed( evt );
316 else
317 {
318 for( int i = 0; i < Math.max( 1, repeatCount ); i++ )
319 listener.actionPerformed( evt );
320 }
321
322
323
324 if( grabAction == null )
325 {
326 if( recorder != null )
327 {
328 if( !( listener instanceof InputHandler.NonRecordable ) )
329 {
330 if( _repeatCount != 1 )
331 recorder.actionPerformed( REPEAT, String.valueOf( _repeatCount ) );
332
333 recorder.actionPerformed( listener, actionCommand );
334 }
335 }
336
337
338
339 if( _repeat )
340 {
341 repeat = false;
342 repeatCount = 0;
343 }
344 }
345 }
346
347 /***
348 * Returns the text area that fired the specified event.
349 *
350 * @param evt
351 * The event
352 */
353 public static JEditTextArea getTextArea( EventObject evt )
354 {
355 if( evt != null )
356 {
357 Object o = evt.getSource();
358 if( o instanceof Component )
359 {
360
361 Component c = ( Component )o;
362 for( ;; )
363 {
364 if( c instanceof JEditTextArea )
365 return ( JEditTextArea )c;
366 else if( c == null )
367 break;
368 if( c instanceof JPopupMenu )
369 c = ( ( JPopupMenu )c ).getInvoker();
370 else
371 c = c.getParent();
372 }
373 }
374 }
375
376
377 System.err.println( "BUG: getTextArea() returning null" );
378 System.err.println( "Report this to Slava Pestov <sp@gjt.org>" );
379 return null;
380 }
381
382
383
384 /***
385 * If a key is being grabbed, this method should be called with the
386 * appropriate key event. It executes the grab action with the typed
387 * character as the parameter.
388 */
389 protected void handleGrabAction( KeyEvent evt )
390 {
391
392
393 ActionListener _grabAction = grabAction;
394 grabAction = null;
395 executeAction( _grabAction, evt.getSource(), String.valueOf( evt.getKeyChar() ) );
396 }
397
398
399 protected ActionListener grabAction;
400 protected boolean repeat;
401 protected int repeatCount;
402 protected InputHandler.MacroRecorder recorder;
403
404 /***
405 * If an action implements this interface, it should not be repeated.
406 * Instead, it will handle the repetition itself.
407 */
408 public interface NonRepeatable
409 {
410 }
411
412 /***
413 * If an action implements this interface, it should not be recorded by the
414 * macro recorder. Instead, it will do its own recording.
415 */
416 public interface NonRecordable
417 {
418 }
419
420 /***
421 * For use by EditAction.Wrapper only.
422 *
423 * @since jEdit 2.2final
424 */
425 public interface Wrapper
426 {
427 }
428
429 /***
430 * Macro recorder.
431 */
432 public interface MacroRecorder
433 {
434 void actionPerformed( ActionListener listener, String actionCommand );
435 }
436
437 public static class backspace implements ActionListener
438 {
439 public void actionPerformed( ActionEvent evt )
440 {
441 JEditTextArea textArea = getTextArea( evt );
442
443 if( !textArea.isEditable() )
444 {
445 textArea.getToolkit().beep();
446 return;
447 }
448
449 if( textArea.getSelectionStart() != textArea.getSelectionEnd() )
450 {
451 textArea.setSelectedText( "" );
452 }
453 else
454 {
455 int caret = textArea.getCaretPosition();
456 if( caret == 0 )
457 {
458 textArea.getToolkit().beep();
459 return;
460 }
461 try
462 {
463 textArea.getDocument().remove( caret - 1, 1 );
464 }
465 catch( BadLocationException bl )
466 {
467 SoapUI.logError( bl );
468 }
469 }
470 }
471 }
472
473 public static class backspace_word implements ActionListener
474 {
475 public void actionPerformed( ActionEvent evt )
476 {
477 JEditTextArea textArea = getTextArea( evt );
478 int start = textArea.getSelectionStart();
479 if( start != textArea.getSelectionEnd() )
480 {
481 textArea.setSelectedText( "" );
482 }
483
484 int line = textArea.getCaretLine();
485 int lineStart = textArea.getLineStartOffset( line );
486 int caret = start - lineStart;
487
488 String lineText = textArea.getLineText( textArea.getCaretLine() );
489
490 if( caret == 0 )
491 {
492 if( lineStart == 0 )
493 {
494 textArea.getToolkit().beep();
495 return;
496 }
497 caret-- ;
498 }
499 else
500 {
501 String noWordSep = ( String )textArea.getDocument().getProperty( "noWordSep" );
502 caret = TextUtilities.findWordStart( lineText, caret, noWordSep );
503 }
504
505 try
506 {
507 textArea.getDocument().remove( caret + lineStart, start - ( caret + lineStart ) );
508 }
509 catch( BadLocationException bl )
510 {
511 SoapUI.logError( bl );
512 }
513 }
514 }
515
516 public static class delete implements ActionListener
517 {
518 public void actionPerformed( ActionEvent evt )
519 {
520 JEditTextArea textArea = getTextArea( evt );
521
522 if( !textArea.isEditable() )
523 {
524 textArea.getToolkit().beep();
525 return;
526 }
527
528 if( textArea.getSelectionStart() != textArea.getSelectionEnd() )
529 {
530 textArea.setSelectedText( "" );
531 }
532 else
533 {
534 int caret = textArea.getCaretPosition();
535 if( caret == textArea.getDocumentLength() )
536 {
537 textArea.getToolkit().beep();
538 return;
539 }
540 try
541 {
542 textArea.getDocument().remove( caret, 1 );
543 }
544 catch( BadLocationException bl )
545 {
546 SoapUI.logError( bl );
547 }
548 }
549 }
550 }
551
552 public static class delete_word implements ActionListener
553 {
554 public void actionPerformed( ActionEvent evt )
555 {
556 JEditTextArea textArea = getTextArea( evt );
557 int start = textArea.getSelectionStart();
558 if( start != textArea.getSelectionEnd() )
559 {
560 textArea.setSelectedText( "" );
561 }
562
563 int line = textArea.getCaretLine();
564 int lineStart = textArea.getLineStartOffset( line );
565 int caret = start - lineStart;
566
567 String lineText = textArea.getLineText( textArea.getCaretLine() );
568
569 if( caret == lineText.length() )
570 {
571 if( lineStart + caret == textArea.getDocumentLength() )
572 {
573 textArea.getToolkit().beep();
574 return;
575 }
576 caret++ ;
577 }
578 else
579 {
580 String noWordSep = ( String )textArea.getDocument().getProperty( "noWordSep" );
581 caret = TextUtilities.findWordEnd( lineText, caret, noWordSep );
582 }
583
584 try
585 {
586 textArea.getDocument().remove( start, ( caret + lineStart ) - start );
587 }
588 catch( BadLocationException bl )
589 {
590 SoapUI.logError( bl );
591 }
592 }
593 }
594
595 public static class end implements ActionListener
596 {
597 private boolean select;
598
599 public end( boolean select )
600 {
601 this.select = select;
602 }
603
604 public void actionPerformed( ActionEvent evt )
605 {
606 JEditTextArea textArea = getTextArea( evt );
607
608 int caret = textArea.getCaretPosition();
609
610 int lastOfLine = textArea.getLineEndOffset( textArea.getCaretLine() ) - 1;
611 int lastVisibleLine = textArea.getFirstLine() + textArea.getVisibleLines();
612 if( lastVisibleLine >= textArea.getLineCount() )
613 {
614 lastVisibleLine = Math.min( textArea.getLineCount() - 1, lastVisibleLine );
615 }
616 else
617 lastVisibleLine -= 1;
618
619 int lastVisible = textArea.getLineEndOffset( lastVisibleLine ) - 1;
620 int lastDocument = textArea.getDocumentLength();
621
622 if( caret == lastDocument )
623 {
624 textArea.getToolkit().beep();
625 return;
626 }
627 else if( !Boolean.TRUE.equals( textArea.getClientProperty( SMART_HOME_END_PROPERTY ) ) )
628 caret = lastOfLine;
629 else if( caret == lastVisible )
630 caret = lastDocument;
631 else if( caret == lastOfLine )
632 caret = lastVisible;
633 else
634 caret = lastOfLine;
635
636 if( select )
637 textArea.select( textArea.getMarkPosition(), caret );
638 else
639 textArea.setCaretPosition( caret );
640 }
641 }
642
643 public static class select_all implements ActionListener
644 {
645 public void actionPerformed( ActionEvent evt )
646 {
647 JEditTextArea textArea = getTextArea( evt );
648 textArea.selectAll();
649 }
650 }
651
652 public static class document_end implements ActionListener
653 {
654 private boolean select;
655
656 public document_end( boolean select )
657 {
658 this.select = select;
659 }
660
661 public void actionPerformed( ActionEvent evt )
662 {
663 JEditTextArea textArea = getTextArea( evt );
664 if( select )
665 textArea.select( textArea.getMarkPosition(), textArea.getDocumentLength() );
666 else
667 textArea.setCaretPosition( textArea.getDocumentLength() );
668 }
669 }
670
671 public static class home implements ActionListener
672 {
673 private boolean select;
674
675 public home( boolean select )
676 {
677 this.select = select;
678 }
679
680 public void actionPerformed( ActionEvent evt )
681 {
682 JEditTextArea textArea = getTextArea( evt );
683
684 int caret = textArea.getCaretPosition();
685
686 int firstLine = textArea.getFirstLine();
687
688 int firstOfLine = textArea.getLineStartOffset( textArea.getCaretLine() );
689 int firstVisibleLine = ( firstLine == 0 ? 0 : firstLine + 1 );
690 int firstVisible = textArea.getLineStartOffset( firstVisibleLine );
691
692 if( caret == 0 )
693 {
694 textArea.getToolkit().beep();
695 return;
696 }
697 else if( !Boolean.TRUE.equals( textArea.getClientProperty( SMART_HOME_END_PROPERTY ) ) )
698 caret = firstOfLine;
699 else if( caret == firstVisible )
700 caret = 0;
701 else if( caret == firstOfLine )
702 caret = firstVisible;
703 else
704 caret = firstOfLine;
705
706 if( select )
707 textArea.select( textArea.getMarkPosition(), caret );
708 else
709 textArea.setCaretPosition( caret );
710 }
711 }
712
713 public static class document_home implements ActionListener
714 {
715 private boolean select;
716
717 public document_home( boolean select )
718 {
719 this.select = select;
720 }
721
722 public void actionPerformed( ActionEvent evt )
723 {
724 JEditTextArea textArea = getTextArea( evt );
725 if( select )
726 textArea.select( textArea.getMarkPosition(), 0 );
727 else
728 textArea.setCaretPosition( 0 );
729 }
730 }
731
732 public static class insert_break implements ActionListener
733 {
734 public void actionPerformed( ActionEvent evt )
735 {
736 JEditTextArea textArea = getTextArea( evt );
737
738 if( !textArea.isEditable() )
739 {
740 textArea.getToolkit().beep();
741 return;
742 }
743
744 textArea.setSelectedText( "\n" );
745 }
746 }
747
748 public static class insert_tab implements ActionListener
749 {
750 public void actionPerformed( ActionEvent evt )
751 {
752 JEditTextArea textArea = getTextArea( evt );
753
754 if( !textArea.isEditable() )
755 {
756 textArea.getToolkit().beep();
757 return;
758 }
759
760 textArea.overwriteSetSelectedText( "\t" );
761 }
762 }
763
764 public static class next_char implements ActionListener
765 {
766 private boolean select;
767
768 public next_char( boolean select )
769 {
770 this.select = select;
771 }
772
773 public void actionPerformed( ActionEvent evt )
774 {
775 JEditTextArea textArea = getTextArea( evt );
776 int caret = textArea.getCaretPosition();
777 if( caret == textArea.getDocumentLength() )
778 {
779 textArea.getToolkit().beep();
780 return;
781 }
782
783 if( select )
784 textArea.select( textArea.getMarkPosition(), caret + 1 );
785 else
786 textArea.setCaretPosition( caret + 1 );
787 }
788 }
789
790 public static class next_line implements ActionListener
791 {
792 private boolean select;
793
794 public next_line( boolean select )
795 {
796 this.select = select;
797 }
798
799 public void actionPerformed( ActionEvent evt )
800 {
801 JEditTextArea textArea = getTextArea( evt );
802 int caret = textArea.getCaretPosition();
803 int line = textArea.getCaretLine();
804
805 if( line == textArea.getLineCount() - 1 )
806 {
807 textArea.getToolkit().beep();
808 return;
809 }
810
811 int magic = textArea.getMagicCaretPosition();
812 if( magic == -1 )
813 {
814 magic = textArea.offsetToX( line, caret - textArea.getLineStartOffset( line ) );
815 }
816
817 caret = textArea.getLineStartOffset( line + 1 ) + textArea.xToOffset( line + 1, magic );
818 if( select )
819 textArea.select( textArea.getMarkPosition(), caret );
820 else
821 textArea.setCaretPosition( caret );
822 textArea.setMagicCaretPosition( magic );
823 }
824 }
825
826 public static class next_page implements ActionListener
827 {
828 private boolean select;
829
830 public next_page( boolean select )
831 {
832 this.select = select;
833 }
834
835 public void actionPerformed( ActionEvent evt )
836 {
837 JEditTextArea textArea = getTextArea( evt );
838 int lineCount = textArea.getLineCount();
839 int firstLine = textArea.getFirstLine();
840 int visibleLines = textArea.getVisibleLines();
841 int line = textArea.getCaretLine();
842
843 firstLine += visibleLines;
844
845 if( firstLine + visibleLines >= lineCount - 1 )
846 firstLine = lineCount - visibleLines;
847
848 textArea.setFirstLine( firstLine );
849
850 int caret = textArea.getLineStartOffset( Math.min( textArea.getLineCount() - 1, line + visibleLines ) );
851 if( select )
852 textArea.select( textArea.getMarkPosition(), caret );
853 else
854 textArea.setCaretPosition( caret );
855 }
856 }
857
858 public static class next_word implements ActionListener
859 {
860 private boolean select;
861
862 public next_word( boolean select )
863 {
864 this.select = select;
865 }
866
867 public void actionPerformed( ActionEvent evt )
868 {
869 JEditTextArea textArea = getTextArea( evt );
870 int caret = textArea.getCaretPosition();
871 int line = textArea.getCaretLine();
872 int lineStart = textArea.getLineStartOffset( line );
873 caret -= lineStart;
874
875 String lineText = textArea.getLineText( textArea.getCaretLine() );
876
877 if( caret == lineText.length() )
878 {
879 if( lineStart + caret == textArea.getDocumentLength() )
880 {
881 textArea.getToolkit().beep();
882 return;
883 }
884 caret++ ;
885 }
886 else
887 {
888 String noWordSep = ( String )textArea.getDocument().getProperty( "noWordSep" );
889 caret = TextUtilities.findWordEnd( lineText, caret, noWordSep );
890 }
891
892 if( select )
893 textArea.select( textArea.getMarkPosition(), lineStart + caret );
894 else
895 textArea.setCaretPosition( lineStart + caret );
896 }
897 }
898
899 public static class overwrite implements ActionListener
900 {
901 public void actionPerformed( ActionEvent evt )
902 {
903 JEditTextArea textArea = getTextArea( evt );
904 textArea.setOverwriteEnabled( !textArea.isOverwriteEnabled() );
905 }
906 }
907
908 public static class prev_char implements ActionListener
909 {
910 private boolean select;
911
912 public prev_char( boolean select )
913 {
914 this.select = select;
915 }
916
917 public void actionPerformed( ActionEvent evt )
918 {
919 JEditTextArea textArea = getTextArea( evt );
920 int caret = textArea.getCaretPosition();
921 if( caret == 0 )
922 {
923 textArea.getToolkit().beep();
924 return;
925 }
926
927 if( select )
928 textArea.select( textArea.getMarkPosition(), caret - 1 );
929 else
930 textArea.setCaretPosition( caret - 1 );
931 }
932 }
933
934 public static class prev_line implements ActionListener
935 {
936 private boolean select;
937
938 public prev_line( boolean select )
939 {
940 this.select = select;
941 }
942
943 public void actionPerformed( ActionEvent evt )
944 {
945 JEditTextArea textArea = getTextArea( evt );
946 int caret = textArea.getCaretPosition();
947 int line = textArea.getCaretLine();
948
949 if( line == 0 )
950 {
951 textArea.getToolkit().beep();
952 return;
953 }
954
955 int magic = textArea.getMagicCaretPosition();
956 if( magic == -1 )
957 {
958 magic = textArea.offsetToX( line, caret - textArea.getLineStartOffset( line ) );
959 }
960
961 caret = textArea.getLineStartOffset( line - 1 ) + textArea.xToOffset( line - 1, magic );
962 if( select )
963 textArea.select( textArea.getMarkPosition(), caret );
964 else
965 textArea.setCaretPosition( caret );
966 textArea.setMagicCaretPosition( magic );
967 }
968 }
969
970 public static class prev_page implements ActionListener
971 {
972 private boolean select;
973
974 public prev_page( boolean select )
975 {
976 this.select = select;
977 }
978
979 public void actionPerformed( ActionEvent evt )
980 {
981 JEditTextArea textArea = getTextArea( evt );
982 int firstLine = textArea.getFirstLine();
983 int visibleLines = textArea.getVisibleLines();
984 int line = textArea.getCaretLine();
985
986 if( firstLine < visibleLines )
987 firstLine = visibleLines;
988
989 textArea.setFirstLine( firstLine - visibleLines );
990
991 int caret = textArea.getLineStartOffset( Math.max( 0, line - visibleLines ) );
992 if( select )
993 textArea.select( textArea.getMarkPosition(), caret );
994 else
995 textArea.setCaretPosition( caret );
996 }
997 }
998
999 public static class prev_word implements ActionListener
1000 {
1001 private boolean select;
1002
1003 public prev_word( boolean select )
1004 {
1005 this.select = select;
1006 }
1007
1008 public void actionPerformed( ActionEvent evt )
1009 {
1010 JEditTextArea textArea = getTextArea( evt );
1011 int caret = textArea.getCaretPosition();
1012 int line = textArea.getCaretLine();
1013 int lineStart = textArea.getLineStartOffset( line );
1014 caret -= lineStart;
1015
1016 String lineText = textArea.getLineText( textArea.getCaretLine() );
1017
1018 if( caret == 0 )
1019 {
1020 if( lineStart == 0 )
1021 {
1022 textArea.getToolkit().beep();
1023 return;
1024 }
1025 caret-- ;
1026 }
1027 else
1028 {
1029 String noWordSep = ( String )textArea.getDocument().getProperty( "noWordSep" );
1030 caret = TextUtilities.findWordStart( lineText, caret, noWordSep );
1031 }
1032
1033 if( select )
1034 textArea.select( textArea.getMarkPosition(), lineStart + caret );
1035 else
1036 textArea.setCaretPosition( lineStart + caret );
1037 }
1038 }
1039
1040 public static class repeat implements ActionListener, InputHandler.NonRecordable
1041 {
1042 public void actionPerformed( ActionEvent evt )
1043 {
1044 JEditTextArea textArea = getTextArea( evt );
1045 textArea.getInputHandler().setRepeatEnabled( true );
1046 String actionCommand = evt.getActionCommand();
1047 if( actionCommand != null )
1048 {
1049 textArea.getInputHandler().setRepeatCount( Integer.parseInt( actionCommand ) );
1050 }
1051 }
1052 }
1053
1054 public static class toggle_rect implements ActionListener
1055 {
1056 public void actionPerformed( ActionEvent evt )
1057 {
1058 JEditTextArea textArea = getTextArea( evt );
1059 textArea.setSelectionRectangular( !textArea.isSelectionRectangular() );
1060 }
1061 }
1062
1063 public static class insert_char implements ActionListener, InputHandler.NonRepeatable
1064 {
1065 public void actionPerformed( ActionEvent evt )
1066 {
1067 JEditTextArea textArea = getTextArea( evt );
1068 String str = evt.getActionCommand();
1069 int repeatCount = textArea.getInputHandler().getRepeatCount();
1070
1071 if( textArea.isEditable() )
1072 {
1073 StringBuffer buf = new StringBuffer();
1074 for( int i = 0; i < repeatCount; i++ )
1075 buf.append( str );
1076 textArea.overwriteSetSelectedText( buf.toString() );
1077 }
1078 else
1079 {
1080 textArea.getToolkit().beep();
1081 }
1082 }
1083 }
1084
1085 public static class clip_copy extends AbstractAction
1086 {
1087
1088 public clip_copy()
1089 {
1090 super( "Copy" );
1091 putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu C" ) );
1092 }
1093
1094 public void actionPerformed( ActionEvent evt )
1095 {
1096 JEditTextArea textArea = getTextArea( evt );
1097 textArea.copy();
1098 }
1099 }
1100
1101 public static class clip_paste extends AbstractAction
1102 {
1103
1104 public clip_paste()
1105 {
1106 super( "Paste" );
1107 putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu V" ) );
1108 }
1109
1110 public void actionPerformed( ActionEvent evt )
1111 {
1112 JEditTextArea textArea = getTextArea( evt );
1113 textArea.paste();
1114 }
1115 }
1116
1117 public static class clip_cut extends AbstractAction
1118 {
1119
1120 public clip_cut()
1121 {
1122 super( "Cut" );
1123 putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu X" ) );
1124 }
1125
1126 public void actionPerformed( ActionEvent evt )
1127 {
1128 JEditTextArea textArea = getTextArea( evt );
1129 textArea.cut();
1130 }
1131 }
1132 }