OSDN Git Service

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