Source for javax.swing.text.DefaultEditorKit

   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.Toolkit;
  42: import java.awt.event.ActionEvent;
  43: import java.io.BufferedReader;
  44: import java.io.IOException;
  45: import java.io.InputStream;
  46: import java.io.InputStreamReader;
  47: import java.io.OutputStream;
  48: import java.io.OutputStreamWriter;
  49: import java.io.Reader;
  50: import java.io.Writer;
  51: 
  52: import javax.swing.Action;
  53: 
  54: /**
  55:  * The default implementation of {@link EditorKit}. This <code>EditorKit</code>
  56:  * a plain text <code>Document</code> and several commands that together
  57:  * make up a basic editor, like cut / copy + paste.
  58:  *
  59:  * @author original author unknown
  60:  * @author Roman Kennke (roman@kennke.org)
  61:  */
  62: public class DefaultEditorKit extends EditorKit
  63: {
  64:   /**
  65:    * Creates a beep on the PC speaker.
  66:    *
  67:    * @see Toolkit#beep()
  68:    */
  69:   public static class BeepAction
  70:     extends TextAction
  71:   {
  72:     /**
  73:      * Creates a new <code>BeepAction</code>.
  74:      */
  75:     public BeepAction()
  76:     {
  77:       super(beepAction);
  78:     }
  79: 
  80:     /**
  81:      * Performs the <code>Action</code>.
  82:      *
  83:      * @param event the action event describing the user action
  84:      */
  85:     public void actionPerformed(ActionEvent event)
  86:     {
  87:       Toolkit.getDefaultToolkit().beep();
  88:     }
  89:   }
  90: 
  91:   /**
  92:    * Copies the selected content into the system clipboard.
  93:    *
  94:    * @see Toolkit#getSystemClipboard()
  95:    * @see CutAction
  96:    * @see PasteAction
  97:    */
  98:   public static class CopyAction 
  99:     extends TextAction
 100:   {
 101: 
 102:     /**
 103:      * Create a new <code>CopyAction</code>.
 104:      */
 105:     public CopyAction()
 106:     {
 107:       super(copyAction);
 108:     }
 109: 
 110:     /**
 111:      * Performs the <code>Action</code>.
 112:      *
 113:      * @param event the action event describing the user action
 114:      */
 115:     public void actionPerformed(ActionEvent event)
 116:     {
 117:       // FIXME: Implement me. Tookit.getSystemClipboard should be used
 118:       // for that.
 119:     }
 120:   }
 121: 
 122: 
 123:   /**
 124:    * Copies the selected content into the system clipboard and deletes the
 125:    * selection.
 126:    *
 127:    * @see Toolkit#getSystemClipboard()
 128:    * @see CopyAction
 129:    * @see PasteAction
 130:    */
 131:   public static class CutAction 
 132:     extends TextAction
 133:   {
 134: 
 135:     /**
 136:      * Create a new <code>CutAction</code>.
 137:      */
 138:     public CutAction()
 139:     {
 140:       super(cutAction);
 141:     }
 142: 
 143:     /**
 144:      * Performs the <code>Action</code>.
 145:      *
 146:      * @param event the action event describing the user action
 147:      */
 148:     public void actionPerformed(ActionEvent event)
 149:     {
 150:       // FIXME: Implement me. Tookit.getSystemClipboard should be used
 151:       // for that.
 152:     }
 153:   }
 154: 
 155:   /**
 156:    * Copies content from the system clipboard into the editor.
 157:    *
 158:    * @see Toolkit#getSystemClipboard()
 159:    * @see CopyAction
 160:    * @see CutAction
 161:    */
 162:   public static class PasteAction 
 163:     extends TextAction
 164:   {
 165: 
 166:     /**
 167:      * Create a new <code>PasteAction</code>.
 168:      */
 169:     public PasteAction()
 170:     {
 171:       super(pasteAction);
 172:     }
 173: 
 174:     /**
 175:      * Performs the <code>Action</code>.
 176:      *
 177:      * @param event the action event describing the user action
 178:      */
 179:     public void actionPerformed(ActionEvent event)
 180:     {
 181:       // FIXME: Implement me. Tookit.getSystemClipboard should be used
 182:       // for that.
 183:     }
 184:   }
 185: 
 186:   /**
 187:    * This action is executed as default action when a KEY_TYPED
 188:    * event is received and no keymap entry exists for that. The purpose
 189:    * of this action is to filter out a couple of characters. This includes
 190:    * the control characters and characters with the ALT-modifier.
 191:    * 
 192:    * If an event does not get filtered, it is inserted into the document
 193:    * of the text component. If there is some text selected in the text
 194:    * component, this text will be replaced.
 195:    */
 196:   public static class DefaultKeyTypedAction 
 197:     extends TextAction
 198:   {
 199: 
 200:     /**
 201:      * Creates a new <code>DefaultKeyTypedAction</code>.
 202:      */
 203:     public DefaultKeyTypedAction()
 204:     {
 205:       super(defaultKeyTypedAction);
 206:     }
 207: 
 208:     /**
 209:      * Performs the <code>Action</code>.
 210:      *
 211:      * @param event the action event describing the user action
 212:      */
 213:     public void actionPerformed(ActionEvent event)
 214:     {
 215:       // first we filter the following events:
 216:       // - control characters
 217:       // - key events with the ALT modifier (FIXME: filter that too!)
 218:       char c = event.getActionCommand().charAt(0);
 219:       if (Character.isISOControl(c))
 220:         return;
 221: 
 222:       JTextComponent t = getTextComponent(event);
 223:       if (t != null)
 224:         {
 225:           try
 226:             {
 227:               t.getDocument().insertString(t.getCaret().getDot(),
 228:                                            event.getActionCommand(), null);
 229:               t.getCaret().setDot(Math.min(t.getCaret().getDot() + 1,
 230:                                            t.getDocument().getEndPosition()
 231:                                            .getOffset()));
 232:             }
 233:           catch (BadLocationException be)
 234:             {
 235:               // FIXME: we're not authorized to throw this.. swallow it?
 236:             }
 237:         }
 238:     }
 239:   }
 240: 
 241:   /**
 242:    * This action inserts a newline character into the document
 243:    * of the text component. This is typically triggered by hitting
 244:    * ENTER on the keyboard.
 245:    */
 246:   public static class InsertBreakAction 
 247:     extends TextAction
 248:   {
 249: 
 250:     /**
 251:      * Creates a new <code>InsertBreakAction</code>.
 252:      */
 253:     public InsertBreakAction()
 254:     {
 255:       super(insertBreakAction);
 256:     }
 257: 
 258:     /**
 259:      * Performs the <code>Action</code>.
 260:      *
 261:      * @param event the action event describing the user action
 262:      */
 263:     public void actionPerformed(ActionEvent event)
 264:     {
 265:       JTextComponent t = getTextComponent(event);
 266:       t.replaceSelection("\n");
 267:     }
 268:   }
 269: 
 270:   /**
 271:    * Places content into the associated editor. If there currently is a
 272:    * selection, this selection is replaced.
 273:    */
 274:   // FIXME: Figure out what this Action is supposed to do. Obviously text
 275:   // that is entered by the user is inserted through DefaultKeyTypedAction.
 276:   public static class InsertContentAction 
 277:     extends TextAction
 278:   {
 279: 
 280:     /**
 281:      * Creates a new <code>InsertContentAction</code>.
 282:      */
 283:     public InsertContentAction()
 284:     {
 285:       super(insertContentAction);
 286:     }
 287: 
 288:     /**
 289:      * Performs the <code>Action</code>.
 290:      *
 291:      * @param event the action event describing the user action
 292:      */
 293:     public void actionPerformed(ActionEvent event)
 294:     {
 295:     }
 296:   }
 297: 
 298:   /**
 299:    * Inserts a TAB character into the text editor.
 300:    */
 301:   public static class InsertTabAction 
 302:     extends TextAction
 303:   {
 304: 
 305:     /**
 306:      * Creates a new <code>TabAction</code>.
 307:      */
 308:     public InsertTabAction()
 309:     {
 310:       super(insertTabAction);
 311:     }
 312: 
 313:     /**
 314:      * Performs the <code>Action</code>.
 315:      *
 316:      * @param event the action event describing the user action
 317:      */
 318:     public void actionPerformed(ActionEvent event)
 319:     {
 320:       // FIXME: Implement this.
 321:     }
 322:   }
 323: 
 324:   /**
 325:    * The serial version of DefaultEditorKit.
 326:    */
 327:   private static final long serialVersionUID = 9017245433028523428L;
 328: 
 329:   /**
 330:    * The name of the <code>Action</code> that moves the caret one character
 331:    * backwards.
 332:    *
 333:    * @see #getActions()
 334:    */
 335:   public static final String backwardAction = "caret-backward";
 336: 
 337:   /**
 338:    * The name of the <code>Action</code> that creates a beep in the speaker.
 339:    *
 340:    * @see #getActions()
 341:    */
 342:   public static final String beepAction = "beep";
 343: 
 344:   /**
 345:    * The name of the <code>Action</code> that moves the caret to the beginning
 346:    * of the <code>Document</code>.
 347:    *
 348:    * @see #getActions()
 349:    */
 350:   public static final String beginAction = "caret-begin";
 351: 
 352:   /**
 353:    * The name of the <code>Action</code> that moves the caret to the beginning
 354:    * of the current line.
 355:    *
 356:    * @see #getActions()
 357:    */
 358:   public static final String beginLineAction = "caret-begin-line";
 359: 
 360:   /**
 361:    * The name of the <code>Action</code> that moves the caret to the beginning
 362:    * of the current paragraph.
 363:    *
 364:    * @see #getActions()
 365:    */
 366:   public static final String beginParagraphAction = "caret-begin-paragraph";
 367: 
 368:   /**
 369:    * The name of the <code>Action</code> that moves the caret to the beginning
 370:    * of the current word.
 371:    *
 372:    * @see #getActions()
 373:    */
 374:   public static final String beginWordAction = "caret-begin-word";
 375: 
 376:   /**
 377:    * The name of the <code>Action</code> that copies the selected content
 378:    * into the system clipboard.
 379:    *
 380:    * @see #getActions()
 381:    */
 382:   public static final String copyAction = "copy-to-clipboard";
 383: 
 384:   /**
 385:    * The name of the <code>Action</code> that copies the selected content
 386:    * into the system clipboard and removes the selection.
 387:    *
 388:    * @see #getActions()
 389:    */
 390:   public static final String cutAction = "cut-to-clipboard";
 391: 
 392:   /**
 393:    * The name of the <code>Action</code> that is performed by default if
 394:    * a key is typed and there is no keymap entry.
 395:    *
 396:    * @see #getActions()
 397:    */
 398:   public static final String defaultKeyTypedAction = "default-typed";
 399: 
 400:   /**
 401:    * The name of the <code>Action</code> that deletes the character that
 402:    * follows the current caret position.
 403:    *
 404:    * @see #getActions()
 405:    */
 406:   public static final String deleteNextCharAction = "delete-next";
 407: 
 408:   /**
 409:    * The name of the <code>Action</code> that deletes the character that
 410:    * precedes the current caret position.
 411:    *
 412:    * @see #getActions()
 413:    */
 414:   public static final String deletePrevCharAction = "delete-previous";
 415: 
 416:   /**
 417:    * The name of the <code>Action</code> that moves the caret one line down.
 418:    *
 419:    * @see #getActions()
 420:    */
 421:   public static final String downAction = "caret-down";
 422: 
 423:   /**
 424:    * The name of the <code>Action</code> that moves the caret to the end
 425:    * of the <code>Document</code>.
 426:    *
 427:    * @see #getActions()
 428:    */
 429:   public static final String endAction = "caret-end";
 430: 
 431:   /**
 432:    * The name of the <code>Action</code> that moves the caret to the end
 433:    * of the current line.
 434:    *
 435:    * @see #getActions()
 436:    */
 437:   public static final String endLineAction = "caret-end-line";
 438: 
 439:   /**
 440:    * When a document is read and an CRLF is encountered, then we add a property
 441:    * with this name and a value of &quot;\r\n&quot;.
 442:    */
 443:   public static final String EndOfLineStringProperty = "__EndOfLine__";
 444: 
 445:   /**
 446:    * The name of the <code>Action</code> that moves the caret to the end
 447:    * of the current paragraph.
 448:    *
 449:    * @see #getActions()
 450:    */
 451:   public static final String endParagraphAction = "caret-end-paragraph";
 452: 
 453:   /**
 454:    * The name of the <code>Action</code> that moves the caret to the end
 455:    * of the current word.
 456:    *
 457:    * @see #getActions()
 458:    */
 459:   public static final String endWordAction = "caret-end-word";
 460: 
 461:   /**
 462:    * The name of the <code>Action</code> that moves the caret one character
 463:    * forward.
 464:    *
 465:    * @see #getActions()
 466:    */
 467:   public static final String forwardAction = "caret-forward";
 468: 
 469:   /**
 470:    * The name of the <code>Action</code> that inserts a line break.
 471:    *
 472:    * @see #getActions()
 473:    */
 474:   public static final String insertBreakAction = "insert-break";
 475: 
 476:   /**
 477:    * The name of the <code>Action</code> that inserts some content.
 478:    *
 479:    * @see #getActions()
 480:    */
 481:   public static final String insertContentAction = "insert-content";
 482: 
 483:   /**
 484:    * The name of the <code>Action</code> that inserts a TAB.
 485:    *
 486:    * @see #getActions()
 487:    */
 488:   public static final String insertTabAction = "insert-tab";
 489: 
 490:   /**
 491:    * The name of the <code>Action</code> that moves the caret to the beginning
 492:    * of the next word.
 493:    *
 494:    * @see #getActions()
 495:    */
 496:   public static final String nextWordAction = "caret-next-word";
 497: 
 498:   /**
 499:    * The name of the <code>Action</code> that moves the caret one page down.
 500:    *
 501:    * @see #getActions()
 502:    */
 503:   public static final String pageDownAction = "page-down";
 504: 
 505:   /**
 506:    * The name of the <code>Action</code> that moves the caret one page up.
 507:    *
 508:    * @see #getActions()
 509:    */
 510:   public static final String pageUpAction = "page-up";
 511: 
 512:   /**
 513:    * The name of the <code>Action</code> that copies content from the system
 514:    * clipboard into the document.
 515:    *
 516:    * @see #getActions()
 517:    */
 518:   public static final String pasteAction = "paste-from-clipboard";
 519: 
 520:   /**
 521:    * The name of the <code>Action</code> that moves the caret to the beginning
 522:    * of the previous word.
 523:    *
 524:    * @see #getActions()
 525:    */
 526:   public static final String previousWordAction = "caret-previous-word";
 527: 
 528:   /**
 529:    * The name of the <code>Action</code> that sets the editor in read only
 530:    * mode.
 531:    *
 532:    * @see #getActions()
 533:    */
 534:   public static final String readOnlyAction = "set-read-only";
 535: 
 536:   /**
 537:    * The name of the <code>Action</code> that selects the whole document.
 538:    *
 539:    * @see #getActions()
 540:    */
 541:   public static final String selectAllAction = "select-all";
 542: 
 543:   /**
 544:    * The name of the <code>Action</code> that moves the caret one character
 545:    * backwards, possibly extending the current selection.
 546:    *
 547:    * @see #getActions()
 548:    */
 549:   public static final String selectionBackwardAction = "selection-backward";
 550: 
 551:   /**
 552:    * The name of the <code>Action</code> that moves the caret to the beginning
 553:    * of the document, possibly extending the current selection.
 554:    *
 555:    * @see #getActions()
 556:    */
 557:   public static final String selectionBeginAction = "selection-begin";
 558: 
 559:   /**
 560:    * The name of the <code>Action</code> that moves the caret to the beginning
 561:    * of the current line, possibly extending the current selection.
 562:    *
 563:    * @see #getActions()
 564:    */
 565:   public static final String selectionBeginLineAction = "selection-begin-line";
 566: 
 567:   /**
 568:    * The name of the <code>Action</code> that moves the caret to the beginning
 569:    * of the current paragraph, possibly extending the current selection.
 570:    *
 571:    * @see #getActions()
 572:    */
 573:   public static final String selectionBeginParagraphAction =
 574:     "selection-begin-paragraph";
 575: 
 576:   /**
 577:    * The name of the <code>Action</code> that moves the caret to the beginning
 578:    * of the current word, possibly extending the current selection.
 579:    *
 580:    * @see #getActions()
 581:    */
 582:   public static final String selectionBeginWordAction = "selection-begin-word";
 583: 
 584:   /**
 585:    * The name of the <code>Action</code> that moves the caret one line down,
 586:    * possibly extending the current selection.
 587:    *
 588:    * @see #getActions()
 589:    */
 590:   public static final String selectionDownAction = "selection-down";
 591: 
 592:   /**
 593:    * The name of the <code>Action</code> that moves the caret to the end
 594:    * of the document, possibly extending the current selection.
 595:    *
 596:    * @see #getActions()
 597:    */
 598:   public static final String selectionEndAction = "selection-end";
 599: 
 600:   /**
 601:    * The name of the <code>Action</code> that moves the caret to the end
 602:    * of the current line, possibly extending the current selection.
 603:    *
 604:    * @see #getActions()
 605:    */
 606:   public static final String selectionEndLineAction = "selection-end-line";
 607: 
 608:   /**
 609:    * The name of the <code>Action</code> that moves the caret to the end
 610:    * of the current paragraph, possibly extending the current selection.
 611:    *
 612:    * @see #getActions()
 613:    */
 614:   public static final String selectionEndParagraphAction =
 615:     "selection-end-paragraph";
 616: 
 617:   /**
 618:    * The name of the <code>Action</code> that moves the caret to the end
 619:    * of the current word, possibly extending the current selection.
 620:    *
 621:    * @see #getActions()
 622:    */
 623:   public static final String selectionEndWordAction = "selection-end-word";
 624: 
 625:   /**
 626:    * The name of the <code>Action</code> that moves the caret one character
 627:    * forwards, possibly extending the current selection.
 628:    *
 629:    * @see #getActions()
 630:    */
 631:   public static final String selectionForwardAction = "selection-forward";
 632: 
 633:   /**
 634:    * The name of the <code>Action</code> that moves the caret to the beginning
 635:    * of the next word, possibly extending the current selection.
 636:    *
 637:    * @see #getActions()
 638:    */
 639:   public static final String selectionNextWordAction = "selection-next-word";
 640: 
 641:   /**
 642:    * The name of the <code>Action</code> that moves the caret to the beginning
 643:    * of the previous word, possibly extending the current selection.
 644:    *
 645:    * @see #getActions()
 646:    */
 647:   public static final String selectionPreviousWordAction =
 648:     "selection-previous-word";
 649: 
 650:   /**
 651:    * The name of the <code>Action</code> that moves the caret one line up,
 652:    * possibly extending the current selection.
 653:    *
 654:    * @see #getActions()
 655:    */
 656:   public static final String selectionUpAction = "selection-up";
 657: 
 658:   /**
 659:    * The name of the <code>Action</code> that selects the line around the
 660:    * caret.
 661:    *
 662:    * @see #getActions()
 663:    */
 664:   public static final String selectLineAction = "select-line";
 665: 
 666:   /**
 667:    * The name of the <code>Action</code> that selects the paragraph around the
 668:    * caret.
 669:    *
 670:    * @see #getActions()
 671:    */
 672:   public static final String selectParagraphAction = "select-paragraph";
 673: 
 674:   /**
 675:    * The name of the <code>Action</code> that selects the word around the
 676:    * caret.
 677:    *
 678:    * @see #getActions()
 679:    */
 680:   public static final String selectWordAction = "select-word";
 681: 
 682:   /**
 683:    * The name of the <code>Action</code> that moves the caret one line up.
 684:    *
 685:    * @see #getActions()
 686:    */
 687:   public static final String upAction = "caret-up";
 688: 
 689:   /**
 690:    * The name of the <code>Action</code> that sets the editor in read-write
 691:    * mode.
 692:    *
 693:    * @see #getActions()
 694:    */
 695:   public static final String writableAction = "set-writable";
 696: 
 697:   /**
 698:    * Creates a new <code>DefaultEditorKit</code>.
 699:    */
 700:   public DefaultEditorKit()
 701:   {
 702:   }
 703: 
 704:   /**
 705:    * The <code>Action</code>s that are supported by the
 706:    * <code>DefaultEditorKit</code>.
 707:    */
 708:   // TODO: All these inner classes look ugly. Maybe work out a better way
 709:   // to handle this.
 710:   private static Action[] defaultActions = 
 711:   new Action[] {
 712:     new BeepAction(),
 713:     new CopyAction(),
 714:     new CutAction(),
 715:     new DefaultKeyTypedAction(),
 716:     new InsertBreakAction(),
 717:     new InsertContentAction(),
 718:     new InsertTabAction(),
 719:     new PasteAction(),
 720:     new TextAction(deleteNextCharAction) 
 721:     { 
 722:       public void actionPerformed(ActionEvent event)
 723:       {
 724:         JTextComponent t = getTextComponent(event);
 725:         if (t != null)
 726:           {
 727:             try
 728:               {
 729:                 int pos = t.getCaret().getDot();
 730:                 if (pos < t.getDocument().getEndPosition().getOffset())
 731:                   {
 732:                     t.getDocument().remove(t.getCaret().getDot(), 1);
 733:                   }
 734:               }
 735:             catch (BadLocationException e)
 736:               {
 737:                 // FIXME: we're not authorized to throw this.. swallow it?
 738:               }
 739:           }
 740:       }
 741:     },
 742:     new TextAction(deletePrevCharAction) 
 743:     { 
 744:       public void actionPerformed(ActionEvent event)
 745:       {
 746:         JTextComponent t = getTextComponent(event);
 747:         if (t != null)
 748:           {
 749:             try
 750:               {
 751:                 int pos = t.getCaret().getDot();
 752:                 if (pos > t.getDocument().getStartPosition().getOffset())
 753:                   {
 754:                     t.getDocument().remove(pos - 1, 1);
 755:                     t.getCaret().setDot(pos - 1);
 756:                   }
 757:               }
 758:             catch (BadLocationException e)
 759:               {
 760:                 // FIXME: we're not authorized to throw this.. swallow it?
 761:               }
 762:           }
 763:       }
 764:     },
 765:     new TextAction(backwardAction) 
 766:     { 
 767:       public void actionPerformed(ActionEvent event)
 768:       {
 769:         JTextComponent t = getTextComponent(event);
 770:         if (t != null)
 771:           {
 772:             t.getCaret().setDot(Math.max(t.getCaret().getDot() - 1,
 773:                                          t.getDocument().getStartPosition().getOffset()));
 774:           }
 775:       }
 776:     },
 777:     new TextAction(forwardAction) 
 778:     { 
 779:       public void actionPerformed(ActionEvent event)
 780:       {
 781:         JTextComponent t = getTextComponent(event);
 782:         if (t != null)
 783:           {
 784:             t.getCaret().setDot(Math.min(t.getCaret().getDot() + 1,
 785:                                          t.getDocument().getEndPosition().getOffset()));
 786:           }
 787:       }
 788:     },
 789:     new TextAction(selectionBackwardAction)
 790:     {
 791:       public void actionPerformed(ActionEvent event)
 792:       {
 793:     JTextComponent t = getTextComponent(event);
 794:     if (t != null)
 795:       {
 796:         t.getCaret().moveDot(Math.max(t.getCaret().getDot() - 1,
 797:                       t.getDocument().getStartPosition().getOffset()));
 798:       }
 799:       }
 800:     },
 801:     new TextAction(selectionForwardAction)
 802:     {
 803:       public void actionPerformed(ActionEvent event)
 804:       {
 805:         JTextComponent t = getTextComponent(event);
 806:         if (t != null)
 807:           {
 808:             t.getCaret().moveDot(Math.min(t.getCaret().getDot() + 1,
 809:                                           t.getDocument().getEndPosition().getOffset()));
 810:           }
 811:       }
 812:     },
 813:   };
 814: 
 815:   /**
 816:    * Creates the <code>Caret</code> for this <code>EditorKit</code>. This
 817:    * returns a {@link DefaultCaret} in this case.
 818:    *
 819:    * @return the <code>Caret</code> for this <code>EditorKit</code>
 820:    */
 821:   public Caret createCaret()
 822:   {
 823:     return new DefaultCaret();
 824:   }
 825: 
 826:   /**
 827:    * Creates the default {@link Document} that this <code>EditorKit</code>
 828:    * supports. This is a {@link PlainDocument} in this case.
 829:    *
 830:    * @return the default {@link Document} that this <code>EditorKit</code>
 831:    *         supports
 832:    */
 833:   public Document createDefaultDocument()
 834:   {
 835:     return new PlainDocument();
 836:   }
 837: 
 838:   /**
 839:    * Returns the <code>Action</code>s supported by this <code>EditorKit</code>.
 840:    *
 841:    * @return the <code>Action</code>s supported by this <code>EditorKit</code>
 842:    */
 843:   public Action[] getActions()
 844:   {
 845:     return defaultActions;
 846:   }
 847: 
 848:   /**
 849:    * Returns the content type that this <code>EditorKit</code> supports.
 850:    * The <code>DefaultEditorKit</code> supports the content type
 851:    * <code>text/plain</code>.
 852:    *
 853:    * @return the content type that this <code>EditorKit</code> supports
 854:    */
 855:   public String getContentType()
 856:   {
 857:     return "text/plain";
 858:   }
 859: 
 860:   /**
 861:    * Returns a {@link ViewFactory} that is able to create {@link View}s for
 862:    * the <code>Element</code>s that are used in this <code>EditorKit</code>'s
 863:    * model. This returns null which lets the UI of the text component supply
 864:    * <code>View</code>s.
 865:    *
 866:    * @return a {@link ViewFactory} that is able to create {@link View}s for
 867:    *         the <code>Element</code>s that are used in this
 868:    *         <code>EditorKit</code>'s model
 869:    */
 870:   public ViewFactory getViewFactory()
 871:   {
 872:     return null;
 873:   }
 874: 
 875:   /**
 876:    * Reads a document of the supported content type from an {@link InputStream}
 877:    * into the actual {@link Document} object.
 878:    *
 879:    * @param in the stream from which to read the document
 880:    * @param document the document model into which the content is read
 881:    * @param offset the offset inside to document where the content is inserted
 882:    *
 883:    * @throws BadLocationException if <code>offset</code> is an invalid location
 884:    *         inside <code>document</code>
 885:    * @throws IOException if something goes wrong while reading from
 886:    *        <code>in</code>
 887:    */
 888:   public void read(InputStream in, Document document, int offset)
 889:     throws BadLocationException, IOException
 890:   {
 891:     read(new InputStreamReader(in), document, offset);
 892:   }
 893: 
 894:   /**
 895:    * Reads a document of the supported content type from a {@link Reader}
 896:    * into the actual {@link Document} object.
 897:    *
 898:    * @param in the reader from which to read the document
 899:    * @param document the document model into which the content is read
 900:    * @param offset the offset inside to document where the content is inserted
 901:    *
 902:    * @throws BadLocationException if <code>offset</code> is an invalid location
 903:    *         inside <code>document</code>
 904:    * @throws IOException if something goes wrong while reading from
 905:    *        <code>in</code>
 906:    */
 907:   public void read(Reader in, Document document, int offset)
 908:     throws BadLocationException, IOException
 909:   {
 910:     BufferedReader reader = new BufferedReader(in);
 911: 
 912:     String line;
 913:     StringBuffer content = new StringBuffer();
 914: 
 915:     while ((line = reader.readLine()) != null)
 916:       {
 917:     content.append(line);
 918:     content.append("\n");
 919:       }
 920:     
 921:     document.insertString(offset, content.toString(),
 922:               SimpleAttributeSet.EMPTY);
 923:   }
 924: 
 925:   /**
 926:    * Writes the <code>Document</code> (or a fragment of the
 927:    * <code>Document</code>) to an {@link OutputStream} in the
 928:    * supported content type format.
 929:    *
 930:    * @param out the stream to write to
 931:    * @param document the document that should be written out
 932:    * @param offset the beginning offset from where to write
 933:    * @param len the length of the fragment to write
 934:    *
 935:    * @throws BadLocationException if <code>offset</code> or
 936:    *         <code>offset + len</code>is an invalid location inside
 937:    *         <code>document</code>
 938:    * @throws IOException if something goes wrong while writing to
 939:    *        <code>out</code>
 940:    */
 941:   public void write(OutputStream out, Document document, int offset, int len)
 942:     throws BadLocationException, IOException
 943:   {
 944:     write(new OutputStreamWriter(out), document, offset, len);
 945:   }
 946: 
 947:   /**
 948:    * Writes the <code>Document</code> (or a fragment of the
 949:    * <code>Document</code>) to a {@link Writer} in the
 950:    * supported content type format.
 951:    *
 952:    * @param out the writer to write to
 953:    * @param document the document that should be written out
 954:    * @param offset the beginning offset from where to write
 955:    * @param len the length of the fragment to write
 956:    *
 957:    * @throws BadLocationException if <code>offset</code> or
 958:    *         <code>offset + len</code>is an invalid location inside
 959:    *         <code>document</code>
 960:    * @throws IOException if something goes wrong while writing to
 961:    *        <code>out</code>
 962:    */
 963:   public void write(Writer out, Document document, int offset, int len)
 964:     throws BadLocationException, IOException
 965:   {
 966:     // TODO: Implement this properly.
 967:   }
 968: }