Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    * Copyright (c) 1995, 2006, 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 java.awt;
   26   
   27   import java.awt.peer.TextComponentPeer;
   28   import java.awt.event;
   29   import java.util.EventListener;
   30   import java.io.ObjectOutputStream;
   31   import java.io.ObjectInputStream;
   32   import java.io.IOException;
   33   import sun.awt.InputMethodSupport;
   34   import java.text.BreakIterator;
   35   import javax.swing.text.AttributeSet;
   36   import javax.accessibility;
   37   import java.awt.im.InputMethodRequests;
   38   
   39   
   40   /**
   41    * The <code>TextComponent</code> class is the superclass of
   42    * any component that allows the editing of some text.
   43    * <p>
   44    * A text component embodies a string of text.  The
   45    * <code>TextComponent</code> class defines a set of methods
   46    * that determine whether or not this text is editable. If the
   47    * component is editable, it defines another set of methods
   48    * that supports a text insertion caret.
   49    * <p>
   50    * In addition, the class defines methods that are used
   51    * to maintain a current <em>selection</em> from the text.
   52    * The text selection, a substring of the component's text,
   53    * is the target of editing operations. It is also referred
   54    * to as the <em>selected text</em>.
   55    *
   56    * @author      Sami Shaio
   57    * @author      Arthur van Hoff
   58    * @since       JDK1.0
   59    */
   60   public class TextComponent extends Component implements Accessible {
   61   
   62       /**
   63        * The value of the text.
   64        * A <code>null</code> value is the same as "".
   65        *
   66        * @serial
   67        * @see #setText(String)
   68        * @see #getText()
   69        */
   70       String text;
   71   
   72       /**
   73        * A boolean indicating whether or not this
   74        * <code>TextComponent</code> is editable.
   75        * It will be <code>true</code> if the text component
   76        * is editable and <code>false</code> if not.
   77        *
   78        * @serial
   79        * @see #isEditable()
   80        */
   81       boolean editable = true;
   82   
   83       /**
   84        * The selection refers to the selected text, and the
   85        * <code>selectionStart</code> is the start position
   86        * of the selected text.
   87        *
   88        * @serial
   89        * @see #getSelectionStart()
   90        * @see #setSelectionStart(int)
   91        */
   92       int selectionStart;
   93   
   94       /**
   95        * The selection refers to the selected text, and the
   96        * <code>selectionEnd</code>
   97        * is the end position of the selected text.
   98        *
   99        * @serial
  100        * @see #getSelectionEnd()
  101        * @see #setSelectionEnd(int)
  102        */
  103       int selectionEnd;
  104   
  105       // A flag used to tell whether the background has been set by
  106       // developer code (as opposed to AWT code).  Used to determine
  107       // the background color of non-editable TextComponents.
  108       boolean backgroundSetByClientCode = false;
  109   
  110       /**
  111        * True if this <code>TextComponent</code> has access
  112        * to the System clipboard.
  113        */
  114       transient private boolean canAccessClipboard;
  115   
  116       transient protected TextListener textListener;
  117   
  118       /*
  119        * JDK 1.1 serialVersionUID
  120        */
  121       private static final long serialVersionUID = -2214773872412987419L;
  122   
  123       /**
  124        * Constructs a new text component initialized with the
  125        * specified text. Sets the value of the cursor to
  126        * <code>Cursor.TEXT_CURSOR</code>.
  127        * @param      text       the text to be displayed; if
  128        *             <code>text</code> is <code>null</code>, the empty
  129        *             string <code>""</code> will be displayed
  130        * @exception  HeadlessException if
  131        *             <code>GraphicsEnvironment.isHeadless</code>
  132        *             returns true
  133        * @see        java.awt.GraphicsEnvironment#isHeadless
  134        * @see        java.awt.Cursor
  135        */
  136       TextComponent(String text) throws HeadlessException {
  137           GraphicsEnvironment.checkHeadless();
  138           this.text = (text != null) ? text : "";
  139           setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
  140           checkSystemClipboardAccess();
  141       }
  142   
  143       private void enableInputMethodsIfNecessary() {
  144           if (checkForEnableIM) {
  145               checkForEnableIM = false;
  146               try {
  147                   Toolkit toolkit = Toolkit.getDefaultToolkit();
  148                   boolean shouldEnable = false;
  149                   if (toolkit instanceof InputMethodSupport) {
  150                       shouldEnable = ((InputMethodSupport)toolkit)
  151                         .enableInputMethodsForTextComponent();
  152                   }
  153                   enableInputMethods(shouldEnable);
  154               } catch (Exception e) {
  155                   // if something bad happens, just don't enable input methods
  156               }
  157           }
  158       }
  159   
  160       /**
  161        * Enables or disables input method support for this text component. If input
  162        * method support is enabled and the text component also processes key events,
  163        * incoming events are offered to the current input method and will only be
  164        * processed by the component or dispatched to its listeners if the input method
  165        * does not consume them. Whether and how input method support for this text
  166        * component is enabled or disabled by default is implementation dependent.
  167        *
  168        * @param enable true to enable, false to disable
  169        * @see #processKeyEvent
  170        * @since 1.2
  171        */
  172       public void enableInputMethods(boolean enable) {
  173           checkForEnableIM = false;
  174           super.enableInputMethods(enable);
  175       }
  176   
  177       boolean areInputMethodsEnabled() {
  178           // moved from the constructor above to here and addNotify below,
  179           // this call will initialize the toolkit if not already initialized.
  180           if (checkForEnableIM) {
  181               enableInputMethodsIfNecessary();
  182           }
  183   
  184           // TextComponent handles key events without touching the eventMask or
  185           // having a key listener, so just check whether the flag is set
  186           return (eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0;
  187       }
  188   
  189       public InputMethodRequests getInputMethodRequests() {
  190           TextComponentPeer peer = (TextComponentPeer)this.peer;
  191           if (peer != null) return peer.getInputMethodRequests();
  192           else return null;
  193       }
  194   
  195   
  196   
  197       /**
  198        * Makes this Component displayable by connecting it to a
  199        * native screen resource.
  200        * This method is called internally by the toolkit and should
  201        * not be called directly by programs.
  202        * @see       java.awt.TextComponent#removeNotify
  203        */
  204       public void addNotify() {
  205           super.addNotify();
  206           enableInputMethodsIfNecessary();
  207       }
  208   
  209       /**
  210        * Removes the <code>TextComponent</code>'s peer.
  211        * The peer allows us to modify the appearance of the
  212        * <code>TextComponent</code> without changing its
  213        * functionality.
  214        */
  215       public void removeNotify() {
  216           synchronized (getTreeLock()) {
  217               TextComponentPeer peer = (TextComponentPeer)this.peer;
  218               if (peer != null) {
  219                   text = peer.getText();
  220                   selectionStart = peer.getSelectionStart();
  221                   selectionEnd = peer.getSelectionEnd();
  222               }
  223               super.removeNotify();
  224           }
  225       }
  226   
  227       /**
  228        * Sets the text that is presented by this
  229        * text component to be the specified text.
  230        * @param       t   the new text;
  231        *                  if this parameter is <code>null</code> then
  232        *                  the text is set to the empty string ""
  233        * @see         java.awt.TextComponent#getText
  234        */
  235       public synchronized void setText(String t) {
  236           text = (t != null) ? t : "";
  237           TextComponentPeer peer = (TextComponentPeer)this.peer;
  238           if (peer != null) {
  239               peer.setText(text);
  240           }
  241       }
  242   
  243       /**
  244        * Returns the text that is presented by this text component.
  245        * By default, this is an empty string.
  246        *
  247        * @return the value of this <code>TextComponent</code>
  248        * @see     java.awt.TextComponent#setText
  249        */
  250       public synchronized String getText() {
  251           TextComponentPeer peer = (TextComponentPeer)this.peer;
  252           if (peer != null) {
  253               text = peer.getText();
  254           }
  255           return text;
  256       }
  257   
  258       /**
  259        * Returns the selected text from the text that is
  260        * presented by this text component.
  261        * @return      the selected text of this text component
  262        * @see         java.awt.TextComponent#select
  263        */
  264       public synchronized String getSelectedText() {
  265           return getText().substring(getSelectionStart(), getSelectionEnd());
  266       }
  267   
  268       /**
  269        * Indicates whether or not this text component is editable.
  270        * @return     <code>true</code> if this text component is
  271        *                  editable; <code>false</code> otherwise.
  272        * @see        java.awt.TextComponent#setEditable
  273        * @since      JDK1.0
  274        */
  275       public boolean isEditable() {
  276           return editable;
  277       }
  278   
  279       /**
  280        * Sets the flag that determines whether or not this
  281        * text component is editable.
  282        * <p>
  283        * If the flag is set to <code>true</code>, this text component
  284        * becomes user editable. If the flag is set to <code>false</code>,
  285        * the user cannot change the text of this text component.
  286        * By default, non-editable text components have a background color
  287        * of SystemColor.control.  This default can be overridden by
  288        * calling setBackground.
  289        *
  290        * @param     b   a flag indicating whether this text component
  291        *                      is user editable.
  292        * @see       java.awt.TextComponent#isEditable
  293        * @since     JDK1.0
  294        */
  295       public synchronized void setEditable(boolean b) {
  296           if (editable == b) {
  297               return;
  298           }
  299   
  300           editable = b;
  301           TextComponentPeer peer = (TextComponentPeer)this.peer;
  302           if (peer != null) {
  303               peer.setEditable(b);
  304           }
  305       }
  306   
  307       /**
  308        * Gets the background color of this text component.
  309        *
  310        * By default, non-editable text components have a background color
  311        * of SystemColor.control.  This default can be overridden by
  312        * calling setBackground.
  313        *
  314        * @return This text component's background color.
  315        *         If this text component does not have a background color,
  316        *         the background color of its parent is returned.
  317        * @see #setBackground(Color)
  318        * @since JDK1.0
  319        */
  320       public Color getBackground() {
  321           if (!editable && !backgroundSetByClientCode) {
  322               return SystemColor.control;
  323           }
  324   
  325           return super.getBackground();
  326       }
  327   
  328       /**
  329        * Sets the background color of this text component.
  330        *
  331        * @param c The color to become this text component's color.
  332        *        If this parameter is null then this text component
  333        *        will inherit the background color of its parent.
  334        * @see #getBackground()
  335        * @since JDK1.0
  336        */
  337       public void setBackground(Color c) {
  338           backgroundSetByClientCode = true;
  339           super.setBackground(c);
  340       }
  341   
  342       /**
  343        * Gets the start position of the selected text in
  344        * this text component.
  345        * @return      the start position of the selected text
  346        * @see         java.awt.TextComponent#setSelectionStart
  347        * @see         java.awt.TextComponent#getSelectionEnd
  348        */
  349       public synchronized int getSelectionStart() {
  350           TextComponentPeer peer = (TextComponentPeer)this.peer;
  351           if (peer != null) {
  352               selectionStart = peer.getSelectionStart();
  353           }
  354           return selectionStart;
  355       }
  356   
  357       /**
  358        * Sets the selection start for this text component to
  359        * the specified position. The new start point is constrained
  360        * to be at or before the current selection end. It also
  361        * cannot be set to less than zero, the beginning of the
  362        * component's text.
  363        * If the caller supplies a value for <code>selectionStart</code>
  364        * that is out of bounds, the method enforces these constraints
  365        * silently, and without failure.
  366        * @param       selectionStart   the start position of the
  367        *                        selected text
  368        * @see         java.awt.TextComponent#getSelectionStart
  369        * @see         java.awt.TextComponent#setSelectionEnd
  370        * @since       JDK1.1
  371        */
  372       public synchronized void setSelectionStart(int selectionStart) {
  373           /* Route through select method to enforce consistent policy
  374            * between selectionStart and selectionEnd.
  375            */
  376           select(selectionStart, getSelectionEnd());
  377       }
  378   
  379       /**
  380        * Gets the end position of the selected text in
  381        * this text component.
  382        * @return      the end position of the selected text
  383        * @see         java.awt.TextComponent#setSelectionEnd
  384        * @see         java.awt.TextComponent#getSelectionStart
  385        */
  386       public synchronized int getSelectionEnd() {
  387           TextComponentPeer peer = (TextComponentPeer)this.peer;
  388           if (peer != null) {
  389               selectionEnd = peer.getSelectionEnd();
  390           }
  391           return selectionEnd;
  392       }
  393   
  394       /**
  395        * Sets the selection end for this text component to
  396        * the specified position. The new end point is constrained
  397        * to be at or after the current selection start. It also
  398        * cannot be set beyond the end of the component's text.
  399        * If the caller supplies a value for <code>selectionEnd</code>
  400        * that is out of bounds, the method enforces these constraints
  401        * silently, and without failure.
  402        * @param       selectionEnd   the end position of the
  403        *                        selected text
  404        * @see         java.awt.TextComponent#getSelectionEnd
  405        * @see         java.awt.TextComponent#setSelectionStart
  406        * @since       JDK1.1
  407        */
  408       public synchronized void setSelectionEnd(int selectionEnd) {
  409           /* Route through select method to enforce consistent policy
  410            * between selectionStart and selectionEnd.
  411            */
  412           select(getSelectionStart(), selectionEnd);
  413       }
  414   
  415       /**
  416        * Selects the text between the specified start and end positions.
  417        * <p>
  418        * This method sets the start and end positions of the
  419        * selected text, enforcing the restriction that the start position
  420        * must be greater than or equal to zero.  The end position must be
  421        * greater than or equal to the start position, and less than or
  422        * equal to the length of the text component's text.  The
  423        * character positions are indexed starting with zero.
  424        * The length of the selection is
  425        * <code>endPosition</code> - <code>startPosition</code>, so the
  426        * character at <code>endPosition</code> is not selected.
  427        * If the start and end positions of the selected text are equal,
  428        * all text is deselected.
  429        * <p>
  430        * If the caller supplies values that are inconsistent or out of
  431        * bounds, the method enforces these constraints silently, and
  432        * without failure. Specifically, if the start position or end
  433        * position is greater than the length of the text, it is reset to
  434        * equal the text length. If the start position is less than zero,
  435        * it is reset to zero, and if the end position is less than the
  436        * start position, it is reset to the start position.
  437        *
  438        * @param        selectionStart the zero-based index of the first
  439                          character (<code>char</code> value) to be selected
  440        * @param        selectionEnd the zero-based end position of the
  441                          text to be selected; the character (<code>char</code> value) at
  442                          <code>selectionEnd</code> is not selected
  443        * @see          java.awt.TextComponent#setSelectionStart
  444        * @see          java.awt.TextComponent#setSelectionEnd
  445        * @see          java.awt.TextComponent#selectAll
  446        */
  447       public synchronized void select(int selectionStart, int selectionEnd) {
  448           String text = getText();
  449           if (selectionStart < 0) {
  450               selectionStart = 0;
  451           }
  452           if (selectionStart > text.length()) {
  453               selectionStart = text.length();
  454           }
  455           if (selectionEnd > text.length()) {
  456               selectionEnd = text.length();
  457           }
  458           if (selectionEnd < selectionStart) {
  459               selectionEnd = selectionStart;
  460           }
  461   
  462           this.selectionStart = selectionStart;
  463           this.selectionEnd = selectionEnd;
  464   
  465           TextComponentPeer peer = (TextComponentPeer)this.peer;
  466           if (peer != null) {
  467               peer.select(selectionStart, selectionEnd);
  468           }
  469       }
  470   
  471       /**
  472        * Selects all the text in this text component.
  473        * @see        java.awt.TextComponent#select
  474        */
  475       public synchronized void selectAll() {
  476           this.selectionStart = 0;
  477           this.selectionEnd = getText().length();
  478   
  479           TextComponentPeer peer = (TextComponentPeer)this.peer;
  480           if (peer != null) {
  481               peer.select(selectionStart, selectionEnd);
  482           }
  483       }
  484   
  485       /**
  486        * Sets the position of the text insertion caret.
  487        * The caret position is constrained to be between 0
  488        * and the last character of the text, inclusive.
  489        * If the passed-in value is greater than this range,
  490        * the value is set to the last character (or 0 if
  491        * the <code>TextComponent</code> contains no text)
  492        * and no error is returned.  If the passed-in value is
  493        * less than 0, an <code>IllegalArgumentException</code>
  494        * is thrown.
  495        *
  496        * @param        position the position of the text insertion caret
  497        * @exception    IllegalArgumentException if <code>position</code>
  498        *               is less than zero
  499        * @since        JDK1.1
  500        */
  501       public synchronized void setCaretPosition(int position) {
  502           if (position < 0) {
  503               throw new IllegalArgumentException("position less than zero.");
  504           }
  505   
  506           int maxposition = getText().length();
  507           if (position > maxposition) {
  508               position = maxposition;
  509           }
  510   
  511           TextComponentPeer peer = (TextComponentPeer)this.peer;
  512           if (peer != null) {
  513               peer.setCaretPosition(position);
  514           } else {
  515               select(position, position);
  516           }
  517       }
  518   
  519       /**
  520        * Returns the position of the text insertion caret.
  521        * The caret position is constrained to be between 0
  522        * and the last character of the text, inclusive.
  523        * If the text or caret have not been set, the default
  524        * caret position is 0.
  525        *
  526        * @return       the position of the text insertion caret
  527        * @see #setCaretPosition(int)
  528        * @since        JDK1.1
  529        */
  530       public synchronized int getCaretPosition() {
  531           TextComponentPeer peer = (TextComponentPeer)this.peer;
  532           int position = 0;
  533   
  534           if (peer != null) {
  535               position = peer.getCaretPosition();
  536           } else {
  537               position = selectionStart;
  538           }
  539           int maxposition = getText().length();
  540           if (position > maxposition) {
  541               position = maxposition;
  542           }
  543           return position;
  544       }
  545   
  546       /**
  547        * Adds the specified text event listener to receive text events
  548        * from this text component.
  549        * If <code>l</code> is <code>null</code>, no exception is
  550        * thrown and no action is performed.
  551        * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
  552        * >AWT Threading Issues</a> for details on AWT's threading model.
  553        *
  554        * @param l the text event listener
  555        * @see             #removeTextListener
  556        * @see             #getTextListeners
  557        * @see             java.awt.event.TextListener
  558        */
  559       public synchronized void addTextListener(TextListener l) {
  560           if (l == null) {
  561               return;
  562           }
  563           textListener = AWTEventMulticaster.add(textListener, l);
  564           newEventsOnly = true;
  565       }
  566   
  567       /**
  568        * Removes the specified text event listener so that it no longer
  569        * receives text events from this text component
  570        * If <code>l</code> is <code>null</code>, no exception is
  571        * thrown and no action is performed.
  572        * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
  573        * >AWT Threading Issues</a> for details on AWT's threading model.
  574        *
  575        * @param           l     the text listener
  576        * @see             #addTextListener
  577        * @see             #getTextListeners
  578        * @see             java.awt.event.TextListener
  579        * @since           JDK1.1
  580        */
  581       public synchronized void removeTextListener(TextListener l) {
  582           if (l == null) {
  583               return;
  584           }
  585           textListener = AWTEventMulticaster.remove(textListener, l);
  586       }
  587   
  588       /**
  589        * Returns an array of all the text listeners
  590        * registered on this text component.
  591        *
  592        * @return all of this text component's <code>TextListener</code>s
  593        *         or an empty array if no text
  594        *         listeners are currently registered
  595        *
  596        *
  597        * @see #addTextListener
  598        * @see #removeTextListener
  599        * @since 1.4
  600        */
  601       public synchronized TextListener[] getTextListeners() {
  602           return (TextListener[])(getListeners(TextListener.class));
  603       }
  604   
  605       /**
  606        * Returns an array of all the objects currently registered
  607        * as <code><em>Foo</em>Listener</code>s
  608        * upon this <code>TextComponent</code>.
  609        * <code><em>Foo</em>Listener</code>s are registered using the
  610        * <code>add<em>Foo</em>Listener</code> method.
  611        *
  612        * <p>
  613        * You can specify the <code>listenerType</code> argument
  614        * with a class literal, such as
  615        * <code><em>Foo</em>Listener.class</code>.
  616        * For example, you can query a
  617        * <code>TextComponent</code> <code>t</code>
  618        * for its text listeners with the following code:
  619        *
  620        * <pre>TextListener[] tls = (TextListener[])(t.getListeners(TextListener.class));</pre>
  621        *
  622        * If no such listeners exist, this method returns an empty array.
  623        *
  624        * @param listenerType the type of listeners requested; this parameter
  625        *          should specify an interface that descends from
  626        *          <code>java.util.EventListener</code>
  627        * @return an array of all objects registered as
  628        *          <code><em>Foo</em>Listener</code>s on this text component,
  629        *          or an empty array if no such
  630        *          listeners have been added
  631        * @exception ClassCastException if <code>listenerType</code>
  632        *          doesn't specify a class or interface that implements
  633        *          <code>java.util.EventListener</code>
  634        *
  635        * @see #getTextListeners
  636        * @since 1.3
  637        */
  638       public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
  639           EventListener l = null;
  640           if  (listenerType == TextListener.class) {
  641               l = textListener;
  642           } else {
  643               return super.getListeners(listenerType);
  644           }
  645           return AWTEventMulticaster.getListeners(l, listenerType);
  646       }
  647   
  648       // REMIND: remove when filtering is done at lower level
  649       boolean eventEnabled(AWTEvent e) {
  650           if (e.id == TextEvent.TEXT_VALUE_CHANGED) {
  651               if ((eventMask & AWTEvent.TEXT_EVENT_MASK) != 0 ||
  652                   textListener != null) {
  653                   return true;
  654               }
  655               return false;
  656           }
  657           return super.eventEnabled(e);
  658       }
  659   
  660       /**
  661        * Processes events on this text component. If the event is a
  662        * <code>TextEvent</code>, it invokes the <code>processTextEvent</code>
  663        * method else it invokes its superclass's <code>processEvent</code>.
  664        * <p>Note that if the event parameter is <code>null</code>
  665        * the behavior is unspecified and may result in an
  666        * exception.
  667        *
  668        * @param e the event
  669        */
  670       protected void processEvent(AWTEvent e) {
  671           if (e instanceof TextEvent) {
  672               processTextEvent((TextEvent)e);
  673               return;
  674           }
  675           super.processEvent(e);
  676       }
  677   
  678       /**
  679        * Processes text events occurring on this text component by
  680        * dispatching them to any registered <code>TextListener</code> objects.
  681        * <p>
  682        * NOTE: This method will not be called unless text events
  683        * are enabled for this component. This happens when one of the
  684        * following occurs:
  685        * <ul>
  686        * <li>A <code>TextListener</code> object is registered
  687        * via <code>addTextListener</code>
  688        * <li>Text events are enabled via <code>enableEvents</code>
  689        * </ul>
  690        * <p>Note that if the event parameter is <code>null</code>
  691        * the behavior is unspecified and may result in an
  692        * exception.
  693        *
  694        * @param e the text event
  695        * @see Component#enableEvents
  696        */
  697       protected void processTextEvent(TextEvent e) {
  698           TextListener listener = textListener;
  699           if (listener != null) {
  700               int id = e.getID();
  701               switch (id) {
  702               case TextEvent.TEXT_VALUE_CHANGED:
  703                   listener.textValueChanged(e);
  704                   break;
  705               }
  706           }
  707       }
  708   
  709       /**
  710        * Returns a string representing the state of this
  711        * <code>TextComponent</code>. This
  712        * method is intended to be used only for debugging purposes, and the
  713        * content and format of the returned string may vary between
  714        * implementations. The returned string may be empty but may not be
  715        * <code>null</code>.
  716        *
  717        * @return      the parameter string of this text component
  718        */
  719       protected String paramString() {
  720           String str = super.paramString() + ",text=" + getText();
  721           if (editable) {
  722               str += ",editable";
  723           }
  724           return str + ",selection=" + getSelectionStart() + "-" + getSelectionEnd();
  725       }
  726   
  727       /**
  728        * Assigns a valid value to the canAccessClipboard instance variable.
  729        */
  730       private void checkSystemClipboardAccess() {
  731           canAccessClipboard = true;
  732           SecurityManager sm = System.getSecurityManager();
  733           if (sm != null) {
  734               try {
  735                   sm.checkSystemClipboardAccess();
  736               }
  737               catch (SecurityException e) {
  738                   canAccessClipboard = false;
  739               }
  740           }
  741       }
  742   
  743       /*
  744        * Serialization support.
  745        */
  746       /**
  747        * The textComponent SerializedDataVersion.
  748        *
  749        * @serial
  750        */
  751       private int textComponentSerializedDataVersion = 1;
  752   
  753       /**
  754        * Writes default serializable fields to stream.  Writes
  755        * a list of serializable TextListener(s) as optional data.
  756        * The non-serializable TextListener(s) are detected and
  757        * no attempt is made to serialize them.
  758        *
  759        * @serialData Null terminated sequence of zero or more pairs.
  760        *             A pair consists of a String and Object.
  761        *             The String indicates the type of object and
  762        *             is one of the following :
  763        *             textListenerK indicating and TextListener object.
  764        *
  765        * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
  766        * @see java.awt.Component#textListenerK
  767        */
  768       private void writeObject(java.io.ObjectOutputStream s)
  769         throws IOException
  770       {
  771           // Serialization support.  Since the value of the fields
  772           // selectionStart, selectionEnd, and text aren't necessarily
  773           // up to date, we sync them up with the peer before serializing.
  774           TextComponentPeer peer = (TextComponentPeer)this.peer;
  775           if (peer != null) {
  776               text = peer.getText();
  777               selectionStart = peer.getSelectionStart();
  778               selectionEnd = peer.getSelectionEnd();
  779           }
  780   
  781           s.defaultWriteObject();
  782   
  783           AWTEventMulticaster.save(s, textListenerK, textListener);
  784           s.writeObject(null);
  785       }
  786   
  787       /**
  788        * Read the ObjectInputStream, and if it isn't null,
  789        * add a listener to receive text events fired by the
  790        * TextComponent.  Unrecognized keys or values will be
  791        * ignored.
  792        *
  793        * @exception HeadlessException if
  794        * <code>GraphicsEnvironment.isHeadless()</code> returns
  795        * <code>true</code>
  796        * @see #removeTextListener
  797        * @see #addTextListener
  798        * @see java.awt.GraphicsEnvironment#isHeadless
  799        */
  800       private void readObject(ObjectInputStream s)
  801           throws ClassNotFoundException, IOException, HeadlessException
  802       {
  803           GraphicsEnvironment.checkHeadless();
  804           s.defaultReadObject();
  805   
  806           // Make sure the state we just read in for text,
  807           // selectionStart and selectionEnd has legal values
  808           this.text = (text != null) ? text : "";
  809           select(selectionStart, selectionEnd);
  810   
  811           Object keyOrNull;
  812           while(null != (keyOrNull = s.readObject())) {
  813               String key = ((String)keyOrNull).intern();
  814   
  815               if (textListenerK == key) {
  816                   addTextListener((TextListener)(s.readObject()));
  817               } else {
  818                   // skip value for unrecognized key
  819                   s.readObject();
  820               }
  821           }
  822           enableInputMethodsIfNecessary();
  823           checkSystemClipboardAccess();
  824       }
  825   
  826   
  827   /////////////////
  828   // Accessibility support
  829   ////////////////
  830   
  831   
  832       /**
  833        *
  834        */
  835       int getIndexAtPoint(Point p) {
  836           return -1;
  837   /* To be fully implemented in a future release
  838           if (peer == null) {
  839               return -1;
  840           }
  841           TextComponentPeer peer = (TextComponentPeer)this.peer;
  842           return peer.getIndexAtPoint(p.x, p.y);
  843   */
  844       }
  845   
  846   
  847       /**
  848        *
  849        */
  850       Rectangle getCharacterBounds(int i) {
  851           return null;
  852   /* To be fully implemented in a future release
  853           if (peer == null) {
  854               return null;
  855           }
  856           TextComponentPeer peer = (TextComponentPeer)this.peer;
  857           return peer.getCharacterBounds(i);
  858   */
  859       }
  860   
  861   
  862       /**
  863        * Gets the AccessibleContext associated with this TextComponent.
  864        * For text components, the AccessibleContext takes the form of an
  865        * AccessibleAWTTextComponent.
  866        * A new AccessibleAWTTextComponent instance is created if necessary.
  867        *
  868        * @return an AccessibleAWTTextComponent that serves as the
  869        *         AccessibleContext of this TextComponent
  870        * @since 1.3
  871        */
  872       public AccessibleContext getAccessibleContext() {
  873           if (accessibleContext == null) {
  874               accessibleContext = new AccessibleAWTTextComponent();
  875           }
  876           return accessibleContext;
  877       }
  878   
  879       /**
  880        * This class implements accessibility support for the
  881        * <code>TextComponent</code> class.  It provides an implementation of the
  882        * Java Accessibility API appropriate to text component user-interface
  883        * elements.
  884        * @since 1.3
  885        */
  886       protected class AccessibleAWTTextComponent extends AccessibleAWTComponent
  887           implements AccessibleText, TextListener
  888       {
  889           /*
  890            * JDK 1.3 serialVersionUID
  891            */
  892           private static final long serialVersionUID = 3631432373506317811L;
  893   
  894           /**
  895            * Constructs an AccessibleAWTTextComponent.  Adds a listener to track
  896            * caret change.
  897            */
  898           public AccessibleAWTTextComponent() {
  899               TextComponent.this.addTextListener(this);
  900           }
  901   
  902           /**
  903            * TextListener notification of a text value change.
  904            */
  905           public void textValueChanged(TextEvent textEvent)  {
  906               Integer cpos = Integer.valueOf(TextComponent.this.getCaretPosition());
  907               firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, cpos);
  908           }
  909   
  910           /**
  911            * Gets the state set of the TextComponent.
  912            * The AccessibleStateSet of an object is composed of a set of
  913            * unique AccessibleStates.  A change in the AccessibleStateSet
  914            * of an object will cause a PropertyChangeEvent to be fired
  915            * for the AccessibleContext.ACCESSIBLE_STATE_PROPERTY property.
  916            *
  917            * @return an instance of AccessibleStateSet containing the
  918            * current state set of the object
  919            * @see AccessibleStateSet
  920            * @see AccessibleState
  921            * @see #addPropertyChangeListener
  922            */
  923           public AccessibleStateSet getAccessibleStateSet() {
  924               AccessibleStateSet states = super.getAccessibleStateSet();
  925               if (TextComponent.this.isEditable()) {
  926                   states.add(AccessibleState.EDITABLE);
  927               }
  928               return states;
  929           }
  930   
  931   
  932           /**
  933            * Gets the role of this object.
  934            *
  935            * @return an instance of AccessibleRole describing the role of the
  936            * object (AccessibleRole.TEXT)
  937            * @see AccessibleRole
  938            */
  939           public AccessibleRole getAccessibleRole() {
  940               return AccessibleRole.TEXT;
  941           }
  942   
  943           /**
  944            * Get the AccessibleText associated with this object.  In the
  945            * implementation of the Java Accessibility API for this class,
  946            * return this object, which is responsible for implementing the
  947            * AccessibleText interface on behalf of itself.
  948            *
  949            * @return this object
  950            */
  951           public AccessibleText getAccessibleText() {
  952               return this;
  953           }
  954   
  955   
  956           // --- interface AccessibleText methods ------------------------
  957   
  958           /**
  959            * Many of these methods are just convenience methods; they
  960            * just call the equivalent on the parent
  961            */
  962   
  963           /**
  964            * Given a point in local coordinates, return the zero-based index
  965            * of the character under that Point.  If the point is invalid,
  966            * this method returns -1.
  967            *
  968            * @param p the Point in local coordinates
  969            * @return the zero-based index of the character under Point p.
  970            */
  971           public int getIndexAtPoint(Point p) {
  972               return TextComponent.this.getIndexAtPoint(p);
  973           }
  974   
  975           /**
  976            * Determines the bounding box of the character at the given
  977            * index into the string.  The bounds are returned in local
  978            * coordinates.  If the index is invalid a null rectangle
  979            * is returned.
  980            *
  981            * @param i the index into the String >= 0
  982            * @return the screen coordinates of the character's bounding box
  983            */
  984           public Rectangle getCharacterBounds(int i) {
  985               return TextComponent.this.getCharacterBounds(i);
  986           }
  987   
  988           /**
  989            * Returns the number of characters (valid indicies)
  990            *
  991            * @return the number of characters >= 0
  992            */
  993           public int getCharCount() {
  994               return TextComponent.this.getText().length();
  995           }
  996   
  997           /**
  998            * Returns the zero-based offset of the caret.
  999            *
 1000            * Note: The character to the right of the caret will have the
 1001            * same index value as the offset (the caret is between
 1002            * two characters).
 1003            *
 1004            * @return the zero-based offset of the caret.
 1005            */
 1006           public int getCaretPosition() {
 1007               return TextComponent.this.getCaretPosition();
 1008           }
 1009   
 1010           /**
 1011            * Returns the AttributeSet for a given character (at a given index).
 1012            *
 1013            * @param i the zero-based index into the text
 1014            * @return the AttributeSet of the character
 1015            */
 1016           public AttributeSet getCharacterAttribute(int i) {
 1017               return null; // No attributes in TextComponent
 1018           }
 1019   
 1020           /**
 1021            * Returns the start offset within the selected text.
 1022            * If there is no selection, but there is
 1023            * a caret, the start and end offsets will be the same.
 1024            * Return 0 if the text is empty, or the caret position
 1025            * if no selection.
 1026            *
 1027            * @return the index into the text of the start of the selection >= 0
 1028            */
 1029           public int getSelectionStart() {
 1030               return TextComponent.this.getSelectionStart();
 1031           }
 1032   
 1033           /**
 1034            * Returns the end offset within the selected text.
 1035            * If there is no selection, but there is
 1036            * a caret, the start and end offsets will be the same.
 1037            * Return 0 if the text is empty, or the caret position
 1038            * if no selection.
 1039            *
 1040            * @return the index into teh text of the end of the selection >= 0
 1041            */
 1042           public int getSelectionEnd() {
 1043               return TextComponent.this.getSelectionEnd();
 1044           }
 1045   
 1046           /**
 1047            * Returns the portion of the text that is selected.
 1048            *
 1049            * @return the text, null if no selection
 1050            */
 1051           public String getSelectedText() {
 1052               String selText = TextComponent.this.getSelectedText();
 1053               // Fix for 4256662
 1054               if (selText == null || selText.equals("")) {
 1055                   return null;
 1056               }
 1057               return selText;
 1058           }
 1059   
 1060           /**
 1061            * Returns the String at a given index.
 1062            *
 1063            * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
 1064            * or AccessibleText.SENTENCE to retrieve
 1065            * @param index an index within the text >= 0
 1066            * @return the letter, word, or sentence,
 1067            *   null for an invalid index or part
 1068            */
 1069           public String getAtIndex(int part, int index) {
 1070               if (index < 0 || index >= TextComponent.this.getText().length()) {
 1071                   return null;
 1072               }
 1073               switch (part) {
 1074               case AccessibleText.CHARACTER:
 1075                   return TextComponent.this.getText().substring(index, index+1);
 1076               case AccessibleText.WORD:  {
 1077                       String s = TextComponent.this.getText();
 1078                       BreakIterator words = BreakIterator.getWordInstance();
 1079                       words.setText(s);
 1080                       int end = words.following(index);
 1081                       return s.substring(words.previous(), end);
 1082                   }
 1083               case AccessibleText.SENTENCE:  {
 1084                       String s = TextComponent.this.getText();
 1085                       BreakIterator sentence = BreakIterator.getSentenceInstance();
 1086                       sentence.setText(s);
 1087                       int end = sentence.following(index);
 1088                       return s.substring(sentence.previous(), end);
 1089                   }
 1090               default:
 1091                   return null;
 1092               }
 1093           }
 1094   
 1095           private static final boolean NEXT = true;
 1096           private static final boolean PREVIOUS = false;
 1097   
 1098           /**
 1099            * Needed to unify forward and backward searching.
 1100            * The method assumes that s is the text assigned to words.
 1101            */
 1102           private int findWordLimit(int index, BreakIterator words, boolean direction,
 1103                                            String s) {
 1104               // Fix for 4256660 and 4256661.
 1105               // Words iterator is different from character and sentence iterators
 1106               // in that end of one word is not necessarily start of another word.
 1107               // Please see java.text.BreakIterator JavaDoc. The code below is
 1108               // based on nextWordStartAfter example from BreakIterator.java.
 1109               int last = (direction == NEXT) ? words.following(index)
 1110                                              : words.preceding(index);
 1111               int current = (direction == NEXT) ? words.next()
 1112                                                 : words.previous();
 1113               while (current != BreakIterator.DONE) {
 1114                   for (int p = Math.min(last, current); p < Math.max(last, current); p++) {
 1115                       if (Character.isLetter(s.charAt(p))) {
 1116                           return last;
 1117                       }
 1118                   }
 1119                   last = current;
 1120                   current = (direction == NEXT) ? words.next()
 1121                                                 : words.previous();
 1122               }
 1123               return BreakIterator.DONE;
 1124           }
 1125   
 1126           /**
 1127            * Returns the String after a given index.
 1128            *
 1129            * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
 1130            * or AccessibleText.SENTENCE to retrieve
 1131            * @param index an index within the text >= 0
 1132            * @return the letter, word, or sentence, null for an invalid
 1133            *  index or part
 1134            */
 1135           public String getAfterIndex(int part, int index) {
 1136               if (index < 0 || index >= TextComponent.this.getText().length()) {
 1137                   return null;
 1138               }
 1139               switch (part) {
 1140               case AccessibleText.CHARACTER:
 1141                   if (index+1 >= TextComponent.this.getText().length()) {
 1142                      return null;
 1143                   }
 1144                   return TextComponent.this.getText().substring(index+1, index+2);
 1145               case AccessibleText.WORD:  {
 1146                       String s = TextComponent.this.getText();
 1147                       BreakIterator words = BreakIterator.getWordInstance();
 1148                       words.setText(s);
 1149                       int start = findWordLimit(index, words, NEXT, s);
 1150                       if (start == BreakIterator.DONE || start >= s.length()) {
 1151                           return null;
 1152                       }
 1153                       int end = words.following(start);
 1154                       if (end == BreakIterator.DONE || end >= s.length()) {
 1155                           return null;
 1156                       }
 1157                       return s.substring(start, end);
 1158                   }
 1159               case AccessibleText.SENTENCE:  {
 1160                       String s = TextComponent.this.getText();
 1161                       BreakIterator sentence = BreakIterator.getSentenceInstance();
 1162                       sentence.setText(s);
 1163                       int start = sentence.following(index);
 1164                       if (start == BreakIterator.DONE || start >= s.length()) {
 1165                           return null;
 1166                       }
 1167                       int end = sentence.following(start);
 1168                       if (end == BreakIterator.DONE || end >= s.length()) {
 1169                           return null;
 1170                       }
 1171                       return s.substring(start, end);
 1172                   }
 1173               default:
 1174                   return null;
 1175               }
 1176           }
 1177   
 1178   
 1179           /**
 1180            * Returns the String before a given index.
 1181            *
 1182            * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
 1183            *   or AccessibleText.SENTENCE to retrieve
 1184            * @param index an index within the text >= 0
 1185            * @return the letter, word, or sentence, null for an invalid index
 1186            *  or part
 1187            */
 1188           public String getBeforeIndex(int part, int index) {
 1189               if (index < 0 || index > TextComponent.this.getText().length()-1) {
 1190                   return null;
 1191               }
 1192               switch (part) {
 1193               case AccessibleText.CHARACTER:
 1194                   if (index == 0) {
 1195                       return null;
 1196                   }
 1197                   return TextComponent.this.getText().substring(index-1, index);
 1198               case AccessibleText.WORD:  {
 1199                       String s = TextComponent.this.getText();
 1200                       BreakIterator words = BreakIterator.getWordInstance();
 1201                       words.setText(s);
 1202                       int end = findWordLimit(index, words, PREVIOUS, s);
 1203                       if (end == BreakIterator.DONE) {
 1204                           return null;
 1205                       }
 1206                       int start = words.preceding(end);
 1207                       if (start == BreakIterator.DONE) {
 1208                           return null;
 1209                       }
 1210                       return s.substring(start, end);
 1211                   }
 1212               case AccessibleText.SENTENCE:  {
 1213                       String s = TextComponent.this.getText();
 1214                       BreakIterator sentence = BreakIterator.getSentenceInstance();
 1215                       sentence.setText(s);
 1216                       int end = sentence.following(index);
 1217                       end = sentence.previous();
 1218                       int start = sentence.previous();
 1219                       if (start == BreakIterator.DONE) {
 1220                           return null;
 1221                       }
 1222                       return s.substring(start, end);
 1223                   }
 1224               default:
 1225                   return null;
 1226               }
 1227           }
 1228       }  // end of AccessibleAWTTextComponent
 1229   
 1230       private boolean checkForEnableIM = true;
 1231   }

Home » openjdk-7 » java » awt » [javadoc | source]