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

Save This Page
Home » openjdk-7 » javax » swing » text » [javadoc | source]