0N/A/*
2362N/A * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/Apackage java.awt;
0N/A
0N/Aimport java.awt.peer.TextComponentPeer;
0N/Aimport java.awt.event.*;
0N/Aimport java.util.EventListener;
0N/Aimport java.io.ObjectOutputStream;
0N/Aimport java.io.ObjectInputStream;
0N/Aimport java.io.IOException;
0N/Aimport sun.awt.InputMethodSupport;
0N/Aimport java.text.BreakIterator;
0N/Aimport javax.swing.text.AttributeSet;
0N/Aimport javax.accessibility.*;
0N/Aimport java.awt.im.InputMethodRequests;
0N/A
0N/A
0N/A/**
0N/A * The <code>TextComponent</code> class is the superclass of
0N/A * any component that allows the editing of some text.
0N/A * <p>
0N/A * A text component embodies a string of text. The
0N/A * <code>TextComponent</code> class defines a set of methods
0N/A * that determine whether or not this text is editable. If the
0N/A * component is editable, it defines another set of methods
0N/A * that supports a text insertion caret.
0N/A * <p>
0N/A * In addition, the class defines methods that are used
0N/A * to maintain a current <em>selection</em> from the text.
0N/A * The text selection, a substring of the component's text,
0N/A * is the target of editing operations. It is also referred
0N/A * to as the <em>selected text</em>.
0N/A *
0N/A * @author Sami Shaio
0N/A * @author Arthur van Hoff
0N/A * @since JDK1.0
0N/A */
0N/Apublic class TextComponent extends Component implements Accessible {
0N/A
0N/A /**
0N/A * The value of the text.
0N/A * A <code>null</code> value is the same as "".
0N/A *
0N/A * @serial
0N/A * @see #setText(String)
0N/A * @see #getText()
0N/A */
0N/A String text;
0N/A
0N/A /**
0N/A * A boolean indicating whether or not this
0N/A * <code>TextComponent</code> is editable.
0N/A * It will be <code>true</code> if the text component
0N/A * is editable and <code>false</code> if not.
0N/A *
0N/A * @serial
0N/A * @see #isEditable()
0N/A */
0N/A boolean editable = true;
0N/A
0N/A /**
0N/A * The selection refers to the selected text, and the
0N/A * <code>selectionStart</code> is the start position
0N/A * of the selected text.
0N/A *
0N/A * @serial
0N/A * @see #getSelectionStart()
0N/A * @see #setSelectionStart(int)
0N/A */
0N/A int selectionStart;
0N/A
0N/A /**
0N/A * The selection refers to the selected text, and the
0N/A * <code>selectionEnd</code>
0N/A * is the end position of the selected text.
0N/A *
0N/A * @serial
0N/A * @see #getSelectionEnd()
0N/A * @see #setSelectionEnd(int)
0N/A */
0N/A int selectionEnd;
0N/A
0N/A // A flag used to tell whether the background has been set by
0N/A // developer code (as opposed to AWT code). Used to determine
0N/A // the background color of non-editable TextComponents.
0N/A boolean backgroundSetByClientCode = false;
0N/A
0N/A transient protected TextListener textListener;
0N/A
0N/A /*
0N/A * JDK 1.1 serialVersionUID
0N/A */
0N/A private static final long serialVersionUID = -2214773872412987419L;
0N/A
0N/A /**
0N/A * Constructs a new text component initialized with the
0N/A * specified text. Sets the value of the cursor to
0N/A * <code>Cursor.TEXT_CURSOR</code>.
0N/A * @param text the text to be displayed; if
0N/A * <code>text</code> is <code>null</code>, the empty
0N/A * string <code>""</code> will be displayed
0N/A * @exception HeadlessException if
0N/A * <code>GraphicsEnvironment.isHeadless</code>
0N/A * returns true
0N/A * @see java.awt.GraphicsEnvironment#isHeadless
0N/A * @see java.awt.Cursor
0N/A */
0N/A TextComponent(String text) throws HeadlessException {
0N/A GraphicsEnvironment.checkHeadless();
0N/A this.text = (text != null) ? text : "";
0N/A setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
0N/A }
0N/A
0N/A private void enableInputMethodsIfNecessary() {
0N/A if (checkForEnableIM) {
0N/A checkForEnableIM = false;
0N/A try {
0N/A Toolkit toolkit = Toolkit.getDefaultToolkit();
0N/A boolean shouldEnable = false;
0N/A if (toolkit instanceof InputMethodSupport) {
0N/A shouldEnable = ((InputMethodSupport)toolkit)
0N/A .enableInputMethodsForTextComponent();
0N/A }
0N/A enableInputMethods(shouldEnable);
0N/A } catch (Exception e) {
0N/A // if something bad happens, just don't enable input methods
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Enables or disables input method support for this text component. If input
0N/A * method support is enabled and the text component also processes key events,
0N/A * incoming events are offered to the current input method and will only be
0N/A * processed by the component or dispatched to its listeners if the input method
0N/A * does not consume them. Whether and how input method support for this text
0N/A * component is enabled or disabled by default is implementation dependent.
0N/A *
0N/A * @param enable true to enable, false to disable
0N/A * @see #processKeyEvent
0N/A * @since 1.2
0N/A */
0N/A public void enableInputMethods(boolean enable) {
0N/A checkForEnableIM = false;
0N/A super.enableInputMethods(enable);
0N/A }
0N/A
0N/A boolean areInputMethodsEnabled() {
0N/A // moved from the constructor above to here and addNotify below,
0N/A // this call will initialize the toolkit if not already initialized.
0N/A if (checkForEnableIM) {
0N/A enableInputMethodsIfNecessary();
0N/A }
0N/A
0N/A // TextComponent handles key events without touching the eventMask or
0N/A // having a key listener, so just check whether the flag is set
0N/A return (eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0;
0N/A }
0N/A
0N/A public InputMethodRequests getInputMethodRequests() {
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) return peer.getInputMethodRequests();
0N/A else return null;
0N/A }
0N/A
0N/A
0N/A
0N/A /**
0N/A * Makes this Component displayable by connecting it to a
0N/A * native screen resource.
0N/A * This method is called internally by the toolkit and should
0N/A * not be called directly by programs.
0N/A * @see java.awt.TextComponent#removeNotify
0N/A */
0N/A public void addNotify() {
0N/A super.addNotify();
0N/A enableInputMethodsIfNecessary();
0N/A }
0N/A
0N/A /**
0N/A * Removes the <code>TextComponent</code>'s peer.
0N/A * The peer allows us to modify the appearance of the
0N/A * <code>TextComponent</code> without changing its
0N/A * functionality.
0N/A */
0N/A public void removeNotify() {
0N/A synchronized (getTreeLock()) {
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A text = peer.getText();
0N/A selectionStart = peer.getSelectionStart();
0N/A selectionEnd = peer.getSelectionEnd();
0N/A }
0N/A super.removeNotify();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Sets the text that is presented by this
0N/A * text component to be the specified text.
0N/A * @param t the new text;
0N/A * if this parameter is <code>null</code> then
0N/A * the text is set to the empty string ""
0N/A * @see java.awt.TextComponent#getText
0N/A */
0N/A public synchronized void setText(String t) {
5240N/A boolean skipTextEvent = (text == null || text.isEmpty())
5240N/A && (t == null || t.isEmpty());
0N/A text = (t != null) ? t : "";
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
5240N/A // Please note that we do not want to post an event
5240N/A // if TextArea.setText() or TextField.setText() replaces an empty text
5240N/A // by an empty text, that is, if component's text remains unchanged.
5240N/A if (peer != null && !skipTextEvent) {
0N/A peer.setText(text);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the text that is presented by this text component.
0N/A * By default, this is an empty string.
0N/A *
0N/A * @return the value of this <code>TextComponent</code>
0N/A * @see java.awt.TextComponent#setText
0N/A */
0N/A public synchronized String getText() {
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A text = peer.getText();
0N/A }
0N/A return text;
0N/A }
0N/A
0N/A /**
0N/A * Returns the selected text from the text that is
0N/A * presented by this text component.
0N/A * @return the selected text of this text component
0N/A * @see java.awt.TextComponent#select
0N/A */
0N/A public synchronized String getSelectedText() {
0N/A return getText().substring(getSelectionStart(), getSelectionEnd());
0N/A }
0N/A
0N/A /**
0N/A * Indicates whether or not this text component is editable.
0N/A * @return <code>true</code> if this text component is
0N/A * editable; <code>false</code> otherwise.
0N/A * @see java.awt.TextComponent#setEditable
0N/A * @since JDK1.0
0N/A */
0N/A public boolean isEditable() {
0N/A return editable;
0N/A }
0N/A
0N/A /**
0N/A * Sets the flag that determines whether or not this
0N/A * text component is editable.
0N/A * <p>
0N/A * If the flag is set to <code>true</code>, this text component
0N/A * becomes user editable. If the flag is set to <code>false</code>,
0N/A * the user cannot change the text of this text component.
0N/A * By default, non-editable text components have a background color
0N/A * of SystemColor.control. This default can be overridden by
0N/A * calling setBackground.
0N/A *
0N/A * @param b a flag indicating whether this text component
0N/A * is user editable.
0N/A * @see java.awt.TextComponent#isEditable
0N/A * @since JDK1.0
0N/A */
0N/A public synchronized void setEditable(boolean b) {
0N/A if (editable == b) {
0N/A return;
0N/A }
0N/A
0N/A editable = b;
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A peer.setEditable(b);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the background color of this text component.
0N/A *
0N/A * By default, non-editable text components have a background color
0N/A * of SystemColor.control. This default can be overridden by
0N/A * calling setBackground.
0N/A *
0N/A * @return This text component's background color.
0N/A * If this text component does not have a background color,
0N/A * the background color of its parent is returned.
0N/A * @see #setBackground(Color)
0N/A * @since JDK1.0
0N/A */
0N/A public Color getBackground() {
0N/A if (!editable && !backgroundSetByClientCode) {
0N/A return SystemColor.control;
0N/A }
0N/A
0N/A return super.getBackground();
0N/A }
0N/A
0N/A /**
0N/A * Sets the background color of this text component.
0N/A *
0N/A * @param c The color to become this text component's color.
0N/A * If this parameter is null then this text component
0N/A * will inherit the background color of its parent.
0N/A * @see #getBackground()
0N/A * @since JDK1.0
0N/A */
0N/A public void setBackground(Color c) {
0N/A backgroundSetByClientCode = true;
0N/A super.setBackground(c);
0N/A }
0N/A
0N/A /**
0N/A * Gets the start position of the selected text in
0N/A * this text component.
0N/A * @return the start position of the selected text
0N/A * @see java.awt.TextComponent#setSelectionStart
0N/A * @see java.awt.TextComponent#getSelectionEnd
0N/A */
0N/A public synchronized int getSelectionStart() {
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A selectionStart = peer.getSelectionStart();
0N/A }
0N/A return selectionStart;
0N/A }
0N/A
0N/A /**
0N/A * Sets the selection start for this text component to
0N/A * the specified position. The new start point is constrained
0N/A * to be at or before the current selection end. It also
0N/A * cannot be set to less than zero, the beginning of the
0N/A * component's text.
0N/A * If the caller supplies a value for <code>selectionStart</code>
0N/A * that is out of bounds, the method enforces these constraints
0N/A * silently, and without failure.
0N/A * @param selectionStart the start position of the
0N/A * selected text
0N/A * @see java.awt.TextComponent#getSelectionStart
0N/A * @see java.awt.TextComponent#setSelectionEnd
0N/A * @since JDK1.1
0N/A */
0N/A public synchronized void setSelectionStart(int selectionStart) {
0N/A /* Route through select method to enforce consistent policy
0N/A * between selectionStart and selectionEnd.
0N/A */
0N/A select(selectionStart, getSelectionEnd());
0N/A }
0N/A
0N/A /**
0N/A * Gets the end position of the selected text in
0N/A * this text component.
0N/A * @return the end position of the selected text
0N/A * @see java.awt.TextComponent#setSelectionEnd
0N/A * @see java.awt.TextComponent#getSelectionStart
0N/A */
0N/A public synchronized int getSelectionEnd() {
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A selectionEnd = peer.getSelectionEnd();
0N/A }
0N/A return selectionEnd;
0N/A }
0N/A
0N/A /**
0N/A * Sets the selection end for this text component to
0N/A * the specified position. The new end point is constrained
0N/A * to be at or after the current selection start. It also
0N/A * cannot be set beyond the end of the component's text.
0N/A * If the caller supplies a value for <code>selectionEnd</code>
0N/A * that is out of bounds, the method enforces these constraints
0N/A * silently, and without failure.
0N/A * @param selectionEnd the end position of the
0N/A * selected text
0N/A * @see java.awt.TextComponent#getSelectionEnd
0N/A * @see java.awt.TextComponent#setSelectionStart
0N/A * @since JDK1.1
0N/A */
0N/A public synchronized void setSelectionEnd(int selectionEnd) {
0N/A /* Route through select method to enforce consistent policy
0N/A * between selectionStart and selectionEnd.
0N/A */
0N/A select(getSelectionStart(), selectionEnd);
0N/A }
0N/A
0N/A /**
0N/A * Selects the text between the specified start and end positions.
0N/A * <p>
0N/A * This method sets the start and end positions of the
0N/A * selected text, enforcing the restriction that the start position
0N/A * must be greater than or equal to zero. The end position must be
0N/A * greater than or equal to the start position, and less than or
0N/A * equal to the length of the text component's text. The
0N/A * character positions are indexed starting with zero.
0N/A * The length of the selection is
0N/A * <code>endPosition</code> - <code>startPosition</code>, so the
0N/A * character at <code>endPosition</code> is not selected.
0N/A * If the start and end positions of the selected text are equal,
0N/A * all text is deselected.
0N/A * <p>
0N/A * If the caller supplies values that are inconsistent or out of
0N/A * bounds, the method enforces these constraints silently, and
0N/A * without failure. Specifically, if the start position or end
0N/A * position is greater than the length of the text, it is reset to
0N/A * equal the text length. If the start position is less than zero,
0N/A * it is reset to zero, and if the end position is less than the
0N/A * start position, it is reset to the start position.
0N/A *
0N/A * @param selectionStart the zero-based index of the first
0N/A character (<code>char</code> value) to be selected
0N/A * @param selectionEnd the zero-based end position of the
0N/A text to be selected; the character (<code>char</code> value) at
0N/A <code>selectionEnd</code> is not selected
0N/A * @see java.awt.TextComponent#setSelectionStart
0N/A * @see java.awt.TextComponent#setSelectionEnd
0N/A * @see java.awt.TextComponent#selectAll
0N/A */
0N/A public synchronized void select(int selectionStart, int selectionEnd) {
0N/A String text = getText();
0N/A if (selectionStart < 0) {
0N/A selectionStart = 0;
0N/A }
0N/A if (selectionStart > text.length()) {
0N/A selectionStart = text.length();
0N/A }
0N/A if (selectionEnd > text.length()) {
0N/A selectionEnd = text.length();
0N/A }
0N/A if (selectionEnd < selectionStart) {
0N/A selectionEnd = selectionStart;
0N/A }
0N/A
0N/A this.selectionStart = selectionStart;
0N/A this.selectionEnd = selectionEnd;
0N/A
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A peer.select(selectionStart, selectionEnd);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Selects all the text in this text component.
0N/A * @see java.awt.TextComponent#select
0N/A */
0N/A public synchronized void selectAll() {
0N/A this.selectionStart = 0;
0N/A this.selectionEnd = getText().length();
0N/A
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A peer.select(selectionStart, selectionEnd);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Sets the position of the text insertion caret.
0N/A * The caret position is constrained to be between 0
0N/A * and the last character of the text, inclusive.
0N/A * If the passed-in value is greater than this range,
0N/A * the value is set to the last character (or 0 if
0N/A * the <code>TextComponent</code> contains no text)
0N/A * and no error is returned. If the passed-in value is
0N/A * less than 0, an <code>IllegalArgumentException</code>
0N/A * is thrown.
0N/A *
0N/A * @param position the position of the text insertion caret
0N/A * @exception IllegalArgumentException if <code>position</code>
0N/A * is less than zero
0N/A * @since JDK1.1
0N/A */
0N/A public synchronized void setCaretPosition(int position) {
0N/A if (position < 0) {
0N/A throw new IllegalArgumentException("position less than zero.");
0N/A }
0N/A
0N/A int maxposition = getText().length();
0N/A if (position > maxposition) {
0N/A position = maxposition;
0N/A }
0N/A
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A peer.setCaretPosition(position);
0N/A } else {
0N/A select(position, position);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the position of the text insertion caret.
0N/A * The caret position is constrained to be between 0
0N/A * and the last character of the text, inclusive.
0N/A * If the text or caret have not been set, the default
0N/A * caret position is 0.
0N/A *
0N/A * @return the position of the text insertion caret
0N/A * @see #setCaretPosition(int)
0N/A * @since JDK1.1
0N/A */
0N/A public synchronized int getCaretPosition() {
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A int position = 0;
0N/A
0N/A if (peer != null) {
0N/A position = peer.getCaretPosition();
0N/A } else {
0N/A position = selectionStart;
0N/A }
0N/A int maxposition = getText().length();
0N/A if (position > maxposition) {
0N/A position = maxposition;
0N/A }
0N/A return position;
0N/A }
0N/A
0N/A /**
0N/A * Adds the specified text event listener to receive text events
0N/A * from this text component.
0N/A * If <code>l</code> is <code>null</code>, no exception is
0N/A * thrown and no action is performed.
0N/A * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
0N/A * >AWT Threading Issues</a> for details on AWT's threading model.
0N/A *
0N/A * @param l the text event listener
0N/A * @see #removeTextListener
0N/A * @see #getTextListeners
0N/A * @see java.awt.event.TextListener
0N/A */
0N/A public synchronized void addTextListener(TextListener l) {
0N/A if (l == null) {
0N/A return;
0N/A }
0N/A textListener = AWTEventMulticaster.add(textListener, l);
0N/A newEventsOnly = true;
0N/A }
0N/A
0N/A /**
0N/A * Removes the specified text event listener so that it no longer
0N/A * receives text events from this text component
0N/A * If <code>l</code> is <code>null</code>, no exception is
0N/A * thrown and no action is performed.
0N/A * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
0N/A * >AWT Threading Issues</a> for details on AWT's threading model.
0N/A *
0N/A * @param l the text listener
0N/A * @see #addTextListener
0N/A * @see #getTextListeners
0N/A * @see java.awt.event.TextListener
0N/A * @since JDK1.1
0N/A */
0N/A public synchronized void removeTextListener(TextListener l) {
0N/A if (l == null) {
0N/A return;
0N/A }
0N/A textListener = AWTEventMulticaster.remove(textListener, l);
0N/A }
0N/A
0N/A /**
0N/A * Returns an array of all the text listeners
0N/A * registered on this text component.
0N/A *
0N/A * @return all of this text component's <code>TextListener</code>s
0N/A * or an empty array if no text
0N/A * listeners are currently registered
0N/A *
0N/A *
0N/A * @see #addTextListener
0N/A * @see #removeTextListener
0N/A * @since 1.4
0N/A */
0N/A public synchronized TextListener[] getTextListeners() {
0N/A return (TextListener[])(getListeners(TextListener.class));
0N/A }
0N/A
0N/A /**
0N/A * Returns an array of all the objects currently registered
0N/A * as <code><em>Foo</em>Listener</code>s
0N/A * upon this <code>TextComponent</code>.
0N/A * <code><em>Foo</em>Listener</code>s are registered using the
0N/A * <code>add<em>Foo</em>Listener</code> method.
0N/A *
0N/A * <p>
0N/A * You can specify the <code>listenerType</code> argument
0N/A * with a class literal, such as
0N/A * <code><em>Foo</em>Listener.class</code>.
0N/A * For example, you can query a
0N/A * <code>TextComponent</code> <code>t</code>
0N/A * for its text listeners with the following code:
0N/A *
0N/A * <pre>TextListener[] tls = (TextListener[])(t.getListeners(TextListener.class));</pre>
0N/A *
0N/A * If no such listeners exist, this method returns an empty array.
0N/A *
0N/A * @param listenerType the type of listeners requested; this parameter
0N/A * should specify an interface that descends from
0N/A * <code>java.util.EventListener</code>
0N/A * @return an array of all objects registered as
0N/A * <code><em>Foo</em>Listener</code>s on this text component,
0N/A * or an empty array if no such
0N/A * listeners have been added
0N/A * @exception ClassCastException if <code>listenerType</code>
0N/A * doesn't specify a class or interface that implements
0N/A * <code>java.util.EventListener</code>
0N/A *
0N/A * @see #getTextListeners
0N/A * @since 1.3
0N/A */
0N/A public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
0N/A EventListener l = null;
0N/A if (listenerType == TextListener.class) {
0N/A l = textListener;
0N/A } else {
0N/A return super.getListeners(listenerType);
0N/A }
0N/A return AWTEventMulticaster.getListeners(l, listenerType);
0N/A }
0N/A
0N/A // REMIND: remove when filtering is done at lower level
0N/A boolean eventEnabled(AWTEvent e) {
0N/A if (e.id == TextEvent.TEXT_VALUE_CHANGED) {
0N/A if ((eventMask & AWTEvent.TEXT_EVENT_MASK) != 0 ||
0N/A textListener != null) {
0N/A return true;
0N/A }
0N/A return false;
0N/A }
0N/A return super.eventEnabled(e);
0N/A }
0N/A
0N/A /**
0N/A * Processes events on this text component. If the event is a
0N/A * <code>TextEvent</code>, it invokes the <code>processTextEvent</code>
0N/A * method else it invokes its superclass's <code>processEvent</code>.
0N/A * <p>Note that if the event parameter is <code>null</code>
0N/A * the behavior is unspecified and may result in an
0N/A * exception.
0N/A *
0N/A * @param e the event
0N/A */
0N/A protected void processEvent(AWTEvent e) {
0N/A if (e instanceof TextEvent) {
0N/A processTextEvent((TextEvent)e);
0N/A return;
0N/A }
0N/A super.processEvent(e);
0N/A }
0N/A
0N/A /**
0N/A * Processes text events occurring on this text component by
0N/A * dispatching them to any registered <code>TextListener</code> objects.
0N/A * <p>
0N/A * NOTE: This method will not be called unless text events
0N/A * are enabled for this component. This happens when one of the
0N/A * following occurs:
0N/A * <ul>
0N/A * <li>A <code>TextListener</code> object is registered
0N/A * via <code>addTextListener</code>
0N/A * <li>Text events are enabled via <code>enableEvents</code>
0N/A * </ul>
0N/A * <p>Note that if the event parameter is <code>null</code>
0N/A * the behavior is unspecified and may result in an
0N/A * exception.
0N/A *
0N/A * @param e the text event
0N/A * @see Component#enableEvents
0N/A */
0N/A protected void processTextEvent(TextEvent e) {
0N/A TextListener listener = textListener;
0N/A if (listener != null) {
0N/A int id = e.getID();
0N/A switch (id) {
0N/A case TextEvent.TEXT_VALUE_CHANGED:
0N/A listener.textValueChanged(e);
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns a string representing the state of this
0N/A * <code>TextComponent</code>. This
0N/A * method is intended to be used only for debugging purposes, and the
0N/A * content and format of the returned string may vary between
0N/A * implementations. The returned string may be empty but may not be
0N/A * <code>null</code>.
0N/A *
0N/A * @return the parameter string of this text component
0N/A */
0N/A protected String paramString() {
0N/A String str = super.paramString() + ",text=" + getText();
0N/A if (editable) {
0N/A str += ",editable";
0N/A }
0N/A return str + ",selection=" + getSelectionStart() + "-" + getSelectionEnd();
0N/A }
0N/A
0N/A /**
0N/A * Assigns a valid value to the canAccessClipboard instance variable.
0N/A */
5688N/A private boolean canAccessClipboard() {
0N/A SecurityManager sm = System.getSecurityManager();
5688N/A if (sm == null) return true;
5688N/A try {
5688N/A sm.checkSystemClipboardAccess();
5688N/A return true;
5688N/A } catch (SecurityException e) {}
5688N/A return false;
0N/A }
0N/A
0N/A /*
0N/A * Serialization support.
0N/A */
0N/A /**
0N/A * The textComponent SerializedDataVersion.
0N/A *
0N/A * @serial
0N/A */
0N/A private int textComponentSerializedDataVersion = 1;
0N/A
0N/A /**
0N/A * Writes default serializable fields to stream. Writes
0N/A * a list of serializable TextListener(s) as optional data.
0N/A * The non-serializable TextListener(s) are detected and
0N/A * no attempt is made to serialize them.
0N/A *
0N/A * @serialData Null terminated sequence of zero or more pairs.
0N/A * A pair consists of a String and Object.
0N/A * The String indicates the type of object and
0N/A * is one of the following :
0N/A * textListenerK indicating and TextListener object.
0N/A *
0N/A * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
0N/A * @see java.awt.Component#textListenerK
0N/A */
0N/A private void writeObject(java.io.ObjectOutputStream s)
0N/A throws IOException
0N/A {
0N/A // Serialization support. Since the value of the fields
0N/A // selectionStart, selectionEnd, and text aren't necessarily
0N/A // up to date, we sync them up with the peer before serializing.
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A if (peer != null) {
0N/A text = peer.getText();
0N/A selectionStart = peer.getSelectionStart();
0N/A selectionEnd = peer.getSelectionEnd();
0N/A }
0N/A
0N/A s.defaultWriteObject();
0N/A
0N/A AWTEventMulticaster.save(s, textListenerK, textListener);
0N/A s.writeObject(null);
0N/A }
0N/A
0N/A /**
0N/A * Read the ObjectInputStream, and if it isn't null,
0N/A * add a listener to receive text events fired by the
0N/A * TextComponent. Unrecognized keys or values will be
0N/A * ignored.
0N/A *
0N/A * @exception HeadlessException if
0N/A * <code>GraphicsEnvironment.isHeadless()</code> returns
0N/A * <code>true</code>
0N/A * @see #removeTextListener
0N/A * @see #addTextListener
0N/A * @see java.awt.GraphicsEnvironment#isHeadless
0N/A */
0N/A private void readObject(ObjectInputStream s)
0N/A throws ClassNotFoundException, IOException, HeadlessException
0N/A {
0N/A GraphicsEnvironment.checkHeadless();
0N/A s.defaultReadObject();
0N/A
0N/A // Make sure the state we just read in for text,
0N/A // selectionStart and selectionEnd has legal values
0N/A this.text = (text != null) ? text : "";
0N/A select(selectionStart, selectionEnd);
0N/A
0N/A Object keyOrNull;
0N/A while(null != (keyOrNull = s.readObject())) {
0N/A String key = ((String)keyOrNull).intern();
0N/A
0N/A if (textListenerK == key) {
0N/A addTextListener((TextListener)(s.readObject()));
0N/A } else {
0N/A // skip value for unrecognized key
0N/A s.readObject();
0N/A }
0N/A }
0N/A enableInputMethodsIfNecessary();
0N/A }
0N/A
0N/A
0N/A/////////////////
0N/A// Accessibility support
0N/A////////////////
0N/A
0N/A
0N/A /**
0N/A *
0N/A */
0N/A int getIndexAtPoint(Point p) {
0N/A return -1;
0N/A/* To be fully implemented in a future release
0N/A if (peer == null) {
0N/A return -1;
0N/A }
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A return peer.getIndexAtPoint(p.x, p.y);
0N/A*/
0N/A }
0N/A
0N/A
0N/A /**
0N/A *
0N/A */
0N/A Rectangle getCharacterBounds(int i) {
0N/A return null;
0N/A/* To be fully implemented in a future release
0N/A if (peer == null) {
0N/A return null;
0N/A }
0N/A TextComponentPeer peer = (TextComponentPeer)this.peer;
0N/A return peer.getCharacterBounds(i);
0N/A*/
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Gets the AccessibleContext associated with this TextComponent.
0N/A * For text components, the AccessibleContext takes the form of an
0N/A * AccessibleAWTTextComponent.
0N/A * A new AccessibleAWTTextComponent instance is created if necessary.
0N/A *
0N/A * @return an AccessibleAWTTextComponent that serves as the
0N/A * AccessibleContext of this TextComponent
0N/A * @since 1.3
0N/A */
0N/A public AccessibleContext getAccessibleContext() {
0N/A if (accessibleContext == null) {
0N/A accessibleContext = new AccessibleAWTTextComponent();
0N/A }
0N/A return accessibleContext;
0N/A }
0N/A
0N/A /**
0N/A * This class implements accessibility support for the
0N/A * <code>TextComponent</code> class. It provides an implementation of the
0N/A * Java Accessibility API appropriate to text component user-interface
0N/A * elements.
0N/A * @since 1.3
0N/A */
0N/A protected class AccessibleAWTTextComponent extends AccessibleAWTComponent
0N/A implements AccessibleText, TextListener
0N/A {
0N/A /*
0N/A * JDK 1.3 serialVersionUID
0N/A */
0N/A private static final long serialVersionUID = 3631432373506317811L;
0N/A
0N/A /**
0N/A * Constructs an AccessibleAWTTextComponent. Adds a listener to track
0N/A * caret change.
0N/A */
0N/A public AccessibleAWTTextComponent() {
0N/A TextComponent.this.addTextListener(this);
0N/A }
0N/A
0N/A /**
0N/A * TextListener notification of a text value change.
0N/A */
0N/A public void textValueChanged(TextEvent textEvent) {
0N/A Integer cpos = Integer.valueOf(TextComponent.this.getCaretPosition());
0N/A firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, cpos);
0N/A }
0N/A
0N/A /**
0N/A * Gets the state set of the TextComponent.
0N/A * The AccessibleStateSet of an object is composed of a set of
0N/A * unique AccessibleStates. A change in the AccessibleStateSet
0N/A * of an object will cause a PropertyChangeEvent to be fired
0N/A * for the AccessibleContext.ACCESSIBLE_STATE_PROPERTY property.
0N/A *
0N/A * @return an instance of AccessibleStateSet containing the
0N/A * current state set of the object
0N/A * @see AccessibleStateSet
0N/A * @see AccessibleState
0N/A * @see #addPropertyChangeListener
0N/A */
0N/A public AccessibleStateSet getAccessibleStateSet() {
0N/A AccessibleStateSet states = super.getAccessibleStateSet();
0N/A if (TextComponent.this.isEditable()) {
0N/A states.add(AccessibleState.EDITABLE);
0N/A }
0N/A return states;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Gets the role of this object.
0N/A *
0N/A * @return an instance of AccessibleRole describing the role of the
0N/A * object (AccessibleRole.TEXT)
0N/A * @see AccessibleRole
0N/A */
0N/A public AccessibleRole getAccessibleRole() {
0N/A return AccessibleRole.TEXT;
0N/A }
0N/A
0N/A /**
0N/A * Get the AccessibleText associated with this object. In the
0N/A * implementation of the Java Accessibility API for this class,
0N/A * return this object, which is responsible for implementing the
0N/A * AccessibleText interface on behalf of itself.
0N/A *
0N/A * @return this object
0N/A */
0N/A public AccessibleText getAccessibleText() {
0N/A return this;
0N/A }
0N/A
0N/A
0N/A // --- interface AccessibleText methods ------------------------
0N/A
0N/A /**
0N/A * Many of these methods are just convenience methods; they
0N/A * just call the equivalent on the parent
0N/A */
0N/A
0N/A /**
0N/A * Given a point in local coordinates, return the zero-based index
0N/A * of the character under that Point. If the point is invalid,
0N/A * this method returns -1.
0N/A *
0N/A * @param p the Point in local coordinates
0N/A * @return the zero-based index of the character under Point p.
0N/A */
0N/A public int getIndexAtPoint(Point p) {
0N/A return TextComponent.this.getIndexAtPoint(p);
0N/A }
0N/A
0N/A /**
0N/A * Determines the bounding box of the character at the given
0N/A * index into the string. The bounds are returned in local
0N/A * coordinates. If the index is invalid a null rectangle
0N/A * is returned.
0N/A *
0N/A * @param i the index into the String >= 0
0N/A * @return the screen coordinates of the character's bounding box
0N/A */
0N/A public Rectangle getCharacterBounds(int i) {
0N/A return TextComponent.this.getCharacterBounds(i);
0N/A }
0N/A
0N/A /**
0N/A * Returns the number of characters (valid indicies)
0N/A *
0N/A * @return the number of characters >= 0
0N/A */
0N/A public int getCharCount() {
0N/A return TextComponent.this.getText().length();
0N/A }
0N/A
0N/A /**
0N/A * Returns the zero-based offset of the caret.
0N/A *
0N/A * Note: The character to the right of the caret will have the
0N/A * same index value as the offset (the caret is between
0N/A * two characters).
0N/A *
0N/A * @return the zero-based offset of the caret.
0N/A */
0N/A public int getCaretPosition() {
0N/A return TextComponent.this.getCaretPosition();
0N/A }
0N/A
0N/A /**
0N/A * Returns the AttributeSet for a given character (at a given index).
0N/A *
0N/A * @param i the zero-based index into the text
0N/A * @return the AttributeSet of the character
0N/A */
0N/A public AttributeSet getCharacterAttribute(int i) {
0N/A return null; // No attributes in TextComponent
0N/A }
0N/A
0N/A /**
0N/A * Returns the start offset within the selected text.
0N/A * If there is no selection, but there is
0N/A * a caret, the start and end offsets will be the same.
0N/A * Return 0 if the text is empty, or the caret position
0N/A * if no selection.
0N/A *
0N/A * @return the index into the text of the start of the selection >= 0
0N/A */
0N/A public int getSelectionStart() {
0N/A return TextComponent.this.getSelectionStart();
0N/A }
0N/A
0N/A /**
0N/A * Returns the end offset within the selected text.
0N/A * If there is no selection, but there is
0N/A * a caret, the start and end offsets will be the same.
0N/A * Return 0 if the text is empty, or the caret position
0N/A * if no selection.
0N/A *
0N/A * @return the index into teh text of the end of the selection >= 0
0N/A */
0N/A public int getSelectionEnd() {
0N/A return TextComponent.this.getSelectionEnd();
0N/A }
0N/A
0N/A /**
0N/A * Returns the portion of the text that is selected.
0N/A *
0N/A * @return the text, null if no selection
0N/A */
0N/A public String getSelectedText() {
0N/A String selText = TextComponent.this.getSelectedText();
0N/A // Fix for 4256662
0N/A if (selText == null || selText.equals("")) {
0N/A return null;
0N/A }
0N/A return selText;
0N/A }
0N/A
0N/A /**
0N/A * Returns the String at a given index.
0N/A *
0N/A * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
0N/A * or AccessibleText.SENTENCE to retrieve
0N/A * @param index an index within the text >= 0
0N/A * @return the letter, word, or sentence,
0N/A * null for an invalid index or part
0N/A */
0N/A public String getAtIndex(int part, int index) {
0N/A if (index < 0 || index >= TextComponent.this.getText().length()) {
0N/A return null;
0N/A }
0N/A switch (part) {
0N/A case AccessibleText.CHARACTER:
0N/A return TextComponent.this.getText().substring(index, index+1);
0N/A case AccessibleText.WORD: {
0N/A String s = TextComponent.this.getText();
0N/A BreakIterator words = BreakIterator.getWordInstance();
0N/A words.setText(s);
0N/A int end = words.following(index);
0N/A return s.substring(words.previous(), end);
0N/A }
0N/A case AccessibleText.SENTENCE: {
0N/A String s = TextComponent.this.getText();
0N/A BreakIterator sentence = BreakIterator.getSentenceInstance();
0N/A sentence.setText(s);
0N/A int end = sentence.following(index);
0N/A return s.substring(sentence.previous(), end);
0N/A }
0N/A default:
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A private static final boolean NEXT = true;
0N/A private static final boolean PREVIOUS = false;
0N/A
0N/A /**
0N/A * Needed to unify forward and backward searching.
0N/A * The method assumes that s is the text assigned to words.
0N/A */
0N/A private int findWordLimit(int index, BreakIterator words, boolean direction,
0N/A String s) {
0N/A // Fix for 4256660 and 4256661.
0N/A // Words iterator is different from character and sentence iterators
0N/A // in that end of one word is not necessarily start of another word.
0N/A // Please see java.text.BreakIterator JavaDoc. The code below is
0N/A // based on nextWordStartAfter example from BreakIterator.java.
0N/A int last = (direction == NEXT) ? words.following(index)
0N/A : words.preceding(index);
0N/A int current = (direction == NEXT) ? words.next()
0N/A : words.previous();
0N/A while (current != BreakIterator.DONE) {
0N/A for (int p = Math.min(last, current); p < Math.max(last, current); p++) {
0N/A if (Character.isLetter(s.charAt(p))) {
0N/A return last;
0N/A }
0N/A }
0N/A last = current;
0N/A current = (direction == NEXT) ? words.next()
0N/A : words.previous();
0N/A }
0N/A return BreakIterator.DONE;
0N/A }
0N/A
0N/A /**
0N/A * Returns the String after a given index.
0N/A *
0N/A * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
0N/A * or AccessibleText.SENTENCE to retrieve
0N/A * @param index an index within the text >= 0
0N/A * @return the letter, word, or sentence, null for an invalid
0N/A * index or part
0N/A */
0N/A public String getAfterIndex(int part, int index) {
0N/A if (index < 0 || index >= TextComponent.this.getText().length()) {
0N/A return null;
0N/A }
0N/A switch (part) {
0N/A case AccessibleText.CHARACTER:
0N/A if (index+1 >= TextComponent.this.getText().length()) {
0N/A return null;
0N/A }
0N/A return TextComponent.this.getText().substring(index+1, index+2);
0N/A case AccessibleText.WORD: {
0N/A String s = TextComponent.this.getText();
0N/A BreakIterator words = BreakIterator.getWordInstance();
0N/A words.setText(s);
0N/A int start = findWordLimit(index, words, NEXT, s);
0N/A if (start == BreakIterator.DONE || start >= s.length()) {
0N/A return null;
0N/A }
0N/A int end = words.following(start);
0N/A if (end == BreakIterator.DONE || end >= s.length()) {
0N/A return null;
0N/A }
0N/A return s.substring(start, end);
0N/A }
0N/A case AccessibleText.SENTENCE: {
0N/A String s = TextComponent.this.getText();
0N/A BreakIterator sentence = BreakIterator.getSentenceInstance();
0N/A sentence.setText(s);
0N/A int start = sentence.following(index);
0N/A if (start == BreakIterator.DONE || start >= s.length()) {
0N/A return null;
0N/A }
0N/A int end = sentence.following(start);
0N/A if (end == BreakIterator.DONE || end >= s.length()) {
0N/A return null;
0N/A }
0N/A return s.substring(start, end);
0N/A }
0N/A default:
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Returns the String before a given index.
0N/A *
0N/A * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
0N/A * or AccessibleText.SENTENCE to retrieve
0N/A * @param index an index within the text >= 0
0N/A * @return the letter, word, or sentence, null for an invalid index
0N/A * or part
0N/A */
0N/A public String getBeforeIndex(int part, int index) {
0N/A if (index < 0 || index > TextComponent.this.getText().length()-1) {
0N/A return null;
0N/A }
0N/A switch (part) {
0N/A case AccessibleText.CHARACTER:
0N/A if (index == 0) {
0N/A return null;
0N/A }
0N/A return TextComponent.this.getText().substring(index-1, index);
0N/A case AccessibleText.WORD: {
0N/A String s = TextComponent.this.getText();
0N/A BreakIterator words = BreakIterator.getWordInstance();
0N/A words.setText(s);
0N/A int end = findWordLimit(index, words, PREVIOUS, s);
0N/A if (end == BreakIterator.DONE) {
0N/A return null;
0N/A }
0N/A int start = words.preceding(end);
0N/A if (start == BreakIterator.DONE) {
0N/A return null;
0N/A }
0N/A return s.substring(start, end);
0N/A }
0N/A case AccessibleText.SENTENCE: {
0N/A String s = TextComponent.this.getText();
0N/A BreakIterator sentence = BreakIterator.getSentenceInstance();
0N/A sentence.setText(s);
0N/A int end = sentence.following(index);
0N/A end = sentence.previous();
0N/A int start = sentence.previous();
0N/A if (start == BreakIterator.DONE) {
0N/A return null;
0N/A }
0N/A return s.substring(start, end);
0N/A }
0N/A default:
0N/A return null;
0N/A }
0N/A }
0N/A } // end of AccessibleAWTTextComponent
0N/A
0N/A private boolean checkForEnableIM = true;
0N/A}