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

    1   /*
    2    * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   package javax.swing.text;
   26   
   27   import 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                               int newY = getAdjustedY(target, newVis, newIndex);
 1465   
 1466                               if (direction == -1 && newY <= initialY || direction == 1 && newY >= initialY) {
 1467                                   // Change index and correct newVis.y only if won't cause scrolling upward
 1468                                   newVis.y = newY;
 1469   
 1470                                   if (select) {
 1471                                       target.moveCaretPosition(newIndex);
 1472                                   } else {
 1473                                       target.setCaretPosition(newIndex);
 1474                                   }
 1475                               }
 1476                           }
 1477                       } catch (BadLocationException ble) { }
 1478                   } else {
 1479                       newVis.y = constrainY(target,
 1480                               initialY + scrollAmount, visible.height);
 1481                   }
 1482                   if (magicPosition != null) {
 1483                       caret.setMagicCaretPosition(magicPosition);
 1484                   }
 1485                   target.scrollRectToVisible(newVis);
 1486               }
 1487           }
 1488   
 1489           /**
 1490            * Makes sure <code>y</code> is a valid location in
 1491            * <code>target</code>.
 1492            */
 1493           private int constrainY(JTextComponent target, int y, int vis) {
 1494               if (y < 0) {
 1495                   y = 0;
 1496               }
 1497               else if (y + vis > target.getHeight()) {
 1498                   y = Math.max(0, target.getHeight() - vis);
 1499               }
 1500               return y;
 1501           }
 1502   
 1503           /**
 1504            * Ensures that <code>offset</code> is a valid offset into the
 1505            * model for <code>text</code>.
 1506            */
 1507           private int constrainOffset(JTextComponent text, int offset) {
 1508               Document doc = text.getDocument();
 1509   
 1510               if ((offset != 0) && (offset > doc.getLength())) {
 1511                   offset = doc.getLength();
 1512               }
 1513               if (offset  < 0) {
 1514                   offset = 0;
 1515               }
 1516               return offset;
 1517           }
 1518   
 1519           /**
 1520            * Returns adjustsed {@code y} position that indicates the location to scroll to
 1521            * after selecting <code>index</code>.
 1522            */
 1523           private int getAdjustedY(JTextComponent text, Rectangle visible, int index) {
 1524               int result = visible.y;
 1525   
 1526               try {
 1527                   Rectangle dotBounds = text.modelToView(index);
 1528   
 1529                   if (dotBounds.y < visible.y) {
 1530                       result = dotBounds.y;
 1531                   } else {
 1532                       if ((dotBounds.y > visible.y + visible.height) ||
 1533                               (dotBounds.y + dotBounds.height > visible.y + visible.height)) {
 1534                           result = dotBounds.y + dotBounds.height - visible.height;
 1535                       }
 1536                   }
 1537               } catch (BadLocationException ble) {
 1538               }
 1539   
 1540               return result;
 1541           }
 1542   
 1543           /**
 1544            * Adjusts the Rectangle to contain the bounds of the character at
 1545            * <code>index</code> in response to a page up.
 1546            */
 1547           private boolean select;
 1548   
 1549           /**
 1550            * Direction to scroll, 1 is down, -1 is up.
 1551            */
 1552           private int direction;
 1553       }
 1554   
 1555   
 1556       /**
 1557        * Pages one view to the left or right.
 1558        */
 1559       static class PageAction extends TextAction {
 1560   
 1561           /** Create this object with the appropriate identifier. */
 1562           public PageAction(String nm, boolean left, boolean select) {
 1563               super(nm);
 1564               this.select = select;
 1565               this.left = left;
 1566           }
 1567   
 1568           /** The operation to perform when this action is triggered. */
 1569           public void actionPerformed(ActionEvent e) {
 1570               JTextComponent target = getTextComponent(e);
 1571               if (target != null) {
 1572                   int selectedIndex;
 1573                   Rectangle visible = new Rectangle();
 1574                   target.computeVisibleRect(visible);
 1575                   if (left) {
 1576                       visible.x = Math.max(0, visible.x - visible.width);
 1577                   }
 1578                   else {
 1579                       visible.x += visible.width;
 1580                   }
 1581   
 1582                   selectedIndex = target.getCaretPosition();
 1583                   if(selectedIndex != -1) {
 1584                       if (left) {
 1585                           selectedIndex = target.viewToModel
 1586                               (new Point(visible.x, visible.y));
 1587                       }
 1588                       else {
 1589                           selectedIndex = target.viewToModel
 1590                               (new Point(visible.x + visible.width - 1,
 1591                                          visible.y + visible.height - 1));
 1592                       }
 1593                       Document doc = target.getDocument();
 1594                       if ((selectedIndex != 0) &&
 1595                           (selectedIndex  > (doc.getLength()-1))) {
 1596                           selectedIndex = doc.getLength()-1;
 1597                       }
 1598                       else if(selectedIndex  < 0) {
 1599                           selectedIndex = 0;
 1600                       }
 1601                       if (select)
 1602                           target.moveCaretPosition(selectedIndex);
 1603                       else
 1604                           target.setCaretPosition(selectedIndex);
 1605                   }
 1606               }
 1607           }
 1608   
 1609           private boolean select;
 1610           private boolean left;
 1611       }
 1612   
 1613       static class DumpModelAction extends TextAction {
 1614   
 1615           DumpModelAction() {
 1616               super("dump-model");
 1617           }
 1618   
 1619           public void actionPerformed(ActionEvent e) {
 1620               JTextComponent target = getTextComponent(e);
 1621               if (target != null) {
 1622                   Document d = target.getDocument();
 1623                   if (d instanceof AbstractDocument) {
 1624                       ((AbstractDocument) d).dump(System.err);
 1625                   }
 1626               }
 1627           }
 1628       }
 1629   
 1630       /*
 1631        * Action to move the selection by way of the
 1632        * getNextVisualPositionFrom method. Constructor indicates direction
 1633        * to use.
 1634        */
 1635       static class NextVisualPositionAction extends TextAction {
 1636   
 1637           /**
 1638            * Create this action with the appropriate identifier.
 1639            * @param nm  the name of the action, Action.NAME.
 1640            * @param select whether to extend the selection when
 1641            *  changing the caret position.
 1642            */
 1643           NextVisualPositionAction(String nm, boolean select, int direction) {
 1644               super(nm);
 1645               this.select = select;
 1646               this.direction = direction;
 1647           }
 1648   
 1649           /** The operation to perform when this action is triggered. */
 1650           public void actionPerformed(ActionEvent e) {
 1651               JTextComponent target = getTextComponent(e);
 1652               if (target != null) {
 1653                   Caret caret = target.getCaret();
 1654                   DefaultCaret bidiCaret = (caret instanceof DefaultCaret) ?
 1655                                                 (DefaultCaret)caret : null;
 1656                   int dot = caret.getDot();
 1657                   Position.Bias[] bias = new Position.Bias[1];
 1658                   Point magicPosition = caret.getMagicCaretPosition();
 1659   
 1660                   try {
 1661                       if(magicPosition == null &&
 1662                          (direction == SwingConstants.NORTH ||
 1663                           direction == SwingConstants.SOUTH)) {
 1664                           Rectangle r = (bidiCaret != null) ?
 1665                                   target.getUI().modelToView(target, dot,
 1666                                                         bidiCaret.getDotBias()) :
 1667                                   target.modelToView(dot);
 1668                           magicPosition = new Point(r.x, r.y);
 1669                       }
 1670   
 1671                       NavigationFilter filter = target.getNavigationFilter();
 1672   
 1673                       if (filter != null) {
 1674                           dot = filter.getNextVisualPositionFrom
 1675                                        (target, dot, (bidiCaret != null) ?
 1676                                         bidiCaret.getDotBias() :
 1677                                         Position.Bias.Forward, direction, bias);
 1678                       }
 1679                       else {
 1680                           dot = target.getUI().getNextVisualPositionFrom
 1681                                        (target, dot, (bidiCaret != null) ?
 1682                                         bidiCaret.getDotBias() :
 1683                                         Position.Bias.Forward, direction, bias);
 1684                       }
 1685                       if(bias[0] == null) {
 1686                           bias[0] = Position.Bias.Forward;
 1687                       }
 1688                       if(bidiCaret != null) {
 1689                           if (select) {
 1690                               bidiCaret.moveDot(dot, bias[0]);
 1691                           } else {
 1692                               bidiCaret.setDot(dot, bias[0]);
 1693                           }
 1694                       }
 1695                       else {
 1696                           if (select) {
 1697                               caret.moveDot(dot);
 1698                           } else {
 1699                               caret.setDot(dot);
 1700                           }
 1701                       }
 1702                       if(magicPosition != null &&
 1703                          (direction == SwingConstants.NORTH ||
 1704                           direction == SwingConstants.SOUTH)) {
 1705                           target.getCaret().setMagicCaretPosition(magicPosition);
 1706                       }
 1707                   } catch (BadLocationException ex) {
 1708                   }
 1709               }
 1710           }
 1711   
 1712           private boolean select;
 1713           private int direction;
 1714       }
 1715   
 1716       /*
 1717        * Position the caret to the beginning of the word.
 1718        * @see DefaultEditorKit#beginWordAction
 1719        * @see DefaultEditorKit#selectBeginWordAction
 1720        * @see DefaultEditorKit#getActions
 1721        */
 1722       static class BeginWordAction extends TextAction {
 1723   
 1724           /**
 1725            * Create this action with the appropriate identifier.
 1726            * @param nm  the name of the action, Action.NAME.
 1727            * @param select whether to extend the selection when
 1728            *  changing the caret position.
 1729            */
 1730           BeginWordAction(String nm, boolean select) {
 1731               super(nm);
 1732               this.select = select;
 1733           }
 1734   
 1735           /** The operation to perform when this action is triggered. */
 1736           public void actionPerformed(ActionEvent e) {
 1737               JTextComponent target = getTextComponent(e);
 1738               if (target != null) {
 1739                   try {
 1740                       int offs = target.getCaretPosition();
 1741                       int begOffs = Utilities.getWordStart(target, offs);
 1742                       if (select) {
 1743                           target.moveCaretPosition(begOffs);
 1744                       } else {
 1745                           target.setCaretPosition(begOffs);
 1746                       }
 1747                   } catch (BadLocationException bl) {
 1748                       UIManager.getLookAndFeel().provideErrorFeedback(target);
 1749                   }
 1750               }
 1751           }
 1752   
 1753           private boolean select;
 1754       }
 1755   
 1756       /*
 1757        * Position the caret to the end of the word.
 1758        * @see DefaultEditorKit#endWordAction
 1759        * @see DefaultEditorKit#selectEndWordAction
 1760        * @see DefaultEditorKit#getActions
 1761        */
 1762       static class EndWordAction extends TextAction {
 1763   
 1764           /**
 1765            * Create this action with the appropriate identifier.
 1766            * @param nm  the name of the action, Action.NAME.
 1767            * @param select whether to extend the selection when
 1768            *  changing the caret position.
 1769            */
 1770           EndWordAction(String nm, boolean select) {
 1771               super(nm);
 1772               this.select = select;
 1773           }
 1774   
 1775           /** The operation to perform when this action is triggered. */
 1776           public void actionPerformed(ActionEvent e) {
 1777               JTextComponent target = getTextComponent(e);
 1778               if (target != null) {
 1779                   try {
 1780                       int offs = target.getCaretPosition();
 1781                       int endOffs = Utilities.getWordEnd(target, offs);
 1782                       if (select) {
 1783                           target.moveCaretPosition(endOffs);
 1784                       } else {
 1785                           target.setCaretPosition(endOffs);
 1786                       }
 1787                   } catch (BadLocationException bl) {
 1788                       UIManager.getLookAndFeel().provideErrorFeedback(target);
 1789                   }
 1790               }
 1791           }
 1792   
 1793           private boolean select;
 1794       }
 1795   
 1796       /*
 1797        * Position the caret to the beginning of the previous word.
 1798        * @see DefaultEditorKit#previousWordAction
 1799        * @see DefaultEditorKit#selectPreviousWordAction
 1800        * @see DefaultEditorKit#getActions
 1801        */
 1802       static class PreviousWordAction extends TextAction {
 1803   
 1804           /**
 1805            * Create this action with the appropriate identifier.
 1806            * @param nm  the name of the action, Action.NAME.
 1807            * @param select whether to extend the selection when
 1808            *  changing the caret position.
 1809            */
 1810           PreviousWordAction(String nm, boolean select) {
 1811               super(nm);
 1812               this.select = select;
 1813           }
 1814   
 1815           /** The operation to perform when this action is triggered. */
 1816           public void actionPerformed(ActionEvent e) {
 1817               JTextComponent target = getTextComponent(e);
 1818               if (target != null) {
 1819                   int offs = target.getCaretPosition();
 1820                   boolean failed = false;
 1821                   try {
 1822                       Element curPara =
 1823                               Utilities.getParagraphElement(target, offs);
 1824                       offs = Utilities.getPreviousWord(target, offs);
 1825                       if(offs < curPara.getStartOffset()) {
 1826                           // we should first move to the end of the
 1827                           // previous paragraph (bug #4278839)
 1828                           offs = Utilities.getParagraphElement(target, offs).
 1829                                   getEndOffset() - 1;
 1830                       }
 1831                   } catch (BadLocationException bl) {
 1832                       if (offs != 0) {
 1833                           offs = 0;
 1834                       }
 1835                       else {
 1836                           failed = true;
 1837                       }
 1838                   }
 1839                   if (!failed) {
 1840                       if (select) {
 1841                           target.moveCaretPosition(offs);
 1842                       } else {
 1843                           target.setCaretPosition(offs);
 1844                       }
 1845                   }
 1846                   else {
 1847                       UIManager.getLookAndFeel().provideErrorFeedback(target);
 1848                   }
 1849               }
 1850           }
 1851   
 1852           private boolean select;
 1853       }
 1854   
 1855       /*
 1856        * Position the caret to the next of the word.
 1857        * @see DefaultEditorKit#nextWordAction
 1858        * @see DefaultEditorKit#selectNextWordAction
 1859        * @see DefaultEditorKit#getActions
 1860        */
 1861       static class NextWordAction extends TextAction {
 1862   
 1863           /**
 1864            * Create this action with the appropriate identifier.
 1865            * @param nm  the name of the action, Action.NAME.
 1866            * @param select whether to extend the selection when
 1867            *  changing the caret position.
 1868            */
 1869           NextWordAction(String nm, boolean select) {
 1870               super(nm);
 1871               this.select = select;
 1872           }
 1873   
 1874           /** The operation to perform when this action is triggered. */
 1875           public void actionPerformed(ActionEvent e) {
 1876               JTextComponent target = getTextComponent(e);
 1877               if (target != null) {
 1878                   int offs = target.getCaretPosition();
 1879                   boolean failed = false;
 1880                   int oldOffs = offs;
 1881                   Element curPara =
 1882                           Utilities.getParagraphElement(target, offs);
 1883                   try {
 1884                       offs = Utilities.getNextWord(target, offs);
 1885                       if(offs >= curPara.getEndOffset() &&
 1886                               oldOffs != curPara.getEndOffset() - 1) {
 1887                           // we should first move to the end of current
 1888                           // paragraph (bug #4278839)
 1889                           offs = curPara.getEndOffset() - 1;
 1890                       }
 1891                   } catch (BadLocationException bl) {
 1892                       int end = target.getDocument().getLength();
 1893                       if (offs != end) {
 1894                           if(oldOffs != curPara.getEndOffset() - 1) {
 1895                               offs = curPara.getEndOffset() - 1;
 1896                           } else {
 1897                           offs = end;
 1898                       }
 1899                       }
 1900                       else {
 1901                           failed = true;
 1902                       }
 1903                   }
 1904                   if (!failed) {
 1905                       if (select) {
 1906                           target.moveCaretPosition(offs);
 1907                       } else {
 1908                           target.setCaretPosition(offs);
 1909                       }
 1910                   }
 1911                   else {
 1912                       UIManager.getLookAndFeel().provideErrorFeedback(target);
 1913                   }
 1914               }
 1915           }
 1916   
 1917           private boolean select;
 1918       }
 1919   
 1920       /*
 1921        * Position the caret to the beginning of the line.
 1922        * @see DefaultEditorKit#beginLineAction
 1923        * @see DefaultEditorKit#selectBeginLineAction
 1924        * @see DefaultEditorKit#getActions
 1925        */
 1926       static class BeginLineAction extends TextAction {
 1927   
 1928           /**
 1929            * Create this action with the appropriate identifier.
 1930            * @param nm  the name of the action, Action.NAME.
 1931            * @param select whether to extend the selection when
 1932            *  changing the caret position.
 1933            */
 1934           BeginLineAction(String nm, boolean select) {
 1935               super(nm);
 1936               this.select = select;
 1937           }
 1938   
 1939           /** The operation to perform when this action is triggered. */
 1940           public void actionPerformed(ActionEvent e) {
 1941               JTextComponent target = getTextComponent(e);
 1942               if (target != null) {
 1943                   try {
 1944                       int offs = target.getCaretPosition();
 1945                       int begOffs = Utilities.getRowStart(target, offs);
 1946                       if (select) {
 1947                           target.moveCaretPosition(begOffs);
 1948                       } else {
 1949                           target.setCaretPosition(begOffs);
 1950                       }
 1951                   } catch (BadLocationException bl) {
 1952                       UIManager.getLookAndFeel().provideErrorFeedback(target);
 1953                   }
 1954               }
 1955           }
 1956   
 1957           private boolean select;
 1958       }
 1959   
 1960       /*
 1961        * Position the caret to the end of the line.
 1962        * @see DefaultEditorKit#endLineAction
 1963        * @see DefaultEditorKit#selectEndLineAction
 1964        * @see DefaultEditorKit#getActions
 1965        */
 1966       static class EndLineAction extends TextAction {
 1967   
 1968           /**
 1969            * Create this action with the appropriate identifier.
 1970            * @param nm  the name of the action, Action.NAME.
 1971            * @param select whether to extend the selection when
 1972            *  changing the caret position.
 1973            */
 1974           EndLineAction(String nm, boolean select) {
 1975               super(nm);
 1976               this.select = select;
 1977           }
 1978   
 1979           /** The operation to perform when this action is triggered. */
 1980           public void actionPerformed(ActionEvent e) {
 1981               JTextComponent target = getTextComponent(e);
 1982               if (target != null) {
 1983                   try {
 1984                       int offs = target.getCaretPosition();
 1985                       int endOffs = Utilities.getRowEnd(target, offs);
 1986                       if (select) {
 1987                           target.moveCaretPosition(endOffs);
 1988                       } else {
 1989                           target.setCaretPosition(endOffs);
 1990                       }
 1991                   } catch (BadLocationException bl) {
 1992                       UIManager.getLookAndFeel().provideErrorFeedback(target);
 1993                   }
 1994               }
 1995           }
 1996   
 1997           private boolean select;
 1998       }
 1999   
 2000       /*
 2001        * Position the caret to the beginning of the paragraph.
 2002        * @see DefaultEditorKit#beginParagraphAction
 2003        * @see DefaultEditorKit#selectBeginParagraphAction
 2004        * @see DefaultEditorKit#getActions
 2005        */
 2006       static class BeginParagraphAction extends TextAction {
 2007   
 2008           /**
 2009            * Create this action with the appropriate identifier.
 2010            * @param nm  the name of the action, Action.NAME.
 2011            * @param select whether to extend the selection when
 2012            *  changing the caret position.
 2013            */
 2014           BeginParagraphAction(String nm, boolean select) {
 2015               super(nm);
 2016               this.select = select;
 2017           }
 2018   
 2019           /** The operation to perform when this action is triggered. */
 2020           public void actionPerformed(ActionEvent e) {
 2021               JTextComponent target = getTextComponent(e);
 2022               if (target != null) {
 2023                   int offs = target.getCaretPosition();
 2024                   Element elem = Utilities.getParagraphElement(target, offs);
 2025                   offs = elem.getStartOffset();
 2026                   if (select) {
 2027                       target.moveCaretPosition(offs);
 2028                   } else {
 2029                       target.setCaretPosition(offs);
 2030                   }
 2031               }
 2032           }
 2033   
 2034           private boolean select;
 2035       }
 2036   
 2037       /*
 2038        * Position the caret to the end of the paragraph.
 2039        * @see DefaultEditorKit#endParagraphAction
 2040        * @see DefaultEditorKit#selectEndParagraphAction
 2041        * @see DefaultEditorKit#getActions
 2042        */
 2043       static class EndParagraphAction extends TextAction {
 2044   
 2045           /**
 2046            * Create this action with the appropriate identifier.
 2047            * @param nm  the name of the action, Action.NAME.
 2048            * @param select whether to extend the selection when
 2049            *  changing the caret position.
 2050            */
 2051           EndParagraphAction(String nm, boolean select) {
 2052               super(nm);
 2053               this.select = select;
 2054           }
 2055   
 2056           /** The operation to perform when this action is triggered. */
 2057           public void actionPerformed(ActionEvent e) {
 2058               JTextComponent target = getTextComponent(e);
 2059               if (target != null) {
 2060                   int offs = target.getCaretPosition();
 2061                   Element elem = Utilities.getParagraphElement(target, offs);
 2062                   offs = Math.min(target.getDocument().getLength(),
 2063                                   elem.getEndOffset());
 2064                   if (select) {
 2065                       target.moveCaretPosition(offs);
 2066                   } else {
 2067                       target.setCaretPosition(offs);
 2068                   }
 2069               }
 2070           }
 2071   
 2072           private boolean select;
 2073       }
 2074   
 2075       /*
 2076        * Move the caret to the beginning of the document.
 2077        * @see DefaultEditorKit#beginAction
 2078        * @see DefaultEditorKit#getActions
 2079        */
 2080       static class BeginAction extends TextAction {
 2081   
 2082           /* Create this object with the appropriate identifier. */
 2083           BeginAction(String nm, boolean select) {
 2084               super(nm);
 2085               this.select = select;
 2086           }
 2087   
 2088           /** The operation to perform when this action is triggered. */
 2089           public void actionPerformed(ActionEvent e) {
 2090               JTextComponent target = getTextComponent(e);
 2091               if (target != null) {
 2092                   if (select) {
 2093                       target.moveCaretPosition(0);
 2094                   } else {
 2095                       target.setCaretPosition(0);
 2096                   }
 2097               }
 2098           }
 2099   
 2100           private boolean select;
 2101       }
 2102   
 2103       /*
 2104        * Move the caret to the end of the document.
 2105        * @see DefaultEditorKit#endAction
 2106        * @see DefaultEditorKit#getActions
 2107        */
 2108       static class EndAction extends TextAction {
 2109   
 2110           /* Create this object with the appropriate identifier. */
 2111           EndAction(String nm, boolean select) {
 2112               super(nm);
 2113               this.select = select;
 2114           }
 2115   
 2116           /** The operation to perform when this action is triggered. */
 2117           public void actionPerformed(ActionEvent e) {
 2118               JTextComponent target = getTextComponent(e);
 2119               if (target != null) {
 2120                   Document doc = target.getDocument();
 2121                   int dot = doc.getLength();
 2122                   if (select) {
 2123                       target.moveCaretPosition(dot);
 2124                   } else {
 2125                       target.setCaretPosition(dot);
 2126                   }
 2127               }
 2128           }
 2129   
 2130           private boolean select;
 2131       }
 2132   
 2133       /*
 2134        * Select the word around the caret
 2135        * @see DefaultEditorKit#endAction
 2136        * @see DefaultEditorKit#getActions
 2137        */
 2138       static class SelectWordAction extends TextAction {
 2139   
 2140           /**
 2141            * Create this action with the appropriate identifier.
 2142            * @param nm  the name of the action, Action.NAME.
 2143            * @param select whether to extend the selection when
 2144            *  changing the caret position.
 2145            */
 2146           SelectWordAction() {
 2147               super(selectWordAction);
 2148               start = new BeginWordAction("pigdog", false);
 2149               end = new EndWordAction("pigdog", true);
 2150           }
 2151   
 2152           /** The operation to perform when this action is triggered. */
 2153           public void actionPerformed(ActionEvent e) {
 2154               start.actionPerformed(e);
 2155               end.actionPerformed(e);
 2156           }
 2157   
 2158           private Action start;
 2159           private Action end;
 2160       }
 2161   
 2162       /*
 2163        * Select the line around the caret
 2164        * @see DefaultEditorKit#endAction
 2165        * @see DefaultEditorKit#getActions
 2166        */
 2167       static class SelectLineAction extends TextAction {
 2168   
 2169           /**
 2170            * Create this action with the appropriate identifier.
 2171            * @param nm  the name of the action, Action.NAME.
 2172            * @param select whether to extend the selection when
 2173            *  changing the caret position.
 2174            */
 2175           SelectLineAction() {
 2176               super(selectLineAction);
 2177               start = new BeginLineAction("pigdog", false);
 2178               end = new EndLineAction("pigdog", true);
 2179           }
 2180   
 2181           /** The operation to perform when this action is triggered. */
 2182           public void actionPerformed(ActionEvent e) {
 2183               start.actionPerformed(e);
 2184               end.actionPerformed(e);
 2185           }
 2186   
 2187           private Action start;
 2188           private Action end;
 2189       }
 2190   
 2191       /*
 2192        * Select the paragraph around the caret
 2193        * @see DefaultEditorKit#endAction
 2194        * @see DefaultEditorKit#getActions
 2195        */
 2196       static class SelectParagraphAction extends TextAction {
 2197   
 2198           /**
 2199            * Create this action with the appropriate identifier.
 2200            * @param nm  the name of the action, Action.NAME.
 2201            * @param select whether to extend the selection when
 2202            *  changing the caret position.
 2203            */
 2204           SelectParagraphAction() {
 2205               super(selectParagraphAction);
 2206               start = new BeginParagraphAction("pigdog", false);
 2207               end = new EndParagraphAction("pigdog", true);
 2208           }
 2209   
 2210           /** The operation to perform when this action is triggered. */
 2211           public void actionPerformed(ActionEvent e) {
 2212               start.actionPerformed(e);
 2213               end.actionPerformed(e);
 2214           }
 2215   
 2216           private Action start;
 2217           private Action end;
 2218       }
 2219   
 2220       /*
 2221        * Select the entire document
 2222        * @see DefaultEditorKit#endAction
 2223        * @see DefaultEditorKit#getActions
 2224        */
 2225       static class SelectAllAction extends TextAction {
 2226   
 2227           /**
 2228            * Create this action with the appropriate identifier.
 2229            * @param nm  the name of the action, Action.NAME.
 2230            * @param select whether to extend the selection when
 2231            *  changing the caret position.
 2232            */
 2233           SelectAllAction() {
 2234               super(selectAllAction);
 2235           }
 2236   
 2237           /** The operation to perform when this action is triggered. */
 2238           public void actionPerformed(ActionEvent e) {
 2239               JTextComponent target = getTextComponent(e);
 2240               if (target != null) {
 2241                   Document doc = target.getDocument();
 2242                   target.setCaretPosition(0);
 2243                   target.moveCaretPosition(doc.getLength());
 2244               }
 2245           }
 2246   
 2247       }
 2248   
 2249       /*
 2250        * Remove the selection, if any.
 2251        * @see DefaultEditorKit#unselectAction
 2252        * @see DefaultEditorKit#getActions
 2253        */
 2254       static class UnselectAction extends TextAction {
 2255   
 2256           /**
 2257            * Create this action with the appropriate identifier.
 2258            */
 2259           UnselectAction() {
 2260               super(unselectAction);
 2261           }
 2262   
 2263           /** The operation to perform when this action is triggered. */
 2264           public void actionPerformed(ActionEvent e) {
 2265               JTextComponent target = getTextComponent(e);
 2266               if (target != null) {
 2267                   target.setCaretPosition(target.getCaretPosition());
 2268               }
 2269           }
 2270   
 2271       }
 2272   
 2273       /*
 2274        * Toggles the ComponentOrientation of the text component.
 2275        * @see DefaultEditorKit#toggleComponentOrientationAction
 2276        * @see DefaultEditorKit#getActions
 2277        */
 2278       static class ToggleComponentOrientationAction extends TextAction {
 2279   
 2280           /**
 2281            * Create this action with the appropriate identifier.
 2282            */
 2283           ToggleComponentOrientationAction() {
 2284               super(toggleComponentOrientationAction);
 2285           }
 2286   
 2287           /** The operation to perform when this action is triggered. */
 2288           public void actionPerformed(ActionEvent e) {
 2289               JTextComponent target = getTextComponent(e);
 2290               if (target != null) {
 2291                   ComponentOrientation last = target.getComponentOrientation();
 2292                   ComponentOrientation next;
 2293                   if( last == ComponentOrientation.RIGHT_TO_LEFT )
 2294                       next = ComponentOrientation.LEFT_TO_RIGHT;
 2295                   else
 2296                       next = ComponentOrientation.RIGHT_TO_LEFT;
 2297                   target.setComponentOrientation(next);
 2298                   target.repaint();
 2299               }
 2300           }
 2301       }
 2302   
 2303   }

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