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