History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/TextComponent.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/awt/TextComponent.java+1231−0
@@ -0,0 +1,1231 @@
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+}