23 * questions.
24 */
25 package javax.swing;
26
27 import sun.swing.SwingUtilities2;
28
29 import java.awt.*;
30 import java.awt.event.*;
31 import java.beans.*;
32 import javax.swing.text.*;
33 import javax.swing.plaf.*;
34 import javax.swing.event.*;
35 import javax.accessibility.*;
36
37 import java.io.ObjectOutputStream;
38 import java.io.ObjectInputStream;
39 import java.io.IOException;
40 import java.io.Serializable;
41
42 /**
43 * <code>JTextField</code> is a lightweight component that allows the editing
44 * of a single line of text.
45 * For information on and examples of using text fields,
46 * see
47 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html">How to Use Text Fields</a>
48 * in <em>The Java Tutorial.</em>
49 *
50 * <p>
51 * <code>JTextField</code> is intended to be source-compatible
52 * with <code>java.awt.TextField</code> where it is reasonable to do so. This
53 * component has capabilities not found in the <code>java.awt.TextField</code>
54 * class. The superclass should be consulted for additional capabilities.
55 * <p>
56 * <code>JTextField</code> has a method to establish the string used as the
57 * command string for the action event that gets fired. The
58 * <code>java.awt.TextField</code> used the text of the field as the command
59 * string for the <code>ActionEvent</code>.
60 * <code>JTextField</code> will use the command
61 * string set with the <code>setActionCommand</code> method if not <code>null</code>,
62 * otherwise it will use the text of the field as a compatibility with
63 * <code>java.awt.TextField</code>.
64 * <p>
65 * The method <code>setEchoChar</code> and <code>getEchoChar</code>
66 * are not provided directly to avoid a new implementation of a
67 * pluggable look-and-feel inadvertently exposing password characters.
68 * To provide password-like services a separate class <code>JPasswordField</code>
69 * extends <code>JTextField</code> to provide this service with an independently
70 * pluggable look-and-feel.
71 * <p>
72 * The <code>java.awt.TextField</code> could be monitored for changes by adding
73 * a <code>TextListener</code> for <code>TextEvent</code>'s.
74 * In the <code>JTextComponent</code> based
75 * components, changes are broadcasted from the model via a
76 * <code>DocumentEvent</code> to <code>DocumentListeners</code>.
77 * The <code>DocumentEvent</code> gives
78 * the location of the change and the kind of change if desired.
79 * The code fragment might look something like:
80 * <pre><code>
81 * DocumentListener myListener = ??;
82 * JTextField myArea = ??;
83 * myArea.getDocument().addDocumentListener(myListener);
84 * </code></pre>
85 * <p>
86 * The horizontal alignment of <code>JTextField</code> can be set to be left
87 * justified, leading justified, centered, right justified or trailing justified.
88 * Right/trailing justification is useful if the required size
89 * of the field text is smaller than the size allocated to it.
90 * This is determined by the <code>setHorizontalAlignment</code>
91 * and <code>getHorizontalAlignment</code> methods. The default
92 * is to be leading justified.
93 * <p>
94 * How the text field consumes VK_ENTER events depends
95 * on whether the text field has any action listeners.
96 * If so, then VK_ENTER results in the listeners
97 * getting an ActionEvent,
98 * and the VK_ENTER event is consumed.
99 * This is compatible with how AWT text fields handle VK_ENTER events.
100 * If the text field has no action listeners, then as of v 1.3 the VK_ENTER
101 * event is not consumed. Instead, the bindings of ancestor components
102 * are processed, which enables the default button feature of
103 * JFC/Swing to work.
104 * <p>
105 * Customized fields can easily be created by extending the model and
106 * changing the default model provided. For example, the following piece
107 * of code will create a field that holds only upper case characters. It
108 * will work even if text is pasted into from the clipboard or it is altered via
109 * programmatic changes.
110 * <pre><code>
111
132 upper[i] = Character.toUpperCase(upper[i]);
133 }
134 super.insertString(offs, new String(upper), a);
135 }
136 }
137 }
138
139 * </code></pre>
140 * <p>
141 * <strong>Warning:</strong> Swing is not thread safe. For more
142 * information see <a
143 * href="package-summary.html#threading">Swing's Threading
144 * Policy</a>.
145 * <p>
146 * <strong>Warning:</strong>
147 * Serialized objects of this class will not be compatible with
148 * future Swing releases. The current serialization support is
149 * appropriate for short term storage or RMI between applications running
150 * the same version of Swing. As of 1.4, support for long term storage
151 * of all JavaBeans™
152 * has been added to the <code>java.beans</code> package.
153 * Please see {@link java.beans.XMLEncoder}.
154 *
155 * @beaninfo
156 * attribute: isContainer false
157 * description: A component which allows for the editing of a single line of text.
158 *
159 * @author Timothy Prinzing
160 * @see #setActionCommand
161 * @see JPasswordField
162 * @see #addActionListener
163 * @since 1.2
164 */
165 @SuppressWarnings("serial") // Same-version serialization only
166 public class JTextField extends JTextComponent implements SwingConstants {
167
168 /**
169 * Constructs a new <code>TextField</code>. A default model is created,
170 * the initial string is <code>null</code>,
171 * and the number of columns is set to 0.
172 */
173 public JTextField() {
174 this(null, null, 0);
175 }
176
177 /**
178 * Constructs a new <code>TextField</code> initialized with the
179 * specified text. A default model is created and the number of
180 * columns is 0.
181 *
182 * @param text the text to be displayed, or <code>null</code>
183 */
184 public JTextField(String text) {
185 this(null, text, 0);
186 }
187
188 /**
189 * Constructs a new empty <code>TextField</code> with the specified
190 * number of columns.
191 * A default model is created and the initial string is set to
192 * <code>null</code>.
193 *
194 * @param columns the number of columns to use to calculate
195 * the preferred width; if columns is set to zero, the
196 * preferred width will be whatever naturally results from
197 * the component implementation
198 */
199 public JTextField(int columns) {
200 this(null, null, columns);
201 }
202
203 /**
204 * Constructs a new <code>TextField</code> initialized with the
205 * specified text and columns. A default model is created.
206 *
207 * @param text the text to be displayed, or <code>null</code>
208 * @param columns the number of columns to use to calculate
209 * the preferred width; if columns is set to zero, the
210 * preferred width will be whatever naturally results from
211 * the component implementation
212 */
213 public JTextField(String text, int columns) {
214 this(null, text, columns);
215 }
216
217 /**
218 * Constructs a new <code>JTextField</code> that uses the given text
219 * storage model and the given number of columns.
220 * This is the constructor through which the other constructors feed.
221 * If the document is <code>null</code>, a default model is created.
222 *
223 * @param doc the text storage to use; if this is <code>null</code>,
224 * a default will be provided by calling the
225 * <code>createDefaultModel</code> method
226 * @param text the initial string to display, or <code>null</code>
227 * @param columns the number of columns to use to calculate
228 * the preferred width >= 0; if <code>columns</code>
229 * is set to zero, the preferred width will be whatever
230 * naturally results from the component implementation
231 * @exception IllegalArgumentException if <code>columns</code> < 0
232 */
233 public JTextField(Document doc, String text, int columns) {
234 if (columns < 0) {
235 throw new IllegalArgumentException("columns less than zero.");
236 }
237 visibility = new DefaultBoundedRangeModel();
238 visibility.addChangeListener(new ScrollRepainter());
239 this.columns = columns;
240 if (doc == null) {
241 doc = createDefaultModel();
242 }
243 setDocument(doc);
244 if (text != null) {
245 setText(text);
246 }
247 }
248
249 /**
250 * Gets the class ID for a UI.
251 *
262 * Associates the editor with a text document.
263 * The currently registered factory is used to build a view for
264 * the document, which gets displayed by the editor after revalidation.
265 * A PropertyChange event ("document") is propagated to each listener.
266 *
267 * @param doc the document to display/edit
268 * @see #getDocument
269 * @beaninfo
270 * description: the text document model
271 * bound: true
272 * expert: true
273 */
274 public void setDocument(Document doc) {
275 if (doc != null) {
276 doc.putProperty("filterNewlines", Boolean.TRUE);
277 }
278 super.setDocument(doc);
279 }
280
281 /**
282 * Calls to <code>revalidate</code> that come from within the
283 * textfield itself will
284 * be handled by validating the textfield, unless the textfield
285 * is contained within a <code>JViewport</code>,
286 * in which case this returns false.
287 *
288 * @return if the parent of this textfield is a <code>JViewPort</code>
289 * return false, otherwise return true
290 *
291 * @see JComponent#revalidate
292 * @see JComponent#isValidateRoot
293 * @see java.awt.Container#isValidateRoot
294 */
295 @Override
296 public boolean isValidateRoot() {
297 return !(SwingUtilities.getUnwrappedParent(this) instanceof JViewport);
298 }
299
300
301 /**
302 * Returns the horizontal alignment of the text.
303 * Valid keys are:
304 * <ul>
305 * <li><code>JTextField.LEFT</code>
306 * <li><code>JTextField.CENTER</code>
307 * <li><code>JTextField.RIGHT</code>
308 * <li><code>JTextField.LEADING</code>
309 * <li><code>JTextField.TRAILING</code>
310 * </ul>
311 *
312 * @return the horizontal alignment
313 */
314 public int getHorizontalAlignment() {
315 return horizontalAlignment;
316 }
317
318 /**
319 * Sets the horizontal alignment of the text.
320 * Valid keys are:
321 * <ul>
322 * <li><code>JTextField.LEFT</code>
323 * <li><code>JTextField.CENTER</code>
324 * <li><code>JTextField.RIGHT</code>
325 * <li><code>JTextField.LEADING</code>
326 * <li><code>JTextField.TRAILING</code>
327 * </ul>
328 * <code>invalidate</code> and <code>repaint</code> are called when the
329 * alignment is set,
330 * and a <code>PropertyChange</code> event ("horizontalAlignment") is fired.
331 *
332 * @param alignment the alignment
333 * @exception IllegalArgumentException if <code>alignment</code>
334 * is not a valid key
335 * @beaninfo
336 * preferred: true
337 * bound: true
338 * description: Set the field alignment to LEFT, CENTER, RIGHT,
339 * LEADING (the default) or TRAILING
340 * enum: LEFT JTextField.LEFT CENTER JTextField.CENTER RIGHT JTextField.RIGHT
341 * LEADING JTextField.LEADING TRAILING JTextField.TRAILING
342 */
343 public void setHorizontalAlignment(int alignment) {
344 if (alignment == horizontalAlignment) return;
345 int oldValue = horizontalAlignment;
346 if ((alignment == LEFT) || (alignment == CENTER) ||
347 (alignment == RIGHT)|| (alignment == LEADING) ||
348 (alignment == TRAILING)) {
349 horizontalAlignment = alignment;
350 } else {
351 throw new IllegalArgumentException("horizontalAlignment");
352 }
353 firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);
354 invalidate();
355 repaint();
356 }
357
358 /**
359 * Creates the default implementation of the model
360 * to be used at construction if one isn't explicitly
361 * given. An instance of <code>PlainDocument</code> is returned.
362 *
363 * @return the default model implementation
364 */
365 protected Document createDefaultModel() {
366 return new PlainDocument();
367 }
368
369 /**
370 * Returns the number of columns in this <code>TextField</code>.
371 *
372 * @return the number of columns >= 0
373 */
374 public int getColumns() {
375 return columns;
376 }
377
378 /**
379 * Sets the number of columns in this <code>TextField</code>,
380 * and then invalidate the layout.
381 *
382 * @param columns the number of columns >= 0
383 * @exception IllegalArgumentException if <code>columns</code>
384 * is less than 0
385 * @beaninfo
386 * description: the number of columns preferred for display
387 */
388 public void setColumns(int columns) {
389 int oldVal = this.columns;
390 if (columns < 0) {
391 throw new IllegalArgumentException("columns less than zero.");
392 }
393 if (columns != oldVal) {
394 this.columns = columns;
395 invalidate();
396 }
397 }
398
399 /**
400 * Returns the column width.
401 * The meaning of what a column is can be considered a fairly weak
402 * notion for some fonts. This method is used to define the width
403 * of a column. By default this is defined to be the width of the
404 * character <em>m</em> for the font used. This method can be
405 * redefined to be some alternative amount
406 *
407 * @return the column width >= 1
408 */
409 protected int getColumnWidth() {
410 if (columnWidth == 0) {
411 FontMetrics metrics = getFontMetrics(getFont());
412 columnWidth = metrics.charWidth('m');
413 }
414 return columnWidth;
415 }
416
417 /**
418 * Returns the preferred size <code>Dimensions</code> needed for this
419 * <code>TextField</code>. If a non-zero number of columns has been
420 * set, the width is set to the columns multiplied by
421 * the column width.
422 *
423 * @return the dimension of this textfield
424 */
425 public Dimension getPreferredSize() {
426 Dimension size = super.getPreferredSize();
427 if (columns != 0) {
428 Insets insets = getInsets();
429 size.width = columns * getColumnWidth() +
430 insets.left + insets.right;
431 }
432 return size;
433 }
434
435 /**
436 * Sets the current font. This removes cached row height and column
437 * width so the new font will be reflected.
438 * <code>revalidate</code> is called after setting the font.
439 *
440 * @param f the new font
441 */
442 public void setFont(Font f) {
443 super.setFont(f);
444 columnWidth = 0;
445 }
446
447 /**
448 * Adds the specified action listener to receive
449 * action events from this textfield.
450 *
451 * @param l the action listener to be added
452 */
453 public synchronized void addActionListener(ActionListener l) {
454 listenerList.add(ActionListener.class, l);
455 }
456
457 /**
458 * Removes the specified action listener so that it no longer
459 * receives action events from this textfield.
460 *
461 * @param l the action listener to be removed
462 */
463 public synchronized void removeActionListener(ActionListener l) {
464 if ((l != null) && (getAction() == l)) {
465 setAction(null);
466 } else {
467 listenerList.remove(ActionListener.class, l);
468 }
469 }
470
471 /**
472 * Returns an array of all the <code>ActionListener</code>s added
473 * to this JTextField with addActionListener().
474 *
475 * @return all of the <code>ActionListener</code>s added or an empty
476 * array if no listeners have been added
477 * @since 1.4
478 */
479 public synchronized ActionListener[] getActionListeners() {
480 return listenerList.getListeners(ActionListener.class);
481 }
482
483 /**
484 * Notifies all listeners that have registered interest for
485 * notification on this event type. The event instance
486 * is lazily created.
487 * The listener list is processed in last to
488 * first order.
489 * @see EventListenerList
490 */
491 protected void fireActionPerformed() {
492 // Guaranteed to return a non-null array
493 Object[] listeners = listenerList.getListenerList();
494 int modifiers = 0;
495 AWTEvent currentEvent = EventQueue.getCurrentEvent();
508 for (int i = listeners.length-2; i>=0; i-=2) {
509 if (listeners[i]==ActionListener.class) {
510 ((ActionListener)listeners[i+1]).actionPerformed(e);
511 }
512 }
513 }
514
515 /**
516 * Sets the command string used for action events.
517 *
518 * @param command the command string
519 */
520 public void setActionCommand(String command) {
521 this.command = command;
522 }
523
524 private Action action;
525 private PropertyChangeListener actionPropertyChangeListener;
526
527 /**
528 * Sets the <code>Action</code> for the <code>ActionEvent</code> source.
529 * The new <code>Action</code> replaces
530 * any previously set <code>Action</code> but does not affect
531 * <code>ActionListeners</code> independently
532 * added with <code>addActionListener</code>.
533 * If the <code>Action</code> is already a registered
534 * <code>ActionListener</code>
535 * for the <code>ActionEvent</code> source, it is not re-registered.
536 * <p>
537 * Setting the <code>Action</code> results in immediately changing
538 * all the properties described in <a href="Action.html#buttonActions">
539 * Swing Components Supporting <code>Action</code></a>.
540 * Subsequently, the textfield's properties are automatically updated
541 * as the <code>Action</code>'s properties change.
542 * <p>
543 * This method uses three other methods to set
544 * and help track the <code>Action</code>'s property values.
545 * It uses the <code>configurePropertiesFromAction</code> method
546 * to immediately change the textfield's properties.
547 * To track changes in the <code>Action</code>'s property values,
548 * this method registers the <code>PropertyChangeListener</code>
549 * returned by <code>createActionPropertyChangeListener</code>. The
550 * default {@code PropertyChangeListener} invokes the
551 * {@code actionPropertyChanged} method when a property in the
552 * {@code Action} changes.
553 *
554 * @param a the <code>Action</code> for the <code>JTextField</code>,
555 * or <code>null</code>
556 * @since 1.3
557 * @see Action
558 * @see #getAction
559 * @see #configurePropertiesFromAction
560 * @see #createActionPropertyChangeListener
561 * @see #actionPropertyChanged
562 * @beaninfo
563 * bound: true
564 * attribute: visualUpdate true
565 * description: the Action instance connected with this ActionEvent source
566 */
567 public void setAction(Action a) {
568 Action oldValue = getAction();
569 if (action==null || !action.equals(a)) {
570 action = a;
571 if (oldValue!=null) {
572 removeActionListener(oldValue);
573 oldValue.removePropertyChangeListener(actionPropertyChangeListener);
574 actionPropertyChangeListener = null;
575 }
582 // Reverse linkage:
583 actionPropertyChangeListener = createActionPropertyChangeListener(action);
584 action.addPropertyChangeListener(actionPropertyChangeListener);
585 }
586 firePropertyChange("action", oldValue, action);
587 }
588 }
589
590 private boolean isListener(Class<?> c, ActionListener a) {
591 boolean isListener = false;
592 Object[] listeners = listenerList.getListenerList();
593 for (int i = listeners.length-2; i>=0; i-=2) {
594 if (listeners[i]==c && listeners[i+1]==a) {
595 isListener=true;
596 }
597 }
598 return isListener;
599 }
600
601 /**
602 * Returns the currently set <code>Action</code> for this
603 * <code>ActionEvent</code> source, or <code>null</code>
604 * if no <code>Action</code> is set.
605 *
606 * @return the <code>Action</code> for this <code>ActionEvent</code> source,
607 * or <code>null</code>
608 * @since 1.3
609 * @see Action
610 * @see #setAction
611 */
612 public Action getAction() {
613 return action;
614 }
615
616 /**
617 * Sets the properties on this textfield to match those in the specified
618 * <code>Action</code>. Refer to <a href="Action.html#buttonActions">
619 * Swing Components Supporting <code>Action</code></a> for more
620 * details as to which properties this sets.
621 *
622 * @param a the <code>Action</code> from which to get the properties,
623 * or <code>null</code>
624 * @since 1.3
625 * @see Action
626 * @see #setAction
627 */
628 protected void configurePropertiesFromAction(Action a) {
629 AbstractAction.setEnabledFromAction(this, a);
630 AbstractAction.setToolTipTextFromAction(this, a);
631 setActionCommandFromAction(a);
632 }
633
634 /**
635 * Updates the textfield's state in response to property changes in
636 * associated action. This method is invoked from the
637 * {@code PropertyChangeListener} returned from
638 * {@code createActionPropertyChangeListener}. Subclasses do not normally
639 * need to invoke this. Subclasses that support additional {@code Action}
640 * properties should override this and
641 * {@code configurePropertiesFromAction}.
642 * <p>
643 * Refer to the table at <a href="Action.html#buttonActions">
644 * Swing Components Supporting <code>Action</code></a> for a list of
645 * the properties this method sets.
646 *
647 * @param action the <code>Action</code> associated with this textfield
648 * @param propertyName the name of the property that changed
649 * @since 1.6
650 * @see Action
651 * @see #configurePropertiesFromAction
652 */
653 protected void actionPropertyChanged(Action action, String propertyName) {
654 if (propertyName == Action.ACTION_COMMAND_KEY) {
655 setActionCommandFromAction(action);
656 } else if (propertyName == "enabled") {
657 AbstractAction.setEnabledFromAction(this, action);
658 } else if (propertyName == Action.SHORT_DESCRIPTION) {
659 AbstractAction.setToolTipTextFromAction(this, action);
660 }
661 }
662
663 private void setActionCommandFromAction(Action action) {
664 setActionCommand((action == null) ? null :
665 (String)action.getValue(Action.ACTION_COMMAND_KEY));
666 }
667
668 /**
669 * Creates and returns a <code>PropertyChangeListener</code> that is
670 * responsible for listening for changes from the specified
671 * <code>Action</code> and updating the appropriate properties.
672 * <p>
673 * <b>Warning:</b> If you subclass this do not create an anonymous
674 * inner class. If you do the lifetime of the textfield will be tied to
675 * that of the <code>Action</code>.
676 *
677 * @param a the textfield's action
678 * @return a {@code PropertyChangeListener} that is responsible for
679 * listening for changes from the specified {@code Action} and
680 * updating the appropriate properties
681 * @since 1.3
682 * @see Action
683 * @see #setAction
684 */
685 protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
686 return new TextFieldActionPropertyChangeListener(this, a);
687 }
688
689 private static class TextFieldActionPropertyChangeListener extends
690 ActionPropertyChangeListener<JTextField> {
691 TextFieldActionPropertyChangeListener(JTextField tf, Action a) {
692 super(tf, a);
693 }
694
695 protected void actionPropertyChanged(JTextField textField,
701 textField.actionPropertyChanged(action, e.getPropertyName());
702 }
703 }
704 }
705
706 /**
707 * Fetches the command list for the editor. This is
708 * the list of commands supported by the plugged-in UI
709 * augmented by the collection of commands that the
710 * editor itself supports. These are useful for binding
711 * to events, such as in a keymap.
712 *
713 * @return the command list
714 */
715 public Action[] getActions() {
716 return TextAction.augmentList(super.getActions(), defaultActions);
717 }
718
719 /**
720 * Processes action events occurring on this textfield by
721 * dispatching them to any registered <code>ActionListener</code> objects.
722 * This is normally called by the controller registered with
723 * textfield.
724 */
725 public void postActionEvent() {
726 fireActionPerformed();
727 }
728
729 // --- Scrolling support -----------------------------------
730
731 /**
732 * Gets the visibility of the text field. This can
733 * be adjusted to change the location of the visible
734 * area if the size of the field is greater than
735 * the area that was allocated to the field.
736 *
737 * <p>
738 * The fields look-and-feel implementation manages
739 * the values of the minimum, maximum, and extent
740 * properties on the <code>BoundedRangeModel</code>.
741 *
742 * @return the visibility
743 * @see BoundedRangeModel
744 */
745 public BoundedRangeModel getHorizontalVisibility() {
746 return visibility;
747 }
748
749 /**
750 * Gets the scroll offset, in pixels.
751 *
752 * @return the offset >= 0
753 */
754 public int getScrollOffset() {
755 return visibility.getValue();
756 }
757
758 /**
759 * Sets the scroll offset, in pixels.
760 *
767 /**
768 * Scrolls the field left or right.
769 *
770 * @param r the region to scroll
771 */
772 public void scrollRectToVisible(Rectangle r) {
773 // convert to coordinate system of the bounded range
774 Insets i = getInsets();
775 int x0 = r.x + visibility.getValue() - i.left;
776 int x1 = x0 + r.width;
777 if (x0 < visibility.getValue()) {
778 // Scroll to the left
779 visibility.setValue(x0);
780 } else if(x1 > visibility.getValue() + visibility.getExtent()) {
781 // Scroll to the right
782 visibility.setValue(x1 - visibility.getExtent());
783 }
784 }
785
786 /**
787 * Returns true if the receiver has an <code>ActionListener</code>
788 * installed.
789 */
790 boolean hasActionListener() {
791 // Guaranteed to return a non-null array
792 Object[] listeners = listenerList.getListenerList();
793 // Process the listeners last to first, notifying
794 // those that are interested in this event
795 for (int i = listeners.length-2; i>=0; i-=2) {
796 if (listeners[i]==ActionListener.class) {
797 return true;
798 }
799 }
800 return false;
801 }
802
803 // --- variables -------------------------------------------
804
805 /**
806 * Name of the action to send notification that the
807 * contents of the field have been accepted. Typically
844
845 public boolean isEnabled() {
846 JTextComponent target = getFocusedComponent();
847 if (target instanceof JTextField) {
848 return ((JTextField)target).hasActionListener();
849 }
850 return false;
851 }
852 }
853
854 class ScrollRepainter implements ChangeListener, Serializable {
855
856 public void stateChanged(ChangeEvent e) {
857 repaint();
858 }
859
860 }
861
862
863 /**
864 * See <code>readObject</code> and <code>writeObject</code> in
865 * <code>JComponent</code> for more
866 * information about serialization in Swing.
867 */
868 private void writeObject(ObjectOutputStream s) throws IOException {
869 s.defaultWriteObject();
870 if (getUIClassID().equals(uiClassID)) {
871 byte count = JComponent.getWriteObjCounter(this);
872 JComponent.setWriteObjCounter(this, --count);
873 if (count == 0 && ui != null) {
874 ui.installUI(this);
875 }
876 }
877 }
878
879
880 /**
881 * Returns a string representation of this <code>JTextField</code>.
882 * This method is intended to be used only for debugging purposes,
883 * and the content and format of the returned string may vary between
884 * implementations. The returned string may be empty but may not
885 * be <code>null</code>.
886 *
887 * @return a string representation of this <code>JTextField</code>
888 */
889 protected String paramString() {
890 String horizontalAlignmentString;
891 if (horizontalAlignment == LEFT) {
892 horizontalAlignmentString = "LEFT";
893 } else if (horizontalAlignment == CENTER) {
894 horizontalAlignmentString = "CENTER";
895 } else if (horizontalAlignment == RIGHT) {
896 horizontalAlignmentString = "RIGHT";
897 } else if (horizontalAlignment == LEADING) {
898 horizontalAlignmentString = "LEADING";
899 } else if (horizontalAlignment == TRAILING) {
900 horizontalAlignmentString = "TRAILING";
901 } else horizontalAlignmentString = "";
902 String commandString = (command != null ?
903 command : "");
904
905 return super.paramString() +
906 ",columns=" + columns +
907 ",columnWidth=" + columnWidth +
908 ",command=" + commandString +
909 ",horizontalAlignment=" + horizontalAlignmentString;
910 }
911
912
913 /////////////////
914 // Accessibility support
915 ////////////////
916
917
918 /**
919 * Gets the <code>AccessibleContext</code> associated with this
920 * <code>JTextField</code>. For <code>JTextFields</code>,
921 * the <code>AccessibleContext</code> takes the form of an
922 * <code>AccessibleJTextField</code>.
923 * A new <code>AccessibleJTextField</code> instance is created
924 * if necessary.
925 *
926 * @return an <code>AccessibleJTextField</code> that serves as the
927 * <code>AccessibleContext</code> of this <code>JTextField</code>
928 */
929 public AccessibleContext getAccessibleContext() {
930 if (accessibleContext == null) {
931 accessibleContext = new AccessibleJTextField();
932 }
933 return accessibleContext;
934 }
935
936 /**
937 * This class implements accessibility support for the
938 * <code>JTextField</code> class. It provides an implementation of the
939 * Java Accessibility API appropriate to text field user-interface
940 * elements.
941 * <p>
942 * <strong>Warning:</strong>
943 * Serialized objects of this class will not be compatible with
944 * future Swing releases. The current serialization support is
945 * appropriate for short term storage or RMI between applications running
946 * the same version of Swing. As of 1.4, support for long term storage
947 * of all JavaBeans™
948 * has been added to the <code>java.beans</code> package.
949 * Please see {@link java.beans.XMLEncoder}.
950 */
951 @SuppressWarnings("serial") // Same-version serialization only
952 protected class AccessibleJTextField extends AccessibleJTextComponent {
953
954 /**
955 * Gets the state set of this object.
956 *
957 * @return an instance of AccessibleStateSet describing the states
958 * of the object
959 * @see AccessibleState
960 */
961 public AccessibleStateSet getAccessibleStateSet() {
962 AccessibleStateSet states = super.getAccessibleStateSet();
963 states.add(AccessibleState.SINGLE_LINE);
964 return states;
965 }
966 }
967 }
|
23 * questions.
24 */
25 package javax.swing;
26
27 import sun.swing.SwingUtilities2;
28
29 import java.awt.*;
30 import java.awt.event.*;
31 import java.beans.*;
32 import javax.swing.text.*;
33 import javax.swing.plaf.*;
34 import javax.swing.event.*;
35 import javax.accessibility.*;
36
37 import java.io.ObjectOutputStream;
38 import java.io.ObjectInputStream;
39 import java.io.IOException;
40 import java.io.Serializable;
41
42 /**
43 * {@code JTextField} is a lightweight component that allows the editing
44 * of a single line of text.
45 * For information on and examples of using text fields,
46 * see
47 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html">How to Use Text Fields</a>
48 * in <em>The Java Tutorial.</em>
49 *
50 * <p>
51 * {@code JTextField} is intended to be source-compatible
52 * with {@code java.awt.TextField} where it is reasonable to do so. This
53 * component has capabilities not found in the {@code java.awt.TextField}
54 * class. The superclass should be consulted for additional capabilities.
55 * <p>
56 * {@code JTextField} has a method to establish the string used as the
57 * command string for the action event that gets fired. The
58 * {@code java.awt.TextField} used the text of the field as the command
59 * string for the {@code ActionEvent}.
60 * {@code JTextField} will use the command
61 * string set with the {@code setActionCommand} method if not {@code null},
62 * otherwise it will use the text of the field as a compatibility with
63 * {@code java.awt.TextField}.
64 * <p>
65 * The method {@code setEchoChar} and {@code getEchoChar}
66 * are not provided directly to avoid a new implementation of a
67 * pluggable look-and-feel inadvertently exposing password characters.
68 * To provide password-like services a separate class {@code JPasswordField}
69 * extends {@code JTextField} to provide this service with an independently
70 * pluggable look-and-feel.
71 * <p>
72 * The {@code java.awt.TextField} could be monitored for changes by adding
73 * a {@code TextListener} for {@code TextEvent}'s.
74 * In the {@code JTextComponent} based
75 * components, changes are broadcasted from the model via a
76 * {@code DocumentEvent} to {@code DocumentListeners}.
77 * The {@code DocumentEvent} gives
78 * the location of the change and the kind of change if desired.
79 * The code fragment might look something like:
80 * <pre><code>
81 * DocumentListener myListener = ??;
82 * JTextField myArea = ??;
83 * myArea.getDocument().addDocumentListener(myListener);
84 * </code></pre>
85 * <p>
86 * The horizontal alignment of {@code JTextField} can be set to be left
87 * justified, leading justified, centered, right justified or trailing justified.
88 * Right/trailing justification is useful if the required size
89 * of the field text is smaller than the size allocated to it.
90 * This is determined by the {@code setHorizontalAlignment}
91 * and {@code getHorizontalAlignment} methods. The default
92 * is to be leading justified.
93 * <p>
94 * How the text field consumes VK_ENTER events depends
95 * on whether the text field has any action listeners.
96 * If so, then VK_ENTER results in the listeners
97 * getting an ActionEvent,
98 * and the VK_ENTER event is consumed.
99 * This is compatible with how AWT text fields handle VK_ENTER events.
100 * If the text field has no action listeners, then as of v 1.3 the VK_ENTER
101 * event is not consumed. Instead, the bindings of ancestor components
102 * are processed, which enables the default button feature of
103 * JFC/Swing to work.
104 * <p>
105 * Customized fields can easily be created by extending the model and
106 * changing the default model provided. For example, the following piece
107 * of code will create a field that holds only upper case characters. It
108 * will work even if text is pasted into from the clipboard or it is altered via
109 * programmatic changes.
110 * <pre><code>
111
132 upper[i] = Character.toUpperCase(upper[i]);
133 }
134 super.insertString(offs, new String(upper), a);
135 }
136 }
137 }
138
139 * </code></pre>
140 * <p>
141 * <strong>Warning:</strong> Swing is not thread safe. For more
142 * information see <a
143 * href="package-summary.html#threading">Swing's Threading
144 * Policy</a>.
145 * <p>
146 * <strong>Warning:</strong>
147 * Serialized objects of this class will not be compatible with
148 * future Swing releases. The current serialization support is
149 * appropriate for short term storage or RMI between applications running
150 * the same version of Swing. As of 1.4, support for long term storage
151 * of all JavaBeans™
152 * has been added to the {@code java.beans} package.
153 * Please see {@link java.beans.XMLEncoder}.
154 *
155 * @beaninfo
156 * attribute: isContainer false
157 * description: A component which allows for the editing of a single line of text.
158 *
159 * @author Timothy Prinzing
160 * @see #setActionCommand
161 * @see JPasswordField
162 * @see #addActionListener
163 * @since 1.2
164 */
165 @SuppressWarnings("serial") // Same-version serialization only
166 public class JTextField extends JTextComponent implements SwingConstants {
167
168 /**
169 * Constructs a new {@code TextField}. A default model is created,
170 * the initial string is {@code null},
171 * and the number of columns is set to 0.
172 */
173 public JTextField() {
174 this(null, null, 0);
175 }
176
177 /**
178 * Constructs a new {@code TextField} initialized with the
179 * specified text. A default model is created and the number of
180 * columns is 0.
181 *
182 * @param text the text to be displayed, or {@code null}
183 */
184 public JTextField(String text) {
185 this(null, text, 0);
186 }
187
188 /**
189 * Constructs a new empty {@code TextField} with the specified
190 * number of columns.
191 * A default model is created and the initial string is set to
192 * {@code null}.
193 *
194 * @param columns the number of columns to use to calculate
195 * the preferred width; if columns is set to zero, the
196 * preferred width will be whatever naturally results from
197 * the component implementation
198 */
199 public JTextField(int columns) {
200 this(null, null, columns);
201 }
202
203 /**
204 * Constructs a new {@code TextField} initialized with the
205 * specified text and columns. A default model is created.
206 *
207 * @param text the text to be displayed, or {@code null}
208 * @param columns the number of columns to use to calculate
209 * the preferred width; if columns is set to zero, the
210 * preferred width will be whatever naturally results from
211 * the component implementation
212 */
213 public JTextField(String text, int columns) {
214 this(null, text, columns);
215 }
216
217 /**
218 * Constructs a new {@code JTextField} that uses the given text
219 * storage model and the given number of columns.
220 * This is the constructor through which the other constructors feed.
221 * If the document is {@code null}, a default model is created.
222 *
223 * @param doc the text storage to use; if this is {@code null},
224 * a default will be provided by calling the
225 * {@code createDefaultModel} method
226 * @param text the initial string to display, or {@code null}
227 * @param columns the number of columns to use to calculate
228 * the preferred width >= 0; if {@code columns}
229 * is set to zero, the preferred width will be whatever
230 * naturally results from the component implementation
231 * @exception IllegalArgumentException if {@code columns < 0}
232 */
233 public JTextField(Document doc, String text, int columns) {
234 if (columns < 0) {
235 throw new IllegalArgumentException("columns less than zero.");
236 }
237 visibility = new DefaultBoundedRangeModel();
238 visibility.addChangeListener(new ScrollRepainter());
239 this.columns = columns;
240 if (doc == null) {
241 doc = createDefaultModel();
242 }
243 setDocument(doc);
244 if (text != null) {
245 setText(text);
246 }
247 }
248
249 /**
250 * Gets the class ID for a UI.
251 *
262 * Associates the editor with a text document.
263 * The currently registered factory is used to build a view for
264 * the document, which gets displayed by the editor after revalidation.
265 * A PropertyChange event ("document") is propagated to each listener.
266 *
267 * @param doc the document to display/edit
268 * @see #getDocument
269 * @beaninfo
270 * description: the text document model
271 * bound: true
272 * expert: true
273 */
274 public void setDocument(Document doc) {
275 if (doc != null) {
276 doc.putProperty("filterNewlines", Boolean.TRUE);
277 }
278 super.setDocument(doc);
279 }
280
281 /**
282 * Calls to {@code revalidate} that come from within the
283 * textfield itself will
284 * be handled by validating the textfield, unless the textfield
285 * is contained within a {@code JViewport},
286 * in which case this returns false.
287 *
288 * @return if the parent of this textfield is a {@code JViewPort}
289 * return false, otherwise return true
290 *
291 * @see JComponent#revalidate
292 * @see JComponent#isValidateRoot
293 * @see java.awt.Container#isValidateRoot
294 */
295 @Override
296 public boolean isValidateRoot() {
297 return !(SwingUtilities.getUnwrappedParent(this) instanceof JViewport);
298 }
299
300
301 /**
302 * Returns the horizontal alignment of the text.
303 * Valid keys are:
304 * <ul>
305 * <li>{@code JTextField.LEFT}
306 * <li>{@code JTextField.CENTER}
307 * <li>{@code JTextField.RIGHT}
308 * <li>{@code JTextField.LEADING}
309 * <li>{@code JTextField.TRAILING}
310 * </ul>
311 *
312 * @return the horizontal alignment
313 */
314 public int getHorizontalAlignment() {
315 return horizontalAlignment;
316 }
317
318 /**
319 * Sets the horizontal alignment of the text.
320 * Valid keys are:
321 * <ul>
322 * <li>{@code JTextField.LEFT}
323 * <li>{@code JTextField.CENTER}
324 * <li>{@code JTextField.RIGHT}
325 * <li>{@code JTextField.LEADING}
326 * <li>{@code JTextField.TRAILING}
327 * </ul>
328 * {@code invalidate} and {@code repaint} are called when the
329 * alignment is set,
330 * and a {@code PropertyChange} event ("horizontalAlignment") is fired.
331 *
332 * @param alignment the alignment
333 * @exception IllegalArgumentException if {@code alignment}
334 * is not a valid key
335 * @beaninfo
336 * preferred: true
337 * bound: true
338 * description: Set the field alignment to LEFT, CENTER, RIGHT,
339 * LEADING (the default) or TRAILING
340 * enum: LEFT JTextField.LEFT CENTER JTextField.CENTER RIGHT JTextField.RIGHT
341 * LEADING JTextField.LEADING TRAILING JTextField.TRAILING
342 */
343 public void setHorizontalAlignment(int alignment) {
344 if (alignment == horizontalAlignment) return;
345 int oldValue = horizontalAlignment;
346 if ((alignment == LEFT) || (alignment == CENTER) ||
347 (alignment == RIGHT)|| (alignment == LEADING) ||
348 (alignment == TRAILING)) {
349 horizontalAlignment = alignment;
350 } else {
351 throw new IllegalArgumentException("horizontalAlignment");
352 }
353 firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);
354 invalidate();
355 repaint();
356 }
357
358 /**
359 * Creates the default implementation of the model
360 * to be used at construction if one isn't explicitly
361 * given. An instance of {@code PlainDocument} is returned.
362 *
363 * @return the default model implementation
364 */
365 protected Document createDefaultModel() {
366 return new PlainDocument();
367 }
368
369 /**
370 * Returns the number of columns in this {@code TextField}.
371 *
372 * @return the number of columns >= 0
373 */
374 public int getColumns() {
375 return columns;
376 }
377
378 /**
379 * Sets the number of columns in this {@code TextField},
380 * and then invalidate the layout.
381 *
382 * @param columns the number of columns >= 0
383 * @exception IllegalArgumentException if {@code columns}
384 * is less than 0
385 * @beaninfo
386 * description: the number of columns preferred for display
387 */
388 public void setColumns(int columns) {
389 int oldVal = this.columns;
390 if (columns < 0) {
391 throw new IllegalArgumentException("columns less than zero.");
392 }
393 if (columns != oldVal) {
394 this.columns = columns;
395 invalidate();
396 }
397 }
398
399 /**
400 * Returns the column width.
401 * The meaning of what a column is can be considered a fairly weak
402 * notion for some fonts. This method is used to define the width
403 * of a column. By default this is defined to be the width of the
404 * character <em>m</em> for the font used. This method can be
405 * redefined to be some alternative amount
406 *
407 * @return the column width >= 1
408 */
409 protected int getColumnWidth() {
410 if (columnWidth == 0) {
411 FontMetrics metrics = getFontMetrics(getFont());
412 columnWidth = metrics.charWidth('m');
413 }
414 return columnWidth;
415 }
416
417 /**
418 * Returns the preferred size {@code Dimensions} needed for this
419 * {@code TextField}. If a non-zero number of columns has been
420 * set, the width is set to the columns multiplied by
421 * the column width.
422 *
423 * @return the dimension of this textfield
424 */
425 public Dimension getPreferredSize() {
426 Dimension size = super.getPreferredSize();
427 if (columns != 0) {
428 Insets insets = getInsets();
429 size.width = columns * getColumnWidth() +
430 insets.left + insets.right;
431 }
432 return size;
433 }
434
435 /**
436 * Sets the current font. This removes cached row height and column
437 * width so the new font will be reflected.
438 * {@code revalidate} is called after setting the font.
439 *
440 * @param f the new font
441 */
442 public void setFont(Font f) {
443 super.setFont(f);
444 columnWidth = 0;
445 }
446
447 /**
448 * Adds the specified action listener to receive
449 * action events from this textfield.
450 *
451 * @param l the action listener to be added
452 */
453 public synchronized void addActionListener(ActionListener l) {
454 listenerList.add(ActionListener.class, l);
455 }
456
457 /**
458 * Removes the specified action listener so that it no longer
459 * receives action events from this textfield.
460 *
461 * @param l the action listener to be removed
462 */
463 public synchronized void removeActionListener(ActionListener l) {
464 if ((l != null) && (getAction() == l)) {
465 setAction(null);
466 } else {
467 listenerList.remove(ActionListener.class, l);
468 }
469 }
470
471 /**
472 * Returns an array of all the {@code ActionListener}s added
473 * to this JTextField with addActionListener().
474 *
475 * @return all of the {@code ActionListener}s added or an empty
476 * array if no listeners have been added
477 * @since 1.4
478 */
479 public synchronized ActionListener[] getActionListeners() {
480 return listenerList.getListeners(ActionListener.class);
481 }
482
483 /**
484 * Notifies all listeners that have registered interest for
485 * notification on this event type. The event instance
486 * is lazily created.
487 * The listener list is processed in last to
488 * first order.
489 * @see EventListenerList
490 */
491 protected void fireActionPerformed() {
492 // Guaranteed to return a non-null array
493 Object[] listeners = listenerList.getListenerList();
494 int modifiers = 0;
495 AWTEvent currentEvent = EventQueue.getCurrentEvent();
508 for (int i = listeners.length-2; i>=0; i-=2) {
509 if (listeners[i]==ActionListener.class) {
510 ((ActionListener)listeners[i+1]).actionPerformed(e);
511 }
512 }
513 }
514
515 /**
516 * Sets the command string used for action events.
517 *
518 * @param command the command string
519 */
520 public void setActionCommand(String command) {
521 this.command = command;
522 }
523
524 private Action action;
525 private PropertyChangeListener actionPropertyChangeListener;
526
527 /**
528 * Sets the {@code Action} for the {@code ActionEvent} source.
529 * The new {@code Action} replaces
530 * any previously set {@code Action} but does not affect
531 * {@code ActionListeners} independently
532 * added with {@code addActionListener}.
533 * If the {@code Action} is already a registered
534 * {@code ActionListener}
535 * for the {@code ActionEvent} source, it is not re-registered.
536 * <p>
537 * Setting the {@code Action} results in immediately changing
538 * all the properties described in <a href="Action.html#buttonActions">
539 * Swing Components Supporting {@code Action}</a>.
540 * Subsequently, the textfield's properties are automatically updated
541 * as the {@code Action}'s properties change.
542 * <p>
543 * This method uses three other methods to set
544 * and help track the {@code Action}'s property values.
545 * It uses the {@code configurePropertiesFromAction} method
546 * to immediately change the textfield's properties.
547 * To track changes in the {@code Action}'s property values,
548 * this method registers the {@code PropertyChangeListener}
549 * returned by {@code createActionPropertyChangeListener}. The
550 * default {@code PropertyChangeListener} invokes the
551 * {@code actionPropertyChanged} method when a property in the
552 * {@code Action} changes.
553 *
554 * @param a the {@code Action} for the {@code JTextField},
555 * or {@code null}
556 * @since 1.3
557 * @see Action
558 * @see #getAction
559 * @see #configurePropertiesFromAction
560 * @see #createActionPropertyChangeListener
561 * @see #actionPropertyChanged
562 * @beaninfo
563 * bound: true
564 * attribute: visualUpdate true
565 * description: the Action instance connected with this ActionEvent source
566 */
567 public void setAction(Action a) {
568 Action oldValue = getAction();
569 if (action==null || !action.equals(a)) {
570 action = a;
571 if (oldValue!=null) {
572 removeActionListener(oldValue);
573 oldValue.removePropertyChangeListener(actionPropertyChangeListener);
574 actionPropertyChangeListener = null;
575 }
582 // Reverse linkage:
583 actionPropertyChangeListener = createActionPropertyChangeListener(action);
584 action.addPropertyChangeListener(actionPropertyChangeListener);
585 }
586 firePropertyChange("action", oldValue, action);
587 }
588 }
589
590 private boolean isListener(Class<?> c, ActionListener a) {
591 boolean isListener = false;
592 Object[] listeners = listenerList.getListenerList();
593 for (int i = listeners.length-2; i>=0; i-=2) {
594 if (listeners[i]==c && listeners[i+1]==a) {
595 isListener=true;
596 }
597 }
598 return isListener;
599 }
600
601 /**
602 * Returns the currently set {@code Action} for this
603 * {@code ActionEvent} source, or {@code null}
604 * if no {@code Action} is set.
605 *
606 * @return the {@code Action} for this {@code ActionEvent} source,
607 * or {@code null}
608 * @since 1.3
609 * @see Action
610 * @see #setAction
611 */
612 public Action getAction() {
613 return action;
614 }
615
616 /**
617 * Sets the properties on this textfield to match those in the specified
618 * {@code Action}. Refer to <a href="Action.html#buttonActions">
619 * Swing Components Supporting {@code Action}</a> for more
620 * details as to which properties this sets.
621 *
622 * @param a the {@code Action} from which to get the properties,
623 * or {@code null}
624 * @since 1.3
625 * @see Action
626 * @see #setAction
627 */
628 protected void configurePropertiesFromAction(Action a) {
629 AbstractAction.setEnabledFromAction(this, a);
630 AbstractAction.setToolTipTextFromAction(this, a);
631 setActionCommandFromAction(a);
632 }
633
634 /**
635 * Updates the textfield's state in response to property changes in
636 * associated action. This method is invoked from the
637 * {@code PropertyChangeListener} returned from
638 * {@code createActionPropertyChangeListener}. Subclasses do not normally
639 * need to invoke this. Subclasses that support additional {@code Action}
640 * properties should override this and
641 * {@code configurePropertiesFromAction}.
642 * <p>
643 * Refer to the table at <a href="Action.html#buttonActions">
644 * Swing Components Supporting {@code Action}</a> for a list of
645 * the properties this method sets.
646 *
647 * @param action the {@code Action} associated with this textfield
648 * @param propertyName the name of the property that changed
649 * @since 1.6
650 * @see Action
651 * @see #configurePropertiesFromAction
652 */
653 protected void actionPropertyChanged(Action action, String propertyName) {
654 if (propertyName == Action.ACTION_COMMAND_KEY) {
655 setActionCommandFromAction(action);
656 } else if (propertyName == "enabled") {
657 AbstractAction.setEnabledFromAction(this, action);
658 } else if (propertyName == Action.SHORT_DESCRIPTION) {
659 AbstractAction.setToolTipTextFromAction(this, action);
660 }
661 }
662
663 private void setActionCommandFromAction(Action action) {
664 setActionCommand((action == null) ? null :
665 (String)action.getValue(Action.ACTION_COMMAND_KEY));
666 }
667
668 /**
669 * Creates and returns a {@code PropertyChangeListener} that is
670 * responsible for listening for changes from the specified
671 * {@code Action} and updating the appropriate properties.
672 * <p>
673 * <b>Warning:</b> If you subclass this do not create an anonymous
674 * inner class. If you do the lifetime of the textfield will be tied to
675 * that of the {@code Action}.
676 *
677 * @param a the textfield's action
678 * @return a {@code PropertyChangeListener} that is responsible for
679 * listening for changes from the specified {@code Action} and
680 * updating the appropriate properties
681 * @since 1.3
682 * @see Action
683 * @see #setAction
684 */
685 protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
686 return new TextFieldActionPropertyChangeListener(this, a);
687 }
688
689 private static class TextFieldActionPropertyChangeListener extends
690 ActionPropertyChangeListener<JTextField> {
691 TextFieldActionPropertyChangeListener(JTextField tf, Action a) {
692 super(tf, a);
693 }
694
695 protected void actionPropertyChanged(JTextField textField,
701 textField.actionPropertyChanged(action, e.getPropertyName());
702 }
703 }
704 }
705
706 /**
707 * Fetches the command list for the editor. This is
708 * the list of commands supported by the plugged-in UI
709 * augmented by the collection of commands that the
710 * editor itself supports. These are useful for binding
711 * to events, such as in a keymap.
712 *
713 * @return the command list
714 */
715 public Action[] getActions() {
716 return TextAction.augmentList(super.getActions(), defaultActions);
717 }
718
719 /**
720 * Processes action events occurring on this textfield by
721 * dispatching them to any registered {@code ActionListener} objects.
722 * This is normally called by the controller registered with
723 * textfield.
724 */
725 public void postActionEvent() {
726 fireActionPerformed();
727 }
728
729 // --- Scrolling support -----------------------------------
730
731 /**
732 * Gets the visibility of the text field. This can
733 * be adjusted to change the location of the visible
734 * area if the size of the field is greater than
735 * the area that was allocated to the field.
736 *
737 * <p>
738 * The fields look-and-feel implementation manages
739 * the values of the minimum, maximum, and extent
740 * properties on the {@code BoundedRangeModel}.
741 *
742 * @return the visibility
743 * @see BoundedRangeModel
744 */
745 public BoundedRangeModel getHorizontalVisibility() {
746 return visibility;
747 }
748
749 /**
750 * Gets the scroll offset, in pixels.
751 *
752 * @return the offset >= 0
753 */
754 public int getScrollOffset() {
755 return visibility.getValue();
756 }
757
758 /**
759 * Sets the scroll offset, in pixels.
760 *
767 /**
768 * Scrolls the field left or right.
769 *
770 * @param r the region to scroll
771 */
772 public void scrollRectToVisible(Rectangle r) {
773 // convert to coordinate system of the bounded range
774 Insets i = getInsets();
775 int x0 = r.x + visibility.getValue() - i.left;
776 int x1 = x0 + r.width;
777 if (x0 < visibility.getValue()) {
778 // Scroll to the left
779 visibility.setValue(x0);
780 } else if(x1 > visibility.getValue() + visibility.getExtent()) {
781 // Scroll to the right
782 visibility.setValue(x1 - visibility.getExtent());
783 }
784 }
785
786 /**
787 * Returns true if the receiver has an {@code ActionListener}
788 * installed.
789 */
790 boolean hasActionListener() {
791 // Guaranteed to return a non-null array
792 Object[] listeners = listenerList.getListenerList();
793 // Process the listeners last to first, notifying
794 // those that are interested in this event
795 for (int i = listeners.length-2; i>=0; i-=2) {
796 if (listeners[i]==ActionListener.class) {
797 return true;
798 }
799 }
800 return false;
801 }
802
803 // --- variables -------------------------------------------
804
805 /**
806 * Name of the action to send notification that the
807 * contents of the field have been accepted. Typically
844
845 public boolean isEnabled() {
846 JTextComponent target = getFocusedComponent();
847 if (target instanceof JTextField) {
848 return ((JTextField)target).hasActionListener();
849 }
850 return false;
851 }
852 }
853
854 class ScrollRepainter implements ChangeListener, Serializable {
855
856 public void stateChanged(ChangeEvent e) {
857 repaint();
858 }
859
860 }
861
862
863 /**
864 * See {@code readObject} and {@code writeObject} in
865 * {@code JComponent} for more
866 * information about serialization in Swing.
867 */
868 private void writeObject(ObjectOutputStream s) throws IOException {
869 s.defaultWriteObject();
870 if (getUIClassID().equals(uiClassID)) {
871 byte count = JComponent.getWriteObjCounter(this);
872 JComponent.setWriteObjCounter(this, --count);
873 if (count == 0 && ui != null) {
874 ui.installUI(this);
875 }
876 }
877 }
878
879
880 /**
881 * Returns a string representation of this {@code JTextField}.
882 * This method is intended to be used only for debugging purposes,
883 * and the content and format of the returned string may vary between
884 * implementations. The returned string may be empty but may not
885 * be {@code null}.
886 *
887 * @return a string representation of this {@code JTextField}
888 */
889 protected String paramString() {
890 String horizontalAlignmentString;
891 if (horizontalAlignment == LEFT) {
892 horizontalAlignmentString = "LEFT";
893 } else if (horizontalAlignment == CENTER) {
894 horizontalAlignmentString = "CENTER";
895 } else if (horizontalAlignment == RIGHT) {
896 horizontalAlignmentString = "RIGHT";
897 } else if (horizontalAlignment == LEADING) {
898 horizontalAlignmentString = "LEADING";
899 } else if (horizontalAlignment == TRAILING) {
900 horizontalAlignmentString = "TRAILING";
901 } else horizontalAlignmentString = "";
902 String commandString = (command != null ?
903 command : "");
904
905 return super.paramString() +
906 ",columns=" + columns +
907 ",columnWidth=" + columnWidth +
908 ",command=" + commandString +
909 ",horizontalAlignment=" + horizontalAlignmentString;
910 }
911
912
913 /////////////////
914 // Accessibility support
915 ////////////////
916
917
918 /**
919 * Gets the {@code AccessibleContext} associated with this
920 * {@code JTextField}. For {@code JTextFields},
921 * the {@code AccessibleContext} takes the form of an
922 * {@code AccessibleJTextField}.
923 * A new {@code AccessibleJTextField} instance is created
924 * if necessary.
925 *
926 * @return an {@code AccessibleJTextField} that serves as the
927 * {@code AccessibleContext} of this {@code JTextField}
928 */
929 public AccessibleContext getAccessibleContext() {
930 if (accessibleContext == null) {
931 accessibleContext = new AccessibleJTextField();
932 }
933 return accessibleContext;
934 }
935
936 /**
937 * This class implements accessibility support for the
938 * {@code JTextField} class. It provides an implementation of the
939 * Java Accessibility API appropriate to text field user-interface
940 * elements.
941 * <p>
942 * <strong>Warning:</strong>
943 * Serialized objects of this class will not be compatible with
944 * future Swing releases. The current serialization support is
945 * appropriate for short term storage or RMI between applications running
946 * the same version of Swing. As of 1.4, support for long term storage
947 * of all JavaBeans™
948 * has been added to the {@code java.beans} package.
949 * Please see {@link java.beans.XMLEncoder}.
950 */
951 @SuppressWarnings("serial") // Same-version serialization only
952 protected class AccessibleJTextField extends AccessibleJTextComponent {
953
954 /**
955 * Gets the state set of this object.
956 *
957 * @return an instance of AccessibleStateSet describing the states
958 * of the object
959 * @see AccessibleState
960 */
961 public AccessibleStateSet getAccessibleStateSet() {
962 AccessibleStateSet states = super.getAccessibleStateSet();
963 states.add(AccessibleState.SINGLE_LINE);
964 return states;
965 }
966 }
967 }
|