1 /* 2 * Copyright (c) 1997, 2017, 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.clone(); 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 char c = content.charAt(0); 882 if ((isPrintableMask && (c >= 0x20) && (c != 0x7F)) || 883 (!isPrintableMask && (c >= 0x200C) && (c <= 0x200D))) { 884 target.replaceSelection(content); 885 } 886 } 887 } 888 } 889 } 890 891 /** 892 * Places content into the associated document. 893 * If there is a selection, it is removed before 894 * the new content is added. 895 * <p> 896 * <strong>Warning:</strong> 897 * Serialized objects of this class will not be compatible with 898 * future Swing releases. The current serialization support is 899 * appropriate for short term storage or RMI between applications running 900 * the same version of Swing. As of 1.4, support for long term storage 901 * of all JavaBeans™ 902 * has been added to the <code>java.beans</code> package. 903 * Please see {@link java.beans.XMLEncoder}. 904 * 905 * @see DefaultEditorKit#insertContentAction 906 * @see DefaultEditorKit#getActions 907 */ 908 @SuppressWarnings("serial") // Same-version serialization only 909 public static class InsertContentAction extends TextAction { 910 911 /** 912 * Creates this object with the appropriate identifier. 913 */ 914 public InsertContentAction() { 915 super(insertContentAction); 916 } 917 918 /** 919 * The operation to perform when this action is triggered. 920 * 921 * @param e the action event 922 */ 923 public void actionPerformed(ActionEvent e) { 924 JTextComponent target = getTextComponent(e); 925 if ((target != null) && (e != null)) { 926 if ((! target.isEditable()) || (! target.isEnabled())) { 927 UIManager.getLookAndFeel().provideErrorFeedback(target); 928 return; 929 } 930 String content = e.getActionCommand(); 931 if (content != null) { 932 target.replaceSelection(content); 933 } else { 934 UIManager.getLookAndFeel().provideErrorFeedback(target); 935 } 936 } 937 } 938 } 939 940 /** 941 * Places a line/paragraph break into the document. 942 * If there is a selection, it is removed before 943 * the break is added. 944 * <p> 945 * <strong>Warning:</strong> 946 * Serialized objects of this class will not be compatible with 947 * future Swing releases. The current serialization support is 948 * appropriate for short term storage or RMI between applications running 949 * the same version of Swing. As of 1.4, support for long term storage 950 * of all JavaBeans™ 951 * has been added to the <code>java.beans</code> package. 952 * Please see {@link java.beans.XMLEncoder}. 953 * 954 * @see DefaultEditorKit#insertBreakAction 955 * @see DefaultEditorKit#getActions 956 */ 957 @SuppressWarnings("serial") // Same-version serialization only 958 public static class InsertBreakAction extends TextAction { 959 960 /** 961 * Creates this object with the appropriate identifier. 962 */ 963 public InsertBreakAction() { 964 super(insertBreakAction); 965 } 966 967 /** 968 * The operation to perform when this action is triggered. 969 * 970 * @param e the action event 971 */ 972 public void actionPerformed(ActionEvent e) { 973 JTextComponent target = getTextComponent(e); 974 if (target != null) { 975 if ((! target.isEditable()) || (! target.isEnabled())) { 976 UIManager.getLookAndFeel().provideErrorFeedback(target); 977 return; 978 } 979 target.replaceSelection("\n"); 980 } 981 } 982 } 983 984 /** 985 * Places a tab character into the document. If there 986 * is a selection, it is removed before the tab is added. 987 * <p> 988 * <strong>Warning:</strong> 989 * Serialized objects of this class will not be compatible with 990 * future Swing releases. The current serialization support is 991 * appropriate for short term storage or RMI between applications running 992 * the same version of Swing. As of 1.4, support for long term storage 993 * of all JavaBeans™ 994 * has been added to the <code>java.beans</code> package. 995 * Please see {@link java.beans.XMLEncoder}. 996 * 997 * @see DefaultEditorKit#insertTabAction 998 * @see DefaultEditorKit#getActions 999 */ 1000 @SuppressWarnings("serial") // Same-version serialization only 1001 public static class InsertTabAction extends TextAction { 1002 1003 /** 1004 * Creates this object with the appropriate identifier. 1005 */ 1006 public InsertTabAction() { 1007 super(insertTabAction); 1008 } 1009 1010 /** 1011 * The operation to perform when this action is triggered. 1012 * 1013 * @param e the action event 1014 */ 1015 public void actionPerformed(ActionEvent e) { 1016 JTextComponent target = getTextComponent(e); 1017 if (target != null) { 1018 if ((! target.isEditable()) || (! target.isEnabled())) { 1019 UIManager.getLookAndFeel().provideErrorFeedback(target); 1020 return; 1021 } 1022 target.replaceSelection("\t"); 1023 } 1024 } 1025 } 1026 1027 /* 1028 * Deletes the character of content that precedes the 1029 * current caret position. 1030 * @see DefaultEditorKit#deletePrevCharAction 1031 * @see DefaultEditorKit#getActions 1032 */ 1033 @SuppressWarnings("serial") // Superclass is not serializable across versions 1034 static class DeletePrevCharAction extends TextAction { 1035 1036 /** 1037 * Creates this object with the appropriate identifier. 1038 */ 1039 DeletePrevCharAction() { 1040 super(deletePrevCharAction); 1041 } 1042 1043 /** 1044 * The operation to perform when this action is triggered. 1045 * 1046 * @param e the action event 1047 */ 1048 public void actionPerformed(ActionEvent e) { 1049 JTextComponent target = getTextComponent(e); 1050 boolean beep = true; 1051 if ((target != null) && (target.isEditable())) { 1052 try { 1053 Document doc = target.getDocument(); 1054 Caret caret = target.getCaret(); 1055 int dot = caret.getDot(); 1056 int mark = caret.getMark(); 1057 if (dot != mark) { 1058 doc.remove(Math.min(dot, mark), Math.abs(dot - mark)); 1059 beep = false; 1060 } else if (dot > 0) { 1061 int delChars = 1; 1062 1063 if (dot > 1) { 1064 String dotChars = doc.getText(dot - 2, 2); 1065 char c0 = dotChars.charAt(0); 1066 char c1 = dotChars.charAt(1); 1067 1068 if (c0 >= '\uD800' && c0 <= '\uDBFF' && 1069 c1 >= '\uDC00' && c1 <= '\uDFFF') { 1070 delChars = 2; 1071 } 1072 } 1073 1074 doc.remove(dot - delChars, delChars); 1075 beep = false; 1076 } 1077 } catch (BadLocationException bl) { 1078 } 1079 } 1080 if (beep) { 1081 UIManager.getLookAndFeel().provideErrorFeedback(target); 1082 } 1083 } 1084 } 1085 1086 /* 1087 * Deletes the character of content that follows the 1088 * current caret position. 1089 * @see DefaultEditorKit#deleteNextCharAction 1090 * @see DefaultEditorKit#getActions 1091 */ 1092 @SuppressWarnings("serial") // Superclass is not serializable across versions 1093 static class DeleteNextCharAction extends TextAction { 1094 1095 /* Create this object with the appropriate identifier. */ 1096 DeleteNextCharAction() { 1097 super(deleteNextCharAction); 1098 } 1099 1100 /** The operation to perform when this action is triggered. */ 1101 public void actionPerformed(ActionEvent e) { 1102 JTextComponent target = getTextComponent(e); 1103 boolean beep = true; 1104 if ((target != null) && (target.isEditable())) { 1105 try { 1106 Document doc = target.getDocument(); 1107 Caret caret = target.getCaret(); 1108 int dot = caret.getDot(); 1109 int mark = caret.getMark(); 1110 if (dot != mark) { 1111 doc.remove(Math.min(dot, mark), Math.abs(dot - mark)); 1112 beep = false; 1113 } else if (dot < doc.getLength()) { 1114 int delChars = 1; 1115 1116 if (dot < doc.getLength() - 1) { 1117 String dotChars = doc.getText(dot, 2); 1118 char c0 = dotChars.charAt(0); 1119 char c1 = dotChars.charAt(1); 1120 1121 if (c0 >= '\uD800' && c0 <= '\uDBFF' && 1122 c1 >= '\uDC00' && c1 <= '\uDFFF') { 1123 delChars = 2; 1124 } 1125 } 1126 1127 doc.remove(dot, delChars); 1128 beep = false; 1129 } 1130 } catch (BadLocationException bl) { 1131 } 1132 } 1133 if (beep) { 1134 UIManager.getLookAndFeel().provideErrorFeedback(target); 1135 } 1136 } 1137 } 1138 1139 1140 /* 1141 * Deletes the word that precedes/follows the beginning of the selection. 1142 * @see DefaultEditorKit#getActions 1143 */ 1144 @SuppressWarnings("serial") // Superclass is not serializable across versions 1145 static class DeleteWordAction extends TextAction { 1146 DeleteWordAction(String name) { 1147 super(name); 1148 assert (name == deletePrevWordAction) 1149 || (name == deleteNextWordAction); 1150 } 1151 /** 1152 * The operation to perform when this action is triggered. 1153 * 1154 * @param e the action event 1155 */ 1156 public void actionPerformed(ActionEvent e) { 1157 final JTextComponent target = getTextComponent(e); 1158 if ((target != null) && (e != null)) { 1159 if ((! target.isEditable()) || (! target.isEnabled())) { 1160 UIManager.getLookAndFeel().provideErrorFeedback(target); 1161 return; 1162 } 1163 boolean beep = true; 1164 try { 1165 final int start = target.getSelectionStart(); 1166 final Element line = 1167 Utilities.getParagraphElement(target, start); 1168 int end; 1169 if (deleteNextWordAction == getValue(Action.NAME)) { 1170 end = Utilities. 1171 getNextWordInParagraph(target, line, start, false); 1172 if (end == java.text.BreakIterator.DONE) { 1173 //last word in the paragraph 1174 final int endOfLine = line.getEndOffset(); 1175 if (start == endOfLine - 1) { 1176 //for last position remove last \n 1177 end = endOfLine; 1178 } else { 1179 //remove to the end of the paragraph 1180 end = endOfLine - 1; 1181 } 1182 } 1183 } else { 1184 end = Utilities. 1185 getPrevWordInParagraph(target, line, start); 1186 if (end == java.text.BreakIterator.DONE) { 1187 //there is no previous word in the paragraph 1188 final int startOfLine = line.getStartOffset(); 1189 if (start == startOfLine) { 1190 //for first position remove previous \n 1191 end = startOfLine - 1; 1192 } else { 1193 //remove to the start of the paragraph 1194 end = startOfLine; 1195 } 1196 } 1197 } 1198 int offs = Math.min(start, end); 1199 int len = Math.abs(end - start); 1200 if (offs >= 0) { 1201 target.getDocument().remove(offs, len); 1202 beep = false; 1203 } 1204 } catch (BadLocationException ignore) { 1205 } 1206 if (beep) { 1207 UIManager.getLookAndFeel().provideErrorFeedback(target); 1208 } 1209 } 1210 } 1211 } 1212 1213 1214 /* 1215 * Sets the editor into read-only mode. 1216 * @see DefaultEditorKit#readOnlyAction 1217 * @see DefaultEditorKit#getActions 1218 */ 1219 @SuppressWarnings("serial") // Superclass is not serializable across versions 1220 static class ReadOnlyAction extends TextAction { 1221 1222 /* Create this object with the appropriate identifier. */ 1223 ReadOnlyAction() { 1224 super(readOnlyAction); 1225 } 1226 1227 /** 1228 * The operation to perform when this action is triggered. 1229 * 1230 * @param e the action event 1231 */ 1232 public void actionPerformed(ActionEvent e) { 1233 JTextComponent target = getTextComponent(e); 1234 if (target != null) { 1235 target.setEditable(false); 1236 } 1237 } 1238 } 1239 1240 /* 1241 * Sets the editor into writeable mode. 1242 * @see DefaultEditorKit#writableAction 1243 * @see DefaultEditorKit#getActions 1244 */ 1245 @SuppressWarnings("serial") // Superclass is not serializable across versions 1246 static class WritableAction extends TextAction { 1247 1248 /* Create this object with the appropriate identifier. */ 1249 WritableAction() { 1250 super(writableAction); 1251 } 1252 1253 /** 1254 * The operation to perform when this action is triggered. 1255 * 1256 * @param e the action event 1257 */ 1258 public void actionPerformed(ActionEvent e) { 1259 JTextComponent target = getTextComponent(e); 1260 if (target != null) { 1261 target.setEditable(true); 1262 } 1263 } 1264 } 1265 1266 /** 1267 * Cuts the selected region and place its contents 1268 * into the system clipboard. 1269 * <p> 1270 * <strong>Warning:</strong> 1271 * Serialized objects of this class will not be compatible with 1272 * future Swing releases. The current serialization support is 1273 * appropriate for short term storage or RMI between applications running 1274 * the same version of Swing. As of 1.4, support for long term storage 1275 * of all JavaBeans™ 1276 * has been added to the <code>java.beans</code> package. 1277 * Please see {@link java.beans.XMLEncoder}. 1278 * 1279 * @see DefaultEditorKit#cutAction 1280 * @see DefaultEditorKit#getActions 1281 */ 1282 @SuppressWarnings("serial") // Same-version serialization only 1283 public static class CutAction extends TextAction { 1284 1285 /** Create this object with the appropriate identifier. */ 1286 public CutAction() { 1287 super(cutAction); 1288 } 1289 1290 /** 1291 * The operation to perform when this action is triggered. 1292 * 1293 * @param e the action event 1294 */ 1295 public void actionPerformed(ActionEvent e) { 1296 JTextComponent target = getTextComponent(e); 1297 if (target != null) { 1298 target.cut(); 1299 } 1300 } 1301 } 1302 1303 /** 1304 * Copies the selected region and place its contents 1305 * into the system clipboard. 1306 * <p> 1307 * <strong>Warning:</strong> 1308 * Serialized objects of this class will not be compatible with 1309 * future Swing releases. The current serialization support is 1310 * appropriate for short term storage or RMI between applications running 1311 * the same version of Swing. As of 1.4, support for long term storage 1312 * of all JavaBeans™ 1313 * has been added to the <code>java.beans</code> package. 1314 * Please see {@link java.beans.XMLEncoder}. 1315 * 1316 * @see DefaultEditorKit#copyAction 1317 * @see DefaultEditorKit#getActions 1318 */ 1319 @SuppressWarnings("serial") // Same-version serialization only 1320 public static class CopyAction extends TextAction { 1321 1322 /** Create this object with the appropriate identifier. */ 1323 public CopyAction() { 1324 super(copyAction); 1325 } 1326 1327 /** 1328 * The operation to perform when this action is triggered. 1329 * 1330 * @param e the action event 1331 */ 1332 public void actionPerformed(ActionEvent e) { 1333 JTextComponent target = getTextComponent(e); 1334 if (target != null) { 1335 target.copy(); 1336 } 1337 } 1338 } 1339 1340 /** 1341 * Pastes the contents of the system clipboard into the 1342 * selected region, or before the caret if nothing is 1343 * selected. 1344 * <p> 1345 * <strong>Warning:</strong> 1346 * Serialized objects of this class will not be compatible with 1347 * future Swing releases. The current serialization support is 1348 * appropriate for short term storage or RMI between applications running 1349 * the same version of Swing. As of 1.4, support for long term storage 1350 * of all JavaBeans™ 1351 * has been added to the <code>java.beans</code> package. 1352 * Please see {@link java.beans.XMLEncoder}. 1353 * 1354 * @see DefaultEditorKit#pasteAction 1355 * @see DefaultEditorKit#getActions 1356 */ 1357 @SuppressWarnings("serial") // Same-version serialization only 1358 public static class PasteAction extends TextAction { 1359 1360 /** Create this object with the appropriate identifier. */ 1361 public PasteAction() { 1362 super(pasteAction); 1363 } 1364 1365 /** 1366 * The operation to perform when this action is triggered. 1367 * 1368 * @param e the action event 1369 */ 1370 public void actionPerformed(ActionEvent e) { 1371 JTextComponent target = getTextComponent(e); 1372 if (target != null) { 1373 target.paste(); 1374 } 1375 } 1376 } 1377 1378 /** 1379 * Creates a beep. 1380 * <p> 1381 * <strong>Warning:</strong> 1382 * Serialized objects of this class will not be compatible with 1383 * future Swing releases. The current serialization support is 1384 * appropriate for short term storage or RMI between applications running 1385 * the same version of Swing. As of 1.4, support for long term storage 1386 * of all JavaBeans™ 1387 * has been added to the <code>java.beans</code> package. 1388 * Please see {@link java.beans.XMLEncoder}. 1389 * 1390 * @see DefaultEditorKit#beepAction 1391 * @see DefaultEditorKit#getActions 1392 */ 1393 @SuppressWarnings("serial") // Same-version serialization only 1394 public static class BeepAction extends TextAction { 1395 1396 /** Create this object with the appropriate identifier. */ 1397 public BeepAction() { 1398 super(beepAction); 1399 } 1400 1401 /** 1402 * The operation to perform when this action is triggered. 1403 * 1404 * @param e the action event 1405 */ 1406 public void actionPerformed(ActionEvent e) { 1407 JTextComponent target = getTextComponent(e); 1408 UIManager.getLookAndFeel().provideErrorFeedback(target); 1409 } 1410 } 1411 1412 /** 1413 * Scrolls up/down vertically. The select version of this action extends 1414 * the selection, instead of simply moving the caret. 1415 * 1416 * @see DefaultEditorKit#pageUpAction 1417 * @see DefaultEditorKit#pageDownAction 1418 * @see DefaultEditorKit#getActions 1419 */ 1420 @SuppressWarnings("serial") // Superclass is not serializable across versions 1421 static class VerticalPageAction extends TextAction { 1422 1423 /** Create this object with the appropriate identifier. */ 1424 public VerticalPageAction(String nm, int direction, boolean select) { 1425 super(nm); 1426 this.select = select; 1427 this.direction = direction; 1428 } 1429 1430 /** The operation to perform when this action is triggered. */ 1431 @SuppressWarnings("deprecation") 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 } else { 1499 // If the caret index is same as the visible offset 1500 // then correct newVis.y so that it won't cause 1501 // unnecessary scrolling upward/downward when 1502 // page-down/page-up is received after ctrl-END/ctrl-HOME 1503 if (direction == -1 && newVis.y <= initialY || 1504 direction == 1 && newVis.y >= initialY) { 1505 newVis.y = initialY; 1506 } 1507 } 1508 } catch (BadLocationException ble) { } 1509 } else { 1510 newVis.y = constrainY(target, 1511 initialY + scrollAmount, visible.height); 1512 } 1513 if (magicPosition != null) { 1514 caret.setMagicCaretPosition(magicPosition); 1515 } 1516 target.scrollRectToVisible(newVis); 1517 } 1518 } 1519 1520 /** 1521 * Makes sure <code>y</code> is a valid location in 1522 * <code>target</code>. 1523 */ 1524 private int constrainY(JTextComponent target, int y, int vis) { 1525 if (y < 0) { 1526 y = 0; 1527 } 1528 else if (y + vis > target.getHeight()) { 1529 y = Math.max(0, target.getHeight() - vis); 1530 } 1531 return y; 1532 } 1533 1534 /** 1535 * Ensures that <code>offset</code> is a valid offset into the 1536 * model for <code>text</code>. 1537 */ 1538 private int constrainOffset(JTextComponent text, int offset) { 1539 Document doc = text.getDocument(); 1540 1541 if ((offset != 0) && (offset > doc.getLength())) { 1542 offset = doc.getLength(); 1543 } 1544 if (offset < 0) { 1545 offset = 0; 1546 } 1547 return offset; 1548 } 1549 1550 /** 1551 * Returns adjustsed {@code y} position that indicates the location to scroll to 1552 * after selecting <code>index</code>. 1553 */ 1554 @SuppressWarnings("deprecation") 1555 private int getAdjustedY(JTextComponent text, Rectangle visible, int index) { 1556 int result = visible.y; 1557 1558 try { 1559 Rectangle dotBounds = text.modelToView(index); 1560 1561 if (dotBounds.y < visible.y) { 1562 result = dotBounds.y; 1563 } else { 1564 if ((dotBounds.y > visible.y + visible.height) || 1565 (dotBounds.y + dotBounds.height > visible.y + visible.height)) { 1566 result = dotBounds.y + dotBounds.height - visible.height; 1567 } 1568 } 1569 } catch (BadLocationException ble) { 1570 } 1571 1572 return result; 1573 } 1574 1575 /** 1576 * Adjusts the Rectangle to contain the bounds of the character at 1577 * <code>index</code> in response to a page up. 1578 */ 1579 private boolean select; 1580 1581 /** 1582 * Direction to scroll, 1 is down, -1 is up. 1583 */ 1584 private int direction; 1585 } 1586 1587 1588 /** 1589 * Pages one view to the left or right. 1590 */ 1591 @SuppressWarnings("serial") // Superclass is not serializable across versions 1592 static class PageAction extends TextAction { 1593 1594 /** Create this object with the appropriate identifier. */ 1595 public PageAction(String nm, boolean left, boolean select) { 1596 super(nm); 1597 this.select = select; 1598 this.left = left; 1599 } 1600 1601 /** The operation to perform when this action is triggered. */ 1602 @SuppressWarnings("deprecation") 1603 public void actionPerformed(ActionEvent e) { 1604 JTextComponent target = getTextComponent(e); 1605 if (target != null) { 1606 int selectedIndex; 1607 Rectangle visible = new Rectangle(); 1608 target.computeVisibleRect(visible); 1609 if (left) { 1610 visible.x = Math.max(0, visible.x - visible.width); 1611 } 1612 else { 1613 visible.x += visible.width; 1614 } 1615 1616 selectedIndex = target.getCaretPosition(); 1617 if(selectedIndex != -1) { 1618 if (left) { 1619 selectedIndex = target.viewToModel 1620 (new Point(visible.x, visible.y)); 1621 } 1622 else { 1623 selectedIndex = target.viewToModel 1624 (new Point(visible.x + visible.width - 1, 1625 visible.y + visible.height - 1)); 1626 } 1627 Document doc = target.getDocument(); 1628 if ((selectedIndex != 0) && 1629 (selectedIndex > (doc.getLength()-1))) { 1630 selectedIndex = doc.getLength()-1; 1631 } 1632 else if(selectedIndex < 0) { 1633 selectedIndex = 0; 1634 } 1635 if (select) 1636 target.moveCaretPosition(selectedIndex); 1637 else 1638 target.setCaretPosition(selectedIndex); 1639 } 1640 } 1641 } 1642 1643 private boolean select; 1644 private boolean left; 1645 } 1646 1647 @SuppressWarnings("serial") // Superclass is not serializable across versions 1648 static class DumpModelAction extends TextAction { 1649 1650 DumpModelAction() { 1651 super("dump-model"); 1652 } 1653 1654 public void actionPerformed(ActionEvent e) { 1655 JTextComponent target = getTextComponent(e); 1656 if (target != null) { 1657 Document d = target.getDocument(); 1658 if (d instanceof AbstractDocument) { 1659 ((AbstractDocument) d).dump(System.err); 1660 } 1661 } 1662 } 1663 } 1664 1665 /* 1666 * Action to move the selection by way of the 1667 * getNextVisualPositionFrom method. Constructor indicates direction 1668 * to use. 1669 */ 1670 @SuppressWarnings("serial") // Superclass is not serializable across versions 1671 static class NextVisualPositionAction extends TextAction { 1672 1673 /** 1674 * Create this action with the appropriate identifier. 1675 * @param nm the name of the action, Action.NAME. 1676 * @param select whether to extend the selection when 1677 * changing the caret position. 1678 */ 1679 NextVisualPositionAction(String nm, boolean select, int direction) { 1680 super(nm); 1681 this.select = select; 1682 this.direction = direction; 1683 } 1684 1685 /** The operation to perform when this action is triggered. */ 1686 @SuppressWarnings("deprecation") 1687 public void actionPerformed(ActionEvent e) { 1688 JTextComponent target = getTextComponent(e); 1689 if (target != null) { 1690 Caret caret = target.getCaret(); 1691 DefaultCaret bidiCaret = (caret instanceof DefaultCaret) ? 1692 (DefaultCaret)caret : null; 1693 int dot = caret.getDot(); 1694 Position.Bias[] bias = new Position.Bias[1]; 1695 Point magicPosition = caret.getMagicCaretPosition(); 1696 1697 try { 1698 if(magicPosition == null && 1699 (direction == SwingConstants.NORTH || 1700 direction == SwingConstants.SOUTH)) { 1701 Rectangle r = (bidiCaret != null) ? 1702 target.getUI().modelToView(target, dot, 1703 bidiCaret.getDotBias()) : 1704 target.modelToView(dot); 1705 magicPosition = new Point(r.x, r.y); 1706 } 1707 1708 NavigationFilter filter = target.getNavigationFilter(); 1709 1710 if (filter != null) { 1711 dot = filter.getNextVisualPositionFrom 1712 (target, dot, (bidiCaret != null) ? 1713 bidiCaret.getDotBias() : 1714 Position.Bias.Forward, direction, bias); 1715 } 1716 else { 1717 dot = target.getUI().getNextVisualPositionFrom 1718 (target, dot, (bidiCaret != null) ? 1719 bidiCaret.getDotBias() : 1720 Position.Bias.Forward, direction, bias); 1721 } 1722 if(bias[0] == null) { 1723 bias[0] = Position.Bias.Forward; 1724 } 1725 if(bidiCaret != null) { 1726 if (select) { 1727 bidiCaret.moveDot(dot, bias[0]); 1728 } else { 1729 bidiCaret.setDot(dot, bias[0]); 1730 } 1731 } 1732 else { 1733 if (select) { 1734 caret.moveDot(dot); 1735 } else { 1736 caret.setDot(dot); 1737 } 1738 } 1739 if(magicPosition != null && 1740 (direction == SwingConstants.NORTH || 1741 direction == SwingConstants.SOUTH)) { 1742 target.getCaret().setMagicCaretPosition(magicPosition); 1743 } 1744 } catch (BadLocationException ex) { 1745 } 1746 } 1747 } 1748 1749 private boolean select; 1750 private int direction; 1751 } 1752 1753 /* 1754 * Position the caret to the beginning of the word. 1755 * @see DefaultEditorKit#beginWordAction 1756 * @see DefaultEditorKit#selectBeginWordAction 1757 * @see DefaultEditorKit#getActions 1758 */ 1759 @SuppressWarnings("serial") // Superclass is not serializable across versions 1760 static class BeginWordAction extends TextAction { 1761 1762 /** 1763 * Create this action with the appropriate identifier. 1764 * @param nm the name of the action, Action.NAME. 1765 * @param select whether to extend the selection when 1766 * changing the caret position. 1767 */ 1768 BeginWordAction(String nm, boolean select) { 1769 super(nm); 1770 this.select = select; 1771 } 1772 1773 /** The operation to perform when this action is triggered. */ 1774 public void actionPerformed(ActionEvent e) { 1775 JTextComponent target = getTextComponent(e); 1776 if (target != null) { 1777 try { 1778 int offs = target.getCaretPosition(); 1779 int begOffs = Utilities.getWordStart(target, offs); 1780 if (select) { 1781 target.moveCaretPosition(begOffs); 1782 } else { 1783 target.setCaretPosition(begOffs); 1784 } 1785 } catch (BadLocationException bl) { 1786 UIManager.getLookAndFeel().provideErrorFeedback(target); 1787 } 1788 } 1789 } 1790 1791 private boolean select; 1792 } 1793 1794 /* 1795 * Position the caret to the end of the word. 1796 * @see DefaultEditorKit#endWordAction 1797 * @see DefaultEditorKit#selectEndWordAction 1798 * @see DefaultEditorKit#getActions 1799 */ 1800 @SuppressWarnings("serial") // Superclass is not serializable across versions 1801 static class EndWordAction extends TextAction { 1802 1803 /** 1804 * Create this action with the appropriate identifier. 1805 * @param nm the name of the action, Action.NAME. 1806 * @param select whether to extend the selection when 1807 * changing the caret position. 1808 */ 1809 EndWordAction(String nm, boolean select) { 1810 super(nm); 1811 this.select = select; 1812 } 1813 1814 /** The operation to perform when this action is triggered. */ 1815 public void actionPerformed(ActionEvent e) { 1816 JTextComponent target = getTextComponent(e); 1817 if (target != null) { 1818 try { 1819 int offs = target.getCaretPosition(); 1820 int endOffs = Utilities.getWordEnd(target, offs); 1821 if (select) { 1822 target.moveCaretPosition(endOffs); 1823 } else { 1824 target.setCaretPosition(endOffs); 1825 } 1826 } catch (BadLocationException bl) { 1827 UIManager.getLookAndFeel().provideErrorFeedback(target); 1828 } 1829 } 1830 } 1831 1832 private boolean select; 1833 } 1834 1835 /* 1836 * Position the caret to the beginning of the previous word. 1837 * @see DefaultEditorKit#previousWordAction 1838 * @see DefaultEditorKit#selectPreviousWordAction 1839 * @see DefaultEditorKit#getActions 1840 */ 1841 @SuppressWarnings("serial") // Superclass is not serializable across versions 1842 static class PreviousWordAction extends TextAction { 1843 1844 /** 1845 * Create this action with the appropriate identifier. 1846 * @param nm the name of the action, Action.NAME. 1847 * @param select whether to extend the selection when 1848 * changing the caret position. 1849 */ 1850 PreviousWordAction(String nm, boolean select) { 1851 super(nm); 1852 this.select = select; 1853 } 1854 1855 /** The operation to perform when this action is triggered. */ 1856 public void actionPerformed(ActionEvent e) { 1857 JTextComponent target = getTextComponent(e); 1858 if (target != null) { 1859 int offs = target.getCaretPosition(); 1860 boolean failed = false; 1861 try { 1862 Element curPara = 1863 Utilities.getParagraphElement(target, offs); 1864 offs = Utilities.getPreviousWord(target, offs); 1865 if(offs < curPara.getStartOffset()) { 1866 // we should first move to the end of the 1867 // previous paragraph (bug #4278839) 1868 offs = Utilities.getParagraphElement(target, offs). 1869 getEndOffset() - 1; 1870 } 1871 } catch (BadLocationException bl) { 1872 if (offs != 0) { 1873 offs = 0; 1874 } 1875 else { 1876 failed = true; 1877 } 1878 } 1879 if (!failed) { 1880 if (select) { 1881 target.moveCaretPosition(offs); 1882 } else { 1883 target.setCaretPosition(offs); 1884 } 1885 } 1886 else { 1887 UIManager.getLookAndFeel().provideErrorFeedback(target); 1888 } 1889 } 1890 } 1891 1892 private boolean select; 1893 } 1894 1895 /* 1896 * Position the caret to the next of the word. 1897 * @see DefaultEditorKit#nextWordAction 1898 * @see DefaultEditorKit#selectNextWordAction 1899 * @see DefaultEditorKit#getActions 1900 */ 1901 @SuppressWarnings("serial") // Superclass is not serializable across versions 1902 static class NextWordAction extends TextAction { 1903 1904 /** 1905 * Create this action with the appropriate identifier. 1906 * @param nm the name of the action, Action.NAME. 1907 * @param select whether to extend the selection when 1908 * changing the caret position. 1909 */ 1910 NextWordAction(String nm, boolean select) { 1911 super(nm); 1912 this.select = select; 1913 } 1914 1915 /** The operation to perform when this action is triggered. */ 1916 public void actionPerformed(ActionEvent e) { 1917 JTextComponent target = getTextComponent(e); 1918 if (target != null) { 1919 int offs = target.getCaretPosition(); 1920 boolean failed = false; 1921 int oldOffs = offs; 1922 Element curPara = 1923 Utilities.getParagraphElement(target, offs); 1924 try { 1925 offs = Utilities.getNextWord(target, offs); 1926 if(offs >= curPara.getEndOffset() && 1927 oldOffs != curPara.getEndOffset() - 1) { 1928 // we should first move to the end of current 1929 // paragraph (bug #4278839) 1930 offs = curPara.getEndOffset() - 1; 1931 } 1932 } catch (BadLocationException bl) { 1933 int end = target.getDocument().getLength(); 1934 if (offs != end) { 1935 if(oldOffs != curPara.getEndOffset() - 1) { 1936 offs = curPara.getEndOffset() - 1; 1937 } else { 1938 offs = end; 1939 } 1940 } 1941 else { 1942 failed = true; 1943 } 1944 } 1945 if (!failed) { 1946 if (select) { 1947 target.moveCaretPosition(offs); 1948 } else { 1949 target.setCaretPosition(offs); 1950 } 1951 } 1952 else { 1953 UIManager.getLookAndFeel().provideErrorFeedback(target); 1954 } 1955 } 1956 } 1957 1958 private boolean select; 1959 } 1960 1961 /* 1962 * Position the caret to the beginning of the line. 1963 * @see DefaultEditorKit#beginLineAction 1964 * @see DefaultEditorKit#selectBeginLineAction 1965 * @see DefaultEditorKit#getActions 1966 */ 1967 @SuppressWarnings("serial") // Superclass is not serializable across versions 1968 static class BeginLineAction extends TextAction { 1969 1970 /** 1971 * Create this action with the appropriate identifier. 1972 * @param nm the name of the action, Action.NAME. 1973 * @param select whether to extend the selection when 1974 * changing the caret position. 1975 */ 1976 BeginLineAction(String nm, boolean select) { 1977 super(nm); 1978 this.select = select; 1979 } 1980 1981 /** The operation to perform when this action is triggered. */ 1982 public void actionPerformed(ActionEvent e) { 1983 JTextComponent target = getTextComponent(e); 1984 if (target != null) { 1985 try { 1986 int offs = target.getCaretPosition(); 1987 int begOffs = Utilities.getRowStart(target, offs); 1988 if (select) { 1989 target.moveCaretPosition(begOffs); 1990 } else { 1991 target.setCaretPosition(begOffs); 1992 } 1993 } catch (BadLocationException bl) { 1994 UIManager.getLookAndFeel().provideErrorFeedback(target); 1995 } 1996 } 1997 } 1998 1999 private boolean select; 2000 } 2001 2002 /* 2003 * Position the caret to the end of the line. 2004 * @see DefaultEditorKit#endLineAction 2005 * @see DefaultEditorKit#selectEndLineAction 2006 * @see DefaultEditorKit#getActions 2007 */ 2008 @SuppressWarnings("serial") // Superclass is not serializable across versions 2009 static class EndLineAction extends TextAction { 2010 2011 /** 2012 * Create this action with the appropriate identifier. 2013 * @param nm the name of the action, Action.NAME. 2014 * @param select whether to extend the selection when 2015 * changing the caret position. 2016 */ 2017 EndLineAction(String nm, boolean select) { 2018 super(nm); 2019 this.select = select; 2020 } 2021 2022 /** The operation to perform when this action is triggered. */ 2023 public void actionPerformed(ActionEvent e) { 2024 JTextComponent target = getTextComponent(e); 2025 if (target != null) { 2026 try { 2027 int offs = target.getCaretPosition(); 2028 int endOffs = Utilities.getRowEnd(target, offs); 2029 if (select) { 2030 target.moveCaretPosition(endOffs); 2031 } else { 2032 target.setCaretPosition(endOffs); 2033 } 2034 } catch (BadLocationException bl) { 2035 UIManager.getLookAndFeel().provideErrorFeedback(target); 2036 } 2037 } 2038 } 2039 2040 private boolean select; 2041 } 2042 2043 /* 2044 * Position the caret to the beginning of the paragraph. 2045 * @see DefaultEditorKit#beginParagraphAction 2046 * @see DefaultEditorKit#selectBeginParagraphAction 2047 * @see DefaultEditorKit#getActions 2048 */ 2049 @SuppressWarnings("serial") // Superclass is not serializable across versions 2050 static class BeginParagraphAction extends TextAction { 2051 2052 /** 2053 * Create this action with the appropriate identifier. 2054 * @param nm the name of the action, Action.NAME. 2055 * @param select whether to extend the selection when 2056 * changing the caret position. 2057 */ 2058 BeginParagraphAction(String nm, boolean select) { 2059 super(nm); 2060 this.select = select; 2061 } 2062 2063 /** The operation to perform when this action is triggered. */ 2064 public void actionPerformed(ActionEvent e) { 2065 JTextComponent target = getTextComponent(e); 2066 if (target != null) { 2067 int offs = target.getCaretPosition(); 2068 Element elem = Utilities.getParagraphElement(target, offs); 2069 offs = elem.getStartOffset(); 2070 if (select) { 2071 target.moveCaretPosition(offs); 2072 } else { 2073 target.setCaretPosition(offs); 2074 } 2075 } 2076 } 2077 2078 private boolean select; 2079 } 2080 2081 /* 2082 * Position the caret to the end of the paragraph. 2083 * @see DefaultEditorKit#endParagraphAction 2084 * @see DefaultEditorKit#selectEndParagraphAction 2085 * @see DefaultEditorKit#getActions 2086 */ 2087 @SuppressWarnings("serial") // Superclass is not serializable across versions 2088 static class EndParagraphAction extends TextAction { 2089 2090 /** 2091 * Create this action with the appropriate identifier. 2092 * @param nm the name of the action, Action.NAME. 2093 * @param select whether to extend the selection when 2094 * changing the caret position. 2095 */ 2096 EndParagraphAction(String nm, boolean select) { 2097 super(nm); 2098 this.select = select; 2099 } 2100 2101 /** The operation to perform when this action is triggered. */ 2102 public void actionPerformed(ActionEvent e) { 2103 JTextComponent target = getTextComponent(e); 2104 if (target != null) { 2105 int offs = target.getCaretPosition(); 2106 Element elem = Utilities.getParagraphElement(target, offs); 2107 offs = Math.min(target.getDocument().getLength(), 2108 elem.getEndOffset()); 2109 if (select) { 2110 target.moveCaretPosition(offs); 2111 } else { 2112 target.setCaretPosition(offs); 2113 } 2114 } 2115 } 2116 2117 private boolean select; 2118 } 2119 2120 /* 2121 * Move the caret to the beginning of the document. 2122 * @see DefaultEditorKit#beginAction 2123 * @see DefaultEditorKit#getActions 2124 */ 2125 @SuppressWarnings("serial") // Superclass is not serializable across versions 2126 static class BeginAction extends TextAction { 2127 2128 /* Create this object with the appropriate identifier. */ 2129 BeginAction(String nm, boolean select) { 2130 super(nm); 2131 this.select = select; 2132 } 2133 2134 /** The operation to perform when this action is triggered. */ 2135 public void actionPerformed(ActionEvent e) { 2136 JTextComponent target = getTextComponent(e); 2137 if (target != null) { 2138 if (select) { 2139 target.moveCaretPosition(0); 2140 } else { 2141 target.setCaretPosition(0); 2142 } 2143 } 2144 } 2145 2146 private boolean select; 2147 } 2148 2149 /* 2150 * Move the caret to the end of the document. 2151 * @see DefaultEditorKit#endAction 2152 * @see DefaultEditorKit#getActions 2153 */ 2154 @SuppressWarnings("serial") // Superclass is not serializable across versions 2155 static class EndAction extends TextAction { 2156 2157 /* Create this object with the appropriate identifier. */ 2158 EndAction(String nm, boolean select) { 2159 super(nm); 2160 this.select = select; 2161 } 2162 2163 /** The operation to perform when this action is triggered. */ 2164 public void actionPerformed(ActionEvent e) { 2165 JTextComponent target = getTextComponent(e); 2166 if (target != null) { 2167 Document doc = target.getDocument(); 2168 int dot = doc.getLength(); 2169 if (select) { 2170 target.moveCaretPosition(dot); 2171 } else { 2172 target.setCaretPosition(dot); 2173 } 2174 } 2175 } 2176 2177 private boolean select; 2178 } 2179 2180 /* 2181 * Select the word around the caret 2182 * @see DefaultEditorKit#endAction 2183 * @see DefaultEditorKit#getActions 2184 */ 2185 @SuppressWarnings("serial") // Superclass is not serializable across versions 2186 static class SelectWordAction extends TextAction { 2187 2188 /** 2189 * Create this action with the appropriate identifier. 2190 */ 2191 SelectWordAction() { 2192 super(selectWordAction); 2193 start = new BeginWordAction("pigdog", false); 2194 end = new EndWordAction("pigdog", true); 2195 } 2196 2197 /** The operation to perform when this action is triggered. */ 2198 public void actionPerformed(ActionEvent e) { 2199 start.actionPerformed(e); 2200 end.actionPerformed(e); 2201 } 2202 2203 private Action start; 2204 private Action end; 2205 } 2206 2207 /* 2208 * Select the line around the caret 2209 * @see DefaultEditorKit#endAction 2210 * @see DefaultEditorKit#getActions 2211 */ 2212 @SuppressWarnings("serial") // Superclass is not serializable across versions 2213 static class SelectLineAction extends TextAction { 2214 2215 /** 2216 * Create this action with the appropriate identifier. 2217 */ 2218 SelectLineAction() { 2219 super(selectLineAction); 2220 start = new BeginLineAction("pigdog", false); 2221 end = new EndLineAction("pigdog", true); 2222 } 2223 2224 /** The operation to perform when this action is triggered. */ 2225 public void actionPerformed(ActionEvent e) { 2226 start.actionPerformed(e); 2227 end.actionPerformed(e); 2228 } 2229 2230 private Action start; 2231 private Action end; 2232 } 2233 2234 /* 2235 * Select the paragraph around the caret 2236 * @see DefaultEditorKit#endAction 2237 * @see DefaultEditorKit#getActions 2238 */ 2239 @SuppressWarnings("serial") // Superclass is not serializable across versions 2240 static class SelectParagraphAction extends TextAction { 2241 2242 /** 2243 * Create this action with the appropriate identifier. 2244 */ 2245 SelectParagraphAction() { 2246 super(selectParagraphAction); 2247 start = new BeginParagraphAction("pigdog", false); 2248 end = new EndParagraphAction("pigdog", true); 2249 } 2250 2251 /** The operation to perform when this action is triggered. */ 2252 public void actionPerformed(ActionEvent e) { 2253 start.actionPerformed(e); 2254 end.actionPerformed(e); 2255 } 2256 2257 private Action start; 2258 private Action end; 2259 } 2260 2261 /* 2262 * Select the entire document 2263 * @see DefaultEditorKit#endAction 2264 * @see DefaultEditorKit#getActions 2265 */ 2266 @SuppressWarnings("serial") // Superclass is not serializable across versions 2267 static class SelectAllAction extends TextAction { 2268 2269 /** 2270 * Create this action with the appropriate identifier. 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 }