1 /* 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing.text; 26 27 import sun.awt.SunToolkit; 28 29 import java.io.*; 30 import java.awt.*; 31 import java.awt.event.ActionEvent; 32 import java.text.*; 33 import javax.swing.Action; 34 import javax.swing.KeyStroke; 35 import javax.swing.SwingConstants; 36 import javax.swing.UIManager; 37 38 /** 39 * This is the set of things needed by a text component 40 * to be a reasonably functioning editor for some <em>type</em> 41 * of text document. This implementation provides a default 42 * implementation which treats text as plain text and 43 * provides a minimal set of actions for a simple editor. 44 * 45 * <dl> 46 * <dt><b>Newlines</b> 47 * <dd> 48 * There are two properties which deal with newlines. The 49 * system property, <code>line.separator</code>, is defined to be 50 * platform-dependent, either "\n", "\r", or "\r\n". There is also 51 * a property defined in <code>DefaultEditorKit</code>, called 52 * <a href=#EndOfLineStringProperty><code>EndOfLineStringProperty</code></a>, 53 * which is defined automatically when a document is loaded, to be 54 * the first occurrence of any of the newline characters. 55 * When a document is loaded, <code>EndOfLineStringProperty</code> 56 * is set appropriately, and when the document is written back out, the 57 * <code>EndOfLineStringProperty</code> is used. But while the document 58 * is in memory, the "\n" character is used to define a 59 * newline, regardless of how the newline is defined when 60 * the document is on disk. Therefore, for searching purposes, 61 * "\n" should always be used. When a new document is created, 62 * and the <code>EndOfLineStringProperty</code> has not been defined, 63 * it will use the System property when writing out the 64 * document. 65 * <p>Note that <code>EndOfLineStringProperty</code> is set 66 * on the <code>Document</code> using the <code>get/putProperty</code> 67 * methods. Subclasses may override this behavior. 68 * 69 * </dl> 70 * 71 * @author Timothy Prinzing 72 */ 73 @SuppressWarnings("serial") // Same-version serialization only 74 public class DefaultEditorKit extends EditorKit { 75 76 /** 77 * default constructor for DefaultEditorKit 78 */ 79 public DefaultEditorKit() { 80 } 81 82 /** 83 * Gets the MIME type of the data that this 84 * kit represents support for. The default 85 * is <code>text/plain</code>. 86 * 87 * @return the type 88 */ 89 public String getContentType() { 90 return "text/plain"; 91 } 92 93 /** 94 * Fetches a factory that is suitable for producing 95 * views of any models that are produced by this 96 * kit. The default is to have the UI produce the 97 * factory, so this method has no implementation. 98 * 99 * @return the view factory 100 */ 101 public ViewFactory getViewFactory() { 102 return null; 103 } 104 105 /** 106 * Fetches the set of commands that can be used 107 * on a text component that is using a model and 108 * view produced by this kit. 109 * 110 * @return the command list 111 */ 112 public Action[] getActions() { 113 return defaultActions; 114 } 115 116 /** 117 * Fetches a caret that can navigate through views 118 * produced by the associated ViewFactory. 119 * 120 * @return the caret 121 */ 122 public Caret createCaret() { 123 return null; 124 } 125 126 /** 127 * Creates an uninitialized text storage model (PlainDocument) 128 * that is appropriate for this type of editor. 129 * 130 * @return the model 131 */ 132 public Document createDefaultDocument() { 133 return new PlainDocument(); 134 } 135 136 /** 137 * Inserts content from the given stream which is expected 138 * to be in a format appropriate for this kind of content 139 * handler. 140 * 141 * @param in The stream to read from 142 * @param doc The destination for the insertion. 143 * @param pos The location in the document to place the 144 * content >=0. 145 * @exception IOException on any I/O error 146 * @exception BadLocationException if pos represents an invalid 147 * location within the document. 148 */ 149 public void read(InputStream in, Document doc, int pos) 150 throws IOException, BadLocationException { 151 152 read(new InputStreamReader(in), doc, pos); 153 } 154 155 /** 156 * Writes content from a document to the given stream 157 * in a format appropriate for this kind of content handler. 158 * 159 * @param out The stream to write to 160 * @param doc The source for the write. 161 * @param pos The location in the document to fetch the 162 * content >=0. 163 * @param len The amount to write out >=0. 164 * @exception IOException on any I/O error 165 * @exception BadLocationException if pos represents an invalid 166 * location within the document. 167 */ 168 public void write(OutputStream out, Document doc, int pos, int len) 169 throws IOException, BadLocationException { 170 OutputStreamWriter osw = new OutputStreamWriter(out); 171 172 write(osw, doc, pos, len); 173 osw.flush(); 174 } 175 176 /** 177 * Gets the input attributes for the pane. This method exists for 178 * the benefit of StyledEditorKit so that the read method will 179 * pick up the correct attributes to apply to inserted text. 180 * This class's implementation simply returns null. 181 * 182 * @return null 183 */ 184 MutableAttributeSet getInputAttributes() { 185 return null; 186 } 187 188 /** 189 * Inserts content from the given stream, which will be 190 * treated as plain text. 191 * 192 * @param in The stream to read from 193 * @param doc The destination for the insertion. 194 * @param pos The location in the document to place the 195 * content >=0. 196 * @exception IOException on any I/O error 197 * @exception BadLocationException if pos represents an invalid 198 * location within the document. 199 */ 200 public void read(Reader in, Document doc, int pos) 201 throws IOException, BadLocationException { 202 203 char[] buff = new char[4096]; 204 int nch; 205 boolean lastWasCR = false; 206 boolean isCRLF = false; 207 boolean isCR = false; 208 int last; 209 boolean wasEmpty = (doc.getLength() == 0); 210 AttributeSet attr = getInputAttributes(); 211 212 // Read in a block at a time, mapping \r\n to \n, as well as single 213 // \r's to \n's. If a \r\n is encountered, \r\n will be set as the 214 // newline string for the document, if \r is encountered it will 215 // be set as the newline character, otherwise the newline property 216 // for the document will be removed. 217 while ((nch = in.read(buff, 0, buff.length)) != -1) { 218 last = 0; 219 for(int counter = 0; counter < nch; counter++) { 220 switch(buff[counter]) { 221 case '\r': 222 if (lastWasCR) { 223 isCR = true; 224 if (counter == 0) { 225 doc.insertString(pos, "\n", attr); 226 pos++; 227 } 228 else { 229 buff[counter - 1] = '\n'; 230 } 231 } 232 else { 233 lastWasCR = true; 234 } 235 break; 236 case '\n': 237 if (lastWasCR) { 238 if (counter > (last + 1)) { 239 doc.insertString(pos, new String(buff, last, 240 counter - last - 1), attr); 241 pos += (counter - last - 1); 242 } 243 // else nothing to do, can skip \r, next write will 244 // write \n 245 lastWasCR = false; 246 last = counter; 247 isCRLF = true; 248 } 249 break; 250 default: 251 if (lastWasCR) { 252 isCR = true; 253 if (counter == 0) { 254 doc.insertString(pos, "\n", attr); 255 pos++; 256 } 257 else { 258 buff[counter - 1] = '\n'; 259 } 260 lastWasCR = false; 261 } 262 break; 263 } 264 } 265 if (last < nch) { 266 if(lastWasCR) { 267 if (last < (nch - 1)) { 268 doc.insertString(pos, new String(buff, last, 269 nch - last - 1), attr); 270 pos += (nch - last - 1); 271 } 272 } 273 else { 274 doc.insertString(pos, new String(buff, last, 275 nch - last), attr); 276 pos += (nch - last); 277 } 278 } 279 } 280 if (lastWasCR) { 281 doc.insertString(pos, "\n", attr); 282 isCR = true; 283 } 284 if (wasEmpty) { 285 if (isCRLF) { 286 doc.putProperty(EndOfLineStringProperty, "\r\n"); 287 } 288 else if (isCR) { 289 doc.putProperty(EndOfLineStringProperty, "\r"); 290 } 291 else { 292 doc.putProperty(EndOfLineStringProperty, "\n"); 293 } 294 } 295 } 296 297 /** 298 * Writes content from a document to the given stream 299 * as plain text. 300 * 301 * @param out The stream to write to 302 * @param doc The source for the write. 303 * @param pos The location in the document to fetch the 304 * content from >=0. 305 * @param len The amount to write out >=0. 306 * @exception IOException on any I/O error 307 * @exception BadLocationException if pos is not within 0 and 308 * the length of the document. 309 */ 310 public void write(Writer out, Document doc, int pos, int len) 311 throws IOException, BadLocationException { 312 313 if ((pos < 0) || ((pos + len) > doc.getLength())) { 314 throw new BadLocationException("DefaultEditorKit.write", pos); 315 } 316 Segment data = new Segment(); 317 int nleft = len; 318 int offs = pos; 319 Object endOfLineProperty = doc.getProperty(EndOfLineStringProperty); 320 if (endOfLineProperty == null) { 321 endOfLineProperty = System.lineSeparator(); 322 } 323 String endOfLine; 324 if (endOfLineProperty instanceof String) { 325 endOfLine = (String)endOfLineProperty; 326 } 327 else { 328 endOfLine = null; 329 } 330 if (endOfLineProperty != null && !endOfLine.equals("\n")) { 331 // There is an end of line string that isn't \n, have to iterate 332 // through and find all \n's and translate to end of line string. 333 while (nleft > 0) { 334 int n = Math.min(nleft, 4096); 335 doc.getText(offs, n, data); 336 int last = data.offset; 337 char[] array = data.array; 338 int maxCounter = last + data.count; 339 for (int counter = last; counter < maxCounter; counter++) { 340 if (array[counter] == '\n') { 341 if (counter > last) { 342 out.write(array, last, counter - last); 343 } 344 out.write(endOfLine); 345 last = counter + 1; 346 } 347 } 348 if (maxCounter > last) { 349 out.write(array, last, maxCounter - last); 350 } 351 offs += n; 352 nleft -= n; 353 } 354 } 355 else { 356 // Just write out text, will already have \n, no mapping to 357 // do. 358 while (nleft > 0) { 359 int n = Math.min(nleft, 4096); 360 doc.getText(offs, n, data); 361 out.write(data.array, data.offset, data.count); 362 offs += n; 363 nleft -= n; 364 } 365 } 366 out.flush(); 367 } 368 369 370 /** 371 * When reading a document if a CRLF is encountered a property 372 * with this name is added and the value will be "\r\n". 373 */ 374 public static final String EndOfLineStringProperty = "__EndOfLine__"; 375 376 // --- names of well-known actions --------------------------- 377 378 /** 379 * Name of the action to place content into the associated 380 * document. If there is a selection, it is removed before 381 * the new content is added. 382 * @see #getActions 383 */ 384 public static final String insertContentAction = "insert-content"; 385 386 /** 387 * Name of the action to place a line/paragraph break into 388 * the document. If there is a selection, it is removed before 389 * the break is added. 390 * @see #getActions 391 */ 392 public static final String insertBreakAction = "insert-break"; 393 394 /** 395 * Name of the action to place a tab character into 396 * the document. If there is a selection, it is removed before 397 * the tab is added. 398 * @see #getActions 399 */ 400 public static final String insertTabAction = "insert-tab"; 401 402 /** 403 * Name of the action to delete the character of content that 404 * precedes the current caret position. 405 * @see #getActions 406 */ 407 public static final String deletePrevCharAction = "delete-previous"; 408 409 /** 410 * Name of the action to delete the character of content that 411 * follows the current caret position. 412 * @see #getActions 413 */ 414 public static final String deleteNextCharAction = "delete-next"; 415 416 /** 417 * Name of the action to delete the word that 418 * follows the beginning of the selection. 419 * @see #getActions 420 * @see JTextComponent#getSelectionStart 421 * @since 1.6 422 */ 423 public static final String deleteNextWordAction = "delete-next-word"; 424 425 /** 426 * Name of the action to delete the word that 427 * precedes the beginning of the selection. 428 * @see #getActions 429 * @see JTextComponent#getSelectionStart 430 * @since 1.6 431 */ 432 public static final String deletePrevWordAction = "delete-previous-word"; 433 434 /** 435 * Name of the action to set the editor into read-only 436 * mode. 437 * @see #getActions 438 */ 439 public static final String readOnlyAction = "set-read-only"; 440 441 /** 442 * Name of the action to set the editor into writeable 443 * mode. 444 * @see #getActions 445 */ 446 public static final String writableAction = "set-writable"; 447 448 /** 449 * Name of the action to cut the selected region 450 * and place the contents into the system clipboard. 451 * @see JTextComponent#cut 452 * @see #getActions 453 */ 454 public static final String cutAction = "cut-to-clipboard"; 455 456 /** 457 * Name of the action to copy the selected region 458 * and place the contents into the system clipboard. 459 * @see JTextComponent#copy 460 * @see #getActions 461 */ 462 public static final String copyAction = "copy-to-clipboard"; 463 464 /** 465 * Name of the action to paste the contents of the 466 * system clipboard into the selected region, or before the 467 * caret if nothing is selected. 468 * @see JTextComponent#paste 469 * @see #getActions 470 */ 471 public static final String pasteAction = "paste-from-clipboard"; 472 473 /** 474 * Name of the action to create a beep. 475 * @see #getActions 476 */ 477 public static final String beepAction = "beep"; 478 479 /** 480 * Name of the action to page up vertically. 481 * @see #getActions 482 */ 483 public static final String pageUpAction = "page-up"; 484 485 /** 486 * Name of the action to page down vertically. 487 * @see #getActions 488 */ 489 public static final String pageDownAction = "page-down"; 490 491 /** 492 * Name of the action to page up vertically, and move the 493 * selection. 494 * @see #getActions 495 */ 496 /*public*/ static final String selectionPageUpAction = "selection-page-up"; 497 498 /** 499 * Name of the action to page down vertically, and move the 500 * selection. 501 * @see #getActions 502 */ 503 /*public*/ static final String selectionPageDownAction = "selection-page-down"; 504 505 /** 506 * Name of the action to page left horizontally, and move the 507 * selection. 508 * @see #getActions 509 */ 510 /*public*/ static final String selectionPageLeftAction = "selection-page-left"; 511 512 /** 513 * Name of the action to page right horizontally, and move the 514 * selection. 515 * @see #getActions 516 */ 517 /*public*/ static final String selectionPageRightAction = "selection-page-right"; 518 519 /** 520 * Name of the Action for moving the caret 521 * logically forward one position. 522 * @see #getActions 523 */ 524 public static final String forwardAction = "caret-forward"; 525 526 /** 527 * Name of the Action for moving the caret 528 * logically backward one position. 529 * @see #getActions 530 */ 531 public static final String backwardAction = "caret-backward"; 532 533 /** 534 * Name of the Action for extending the selection 535 * by moving the caret logically forward one position. 536 * @see #getActions 537 */ 538 public static final String selectionForwardAction = "selection-forward"; 539 540 /** 541 * Name of the Action for extending the selection 542 * by moving the caret logically backward one position. 543 * @see #getActions 544 */ 545 public static final String selectionBackwardAction = "selection-backward"; 546 547 /** 548 * Name of the Action for moving the caret 549 * logically upward one position. 550 * @see #getActions 551 */ 552 public static final String upAction = "caret-up"; 553 554 /** 555 * Name of the Action for moving the caret 556 * logically downward one position. 557 * @see #getActions 558 */ 559 public static final String downAction = "caret-down"; 560 561 /** 562 * Name of the Action for moving the caret 563 * logically upward one position, extending the selection. 564 * @see #getActions 565 */ 566 public static final String selectionUpAction = "selection-up"; 567 568 /** 569 * Name of the Action for moving the caret 570 * logically downward one position, extending the selection. 571 * @see #getActions 572 */ 573 public static final String selectionDownAction = "selection-down"; 574 575 /** 576 * Name of the <code>Action</code> for moving the caret 577 * to the beginning of a word. 578 * @see #getActions 579 */ 580 public static final String beginWordAction = "caret-begin-word"; 581 582 /** 583 * Name of the Action for moving the caret 584 * to the end of a word. 585 * @see #getActions 586 */ 587 public static final String endWordAction = "caret-end-word"; 588 589 /** 590 * Name of the <code>Action</code> for moving the caret 591 * to the beginning of a word, extending the selection. 592 * @see #getActions 593 */ 594 public static final String selectionBeginWordAction = "selection-begin-word"; 595 596 /** 597 * Name of the Action for moving the caret 598 * to the end of a word, extending the selection. 599 * @see #getActions 600 */ 601 public static final String selectionEndWordAction = "selection-end-word"; 602 603 /** 604 * Name of the <code>Action</code> for moving the caret to the 605 * beginning of the previous word. 606 * @see #getActions 607 */ 608 public static final String previousWordAction = "caret-previous-word"; 609 610 /** 611 * Name of the <code>Action</code> for moving the caret to the 612 * beginning of the next word. 613 * @see #getActions 614 */ 615 public static final String nextWordAction = "caret-next-word"; 616 617 /** 618 * Name of the <code>Action</code> for moving the selection to the 619 * beginning of the previous word, extending the selection. 620 * @see #getActions 621 */ 622 public static final String selectionPreviousWordAction = "selection-previous-word"; 623 624 /** 625 * Name of the <code>Action</code> for moving the selection to the 626 * beginning of the next word, extending the selection. 627 * @see #getActions 628 */ 629 public static final String selectionNextWordAction = "selection-next-word"; 630 631 /** 632 * Name of the <code>Action</code> for moving the caret 633 * to the beginning of a line. 634 * @see #getActions 635 */ 636 public static final String beginLineAction = "caret-begin-line"; 637 638 /** 639 * Name of the <code>Action</code> for moving the caret 640 * to the end of a line. 641 * @see #getActions 642 */ 643 public static final String endLineAction = "caret-end-line"; 644 645 /** 646 * Name of the <code>Action</code> for moving the caret 647 * to the beginning of a line, extending the selection. 648 * @see #getActions 649 */ 650 public static final String selectionBeginLineAction = "selection-begin-line"; 651 652 /** 653 * Name of the <code>Action</code> for moving the caret 654 * to the end of a line, extending the selection. 655 * @see #getActions 656 */ 657 public static final String selectionEndLineAction = "selection-end-line"; 658 659 /** 660 * Name of the <code>Action</code> for moving the caret 661 * to the beginning of a paragraph. 662 * @see #getActions 663 */ 664 public static final String beginParagraphAction = "caret-begin-paragraph"; 665 666 /** 667 * Name of the <code>Action</code> for moving the caret 668 * to the end of a paragraph. 669 * @see #getActions 670 */ 671 public static final String endParagraphAction = "caret-end-paragraph"; 672 673 /** 674 * Name of the <code>Action</code> for moving the caret 675 * to the beginning of a paragraph, extending the selection. 676 * @see #getActions 677 */ 678 public static final String selectionBeginParagraphAction = "selection-begin-paragraph"; 679 680 /** 681 * Name of the <code>Action</code> for moving the caret 682 * to the end of a paragraph, extending the selection. 683 * @see #getActions 684 */ 685 public static final String selectionEndParagraphAction = "selection-end-paragraph"; 686 687 /** 688 * Name of the <code>Action</code> for moving the caret 689 * to the beginning of the document. 690 * @see #getActions 691 */ 692 public static final String beginAction = "caret-begin"; 693 694 /** 695 * Name of the <code>Action</code> for moving the caret 696 * to the end of the document. 697 * @see #getActions 698 */ 699 public static final String endAction = "caret-end"; 700 701 /** 702 * Name of the <code>Action</code> for moving the caret 703 * to the beginning of the document. 704 * @see #getActions 705 */ 706 public static final String selectionBeginAction = "selection-begin"; 707 708 /** 709 * Name of the Action for moving the caret 710 * to the end of the document. 711 * @see #getActions 712 */ 713 public static final String selectionEndAction = "selection-end"; 714 715 /** 716 * Name of the Action for selecting a word around the caret. 717 * @see #getActions 718 */ 719 public static final String selectWordAction = "select-word"; 720 721 /** 722 * Name of the Action for selecting a line around the caret. 723 * @see #getActions 724 */ 725 public static final String selectLineAction = "select-line"; 726 727 /** 728 * Name of the Action for selecting a paragraph around the caret. 729 * @see #getActions 730 */ 731 public static final String selectParagraphAction = "select-paragraph"; 732 733 /** 734 * Name of the Action for selecting the entire document 735 * @see #getActions 736 */ 737 public static final String selectAllAction = "select-all"; 738 739 /** 740 * Name of the Action for removing selection 741 * @see #getActions 742 */ 743 /*public*/ static final String unselectAction = "unselect"; 744 745 /** 746 * Name of the Action for toggling the component's orientation. 747 * @see #getActions 748 */ 749 /*public*/ static final String toggleComponentOrientationAction 750 = "toggle-componentOrientation"; 751 752 /** 753 * Name of the action that is executed by default if 754 * a <em>key typed event</em> is received and there 755 * is no keymap entry. 756 * @see #getActions 757 */ 758 public static final String defaultKeyTypedAction = "default-typed"; 759 760 // --- Action implementations --------------------------------- 761 762 private static final Action[] defaultActions = { 763 new InsertContentAction(), new DeletePrevCharAction(), 764 new DeleteNextCharAction(), new ReadOnlyAction(), 765 new DeleteWordAction(deletePrevWordAction), 766 new DeleteWordAction(deleteNextWordAction), 767 new WritableAction(), new CutAction(), 768 new CopyAction(), new PasteAction(), 769 new VerticalPageAction(pageUpAction, -1, false), 770 new VerticalPageAction(pageDownAction, 1, false), 771 new VerticalPageAction(selectionPageUpAction, -1, true), 772 new VerticalPageAction(selectionPageDownAction, 1, true), 773 new PageAction(selectionPageLeftAction, true, true), 774 new PageAction(selectionPageRightAction, false, true), 775 new InsertBreakAction(), new BeepAction(), 776 new NextVisualPositionAction(forwardAction, false, 777 SwingConstants.EAST), 778 new NextVisualPositionAction(backwardAction, false, 779 SwingConstants.WEST), 780 new NextVisualPositionAction(selectionForwardAction, true, 781 SwingConstants.EAST), 782 new NextVisualPositionAction(selectionBackwardAction, true, 783 SwingConstants.WEST), 784 new NextVisualPositionAction(upAction, false, 785 SwingConstants.NORTH), 786 new NextVisualPositionAction(downAction, false, 787 SwingConstants.SOUTH), 788 new NextVisualPositionAction(selectionUpAction, true, 789 SwingConstants.NORTH), 790 new NextVisualPositionAction(selectionDownAction, true, 791 SwingConstants.SOUTH), 792 new BeginWordAction(beginWordAction, false), 793 new EndWordAction(endWordAction, false), 794 new BeginWordAction(selectionBeginWordAction, true), 795 new EndWordAction(selectionEndWordAction, true), 796 new PreviousWordAction(previousWordAction, false), 797 new NextWordAction(nextWordAction, false), 798 new PreviousWordAction(selectionPreviousWordAction, true), 799 new NextWordAction(selectionNextWordAction, true), 800 new BeginLineAction(beginLineAction, false), 801 new EndLineAction(endLineAction, false), 802 new BeginLineAction(selectionBeginLineAction, true), 803 new EndLineAction(selectionEndLineAction, true), 804 new BeginParagraphAction(beginParagraphAction, false), 805 new EndParagraphAction(endParagraphAction, false), 806 new BeginParagraphAction(selectionBeginParagraphAction, true), 807 new EndParagraphAction(selectionEndParagraphAction, true), 808 new BeginAction(beginAction, false), 809 new EndAction(endAction, false), 810 new BeginAction(selectionBeginAction, true), 811 new EndAction(selectionEndAction, true), 812 new DefaultKeyTypedAction(), new InsertTabAction(), 813 new SelectWordAction(), new SelectLineAction(), 814 new SelectParagraphAction(), new SelectAllAction(), 815 new UnselectAction(), new ToggleComponentOrientationAction(), 816 new DumpModelAction() 817 }; 818 819 /** 820 * The action that is executed by default if 821 * a <em>key typed event</em> is received and there 822 * is no keymap entry. There is a variation across 823 * different VM's in what gets sent as a <em>key typed</em> 824 * event, and this action tries to filter out the undesired 825 * events. This filters the control characters and those 826 * with the ALT modifier. It allows Control-Alt sequences 827 * through as these form legitimate unicode characters on 828 * some PC keyboards. 829 * <p> 830 * If the event doesn't get filtered, it will try to insert 831 * content into the text editor. The content is fetched 832 * from the command string of the ActionEvent. The text 833 * entry is done through the <code>replaceSelection</code> 834 * method on the target text component. This is the 835 * action that will be fired for most text entry tasks. 836 * <p> 837 * <strong>Warning:</strong> 838 * Serialized objects of this class will not be compatible with 839 * future Swing releases. The current serialization support is 840 * appropriate for short term storage or RMI between applications running 841 * the same version of Swing. As of 1.4, support for long term storage 842 * of all JavaBeans™ 843 * has been added to the <code>java.beans</code> package. 844 * Please see {@link java.beans.XMLEncoder}. 845 * 846 * @see DefaultEditorKit#defaultKeyTypedAction 847 * @see DefaultEditorKit#getActions 848 * @see Keymap#setDefaultAction 849 * @see Keymap#getDefaultAction 850 */ 851 @SuppressWarnings("serial") // Same-version serialization only 852 public static class DefaultKeyTypedAction extends TextAction { 853 854 /** 855 * Creates this object with the appropriate identifier. 856 */ 857 public DefaultKeyTypedAction() { 858 super(defaultKeyTypedAction); 859 } 860 861 /** 862 * The operation to perform when this action is triggered. 863 * 864 * @param e the action event 865 */ 866 public void actionPerformed(ActionEvent e) { 867 JTextComponent target = getTextComponent(e); 868 if ((target != null) && (e != null)) { 869 if ((! target.isEditable()) || (! target.isEnabled())) { 870 return; 871 } 872 String content = e.getActionCommand(); 873 int mod = e.getModifiers(); 874 if ((content != null) && (content.length() > 0)) { 875 boolean isPrintableMask = true; 876 Toolkit tk = Toolkit.getDefaultToolkit(); 877 if (tk instanceof SunToolkit) { 878 isPrintableMask = ((SunToolkit)tk).isPrintableCharacterModifiersMask(mod); 879 } 880 881 if (isPrintableMask) { 882 char c = content.charAt(0); 883 if ((c >= 0x20) && (c != 0x7F)) { 884 target.replaceSelection(content); 885 } 886 } 887 } 888 } 889 } 890 } 891 892 /** 893 * Places content into the associated document. 894 * If there is a selection, it is removed before 895 * the new content is added. 896 * <p> 897 * <strong>Warning:</strong> 898 * Serialized objects of this class will not be compatible with 899 * future Swing releases. The current serialization support is 900 * appropriate for short term storage or RMI between applications running 901 * the same version of Swing. As of 1.4, support for long term storage 902 * of all JavaBeans™ 903 * has been added to the <code>java.beans</code> package. 904 * Please see {@link java.beans.XMLEncoder}. 905 * 906 * @see DefaultEditorKit#insertContentAction 907 * @see DefaultEditorKit#getActions 908 */ 909 @SuppressWarnings("serial") // Same-version serialization only 910 public static class InsertContentAction extends TextAction { 911 912 /** 913 * Creates this object with the appropriate identifier. 914 */ 915 public InsertContentAction() { 916 super(insertContentAction); 917 } 918 919 /** 920 * The operation to perform when this action is triggered. 921 * 922 * @param e the action event 923 */ 924 public void actionPerformed(ActionEvent e) { 925 JTextComponent target = getTextComponent(e); 926 if ((target != null) && (e != null)) { 927 if ((! target.isEditable()) || (! target.isEnabled())) { 928 UIManager.getLookAndFeel().provideErrorFeedback(target); 929 return; 930 } 931 String content = e.getActionCommand(); 932 if (content != null) { 933 target.replaceSelection(content); 934 } else { 935 UIManager.getLookAndFeel().provideErrorFeedback(target); 936 } 937 } 938 } 939 } 940 941 /** 942 * Places a line/paragraph break into the document. 943 * If there is a selection, it is removed before 944 * the break is added. 945 * <p> 946 * <strong>Warning:</strong> 947 * Serialized objects of this class will not be compatible with 948 * future Swing releases. The current serialization support is 949 * appropriate for short term storage or RMI between applications running 950 * the same version of Swing. As of 1.4, support for long term storage 951 * of all JavaBeans™ 952 * has been added to the <code>java.beans</code> package. 953 * Please see {@link java.beans.XMLEncoder}. 954 * 955 * @see DefaultEditorKit#insertBreakAction 956 * @see DefaultEditorKit#getActions 957 */ 958 @SuppressWarnings("serial") // Same-version serialization only 959 public static class InsertBreakAction extends TextAction { 960 961 /** 962 * Creates this object with the appropriate identifier. 963 */ 964 public InsertBreakAction() { 965 super(insertBreakAction); 966 } 967 968 /** 969 * The operation to perform when this action is triggered. 970 * 971 * @param e the action event 972 */ 973 public void actionPerformed(ActionEvent e) { 974 JTextComponent target = getTextComponent(e); 975 if (target != null) { 976 if ((! target.isEditable()) || (! target.isEnabled())) { 977 UIManager.getLookAndFeel().provideErrorFeedback(target); 978 return; 979 } 980 target.replaceSelection("\n"); 981 } 982 } 983 } 984 985 /** 986 * Places a tab character into the document. If there 987 * is a selection, it is removed before the tab is added. 988 * <p> 989 * <strong>Warning:</strong> 990 * Serialized objects of this class will not be compatible with 991 * future Swing releases. The current serialization support is 992 * appropriate for short term storage or RMI between applications running 993 * the same version of Swing. As of 1.4, support for long term storage 994 * of all JavaBeans™ 995 * has been added to the <code>java.beans</code> package. 996 * Please see {@link java.beans.XMLEncoder}. 997 * 998 * @see DefaultEditorKit#insertTabAction 999 * @see DefaultEditorKit#getActions 1000 */ 1001 @SuppressWarnings("serial") // Same-version serialization only 1002 public static class InsertTabAction extends TextAction { 1003 1004 /** 1005 * Creates this object with the appropriate identifier. 1006 */ 1007 public InsertTabAction() { 1008 super(insertTabAction); 1009 } 1010 1011 /** 1012 * The operation to perform when this action is triggered. 1013 * 1014 * @param e the action event 1015 */ 1016 public void actionPerformed(ActionEvent e) { 1017 JTextComponent target = getTextComponent(e); 1018 if (target != null) { 1019 if ((! target.isEditable()) || (! target.isEnabled())) { 1020 UIManager.getLookAndFeel().provideErrorFeedback(target); 1021 return; 1022 } 1023 target.replaceSelection("\t"); 1024 } 1025 } 1026 } 1027 1028 /* 1029 * Deletes the character of content that precedes the 1030 * current caret position. 1031 * @see DefaultEditorKit#deletePrevCharAction 1032 * @see DefaultEditorKit#getActions 1033 */ 1034 @SuppressWarnings("serial") // Superclass is not serializable across versions 1035 static class DeletePrevCharAction extends TextAction { 1036 1037 /** 1038 * Creates this object with the appropriate identifier. 1039 */ 1040 DeletePrevCharAction() { 1041 super(deletePrevCharAction); 1042 } 1043 1044 /** 1045 * The operation to perform when this action is triggered. 1046 * 1047 * @param e the action event 1048 */ 1049 public void actionPerformed(ActionEvent e) { 1050 JTextComponent target = getTextComponent(e); 1051 boolean beep = true; 1052 if ((target != null) && (target.isEditable())) { 1053 try { 1054 Document doc = target.getDocument(); 1055 Caret caret = target.getCaret(); 1056 int dot = caret.getDot(); 1057 int mark = caret.getMark(); 1058 if (dot != mark) { 1059 doc.remove(Math.min(dot, mark), Math.abs(dot - mark)); 1060 beep = false; 1061 } else if (dot > 0) { 1062 int delChars = 1; 1063 1064 if (dot > 1) { 1065 String dotChars = doc.getText(dot - 2, 2); 1066 char c0 = dotChars.charAt(0); 1067 char c1 = dotChars.charAt(1); 1068 1069 if (c0 >= '\uD800' && c0 <= '\uDBFF' && 1070 c1 >= '\uDC00' && c1 <= '\uDFFF') { 1071 delChars = 2; 1072 } 1073 } 1074 1075 doc.remove(dot - delChars, delChars); 1076 beep = false; 1077 } 1078 } catch (BadLocationException bl) { 1079 } 1080 } 1081 if (beep) { 1082 UIManager.getLookAndFeel().provideErrorFeedback(target); 1083 } 1084 } 1085 } 1086 1087 /* 1088 * Deletes the character of content that follows the 1089 * current caret position. 1090 * @see DefaultEditorKit#deleteNextCharAction 1091 * @see DefaultEditorKit#getActions 1092 */ 1093 @SuppressWarnings("serial") // Superclass is not serializable across versions 1094 static class DeleteNextCharAction extends TextAction { 1095 1096 /* Create this object with the appropriate identifier. */ 1097 DeleteNextCharAction() { 1098 super(deleteNextCharAction); 1099 } 1100 1101 /** The operation to perform when this action is triggered. */ 1102 public void actionPerformed(ActionEvent e) { 1103 JTextComponent target = getTextComponent(e); 1104 boolean beep = true; 1105 if ((target != null) && (target.isEditable())) { 1106 try { 1107 Document doc = target.getDocument(); 1108 Caret caret = target.getCaret(); 1109 int dot = caret.getDot(); 1110 int mark = caret.getMark(); 1111 if (dot != mark) { 1112 doc.remove(Math.min(dot, mark), Math.abs(dot - mark)); 1113 beep = false; 1114 } else if (dot < doc.getLength()) { 1115 int delChars = 1; 1116 1117 if (dot < doc.getLength() - 1) { 1118 String dotChars = doc.getText(dot, 2); 1119 char c0 = dotChars.charAt(0); 1120 char c1 = dotChars.charAt(1); 1121 1122 if (c0 >= '\uD800' && c0 <= '\uDBFF' && 1123 c1 >= '\uDC00' && c1 <= '\uDFFF') { 1124 delChars = 2; 1125 } 1126 } 1127 1128 doc.remove(dot, delChars); 1129 beep = false; 1130 } 1131 } catch (BadLocationException bl) { 1132 } 1133 } 1134 if (beep) { 1135 UIManager.getLookAndFeel().provideErrorFeedback(target); 1136 } 1137 } 1138 } 1139 1140 1141 /* 1142 * Deletes the word that precedes/follows the beginning of the selection. 1143 * @see DefaultEditorKit#getActions 1144 */ 1145 @SuppressWarnings("serial") // Superclass is not serializable across versions 1146 static class DeleteWordAction extends TextAction { 1147 DeleteWordAction(String name) { 1148 super(name); 1149 assert (name == deletePrevWordAction) 1150 || (name == deleteNextWordAction); 1151 } 1152 /** 1153 * The operation to perform when this action is triggered. 1154 * 1155 * @param e the action event 1156 */ 1157 public void actionPerformed(ActionEvent e) { 1158 final JTextComponent target = getTextComponent(e); 1159 if ((target != null) && (e != null)) { 1160 if ((! target.isEditable()) || (! target.isEnabled())) { 1161 UIManager.getLookAndFeel().provideErrorFeedback(target); 1162 return; 1163 } 1164 boolean beep = true; 1165 try { 1166 final int start = target.getSelectionStart(); 1167 final Element line = 1168 Utilities.getParagraphElement(target, start); 1169 int end; 1170 if (deleteNextWordAction == getValue(Action.NAME)) { 1171 end = Utilities. 1172 getNextWordInParagraph(target, line, start, false); 1173 if (end == java.text.BreakIterator.DONE) { 1174 //last word in the paragraph 1175 final int endOfLine = line.getEndOffset(); 1176 if (start == endOfLine - 1) { 1177 //for last position remove last \n 1178 end = endOfLine; 1179 } else { 1180 //remove to the end of the paragraph 1181 end = endOfLine - 1; 1182 } 1183 } 1184 } else { 1185 end = Utilities. 1186 getPrevWordInParagraph(target, line, start); 1187 if (end == java.text.BreakIterator.DONE) { 1188 //there is no previous word in the paragraph 1189 final int startOfLine = line.getStartOffset(); 1190 if (start == startOfLine) { 1191 //for first position remove previous \n 1192 end = startOfLine - 1; 1193 } else { 1194 //remove to the start of the paragraph 1195 end = startOfLine; 1196 } 1197 } 1198 } 1199 int offs = Math.min(start, end); 1200 int len = Math.abs(end - start); 1201 if (offs >= 0) { 1202 target.getDocument().remove(offs, len); 1203 beep = false; 1204 } 1205 } catch (BadLocationException ignore) { 1206 } 1207 if (beep) { 1208 UIManager.getLookAndFeel().provideErrorFeedback(target); 1209 } 1210 } 1211 } 1212 } 1213 1214 1215 /* 1216 * Sets the editor into read-only mode. 1217 * @see DefaultEditorKit#readOnlyAction 1218 * @see DefaultEditorKit#getActions 1219 */ 1220 @SuppressWarnings("serial") // Superclass is not serializable across versions 1221 static class ReadOnlyAction extends TextAction { 1222 1223 /* Create this object with the appropriate identifier. */ 1224 ReadOnlyAction() { 1225 super(readOnlyAction); 1226 } 1227 1228 /** 1229 * The operation to perform when this action is triggered. 1230 * 1231 * @param e the action event 1232 */ 1233 public void actionPerformed(ActionEvent e) { 1234 JTextComponent target = getTextComponent(e); 1235 if (target != null) { 1236 target.setEditable(false); 1237 } 1238 } 1239 } 1240 1241 /* 1242 * Sets the editor into writeable mode. 1243 * @see DefaultEditorKit#writableAction 1244 * @see DefaultEditorKit#getActions 1245 */ 1246 @SuppressWarnings("serial") // Superclass is not serializable across versions 1247 static class WritableAction extends TextAction { 1248 1249 /* Create this object with the appropriate identifier. */ 1250 WritableAction() { 1251 super(writableAction); 1252 } 1253 1254 /** 1255 * The operation to perform when this action is triggered. 1256 * 1257 * @param e the action event 1258 */ 1259 public void actionPerformed(ActionEvent e) { 1260 JTextComponent target = getTextComponent(e); 1261 if (target != null) { 1262 target.setEditable(true); 1263 } 1264 } 1265 } 1266 1267 /** 1268 * Cuts the selected region and place its contents 1269 * into the system clipboard. 1270 * <p> 1271 * <strong>Warning:</strong> 1272 * Serialized objects of this class will not be compatible with 1273 * future Swing releases. The current serialization support is 1274 * appropriate for short term storage or RMI between applications running 1275 * the same version of Swing. As of 1.4, support for long term storage 1276 * of all JavaBeans™ 1277 * has been added to the <code>java.beans</code> package. 1278 * Please see {@link java.beans.XMLEncoder}. 1279 * 1280 * @see DefaultEditorKit#cutAction 1281 * @see DefaultEditorKit#getActions 1282 */ 1283 @SuppressWarnings("serial") // Same-version serialization only 1284 public static class CutAction extends TextAction { 1285 1286 /** Create this object with the appropriate identifier. */ 1287 public CutAction() { 1288 super(cutAction); 1289 } 1290 1291 /** 1292 * The operation to perform when this action is triggered. 1293 * 1294 * @param e the action event 1295 */ 1296 public void actionPerformed(ActionEvent e) { 1297 JTextComponent target = getTextComponent(e); 1298 if (target != null) { 1299 target.cut(); 1300 } 1301 } 1302 } 1303 1304 /** 1305 * Copies the selected region and place its contents 1306 * into the system clipboard. 1307 * <p> 1308 * <strong>Warning:</strong> 1309 * Serialized objects of this class will not be compatible with 1310 * future Swing releases. The current serialization support is 1311 * appropriate for short term storage or RMI between applications running 1312 * the same version of Swing. As of 1.4, support for long term storage 1313 * of all JavaBeans™ 1314 * has been added to the <code>java.beans</code> package. 1315 * Please see {@link java.beans.XMLEncoder}. 1316 * 1317 * @see DefaultEditorKit#copyAction 1318 * @see DefaultEditorKit#getActions 1319 */ 1320 @SuppressWarnings("serial") // Same-version serialization only 1321 public static class CopyAction extends TextAction { 1322 1323 /** Create this object with the appropriate identifier. */ 1324 public CopyAction() { 1325 super(copyAction); 1326 } 1327 1328 /** 1329 * The operation to perform when this action is triggered. 1330 * 1331 * @param e the action event 1332 */ 1333 public void actionPerformed(ActionEvent e) { 1334 JTextComponent target = getTextComponent(e); 1335 if (target != null) { 1336 target.copy(); 1337 } 1338 } 1339 } 1340 1341 /** 1342 * Pastes the contents of the system clipboard into the 1343 * selected region, or before the caret if nothing is 1344 * selected. 1345 * <p> 1346 * <strong>Warning:</strong> 1347 * Serialized objects of this class will not be compatible with 1348 * future Swing releases. The current serialization support is 1349 * appropriate for short term storage or RMI between applications running 1350 * the same version of Swing. As of 1.4, support for long term storage 1351 * of all JavaBeans™ 1352 * has been added to the <code>java.beans</code> package. 1353 * Please see {@link java.beans.XMLEncoder}. 1354 * 1355 * @see DefaultEditorKit#pasteAction 1356 * @see DefaultEditorKit#getActions 1357 */ 1358 @SuppressWarnings("serial") // Same-version serialization only 1359 public static class PasteAction extends TextAction { 1360 1361 /** Create this object with the appropriate identifier. */ 1362 public PasteAction() { 1363 super(pasteAction); 1364 } 1365 1366 /** 1367 * The operation to perform when this action is triggered. 1368 * 1369 * @param e the action event 1370 */ 1371 public void actionPerformed(ActionEvent e) { 1372 JTextComponent target = getTextComponent(e); 1373 if (target != null) { 1374 target.paste(); 1375 } 1376 } 1377 } 1378 1379 /** 1380 * Creates a beep. 1381 * <p> 1382 * <strong>Warning:</strong> 1383 * Serialized objects of this class will not be compatible with 1384 * future Swing releases. The current serialization support is 1385 * appropriate for short term storage or RMI between applications running 1386 * the same version of Swing. As of 1.4, support for long term storage 1387 * of all JavaBeans™ 1388 * has been added to the <code>java.beans</code> package. 1389 * Please see {@link java.beans.XMLEncoder}. 1390 * 1391 * @see DefaultEditorKit#beepAction 1392 * @see DefaultEditorKit#getActions 1393 */ 1394 @SuppressWarnings("serial") // Same-version serialization only 1395 public static class BeepAction extends TextAction { 1396 1397 /** Create this object with the appropriate identifier. */ 1398 public BeepAction() { 1399 super(beepAction); 1400 } 1401 1402 /** 1403 * The operation to perform when this action is triggered. 1404 * 1405 * @param e the action event 1406 */ 1407 public void actionPerformed(ActionEvent e) { 1408 JTextComponent target = getTextComponent(e); 1409 UIManager.getLookAndFeel().provideErrorFeedback(target); 1410 } 1411 } 1412 1413 /** 1414 * Scrolls up/down vertically. The select version of this action extends 1415 * the selection, instead of simply moving the caret. 1416 * 1417 * @see DefaultEditorKit#pageUpAction 1418 * @see DefaultEditorKit#pageDownAction 1419 * @see DefaultEditorKit#getActions 1420 */ 1421 @SuppressWarnings("serial") // Superclass is not serializable across versions 1422 static class VerticalPageAction extends TextAction { 1423 1424 /** Create this object with the appropriate identifier. */ 1425 public VerticalPageAction(String nm, int direction, boolean select) { 1426 super(nm); 1427 this.select = select; 1428 this.direction = direction; 1429 } 1430 1431 /** The operation to perform when this action is triggered. */ 1432 public void actionPerformed(ActionEvent e) { 1433 JTextComponent target = getTextComponent(e); 1434 if (target != null) { 1435 Rectangle visible = target.getVisibleRect(); 1436 Rectangle newVis = new Rectangle(visible); 1437 int selectedIndex = target.getCaretPosition(); 1438 int scrollAmount = direction * 1439 target.getScrollableBlockIncrement( 1440 visible, SwingConstants.VERTICAL, direction); 1441 int initialY = visible.y; 1442 Caret caret = target.getCaret(); 1443 Point magicPosition = caret.getMagicCaretPosition(); 1444 1445 if (selectedIndex != -1) { 1446 try { 1447 Rectangle dotBounds = target.modelToView( 1448 selectedIndex); 1449 int x = (magicPosition != null) ? magicPosition.x : 1450 dotBounds.x; 1451 int h = dotBounds.height; 1452 if (h > 0) { 1453 // We want to scroll by a multiple of caret height, 1454 // rounding towards lower integer 1455 scrollAmount = scrollAmount / h * h; 1456 } 1457 newVis.y = constrainY(target, 1458 initialY + scrollAmount, visible.height); 1459 1460 int newIndex; 1461 1462 if (visible.contains(dotBounds.x, dotBounds.y)) { 1463 // Dot is currently visible, base the new 1464 // location off the old, or 1465 newIndex = target.viewToModel( 1466 new Point(x, constrainY(target, 1467 dotBounds.y + scrollAmount, 0))); 1468 } 1469 else { 1470 // Dot isn't visible, choose the top or the bottom 1471 // for the new location. 1472 if (direction == -1) { 1473 newIndex = target.viewToModel(new Point( 1474 x, newVis.y)); 1475 } 1476 else { 1477 newIndex = target.viewToModel(new Point( 1478 x, newVis.y + visible.height)); 1479 } 1480 } 1481 newIndex = constrainOffset(target, newIndex); 1482 if (newIndex != selectedIndex) { 1483 // Make sure the new visible location contains 1484 // the location of dot, otherwise Caret will 1485 // cause an additional scroll. 1486 int newY = getAdjustedY(target, newVis, newIndex); 1487 1488 if (direction == -1 && newY <= initialY || direction == 1 && newY >= initialY) { 1489 // Change index and correct newVis.y only if won't cause scrolling upward 1490 newVis.y = newY; 1491 1492 if (select) { 1493 target.moveCaretPosition(newIndex); 1494 } else { 1495 target.setCaretPosition(newIndex); 1496 } 1497 } 1498 } 1499 } catch (BadLocationException ble) { } 1500 } else { 1501 newVis.y = constrainY(target, 1502 initialY + scrollAmount, visible.height); 1503 } 1504 if (magicPosition != null) { 1505 caret.setMagicCaretPosition(magicPosition); 1506 } 1507 target.scrollRectToVisible(newVis); 1508 } 1509 } 1510 1511 /** 1512 * Makes sure <code>y</code> is a valid location in 1513 * <code>target</code>. 1514 */ 1515 private int constrainY(JTextComponent target, int y, int vis) { 1516 if (y < 0) { 1517 y = 0; 1518 } 1519 else if (y + vis > target.getHeight()) { 1520 y = Math.max(0, target.getHeight() - vis); 1521 } 1522 return y; 1523 } 1524 1525 /** 1526 * Ensures that <code>offset</code> is a valid offset into the 1527 * model for <code>text</code>. 1528 */ 1529 private int constrainOffset(JTextComponent text, int offset) { 1530 Document doc = text.getDocument(); 1531 1532 if ((offset != 0) && (offset > doc.getLength())) { 1533 offset = doc.getLength(); 1534 } 1535 if (offset < 0) { 1536 offset = 0; 1537 } 1538 return offset; 1539 } 1540 1541 /** 1542 * Returns adjustsed {@code y} position that indicates the location to scroll to 1543 * after selecting <code>index</code>. 1544 */ 1545 private int getAdjustedY(JTextComponent text, Rectangle visible, int index) { 1546 int result = visible.y; 1547 1548 try { 1549 Rectangle dotBounds = text.modelToView(index); 1550 1551 if (dotBounds.y < visible.y) { 1552 result = dotBounds.y; 1553 } else { 1554 if ((dotBounds.y > visible.y + visible.height) || 1555 (dotBounds.y + dotBounds.height > visible.y + visible.height)) { 1556 result = dotBounds.y + dotBounds.height - visible.height; 1557 } 1558 } 1559 } catch (BadLocationException ble) { 1560 } 1561 1562 return result; 1563 } 1564 1565 /** 1566 * Adjusts the Rectangle to contain the bounds of the character at 1567 * <code>index</code> in response to a page up. 1568 */ 1569 private boolean select; 1570 1571 /** 1572 * Direction to scroll, 1 is down, -1 is up. 1573 */ 1574 private int direction; 1575 } 1576 1577 1578 /** 1579 * Pages one view to the left or right. 1580 */ 1581 @SuppressWarnings("serial") // Superclass is not serializable across versions 1582 static class PageAction extends TextAction { 1583 1584 /** Create this object with the appropriate identifier. */ 1585 public PageAction(String nm, boolean left, boolean select) { 1586 super(nm); 1587 this.select = select; 1588 this.left = left; 1589 } 1590 1591 /** The operation to perform when this action is triggered. */ 1592 public void actionPerformed(ActionEvent e) { 1593 JTextComponent target = getTextComponent(e); 1594 if (target != null) { 1595 int selectedIndex; 1596 Rectangle visible = new Rectangle(); 1597 target.computeVisibleRect(visible); 1598 if (left) { 1599 visible.x = Math.max(0, visible.x - visible.width); 1600 } 1601 else { 1602 visible.x += visible.width; 1603 } 1604 1605 selectedIndex = target.getCaretPosition(); 1606 if(selectedIndex != -1) { 1607 if (left) { 1608 selectedIndex = target.viewToModel 1609 (new Point(visible.x, visible.y)); 1610 } 1611 else { 1612 selectedIndex = target.viewToModel 1613 (new Point(visible.x + visible.width - 1, 1614 visible.y + visible.height - 1)); 1615 } 1616 Document doc = target.getDocument(); 1617 if ((selectedIndex != 0) && 1618 (selectedIndex > (doc.getLength()-1))) { 1619 selectedIndex = doc.getLength()-1; 1620 } 1621 else if(selectedIndex < 0) { 1622 selectedIndex = 0; 1623 } 1624 if (select) 1625 target.moveCaretPosition(selectedIndex); 1626 else 1627 target.setCaretPosition(selectedIndex); 1628 } 1629 } 1630 } 1631 1632 private boolean select; 1633 private boolean left; 1634 } 1635 1636 @SuppressWarnings("serial") // Superclass is not serializable across versions 1637 static class DumpModelAction extends TextAction { 1638 1639 DumpModelAction() { 1640 super("dump-model"); 1641 } 1642 1643 public void actionPerformed(ActionEvent e) { 1644 JTextComponent target = getTextComponent(e); 1645 if (target != null) { 1646 Document d = target.getDocument(); 1647 if (d instanceof AbstractDocument) { 1648 ((AbstractDocument) d).dump(System.err); 1649 } 1650 } 1651 } 1652 } 1653 1654 /* 1655 * Action to move the selection by way of the 1656 * getNextVisualPositionFrom method. Constructor indicates direction 1657 * to use. 1658 */ 1659 @SuppressWarnings("serial") // Superclass is not serializable across versions 1660 static class NextVisualPositionAction extends TextAction { 1661 1662 /** 1663 * Create this action with the appropriate identifier. 1664 * @param nm the name of the action, Action.NAME. 1665 * @param select whether to extend the selection when 1666 * changing the caret position. 1667 */ 1668 NextVisualPositionAction(String nm, boolean select, int direction) { 1669 super(nm); 1670 this.select = select; 1671 this.direction = direction; 1672 } 1673 1674 /** The operation to perform when this action is triggered. */ 1675 public void actionPerformed(ActionEvent e) { 1676 JTextComponent target = getTextComponent(e); 1677 if (target != null) { 1678 Caret caret = target.getCaret(); 1679 DefaultCaret bidiCaret = (caret instanceof DefaultCaret) ? 1680 (DefaultCaret)caret : null; 1681 int dot = caret.getDot(); 1682 Position.Bias[] bias = new Position.Bias[1]; 1683 Point magicPosition = caret.getMagicCaretPosition(); 1684 1685 try { 1686 if(magicPosition == null && 1687 (direction == SwingConstants.NORTH || 1688 direction == SwingConstants.SOUTH)) { 1689 Rectangle r = (bidiCaret != null) ? 1690 target.getUI().modelToView(target, dot, 1691 bidiCaret.getDotBias()) : 1692 target.modelToView(dot); 1693 magicPosition = new Point(r.x, r.y); 1694 } 1695 1696 NavigationFilter filter = target.getNavigationFilter(); 1697 1698 if (filter != null) { 1699 dot = filter.getNextVisualPositionFrom 1700 (target, dot, (bidiCaret != null) ? 1701 bidiCaret.getDotBias() : 1702 Position.Bias.Forward, direction, bias); 1703 } 1704 else { 1705 dot = target.getUI().getNextVisualPositionFrom 1706 (target, dot, (bidiCaret != null) ? 1707 bidiCaret.getDotBias() : 1708 Position.Bias.Forward, direction, bias); 1709 } 1710 if(bias[0] == null) { 1711 bias[0] = Position.Bias.Forward; 1712 } 1713 if(bidiCaret != null) { 1714 if (select) { 1715 bidiCaret.moveDot(dot, bias[0]); 1716 } else { 1717 bidiCaret.setDot(dot, bias[0]); 1718 } 1719 } 1720 else { 1721 if (select) { 1722 caret.moveDot(dot); 1723 } else { 1724 caret.setDot(dot); 1725 } 1726 } 1727 if(magicPosition != null && 1728 (direction == SwingConstants.NORTH || 1729 direction == SwingConstants.SOUTH)) { 1730 target.getCaret().setMagicCaretPosition(magicPosition); 1731 } 1732 } catch (BadLocationException ex) { 1733 } 1734 } 1735 } 1736 1737 private boolean select; 1738 private int direction; 1739 } 1740 1741 /* 1742 * Position the caret to the beginning of the word. 1743 * @see DefaultEditorKit#beginWordAction 1744 * @see DefaultEditorKit#selectBeginWordAction 1745 * @see DefaultEditorKit#getActions 1746 */ 1747 @SuppressWarnings("serial") // Superclass is not serializable across versions 1748 static class BeginWordAction extends TextAction { 1749 1750 /** 1751 * Create this action with the appropriate identifier. 1752 * @param nm the name of the action, Action.NAME. 1753 * @param select whether to extend the selection when 1754 * changing the caret position. 1755 */ 1756 BeginWordAction(String nm, boolean select) { 1757 super(nm); 1758 this.select = select; 1759 } 1760 1761 /** The operation to perform when this action is triggered. */ 1762 public void actionPerformed(ActionEvent e) { 1763 JTextComponent target = getTextComponent(e); 1764 if (target != null) { 1765 try { 1766 int offs = target.getCaretPosition(); 1767 int begOffs = Utilities.getWordStart(target, offs); 1768 if (select) { 1769 target.moveCaretPosition(begOffs); 1770 } else { 1771 target.setCaretPosition(begOffs); 1772 } 1773 } catch (BadLocationException bl) { 1774 UIManager.getLookAndFeel().provideErrorFeedback(target); 1775 } 1776 } 1777 } 1778 1779 private boolean select; 1780 } 1781 1782 /* 1783 * Position the caret to the end of the word. 1784 * @see DefaultEditorKit#endWordAction 1785 * @see DefaultEditorKit#selectEndWordAction 1786 * @see DefaultEditorKit#getActions 1787 */ 1788 @SuppressWarnings("serial") // Superclass is not serializable across versions 1789 static class EndWordAction extends TextAction { 1790 1791 /** 1792 * Create this action with the appropriate identifier. 1793 * @param nm the name of the action, Action.NAME. 1794 * @param select whether to extend the selection when 1795 * changing the caret position. 1796 */ 1797 EndWordAction(String nm, boolean select) { 1798 super(nm); 1799 this.select = select; 1800 } 1801 1802 /** The operation to perform when this action is triggered. */ 1803 public void actionPerformed(ActionEvent e) { 1804 JTextComponent target = getTextComponent(e); 1805 if (target != null) { 1806 try { 1807 int offs = target.getCaretPosition(); 1808 int endOffs = Utilities.getWordEnd(target, offs); 1809 if (select) { 1810 target.moveCaretPosition(endOffs); 1811 } else { 1812 target.setCaretPosition(endOffs); 1813 } 1814 } catch (BadLocationException bl) { 1815 UIManager.getLookAndFeel().provideErrorFeedback(target); 1816 } 1817 } 1818 } 1819 1820 private boolean select; 1821 } 1822 1823 /* 1824 * Position the caret to the beginning of the previous word. 1825 * @see DefaultEditorKit#previousWordAction 1826 * @see DefaultEditorKit#selectPreviousWordAction 1827 * @see DefaultEditorKit#getActions 1828 */ 1829 @SuppressWarnings("serial") // Superclass is not serializable across versions 1830 static class PreviousWordAction extends TextAction { 1831 1832 /** 1833 * Create this action with the appropriate identifier. 1834 * @param nm the name of the action, Action.NAME. 1835 * @param select whether to extend the selection when 1836 * changing the caret position. 1837 */ 1838 PreviousWordAction(String nm, boolean select) { 1839 super(nm); 1840 this.select = select; 1841 } 1842 1843 /** The operation to perform when this action is triggered. */ 1844 public void actionPerformed(ActionEvent e) { 1845 JTextComponent target = getTextComponent(e); 1846 if (target != null) { 1847 int offs = target.getCaretPosition(); 1848 boolean failed = false; 1849 try { 1850 Element curPara = 1851 Utilities.getParagraphElement(target, offs); 1852 offs = Utilities.getPreviousWord(target, offs); 1853 if(offs < curPara.getStartOffset()) { 1854 // we should first move to the end of the 1855 // previous paragraph (bug #4278839) 1856 offs = Utilities.getParagraphElement(target, offs). 1857 getEndOffset() - 1; 1858 } 1859 } catch (BadLocationException bl) { 1860 if (offs != 0) { 1861 offs = 0; 1862 } 1863 else { 1864 failed = true; 1865 } 1866 } 1867 if (!failed) { 1868 if (select) { 1869 target.moveCaretPosition(offs); 1870 } else { 1871 target.setCaretPosition(offs); 1872 } 1873 } 1874 else { 1875 UIManager.getLookAndFeel().provideErrorFeedback(target); 1876 } 1877 } 1878 } 1879 1880 private boolean select; 1881 } 1882 1883 /* 1884 * Position the caret to the next of the word. 1885 * @see DefaultEditorKit#nextWordAction 1886 * @see DefaultEditorKit#selectNextWordAction 1887 * @see DefaultEditorKit#getActions 1888 */ 1889 @SuppressWarnings("serial") // Superclass is not serializable across versions 1890 static class NextWordAction extends TextAction { 1891 1892 /** 1893 * Create this action with the appropriate identifier. 1894 * @param nm the name of the action, Action.NAME. 1895 * @param select whether to extend the selection when 1896 * changing the caret position. 1897 */ 1898 NextWordAction(String nm, boolean select) { 1899 super(nm); 1900 this.select = select; 1901 } 1902 1903 /** The operation to perform when this action is triggered. */ 1904 public void actionPerformed(ActionEvent e) { 1905 JTextComponent target = getTextComponent(e); 1906 if (target != null) { 1907 int offs = target.getCaretPosition(); 1908 boolean failed = false; 1909 int oldOffs = offs; 1910 Element curPara = 1911 Utilities.getParagraphElement(target, offs); 1912 try { 1913 offs = Utilities.getNextWord(target, offs); 1914 if(offs >= curPara.getEndOffset() && 1915 oldOffs != curPara.getEndOffset() - 1) { 1916 // we should first move to the end of current 1917 // paragraph (bug #4278839) 1918 offs = curPara.getEndOffset() - 1; 1919 } 1920 } catch (BadLocationException bl) { 1921 int end = target.getDocument().getLength(); 1922 if (offs != end) { 1923 if(oldOffs != curPara.getEndOffset() - 1) { 1924 offs = curPara.getEndOffset() - 1; 1925 } else { 1926 offs = end; 1927 } 1928 } 1929 else { 1930 failed = true; 1931 } 1932 } 1933 if (!failed) { 1934 if (select) { 1935 target.moveCaretPosition(offs); 1936 } else { 1937 target.setCaretPosition(offs); 1938 } 1939 } 1940 else { 1941 UIManager.getLookAndFeel().provideErrorFeedback(target); 1942 } 1943 } 1944 } 1945 1946 private boolean select; 1947 } 1948 1949 /* 1950 * Position the caret to the beginning of the line. 1951 * @see DefaultEditorKit#beginLineAction 1952 * @see DefaultEditorKit#selectBeginLineAction 1953 * @see DefaultEditorKit#getActions 1954 */ 1955 @SuppressWarnings("serial") // Superclass is not serializable across versions 1956 static class BeginLineAction extends TextAction { 1957 1958 /** 1959 * Create this action with the appropriate identifier. 1960 * @param nm the name of the action, Action.NAME. 1961 * @param select whether to extend the selection when 1962 * changing the caret position. 1963 */ 1964 BeginLineAction(String nm, boolean select) { 1965 super(nm); 1966 this.select = select; 1967 } 1968 1969 /** The operation to perform when this action is triggered. */ 1970 public void actionPerformed(ActionEvent e) { 1971 JTextComponent target = getTextComponent(e); 1972 if (target != null) { 1973 try { 1974 int offs = target.getCaretPosition(); 1975 int begOffs = Utilities.getRowStart(target, offs); 1976 if (select) { 1977 target.moveCaretPosition(begOffs); 1978 } else { 1979 target.setCaretPosition(begOffs); 1980 } 1981 } catch (BadLocationException bl) { 1982 UIManager.getLookAndFeel().provideErrorFeedback(target); 1983 } 1984 } 1985 } 1986 1987 private boolean select; 1988 } 1989 1990 /* 1991 * Position the caret to the end of the line. 1992 * @see DefaultEditorKit#endLineAction 1993 * @see DefaultEditorKit#selectEndLineAction 1994 * @see DefaultEditorKit#getActions 1995 */ 1996 @SuppressWarnings("serial") // Superclass is not serializable across versions 1997 static class EndLineAction extends TextAction { 1998 1999 /** 2000 * Create this action with the appropriate identifier. 2001 * @param nm the name of the action, Action.NAME. 2002 * @param select whether to extend the selection when 2003 * changing the caret position. 2004 */ 2005 EndLineAction(String nm, boolean select) { 2006 super(nm); 2007 this.select = select; 2008 } 2009 2010 /** The operation to perform when this action is triggered. */ 2011 public void actionPerformed(ActionEvent e) { 2012 JTextComponent target = getTextComponent(e); 2013 if (target != null) { 2014 try { 2015 int offs = target.getCaretPosition(); 2016 int endOffs = Utilities.getRowEnd(target, offs); 2017 if (select) { 2018 target.moveCaretPosition(endOffs); 2019 } else { 2020 target.setCaretPosition(endOffs); 2021 } 2022 } catch (BadLocationException bl) { 2023 UIManager.getLookAndFeel().provideErrorFeedback(target); 2024 } 2025 } 2026 } 2027 2028 private boolean select; 2029 } 2030 2031 /* 2032 * Position the caret to the beginning of the paragraph. 2033 * @see DefaultEditorKit#beginParagraphAction 2034 * @see DefaultEditorKit#selectBeginParagraphAction 2035 * @see DefaultEditorKit#getActions 2036 */ 2037 @SuppressWarnings("serial") // Superclass is not serializable across versions 2038 static class BeginParagraphAction extends TextAction { 2039 2040 /** 2041 * Create this action with the appropriate identifier. 2042 * @param nm the name of the action, Action.NAME. 2043 * @param select whether to extend the selection when 2044 * changing the caret position. 2045 */ 2046 BeginParagraphAction(String nm, boolean select) { 2047 super(nm); 2048 this.select = select; 2049 } 2050 2051 /** The operation to perform when this action is triggered. */ 2052 public void actionPerformed(ActionEvent e) { 2053 JTextComponent target = getTextComponent(e); 2054 if (target != null) { 2055 int offs = target.getCaretPosition(); 2056 Element elem = Utilities.getParagraphElement(target, offs); 2057 offs = elem.getStartOffset(); 2058 if (select) { 2059 target.moveCaretPosition(offs); 2060 } else { 2061 target.setCaretPosition(offs); 2062 } 2063 } 2064 } 2065 2066 private boolean select; 2067 } 2068 2069 /* 2070 * Position the caret to the end of the paragraph. 2071 * @see DefaultEditorKit#endParagraphAction 2072 * @see DefaultEditorKit#selectEndParagraphAction 2073 * @see DefaultEditorKit#getActions 2074 */ 2075 @SuppressWarnings("serial") // Superclass is not serializable across versions 2076 static class EndParagraphAction extends TextAction { 2077 2078 /** 2079 * Create this action with the appropriate identifier. 2080 * @param nm the name of the action, Action.NAME. 2081 * @param select whether to extend the selection when 2082 * changing the caret position. 2083 */ 2084 EndParagraphAction(String nm, boolean select) { 2085 super(nm); 2086 this.select = select; 2087 } 2088 2089 /** The operation to perform when this action is triggered. */ 2090 public void actionPerformed(ActionEvent e) { 2091 JTextComponent target = getTextComponent(e); 2092 if (target != null) { 2093 int offs = target.getCaretPosition(); 2094 Element elem = Utilities.getParagraphElement(target, offs); 2095 offs = Math.min(target.getDocument().getLength(), 2096 elem.getEndOffset()); 2097 if (select) { 2098 target.moveCaretPosition(offs); 2099 } else { 2100 target.setCaretPosition(offs); 2101 } 2102 } 2103 } 2104 2105 private boolean select; 2106 } 2107 2108 /* 2109 * Move the caret to the beginning of the document. 2110 * @see DefaultEditorKit#beginAction 2111 * @see DefaultEditorKit#getActions 2112 */ 2113 @SuppressWarnings("serial") // Superclass is not serializable across versions 2114 static class BeginAction extends TextAction { 2115 2116 /* Create this object with the appropriate identifier. */ 2117 BeginAction(String nm, boolean select) { 2118 super(nm); 2119 this.select = select; 2120 } 2121 2122 /** The operation to perform when this action is triggered. */ 2123 public void actionPerformed(ActionEvent e) { 2124 JTextComponent target = getTextComponent(e); 2125 if (target != null) { 2126 if (select) { 2127 target.moveCaretPosition(0); 2128 } else { 2129 target.setCaretPosition(0); 2130 } 2131 } 2132 } 2133 2134 private boolean select; 2135 } 2136 2137 /* 2138 * Move the caret to the end of the document. 2139 * @see DefaultEditorKit#endAction 2140 * @see DefaultEditorKit#getActions 2141 */ 2142 @SuppressWarnings("serial") // Superclass is not serializable across versions 2143 static class EndAction extends TextAction { 2144 2145 /* Create this object with the appropriate identifier. */ 2146 EndAction(String nm, boolean select) { 2147 super(nm); 2148 this.select = select; 2149 } 2150 2151 /** The operation to perform when this action is triggered. */ 2152 public void actionPerformed(ActionEvent e) { 2153 JTextComponent target = getTextComponent(e); 2154 if (target != null) { 2155 Document doc = target.getDocument(); 2156 int dot = doc.getLength(); 2157 if (select) { 2158 target.moveCaretPosition(dot); 2159 } else { 2160 target.setCaretPosition(dot); 2161 } 2162 } 2163 } 2164 2165 private boolean select; 2166 } 2167 2168 /* 2169 * Select the word around the caret 2170 * @see DefaultEditorKit#endAction 2171 * @see DefaultEditorKit#getActions 2172 */ 2173 @SuppressWarnings("serial") // Superclass is not serializable across versions 2174 static class SelectWordAction extends TextAction { 2175 2176 /** 2177 * Create this action with the appropriate identifier. 2178 * @param nm the name of the action, Action.NAME. 2179 * @param select whether to extend the selection when 2180 * changing the caret position. 2181 */ 2182 SelectWordAction() { 2183 super(selectWordAction); 2184 start = new BeginWordAction("pigdog", false); 2185 end = new EndWordAction("pigdog", true); 2186 } 2187 2188 /** The operation to perform when this action is triggered. */ 2189 public void actionPerformed(ActionEvent e) { 2190 start.actionPerformed(e); 2191 end.actionPerformed(e); 2192 } 2193 2194 private Action start; 2195 private Action end; 2196 } 2197 2198 /* 2199 * Select the line around the caret 2200 * @see DefaultEditorKit#endAction 2201 * @see DefaultEditorKit#getActions 2202 */ 2203 @SuppressWarnings("serial") // Superclass is not serializable across versions 2204 static class SelectLineAction extends TextAction { 2205 2206 /** 2207 * Create this action with the appropriate identifier. 2208 * @param nm the name of the action, Action.NAME. 2209 * @param select whether to extend the selection when 2210 * changing the caret position. 2211 */ 2212 SelectLineAction() { 2213 super(selectLineAction); 2214 start = new BeginLineAction("pigdog", false); 2215 end = new EndLineAction("pigdog", true); 2216 } 2217 2218 /** The operation to perform when this action is triggered. */ 2219 public void actionPerformed(ActionEvent e) { 2220 start.actionPerformed(e); 2221 end.actionPerformed(e); 2222 } 2223 2224 private Action start; 2225 private Action end; 2226 } 2227 2228 /* 2229 * Select the paragraph around the caret 2230 * @see DefaultEditorKit#endAction 2231 * @see DefaultEditorKit#getActions 2232 */ 2233 @SuppressWarnings("serial") // Superclass is not serializable across versions 2234 static class SelectParagraphAction extends TextAction { 2235 2236 /** 2237 * Create this action with the appropriate identifier. 2238 * @param nm the name of the action, Action.NAME. 2239 * @param select whether to extend the selection when 2240 * changing the caret position. 2241 */ 2242 SelectParagraphAction() { 2243 super(selectParagraphAction); 2244 start = new BeginParagraphAction("pigdog", false); 2245 end = new EndParagraphAction("pigdog", true); 2246 } 2247 2248 /** The operation to perform when this action is triggered. */ 2249 public void actionPerformed(ActionEvent e) { 2250 start.actionPerformed(e); 2251 end.actionPerformed(e); 2252 } 2253 2254 private Action start; 2255 private Action end; 2256 } 2257 2258 /* 2259 * Select the entire document 2260 * @see DefaultEditorKit#endAction 2261 * @see DefaultEditorKit#getActions 2262 */ 2263 @SuppressWarnings("serial") // Superclass is not serializable across versions 2264 static class SelectAllAction extends TextAction { 2265 2266 /** 2267 * Create this action with the appropriate identifier. 2268 * @param nm the name of the action, Action.NAME. 2269 * @param select whether to extend the selection when 2270 * changing the caret position. 2271 */ 2272 SelectAllAction() { 2273 super(selectAllAction); 2274 } 2275 2276 /** The operation to perform when this action is triggered. */ 2277 public void actionPerformed(ActionEvent e) { 2278 JTextComponent target = getTextComponent(e); 2279 if (target != null) { 2280 Document doc = target.getDocument(); 2281 target.setCaretPosition(0); 2282 target.moveCaretPosition(doc.getLength()); 2283 } 2284 } 2285 2286 } 2287 2288 /* 2289 * Remove the selection, if any. 2290 * @see DefaultEditorKit#unselectAction 2291 * @see DefaultEditorKit#getActions 2292 */ 2293 @SuppressWarnings("serial") // Superclass is not serializable across versions 2294 static class UnselectAction extends TextAction { 2295 2296 /** 2297 * Create this action with the appropriate identifier. 2298 */ 2299 UnselectAction() { 2300 super(unselectAction); 2301 } 2302 2303 /** The operation to perform when this action is triggered. */ 2304 public void actionPerformed(ActionEvent e) { 2305 JTextComponent target = getTextComponent(e); 2306 if (target != null) { 2307 target.setCaretPosition(target.getCaretPosition()); 2308 } 2309 } 2310 2311 } 2312 2313 /* 2314 * Toggles the ComponentOrientation of the text component. 2315 * @see DefaultEditorKit#toggleComponentOrientationAction 2316 * @see DefaultEditorKit#getActions 2317 */ 2318 @SuppressWarnings("serial") // Superclass is not serializable across versions 2319 static class ToggleComponentOrientationAction extends TextAction { 2320 2321 /** 2322 * Create this action with the appropriate identifier. 2323 */ 2324 ToggleComponentOrientationAction() { 2325 super(toggleComponentOrientationAction); 2326 } 2327 2328 /** The operation to perform when this action is triggered. */ 2329 public void actionPerformed(ActionEvent e) { 2330 JTextComponent target = getTextComponent(e); 2331 if (target != null) { 2332 ComponentOrientation last = target.getComponentOrientation(); 2333 ComponentOrientation next; 2334 if( last == ComponentOrientation.RIGHT_TO_LEFT ) 2335 next = ComponentOrientation.LEFT_TO_RIGHT; 2336 else 2337 next = ComponentOrientation.RIGHT_TO_LEFT; 2338 target.setComponentOrientation(next); 2339 target.repaint(); 2340 } 2341 } 2342 } 2343 2344 }