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