OSDN Git Service

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