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