001 /* DefaultEditorKit.java --
002 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.swing.text;
040
041 import gnu.java.lang.CPStringBuilder;
042
043 import java.awt.Toolkit;
044 import java.awt.event.ActionEvent;
045
046 import java.io.BufferedReader;
047 import java.io.IOException;
048 import java.io.InputStream;
049 import java.io.InputStreamReader;
050 import java.io.OutputStream;
051 import java.io.OutputStreamWriter;
052 import java.io.Reader;
053 import java.io.Writer;
054
055 import javax.swing.Action;
056 import javax.swing.SwingConstants;
057
058 /**
059 * The default implementation of {@link EditorKit}. This <code>EditorKit</code>
060 * a plain text <code>Document</code> and several commands that together
061 * make up a basic editor, like cut / copy + paste.
062 *
063 * @author original author unknown
064 * @author Roman Kennke (roman@kennke.org)
065 * @author Robert Schuster (robertschuster@fsfe.org)
066 */
067 public class DefaultEditorKit extends EditorKit
068 {
069 static class SelectionPreviousWordAction
070 extends TextAction
071 {
072 SelectionPreviousWordAction()
073 {
074 super(selectionPreviousWordAction);
075 }
076
077 public void actionPerformed(ActionEvent event)
078 {
079 try
080 {
081 JTextComponent t = getTextComponent(event);
082
083 if (t != null)
084 {
085 int offs = Utilities.getPreviousWord(t, t.getCaretPosition());
086
087 Caret c = t.getCaret();
088 c.moveDot(offs);
089 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
090 }
091 }
092 catch(BadLocationException ble)
093 {
094 // Can't happen.
095 }
096 }
097 }
098
099 static class SelectionNextWordAction
100 extends TextAction
101 {
102 SelectionNextWordAction()
103 {
104 super(selectionNextWordAction);
105 }
106
107 public void actionPerformed(ActionEvent event)
108 {
109 try
110 {
111 JTextComponent t = getTextComponent(event);
112
113 if (t != null)
114 {
115 int offs = Utilities.getNextWord(t, t.getCaretPosition());
116
117 Caret c = t.getCaret();
118 c.moveDot(offs);
119 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
120 }
121 }
122 catch(BadLocationException ble)
123 {
124 // Can't happen.
125 }
126 }
127 }
128
129 static class SelectionBeginWordAction extends TextAction
130 {
131 SelectionBeginWordAction()
132 {
133 super(selectionBeginWordAction);
134 }
135
136 public void actionPerformed(ActionEvent event)
137 {
138 try
139 {
140 JTextComponent t = getTextComponent(event);
141
142 if (t != null)
143 {
144 int offs = Utilities.getWordStart(t, t.getCaretPosition());
145
146 Caret c = t.getCaret();
147 c.moveDot(offs);
148 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
149 }
150 }
151 catch(BadLocationException ble)
152 {
153 // Can't happen.
154 }
155 }
156 }
157
158 static class SelectionEndWordAction extends TextAction
159 {
160 SelectionEndWordAction()
161 {
162 super(selectionEndWordAction);
163 }
164
165 public void actionPerformed(ActionEvent event)
166 {
167 try
168 {
169 JTextComponent t = getTextComponent(event);
170
171 if (t != null)
172 {
173 int offs = Utilities.getWordEnd(t, t.getCaretPosition());
174
175 Caret c = t.getCaret();
176 c.moveDot(offs);
177 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
178 }
179 }
180 catch(BadLocationException ble)
181 {
182 // Can't happen.
183 }
184 }
185 }
186
187 static class BeginWordAction extends TextAction
188 {
189 BeginWordAction()
190 {
191 super(beginWordAction);
192 }
193
194 public void actionPerformed(ActionEvent event)
195 {
196 try
197 {
198 JTextComponent t = getTextComponent(event);
199
200 if (t != null)
201 {
202 int offs = Utilities.getWordStart(t, t.getCaretPosition());
203
204 Caret c = t.getCaret();
205 c.setDot(offs);
206 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
207 }
208 }
209 catch(BadLocationException ble)
210 {
211 // Can't happen.
212 }
213 }
214 }
215
216 static class EndWordAction extends TextAction
217 {
218 EndWordAction()
219 {
220 super(endWordAction);
221 }
222
223 public void actionPerformed(ActionEvent event)
224 {
225 try
226 {
227 JTextComponent t = getTextComponent(event);
228
229 if (t != null)
230 {
231 int offs = Utilities.getWordEnd(t, t.getCaretPosition());
232
233 Caret c = t.getCaret();
234 c.setDot(offs);
235 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
236 }
237 }
238 catch(BadLocationException ble)
239 {
240 // Can't happen.
241 }
242 }
243 }
244
245 static class PreviousWordAction
246 extends TextAction
247 {
248 PreviousWordAction()
249 {
250 super(previousWordAction);
251 }
252
253 public void actionPerformed(ActionEvent event)
254 {
255 try
256 {
257 JTextComponent t = getTextComponent(event);
258
259 if (t != null)
260 {
261 int offs = Utilities.getPreviousWord(t, t.getCaretPosition());
262
263 Caret c = t.getCaret();
264 c.setDot(offs);
265 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
266 }
267 }
268 catch(BadLocationException ble)
269 {
270 // Can't happen.
271 }
272 }
273 }
274
275 static class NextWordAction
276 extends TextAction
277 {
278 NextWordAction()
279 {
280 super(nextWordAction);
281 }
282
283 public void actionPerformed(ActionEvent event)
284 {
285 try
286 {
287 JTextComponent t = getTextComponent(event);
288
289 if (t != null)
290 {
291 int offs = Utilities.getNextWord(t, t.getCaretPosition());
292
293 Caret c = t.getCaret();
294 c.setDot(offs);
295 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
296 }
297 }
298 catch(BadLocationException ble)
299 {
300 // Can't happen.
301 }
302 }
303 }
304
305 static class SelectAllAction
306 extends TextAction
307 {
308 SelectAllAction()
309 {
310 super(selectAllAction);
311 }
312
313 public void actionPerformed(ActionEvent event)
314 {
315 JTextComponent t = getTextComponent(event);
316 if (t != null)
317 {
318 int offs = t.getDocument().getLength();
319 Caret c = t.getCaret();
320 c.setDot(0);
321 c.moveDot(offs);
322 try
323 {
324 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
325 }
326 catch(BadLocationException ble)
327 {
328 // Can't happen.
329 }
330 }
331 }
332 }
333
334 static class SelectionBeginAction
335 extends TextAction
336 {
337 SelectionBeginAction()
338 {
339 super(selectionBeginAction);
340 }
341
342 public void actionPerformed(ActionEvent event)
343 {
344 JTextComponent t = getTextComponent(event);
345 if (t != null)
346 {
347 Caret c = t.getCaret();
348 c.moveDot(0);
349 try
350 {
351 c.setMagicCaretPosition(t.modelToView(0).getLocation());
352 }
353 catch(BadLocationException ble)
354 {
355 // Can't happen.
356 }
357 }
358 }
359 }
360
361 static class SelectionEndAction
362 extends TextAction
363 {
364 SelectionEndAction()
365 {
366 super(selectionEndAction);
367 }
368
369 public void actionPerformed(ActionEvent event)
370 {
371 JTextComponent t = getTextComponent(event);
372 if (t != null)
373 {
374 int offs = t.getDocument().getLength();
375 Caret c = t.getCaret();
376 c.moveDot(offs);
377 try
378 {
379 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
380 }
381 catch(BadLocationException ble)
382 {
383 // Can't happen.
384 }
385 }
386 }
387 }
388
389 static class SelectionBeginLineAction
390 extends TextAction
391 {
392
393 SelectionBeginLineAction()
394 {
395 super(selectionBeginLineAction);
396 }
397
398 public void actionPerformed(ActionEvent event)
399 {
400 JTextComponent t = getTextComponent(event);
401 if (t != null)
402 {
403 Caret c = t.getCaret();
404 try
405 {
406 int offs = Utilities.getRowStart(t, c.getDot());
407 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
408 }
409 catch(BadLocationException ble)
410 {
411 // Can't happen.
412 }
413 }
414 }
415 }
416
417 static class SelectionEndLineAction
418 extends TextAction
419 {
420 SelectionEndLineAction()
421 {
422 super(selectionEndLineAction);
423 }
424
425 public void actionPerformed(ActionEvent event)
426 {
427 JTextComponent t = getTextComponent(event);
428 if (t != null)
429 {
430 Caret c = t.getCaret();
431 try
432 {
433 int offs = Utilities.getRowEnd(t, c.getDot());
434 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
435 }
436 catch(BadLocationException ble)
437 {
438 // Can't happen.
439 }
440 }
441 }
442 }
443
444 static class SelectLineAction extends TextAction
445 {
446 SelectLineAction()
447 {
448 super(selectLineAction);
449 }
450
451 public void actionPerformed(ActionEvent event)
452 {
453 JTextComponent t = getTextComponent(event);
454 if (t != null)
455 {
456 Caret c = t.getCaret();
457 try
458 {
459 int offs1 = Utilities.getRowStart(t, c.getDot());
460 int offs2 = Utilities.getRowEnd(t, c.getDot());
461 c.setDot(offs2);
462 c.moveDot(offs1);
463 c.setMagicCaretPosition(t.modelToView(offs2).getLocation());
464 }
465 catch(BadLocationException ble)
466 {
467 // Can't happen.
468 }
469 }
470 }
471 }
472
473 static class SelectWordAction extends TextAction
474 {
475 SelectWordAction()
476 {
477 super(selectWordAction);
478 }
479
480 public void actionPerformed(ActionEvent event)
481 {
482 JTextComponent t = getTextComponent(event);
483 if (t != null)
484 {
485 Caret c = t.getCaret();
486 int dot = c.getDot();
487 try
488 {
489 int wordStart = Utilities.getWordStart(t, dot);
490
491 if (dot == wordStart)
492 {
493 // Current cursor position is on the first character in a word.
494 c.setDot(wordStart);
495 c.moveDot(Utilities.getWordEnd(t, wordStart));
496 }
497 else
498 {
499 // Current cursor position is not on the first character
500 // in a word.
501 int nextWord = Utilities.getNextWord(t, dot);
502 int previousWord = Utilities.getPreviousWord(t, dot);
503 int previousWordEnd = Utilities.getWordEnd(t, previousWord);
504
505 // Cursor position is in the space between two words. In such a
506 // situation just select the space.
507 if (dot >= previousWordEnd && dot <= nextWord)
508 {
509 c.setDot(previousWordEnd);
510 c.moveDot(nextWord);
511 }
512 else
513 {
514 // Cursor position is inside a word. Just select it then.
515 c.setDot(previousWord);
516 c.moveDot(previousWordEnd);
517 }
518 }
519
520 // If the position was updated change the magic caret position
521 // as well.
522 if (c.getDot() != dot)
523 c.setMagicCaretPosition(t.modelToView(c.getDot()).getLocation());
524 }
525 catch(BadLocationException ble)
526 {
527 // Can't happen.
528 }
529 }
530 }
531 }
532
533 static class SelectionDownAction
534 extends TextAction.VerticalMovementAction
535 {
536 SelectionDownAction()
537 {
538 super(selectionDownAction, SwingConstants.SOUTH);
539 }
540
541 protected void actionPerformedImpl(Caret c, int offs)
542 {
543 c.moveDot(offs);
544 }
545
546 }
547
548 static class SelectionUpAction
549 extends TextAction.VerticalMovementAction
550 {
551 SelectionUpAction()
552 {
553 super(selectionUpAction, SwingConstants.NORTH);
554 }
555
556 protected void actionPerformedImpl(Caret c, int offs)
557 {
558 c.moveDot(offs);
559 }
560
561 }
562
563 static class SelectionForwardAction
564 extends TextAction.HorizontalMovementAction
565 {
566 SelectionForwardAction()
567 {
568 super(selectionForwardAction, SwingConstants.EAST);
569 }
570
571 protected void actionPerformedImpl(Caret c, int offs)
572 {
573 c.moveDot(offs);
574 }
575 }
576
577 static class SelectionBackwardAction
578 extends TextAction.HorizontalMovementAction
579 {
580 SelectionBackwardAction()
581 {
582 super(selectionBackwardAction, SwingConstants.WEST);
583 }
584
585 protected void actionPerformedImpl(Caret c, int offs)
586 {
587 c.moveDot(offs);
588 }
589 }
590
591 static class DownAction
592 extends TextAction.VerticalMovementAction
593 {
594 DownAction()
595 {
596 super(downAction, SwingConstants.SOUTH);
597 }
598
599 protected void actionPerformedImpl(Caret c, int offs)
600 {
601 c.setDot(offs);
602 }
603 }
604
605 static class UpAction
606 extends TextAction.VerticalMovementAction
607 {
608 UpAction()
609 {
610 super(upAction, SwingConstants.NORTH);
611 }
612
613 protected void actionPerformedImpl(Caret c, int offs)
614 {
615 c.setDot(offs);
616 }
617
618 }
619
620 static class ForwardAction
621 extends TextAction.HorizontalMovementAction
622 {
623 ForwardAction()
624 {
625 super(forwardAction, SwingConstants.EAST);
626 }
627
628 protected void actionPerformedImpl(Caret c, int offs)
629 {
630 c.setDot(offs);
631 }
632
633 }
634
635 static class BackwardAction
636 extends TextAction.HorizontalMovementAction
637 {
638 BackwardAction()
639 {
640 super(backwardAction, SwingConstants.WEST);
641 }
642
643 protected void actionPerformedImpl(Caret c, int offs)
644 {
645 c.setDot(offs);
646 }
647
648 }
649
650 static class DeletePrevCharAction
651 extends TextAction
652 {
653 DeletePrevCharAction()
654 {
655 super(deletePrevCharAction);
656 }
657
658 public void actionPerformed(ActionEvent event)
659 {
660 JTextComponent t = getTextComponent(event);
661 if (t != null)
662 {
663 try
664 {
665 int pos = t.getSelectionStart();
666 int len = t.getSelectionEnd() - pos;
667
668 if (len > 0)
669 t.getDocument().remove(pos, len);
670 else if (pos > 0)
671 {
672 pos--;
673 t.getDocument().remove(pos, 1);
674 Caret c = t.getCaret();
675 c.setDot(pos);
676 c.setMagicCaretPosition(t.modelToView(pos).getLocation());
677 }
678 }
679 catch (BadLocationException e)
680 {
681 // FIXME: we're not authorized to throw this.. swallow it?
682 }
683 }
684 }
685 }
686
687 static class DeleteNextCharAction
688 extends TextAction
689 {
690 DeleteNextCharAction()
691 {
692 super(deleteNextCharAction);
693 }
694
695 public void actionPerformed(ActionEvent event)
696 {
697 JTextComponent t = getTextComponent(event);
698 if (t != null)
699 {
700 try
701 {
702 int pos = t.getSelectionStart();
703 int len = t.getSelectionEnd() - pos;
704
705 if (len > 0)
706 t.getDocument().remove(pos, len);
707 else if (pos < t.getDocument().getLength())
708 t.getDocument().remove(pos, 1);
709
710 Caret c = t.getCaret();
711 c.setDot(pos);
712 c.setMagicCaretPosition(t.modelToView(pos).getLocation());
713 }
714 catch (BadLocationException e)
715 {
716 // FIXME: we're not authorized to throw this.. swallow it?
717 }
718 }
719 }
720 }
721
722 static class EndLineAction
723 extends TextAction
724 {
725 EndLineAction()
726 {
727 super(endLineAction);
728 }
729
730 public void actionPerformed(ActionEvent event)
731 {
732 JTextComponent t = getTextComponent(event);
733 if (t != null)
734 {
735 try
736 {
737 int offs = Utilities.getRowEnd(t, t.getCaretPosition());
738 if (offs > -1)
739 {
740 Caret c = t.getCaret();
741 c.setDot(offs);
742 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
743 }
744 }
745 catch (BadLocationException ble)
746 {
747 // Nothing to do here
748 }
749 }
750 }
751 }
752
753 static class BeginLineAction
754 extends TextAction
755 {
756 BeginLineAction()
757 {
758 super(beginLineAction);
759 }
760
761 public void actionPerformed(ActionEvent event)
762 {
763 JTextComponent t = getTextComponent(event);
764 if (t != null)
765 {
766 try
767 {
768 int offs = Utilities.getRowStart(t, t.getCaretPosition());
769 if (offs > -1)
770 {
771 Caret c = t.getCaret();
772 c.setDot(offs);
773 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
774 }
775 }
776 catch (BadLocationException ble)
777 {
778 // Do nothing here.
779 }
780 }
781 }
782 }
783
784 static class BeginAction extends TextAction
785 {
786
787 BeginAction()
788 {
789 super(beginAction);
790 }
791
792 public void actionPerformed(ActionEvent event)
793 {
794 JTextComponent t = getTextComponent(event);
795 if (t != null)
796 {
797 Caret c = t.getCaret();
798 c.setDot(0);
799 try
800 {
801 c.setMagicCaretPosition(t.modelToView(0).getLocation());
802 }
803 catch(BadLocationException ble)
804 {
805 // Can't happen.
806 }
807 }
808 }
809 }
810
811 static class EndAction extends TextAction
812 {
813
814 EndAction()
815 {
816 super(endAction);
817 }
818
819 public void actionPerformed(ActionEvent event)
820 {
821 JTextComponent t = getTextComponent(event);
822 if (t != null)
823 {
824 int offs = t.getDocument().getLength();
825 Caret c = t.getCaret();
826 c.setDot(offs);
827 try
828 {
829 c.setMagicCaretPosition(t.modelToView(offs).getLocation());
830 }
831 catch(BadLocationException ble)
832 {
833 // Can't happen.
834 }
835 }
836 }
837 }
838
839 /**
840 * Creates a beep on the PC speaker.
841 *
842 * @see Toolkit#beep()
843 */
844 public static class BeepAction extends TextAction
845 {
846 /**
847 * Creates a new <code>BeepAction</code>.
848 */
849 public BeepAction()
850 {
851 super(beepAction);
852 }
853
854 /**
855 * Performs the <code>Action</code>.
856 *
857 * @param event the action event describing the user action
858 */
859 public void actionPerformed(ActionEvent event)
860 {
861 Toolkit.getDefaultToolkit().beep();
862 }
863 }
864
865 /**
866 * Copies the selected content into the system clipboard.
867 *
868 * @see Toolkit#getSystemClipboard()
869 * @see CutAction
870 * @see PasteAction
871 */
872 public static class CopyAction extends TextAction
873 {
874
875 /**
876 * Create a new <code>CopyAction</code>.
877 */
878 public CopyAction()
879 {
880 super(copyAction);
881 }
882
883 /**
884 * Performs the <code>Action</code>.
885 *
886 * @param event the action event describing the user action
887 */
888 public void actionPerformed(ActionEvent event)
889 {
890 JTextComponent target = getTextComponent(event);
891 if (target != null)
892 target.copy();
893 }
894 }
895
896
897 /**
898 * Copies the selected content into the system clipboard and deletes the
899 * selection.
900 *
901 * @see Toolkit#getSystemClipboard()
902 * @see CopyAction
903 * @see PasteAction
904 */
905 public static class CutAction extends TextAction
906 {
907
908 /**
909 * Create a new <code>CutAction</code>.
910 */
911 public CutAction()
912 {
913 super(cutAction);
914 }
915
916 /**
917 * Performs the <code>Action</code>.
918 *
919 * @param event the action event describing the user action
920 */
921 public void actionPerformed(ActionEvent event)
922 {
923 JTextComponent target = getTextComponent(event);
924 if (target != null)
925 target.cut();
926 }
927 }
928
929 /**
930 * Copies content from the system clipboard into the editor.
931 *
932 * @see Toolkit#getSystemClipboard()
933 * @see CopyAction
934 * @see CutAction
935 */
936 public static class PasteAction extends TextAction
937 {
938
939 /**
940 * Create a new <code>PasteAction</code>.
941 */
942 public PasteAction()
943 {
944 super(pasteAction);
945 }
946
947 /**
948 * Performs the <code>Action</code>.
949 *
950 * @param event the action event describing the user action
951 */
952 public void actionPerformed(ActionEvent event)
953 {
954 JTextComponent target = getTextComponent(event);
955 if (target != null)
956 target.paste();
957 }
958 }
959
960 /**
961 * This action is executed as default action when a KEY_TYPED
962 * event is received and no keymap entry exists for that. The purpose
963 * of this action is to filter out a couple of characters. This includes
964 * the control characters and characters with the ALT-modifier.
965 *
966 * If an event does not get filtered, it is inserted into the document
967 * of the text component. If there is some text selected in the text
968 * component, this text will be replaced.
969 */
970 public static class DefaultKeyTypedAction
971 extends TextAction
972 {
973
974 /**
975 * Creates a new <code>DefaultKeyTypedAction</code>.
976 */
977 public DefaultKeyTypedAction()
978 {
979 super(defaultKeyTypedAction);
980 }
981
982 /**
983 * Performs the <code>Action</code>.
984 *
985 * @param event the action event describing the user action
986 */
987 public void actionPerformed(ActionEvent event)
988 {
989 // first we filter the following events:
990 // - control characters
991 // - key events with the ALT modifier
992 JTextComponent target = getTextComponent(event);
993 if ((target != null) && (event != null))
994 {
995 if ((target.isEditable()) && (target.isEnabled()))
996 {
997 String content = event.getActionCommand();
998 int mod = event.getModifiers();
999 if ((content != null) && (content.length() > 0)
1000 && (mod & ActionEvent.ALT_MASK) == 0
1001 && (mod & ActionEvent.CTRL_MASK) == 0)
1002 {
1003 char c = content.charAt(0);
1004 if ((c >= 0x20) && (c != 0x7F))
1005 {
1006 target.replaceSelection(content);
1007 }
1008 }
1009 }
1010 }
1011 }
1012 }
1013
1014 /**
1015 * This action inserts a newline character into the document
1016 * of the text component. This is typically triggered by hitting
1017 * ENTER on the keyboard.
1018 */
1019 public static class InsertBreakAction extends TextAction
1020 {
1021
1022 /**
1023 * Creates a new <code>InsertBreakAction</code>.
1024 */
1025 public InsertBreakAction()
1026 {
1027 super(insertBreakAction);
1028 }
1029
1030 /**
1031 * Performs the <code>Action</code>.
1032 *
1033 * @param event the action event describing the user action
1034 */
1035 public void actionPerformed(ActionEvent event)
1036 {
1037 JTextComponent t = getTextComponent(event);
1038 if (t != null)
1039 t.replaceSelection("\n");
1040 }
1041 }
1042
1043 /**
1044 * Places content into the associated editor. If there currently is a
1045 * selection, this selection is replaced.
1046 */
1047 // FIXME: Figure out what this Action is supposed to do. Obviously text
1048 // that is entered by the user is inserted through DefaultKeyTypedAction.
1049 public static class InsertContentAction extends TextAction
1050 {
1051
1052 /**
1053 * Creates a new <code>InsertContentAction</code>.
1054 */
1055 public InsertContentAction()
1056 {
1057 super(insertContentAction);
1058 }
1059
1060 /**
1061 * Performs the <code>Action</code>.
1062 *
1063 * @param event the action event describing the user action
1064 */
1065 public void actionPerformed(ActionEvent event)
1066 {
1067 // FIXME: Figure out what this Action is supposed to do. Obviously text
1068 // that is entered by the user is inserted through DefaultKeyTypedAction.
1069 }
1070 }
1071
1072 /**
1073 * Inserts a TAB character into the text editor.
1074 */
1075 public static class InsertTabAction extends TextAction
1076 {
1077
1078 /**
1079 * Creates a new <code>TabAction</code>.
1080 */
1081 public InsertTabAction()
1082 {
1083 super(insertTabAction);
1084 }
1085
1086 /**
1087 * Performs the <code>Action</code>.
1088 *
1089 * @param event the action event describing the user action
1090 */
1091 public void actionPerformed(ActionEvent event)
1092 {
1093 JTextComponent t = getTextComponent(event);
1094 if (t != null)
1095 t.replaceSelection("\t");
1096 }
1097 }
1098
1099 /**
1100 * The serial version of DefaultEditorKit.
1101 */
1102 private static final long serialVersionUID = 9017245433028523428L;
1103
1104 /**
1105 * The name of the <code>Action</code> that moves the caret one character
1106 * backwards.
1107 *
1108 * @see #getActions()
1109 */
1110 public static final String backwardAction = "caret-backward";
1111
1112 /**
1113 * The name of the <code>Action</code> that creates a beep in the speaker.
1114 *
1115 * @see #getActions()
1116 */
1117 public static final String beepAction = "beep";
1118
1119 /**
1120 * The name of the <code>Action</code> that moves the caret to the beginning
1121 * of the <code>Document</code>.
1122 *
1123 * @see #getActions()
1124 */
1125 public static final String beginAction = "caret-begin";
1126
1127 /**
1128 * The name of the <code>Action</code> that moves the caret to the beginning
1129 * of the current line.
1130 *
1131 * @see #getActions()
1132 */
1133 public static final String beginLineAction = "caret-begin-line";
1134
1135 /**
1136 * The name of the <code>Action</code> that moves the caret to the beginning
1137 * of the current paragraph.
1138 *
1139 * @see #getActions()
1140 */
1141 public static final String beginParagraphAction = "caret-begin-paragraph";
1142
1143 /**
1144 * The name of the <code>Action</code> that moves the caret to the beginning
1145 * of the current word.
1146 *
1147 * @see #getActions()
1148 */
1149 public static final String beginWordAction = "caret-begin-word";
1150
1151 /**
1152 * The name of the <code>Action</code> that copies the selected content
1153 * into the system clipboard.
1154 *
1155 * @see #getActions()
1156 */
1157 public static final String copyAction = "copy-to-clipboard";
1158
1159 /**
1160 * The name of the <code>Action</code> that copies the selected content
1161 * into the system clipboard and removes the selection.
1162 *
1163 * @see #getActions()
1164 */
1165 public static final String cutAction = "cut-to-clipboard";
1166
1167 /**
1168 * The name of the <code>Action</code> that is performed by default if
1169 * a key is typed and there is no keymap entry.
1170 *
1171 * @see #getActions()
1172 */
1173 public static final String defaultKeyTypedAction = "default-typed";
1174
1175 /**
1176 * The name of the <code>Action</code> that deletes the character that
1177 * follows the current caret position.
1178 *
1179 * @see #getActions()
1180 */
1181 public static final String deleteNextCharAction = "delete-next";
1182
1183 /**
1184 * The name of the <code>Action</code> that deletes the character that
1185 * precedes the current caret position.
1186 *
1187 * @see #getActions()
1188 */
1189 public static final String deletePrevCharAction = "delete-previous";
1190
1191 /**
1192 * The name of the <code>Action</code> that moves the caret one line down.
1193 *
1194 * @see #getActions()
1195 */
1196 public static final String downAction = "caret-down";
1197
1198 /**
1199 * The name of the <code>Action</code> that moves the caret to the end
1200 * of the <code>Document</code>.
1201 *
1202 * @see #getActions()
1203 */
1204 public static final String endAction = "caret-end";
1205
1206 /**
1207 * The name of the <code>Action</code> that moves the caret to the end
1208 * of the current line.
1209 *
1210 * @see #getActions()
1211 */
1212 public static final String endLineAction = "caret-end-line";
1213
1214 /**
1215 * When a document is read and an CRLF is encountered, then we add a property
1216 * with this name and a value of "\r\n".
1217 */
1218 public static final String EndOfLineStringProperty = "__EndOfLine__";
1219
1220 /**
1221 * The name of the <code>Action</code> that moves the caret to the end
1222 * of the current paragraph.
1223 *
1224 * @see #getActions()
1225 */
1226 public static final String endParagraphAction = "caret-end-paragraph";
1227
1228 /**
1229 * The name of the <code>Action</code> that moves the caret to the end
1230 * of the current word.
1231 *
1232 * @see #getActions()
1233 */
1234 public static final String endWordAction = "caret-end-word";
1235
1236 /**
1237 * The name of the <code>Action</code> that moves the caret one character
1238 * forward.
1239 *
1240 * @see #getActions()
1241 */
1242 public static final String forwardAction = "caret-forward";
1243
1244 /**
1245 * The name of the <code>Action</code> that inserts a line break.
1246 *
1247 * @see #getActions()
1248 */
1249 public static final String insertBreakAction = "insert-break";
1250
1251 /**
1252 * The name of the <code>Action</code> that inserts some content.
1253 *
1254 * @see #getActions()
1255 */
1256 public static final String insertContentAction = "insert-content";
1257
1258 /**
1259 * The name of the <code>Action</code> that inserts a TAB.
1260 *
1261 * @see #getActions()
1262 */
1263 public static final String insertTabAction = "insert-tab";
1264
1265 /**
1266 * The name of the <code>Action</code> that moves the caret to the beginning
1267 * of the next word.
1268 *
1269 * @see #getActions()
1270 */
1271 public static final String nextWordAction = "caret-next-word";
1272
1273 /**
1274 * The name of the <code>Action</code> that moves the caret one page down.
1275 *
1276 * @see #getActions()
1277 */
1278 public static final String pageDownAction = "page-down";
1279
1280 /**
1281 * The name of the <code>Action</code> that moves the caret one page up.
1282 *
1283 * @see #getActions()
1284 */
1285 public static final String pageUpAction = "page-up";
1286
1287 /**
1288 * The name of the <code>Action</code> that copies content from the system
1289 * clipboard into the document.
1290 *
1291 * @see #getActions()
1292 */
1293 public static final String pasteAction = "paste-from-clipboard";
1294
1295 /**
1296 * The name of the <code>Action</code> that moves the caret to the beginning
1297 * of the previous word.
1298 *
1299 * @see #getActions()
1300 */
1301 public static final String previousWordAction = "caret-previous-word";
1302
1303 /**
1304 * The name of the <code>Action</code> that sets the editor in read only
1305 * mode.
1306 *
1307 * @see #getActions()
1308 */
1309 public static final String readOnlyAction = "set-read-only";
1310
1311 /**
1312 * The name of the <code>Action</code> that selects the whole document.
1313 *
1314 * @see #getActions()
1315 */
1316 public static final String selectAllAction = "select-all";
1317
1318 /**
1319 * The name of the <code>Action</code> that moves the caret one character
1320 * backwards, possibly extending the current selection.
1321 *
1322 * @see #getActions()
1323 */
1324 public static final String selectionBackwardAction = "selection-backward";
1325
1326 /**
1327 * The name of the <code>Action</code> that moves the caret to the beginning
1328 * of the document, possibly extending the current selection.
1329 *
1330 * @see #getActions()
1331 */
1332 public static final String selectionBeginAction = "selection-begin";
1333
1334 /**
1335 * The name of the <code>Action</code> that moves the caret to the beginning
1336 * of the current line, possibly extending the current selection.
1337 *
1338 * @see #getActions()
1339 */
1340 public static final String selectionBeginLineAction = "selection-begin-line";
1341
1342 /**
1343 * The name of the <code>Action</code> that moves the caret to the beginning
1344 * of the current paragraph, possibly extending the current selection.
1345 *
1346 * @see #getActions()
1347 */
1348 public static final String selectionBeginParagraphAction =
1349 "selection-begin-paragraph";
1350
1351 /**
1352 * The name of the <code>Action</code> that moves the caret to the beginning
1353 * of the current word, possibly extending the current selection.
1354 *
1355 * @see #getActions()
1356 */
1357 public static final String selectionBeginWordAction = "selection-begin-word";
1358
1359 /**
1360 * The name of the <code>Action</code> that moves the caret one line down,
1361 * possibly extending the current selection.
1362 *
1363 * @see #getActions()
1364 */
1365 public static final String selectionDownAction = "selection-down";
1366
1367 /**
1368 * The name of the <code>Action</code> that moves the caret to the end
1369 * of the document, possibly extending the current selection.
1370 *
1371 * @see #getActions()
1372 */
1373 public static final String selectionEndAction = "selection-end";
1374
1375 /**
1376 * The name of the <code>Action</code> that moves the caret to the end
1377 * of the current line, possibly extending the current selection.
1378 *
1379 * @see #getActions()
1380 */
1381 public static final String selectionEndLineAction = "selection-end-line";
1382
1383 /**
1384 * The name of the <code>Action</code> that moves the caret to the end
1385 * of the current paragraph, possibly extending the current selection.
1386 *
1387 * @see #getActions()
1388 */
1389 public static final String selectionEndParagraphAction =
1390 "selection-end-paragraph";
1391
1392 /**
1393 * The name of the <code>Action</code> that moves the caret to the end
1394 * of the current word, possibly extending the current selection.
1395 *
1396 * @see #getActions()
1397 */
1398 public static final String selectionEndWordAction = "selection-end-word";
1399
1400 /**
1401 * The name of the <code>Action</code> that moves the caret one character
1402 * forwards, possibly extending the current selection.
1403 *
1404 * @see #getActions()
1405 */
1406 public static final String selectionForwardAction = "selection-forward";
1407
1408 /**
1409 * The name of the <code>Action</code> that moves the caret to the beginning
1410 * of the next word, possibly extending the current selection.
1411 *
1412 * @see #getActions()
1413 */
1414 public static final String selectionNextWordAction = "selection-next-word";
1415
1416 /**
1417 * The name of the <code>Action</code> that moves the caret to the beginning
1418 * of the previous word, possibly extending the current selection.
1419 *
1420 * @see #getActions()
1421 */
1422 public static final String selectionPreviousWordAction =
1423 "selection-previous-word";
1424
1425 /**
1426 * The name of the <code>Action</code> that moves the caret one line up,
1427 * possibly extending the current selection.
1428 *
1429 * @see #getActions()
1430 */
1431 public static final String selectionUpAction = "selection-up";
1432
1433 /**
1434 * The name of the <code>Action</code> that selects the line around the
1435 * caret.
1436 *
1437 * @see #getActions()
1438 */
1439 public static final String selectLineAction = "select-line";
1440
1441 /**
1442 * The name of the <code>Action</code> that selects the paragraph around the
1443 * caret.
1444 *
1445 * @see #getActions()
1446 */
1447 public static final String selectParagraphAction = "select-paragraph";
1448
1449 /**
1450 * The name of the <code>Action</code> that selects the word around the
1451 * caret.
1452 *
1453 * @see #getActions()
1454 */
1455 public static final String selectWordAction = "select-word";
1456
1457 /**
1458 * The name of the <code>Action</code> that moves the caret one line up.
1459 *
1460 * @see #getActions()
1461 */
1462 public static final String upAction = "caret-up";
1463
1464 /**
1465 * The name of the <code>Action</code> that sets the editor in read-write
1466 * mode.
1467 *
1468 * @see #getActions()
1469 */
1470 public static final String writableAction = "set-writable";
1471
1472 /**
1473 * Creates a new <code>DefaultEditorKit</code>.
1474 */
1475 public DefaultEditorKit()
1476 {
1477 // Nothing to do here.
1478 }
1479
1480 /**
1481 * The <code>Action</code>s that are supported by the
1482 * <code>DefaultEditorKit</code>.
1483 */
1484 private static Action[] defaultActions =
1485 new Action[] {
1486 // These classes are public because they are so in the RI.
1487 new BeepAction(),
1488 new CopyAction(),
1489 new CutAction(),
1490 new DefaultKeyTypedAction(),
1491 new InsertBreakAction(),
1492 new InsertContentAction(),
1493 new InsertTabAction(),
1494 new PasteAction(),
1495
1496 // These are (package-)private inner classes.
1497 new DeleteNextCharAction(),
1498 new DeletePrevCharAction(),
1499
1500 new BeginLineAction(),
1501 new SelectionBeginLineAction(),
1502
1503 new EndLineAction(),
1504 new SelectionEndLineAction(),
1505
1506 new BackwardAction(),
1507 new SelectionBackwardAction(),
1508
1509 new ForwardAction(),
1510 new SelectionForwardAction(),
1511
1512 new UpAction(),
1513 new SelectionUpAction(),
1514
1515 new DownAction(),
1516 new SelectionDownAction(),
1517
1518 new NextWordAction(),
1519 new SelectionNextWordAction(),
1520
1521 new PreviousWordAction(),
1522 new SelectionPreviousWordAction(),
1523
1524 new BeginAction(),
1525 new SelectionBeginAction(),
1526
1527 new EndAction(),
1528 new SelectionEndAction(),
1529
1530 new BeginWordAction(),
1531 new SelectionBeginWordAction(),
1532
1533 new EndWordAction(),
1534 new SelectionEndWordAction(),
1535
1536 new SelectAllAction(),
1537 new SelectLineAction(),
1538 new SelectWordAction()
1539 };
1540
1541 /**
1542 * Creates the <code>Caret</code> for this <code>EditorKit</code>. This
1543 * returns a {@link DefaultCaret} in this case.
1544 *
1545 * @return the <code>Caret</code> for this <code>EditorKit</code>
1546 */
1547 public Caret createCaret()
1548 {
1549 return new DefaultCaret();
1550 }
1551
1552 /**
1553 * Creates the default {@link Document} that this <code>EditorKit</code>
1554 * supports. This is a {@link PlainDocument} in this case.
1555 *
1556 * @return the default {@link Document} that this <code>EditorKit</code>
1557 * supports
1558 */
1559 public Document createDefaultDocument()
1560 {
1561 return new PlainDocument();
1562 }
1563
1564 /**
1565 * Returns the <code>Action</code>s supported by this <code>EditorKit</code>.
1566 *
1567 * @return the <code>Action</code>s supported by this <code>EditorKit</code>
1568 */
1569 public Action[] getActions()
1570 {
1571 return defaultActions;
1572 }
1573
1574 /**
1575 * Returns the content type that this <code>EditorKit</code> supports.
1576 * The <code>DefaultEditorKit</code> supports the content type
1577 * <code>text/plain</code>.
1578 *
1579 * @return the content type that this <code>EditorKit</code> supports
1580 */
1581 public String getContentType()
1582 {
1583 return "text/plain";
1584 }
1585
1586 /**
1587 * Returns a {@link ViewFactory} that is able to create {@link View}s for
1588 * the <code>Element</code>s that are used in this <code>EditorKit</code>'s
1589 * model. This returns null which lets the UI of the text component supply
1590 * <code>View</code>s.
1591 *
1592 * @return a {@link ViewFactory} that is able to create {@link View}s for
1593 * the <code>Element</code>s that are used in this
1594 * <code>EditorKit</code>'s model
1595 */
1596 public ViewFactory getViewFactory()
1597 {
1598 return null;
1599 }
1600
1601 /**
1602 * Reads a document of the supported content type from an {@link InputStream}
1603 * into the actual {@link Document} object.
1604 *
1605 * @param in the stream from which to read the document
1606 * @param document the document model into which the content is read
1607 * @param offset the offset inside to document where the content is inserted
1608 *
1609 * @throws BadLocationException if <code>offset</code> is an invalid location
1610 * inside <code>document</code>
1611 * @throws IOException if something goes wrong while reading from
1612 * <code>in</code>
1613 */
1614 public void read(InputStream in, Document document, int offset)
1615 throws BadLocationException, IOException
1616 {
1617 read(new InputStreamReader(in), document, offset);
1618 }
1619
1620 /**
1621 * Reads a document of the supported content type from a {@link Reader}
1622 * into the actual {@link Document} object.
1623 *
1624 * @param in the reader from which to read the document
1625 * @param document the document model into which the content is read
1626 * @param offset the offset inside to document where the content is inserted
1627 *
1628 * @throws BadLocationException if <code>offset</code> is an invalid location
1629 * inside <code>document</code>
1630 * @throws IOException if something goes wrong while reading from
1631 * <code>in</code>
1632 */
1633 public void read(Reader in, Document document, int offset)
1634 throws BadLocationException, IOException
1635 {
1636 BufferedReader reader = new BufferedReader(in);
1637
1638 String line;
1639 CPStringBuilder content = new CPStringBuilder();
1640
1641 while ((line = reader.readLine()) != null)
1642 {
1643 content.append(line);
1644 content.append("\n");
1645 }
1646
1647 document.insertString(offset, content.substring(0, content.length() - 1),
1648 SimpleAttributeSet.EMPTY);
1649 }
1650
1651 /**
1652 * Writes the <code>Document</code> (or a fragment of the
1653 * <code>Document</code>) to an {@link OutputStream} in the
1654 * supported content type format.
1655 *
1656 * @param out the stream to write to
1657 * @param document the document that should be written out
1658 * @param offset the beginning offset from where to write
1659 * @param len the length of the fragment to write
1660 *
1661 * @throws BadLocationException if <code>offset</code> or
1662 * <code>offset + len</code>is an invalid location inside
1663 * <code>document</code>
1664 * @throws IOException if something goes wrong while writing to
1665 * <code>out</code>
1666 */
1667 public void write(OutputStream out, Document document, int offset, int len)
1668 throws BadLocationException, IOException
1669 {
1670 write(new OutputStreamWriter(out), document, offset, len);
1671 }
1672
1673 /**
1674 * Writes the <code>Document</code> (or a fragment of the
1675 * <code>Document</code>) to a {@link Writer} in the
1676 * supported content type format.
1677 *
1678 * @param out the writer to write to
1679 * @param document the document that should be written out
1680 * @param offset the beginning offset from where to write
1681 * @param len the length of the fragment to write
1682 *
1683 * @throws BadLocationException if <code>offset</code> is an
1684 * invalid location inside <code>document</code>.
1685 * @throws IOException if something goes wrong while writing to
1686 * <code>out</code>
1687 */
1688 public void write(Writer out, Document document, int offset, int len)
1689 throws BadLocationException, IOException
1690 {
1691 // Throw a BLE if offset is invalid
1692 if (offset < 0 || offset > document.getLength())
1693 throw new BadLocationException("Tried to write to invalid location",
1694 offset);
1695
1696 // If they gave an overly large len, just adjust it
1697 if (offset + len > document.getLength())
1698 len = document.getLength() - offset;
1699
1700 out.write(document.getText(offset, len));
1701 }
1702 }