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/javax/swing/JTextField.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/JTextField.java+961−0
@@ -0,0 +1,961 @@
1/*
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package javax.swing;
26
27import sun.swing.SwingUtilities2;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.beans.*;
32import javax.swing.text.*;
33import javax.swing.plaf.*;
34import javax.swing.event.*;
35import javax.accessibility.*;
36
37import java.io.ObjectOutputStream;
38import java.io.ObjectInputStream;
39import java.io.IOException;
40import 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://java.sun.com/docs/books/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 * &nbsp; DocumentListener myListener = ??;
82 * &nbsp; JTextField myArea = ??;
83 * &nbsp; 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
112&nbsp;public class UpperCaseField extends JTextField {
113&nbsp;
114&nbsp; public UpperCaseField(int cols) {
115&nbsp; super(cols);
116&nbsp; }
117&nbsp;
118&nbsp; protected Document createDefaultModel() {
119&nbsp; return new UpperCaseDocument();
120&nbsp; }
121&nbsp;
122&nbsp; static class UpperCaseDocument extends PlainDocument {
123&nbsp;
124&nbsp; public void insertString(int offs, String str, AttributeSet a)
125&nbsp; throws BadLocationException {
126&nbsp;
127&nbsp; if (str == null) {
128&nbsp; return;
129&nbsp; }
130&nbsp; char[] upper = str.toCharArray();
131&nbsp; for (int i = 0; i < upper.length; i++) {
132&nbsp; upper[i] = Character.toUpperCase(upper[i]);
133&nbsp; }
134&nbsp; super.insertString(offs, new String(upper), a);
135&nbsp; }
136&nbsp; }
137&nbsp;}
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<sup><font size="-2">TM</font></sup>
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 */
164public class JTextField extends JTextComponent implements SwingConstants {
165
166 /**
167 * Constructs a new <code>TextField</code>. A default model is created,
168 * the initial string is <code>null</code>,
169 * and the number of columns is set to 0.
170 */
171 public JTextField() {
172 this(null, null, 0);
173 }
174
175 /**
176 * Constructs a new <code>TextField</code> initialized with the
177 * specified text. A default model is created and the number of
178 * columns is 0.
179 *
180 * @param text the text to be displayed, or <code>null</code>
181 */
182 public JTextField(String text) {
183 this(null, text, 0);
184 }
185
186 /**
187 * Constructs a new empty <code>TextField</code> with the specified
188 * number of columns.
189 * A default model is created and the initial string is set to
190 * <code>null</code>.
191 *
192 * @param columns the number of columns to use to calculate
193 * the preferred width; if columns is set to zero, the
194 * preferred width will be whatever naturally results from
195 * the component implementation
196 */
197 public JTextField(int columns) {
198 this(null, null, columns);
199 }
200
201 /**
202 * Constructs a new <code>TextField</code> initialized with the
203 * specified text and columns. A default model is created.
204 *
205 * @param text the text to be displayed, or <code>null</code>
206 * @param columns the number of columns to use to calculate
207 * the preferred width; if columns is set to zero, the
208 * preferred width will be whatever naturally results from
209 * the component implementation
210 */
211 public JTextField(String text, int columns) {
212 this(null, text, columns);
213 }
214
215 /**
216 * Constructs a new <code>JTextField</code> that uses the given text
217 * storage model and the given number of columns.
218 * This is the constructor through which the other constructors feed.
219 * If the document is <code>null</code>, a default model is created.
220 *
221 * @param doc the text storage to use; if this is <code>null</code>,
222 * a default will be provided by calling the
223 * <code>createDefaultModel</code> method
224 * @param text the initial string to display, or <code>null</code>
225 * @param columns the number of columns to use to calculate
226 * the preferred width >= 0; if <code>columns</code>
227 * is set to zero, the preferred width will be whatever
228 * naturally results from the component implementation
229 * @exception IllegalArgumentException if <code>columns</code> < 0
230 */
231 public JTextField(Document doc, String text, int columns) {
232 if (columns < 0) {
233 throw new IllegalArgumentException("columns less than zero.");
234 }
235 visibility = new DefaultBoundedRangeModel();
236 visibility.addChangeListener(new ScrollRepainter());
237 this.columns = columns;
238 if (doc == null) {
239 doc = createDefaultModel();
240 }
241 setDocument(doc);
242 if (text != null) {
243 setText(text);
244 }
245 }
246
247 /**
248 * Gets the class ID for a UI.
249 *
250 * @return the string "TextFieldUI"
251 * @see JComponent#getUIClassID
252 * @see UIDefaults#getUI
253 */
254 public String getUIClassID() {
255 return uiClassID;
256 }
257
258
259 /**
260 * Associates the editor with a text document.
261 * The currently registered factory is used to build a view for
262 * the document, which gets displayed by the editor after revalidation.
263 * A PropertyChange event ("document") is propagated to each listener.
264 *
265 * @param doc the document to display/edit
266 * @see #getDocument
267 * @beaninfo
268 * description: the text document model
269 * bound: true
270 * expert: true
271 */
272 public void setDocument(Document doc) {
273 if (doc != null) {
274 doc.putProperty("filterNewlines", Boolean.TRUE);
275 }
276 super.setDocument(doc);
277 }
278
279 /**
280 * Calls to <code>revalidate</code> that come from within the
281 * textfield itself will
282 * be handled by validating the textfield, unless the textfield
283 * is contained within a <code>JViewport</code>,
284 * in which case this returns false.
285 *
286 * @return if the parent of this textfield is a <code>JViewPort</code>
287 * return false, otherwise return true
288 *
289 * @see JComponent#revalidate
290 * @see JComponent#isValidateRoot
291 * @see java.awt.Container#isValidateRoot
292 */
293 @Override
294 public boolean isValidateRoot() {
295 return !(SwingUtilities.getUnwrappedParent(this) instanceof JViewport);
296 }
297
298
299 /**
300 * Returns the horizontal alignment of the text.
301 * Valid keys are:
302 * <ul>
303 * <li><code>JTextField.LEFT</code>
304 * <li><code>JTextField.CENTER</code>
305 * <li><code>JTextField.RIGHT</code>
306 * <li><code>JTextField.LEADING</code>
307 * <li><code>JTextField.TRAILING</code>
308 * </ul>
309 *
310 * @return the horizontal alignment
311 */
312 public int getHorizontalAlignment() {
313 return horizontalAlignment;
314 }
315
316 /**
317 * Sets the horizontal alignment of the text.
318 * Valid keys are:
319 * <ul>
320 * <li><code>JTextField.LEFT</code>
321 * <li><code>JTextField.CENTER</code>
322 * <li><code>JTextField.RIGHT</code>
323 * <li><code>JTextField.LEADING</code>
324 * <li><code>JTextField.TRAILING</code>
325 * </ul>
326 * <code>invalidate</code> and <code>repaint</code> are called when the
327 * alignment is set,
328 * and a <code>PropertyChange</code> event ("horizontalAlignment") is fired.
329 *
330 * @param alignment the alignment
331 * @exception IllegalArgumentException if <code>alignment</code>
332 * is not a valid key
333 * @beaninfo
334 * preferred: true
335 * bound: true
336 * description: Set the field alignment to LEFT, CENTER, RIGHT,
337 * LEADING (the default) or TRAILING
338 * enum: LEFT JTextField.LEFT CENTER JTextField.CENTER RIGHT JTextField.RIGHT
339 * LEADING JTextField.LEADING TRAILING JTextField.TRAILING
340 */
341 public void setHorizontalAlignment(int alignment) {
342 if (alignment == horizontalAlignment) return;
343 int oldValue = horizontalAlignment;
344 if ((alignment == LEFT) || (alignment == CENTER) ||
345 (alignment == RIGHT)|| (alignment == LEADING) ||
346 (alignment == TRAILING)) {
347 horizontalAlignment = alignment;
348 } else {
349 throw new IllegalArgumentException("horizontalAlignment");
350 }
351 firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);
352 invalidate();
353 repaint();
354 }
355
356 /**
357 * Creates the default implementation of the model
358 * to be used at construction if one isn't explicitly
359 * given. An instance of <code>PlainDocument</code> is returned.
360 *
361 * @return the default model implementation
362 */
363 protected Document createDefaultModel() {
364 return new PlainDocument();
365 }
366
367 /**
368 * Returns the number of columns in this <code>TextField</code>.
369 *
370 * @return the number of columns >= 0
371 */
372 public int getColumns() {
373 return columns;
374 }
375
376 /**
377 * Sets the number of columns in this <code>TextField</code>,
378 * and then invalidate the layout.
379 *
380 * @param columns the number of columns >= 0
381 * @exception IllegalArgumentException if <code>columns</code>
382 * is less than 0
383 * @beaninfo
384 * description: the number of columns preferred for display
385 */
386 public void setColumns(int columns) {
387 int oldVal = this.columns;
388 if (columns < 0) {
389 throw new IllegalArgumentException("columns less than zero.");
390 }
391 if (columns != oldVal) {
392 this.columns = columns;
393 invalidate();
394 }
395 }
396
397 /**
398 * Returns the column width.
399 * The meaning of what a column is can be considered a fairly weak
400 * notion for some fonts. This method is used to define the width
401 * of a column. By default this is defined to be the width of the
402 * character <em>m</em> for the font used. This method can be
403 * redefined to be some alternative amount
404 *
405 * @return the column width >= 1
406 */
407 protected int getColumnWidth() {
408 if (columnWidth == 0) {
409 FontMetrics metrics = getFontMetrics(getFont());
410 columnWidth = metrics.charWidth('m');
411 }
412 return columnWidth;
413 }
414
415 /**
416 * Returns the preferred size <code>Dimensions</code> needed for this
417 * <code>TextField</code>. If a non-zero number of columns has been
418 * set, the width is set to the columns multiplied by
419 * the column width.
420 *
421 * @return the dimension of this textfield
422 */
423 public Dimension getPreferredSize() {
424 Dimension size = super.getPreferredSize();
425 if (columns != 0) {
426 Insets insets = getInsets();
427 size.width = columns * getColumnWidth() +
428 insets.left + insets.right;
429 }
430 return size;
431 }
432
433 /**
434 * Sets the current font. This removes cached row height and column
435 * width so the new font will be reflected.
436 * <code>revalidate</code> is called after setting the font.
437 *
438 * @param f the new font
439 */
440 public void setFont(Font f) {
441 super.setFont(f);
442 columnWidth = 0;
443 }
444
445 /**
446 * Adds the specified action listener to receive
447 * action events from this textfield.
448 *
449 * @param l the action listener to be added
450 */
451 public synchronized void addActionListener(ActionListener l) {
452 listenerList.add(ActionListener.class, l);
453 }
454
455 /**
456 * Removes the specified action listener so that it no longer
457 * receives action events from this textfield.
458 *
459 * @param l the action listener to be removed
460 */
461 public synchronized void removeActionListener(ActionListener l) {
462 if ((l != null) && (getAction() == l)) {
463 setAction(null);
464 } else {
465 listenerList.remove(ActionListener.class, l);
466 }
467 }
468
469 /**
470 * Returns an array of all the <code>ActionListener</code>s added
471 * to this JTextField with addActionListener().
472 *
473 * @return all of the <code>ActionListener</code>s added or an empty
474 * array if no listeners have been added
475 * @since 1.4
476 */
477 public synchronized ActionListener[] getActionListeners() {
478 return listenerList.getListeners(ActionListener.class);
479 }
480
481 /**
482 * Notifies all listeners that have registered interest for
483 * notification on this event type. The event instance
484 * is lazily created.
485 * The listener list is processed in last to
486 * first order.
487 * @see EventListenerList
488 */
489 protected void fireActionPerformed() {
490 // Guaranteed to return a non-null array
491 Object[] listeners = listenerList.getListenerList();
492 int modifiers = 0;
493 AWTEvent currentEvent = EventQueue.getCurrentEvent();
494 if (currentEvent instanceof InputEvent) {
495 modifiers = ((InputEvent)currentEvent).getModifiers();
496 } else if (currentEvent instanceof ActionEvent) {
497 modifiers = ((ActionEvent)currentEvent).getModifiers();
498 }
499 ActionEvent e =
500 new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
501 (command != null) ? command : getText(),
502 EventQueue.getMostRecentEventTime(), modifiers);
503
504 // Process the listeners last to first, notifying
505 // those that are interested in this event
506 for (int i = listeners.length-2; i>=0; i-=2) {
507 if (listeners[i]==ActionListener.class) {
508 ((ActionListener)listeners[i+1]).actionPerformed(e);
509 }
510 }
511 }
512
513 /**
514 * Sets the command string used for action events.
515 *
516 * @param command the command string
517 */
518 public void setActionCommand(String command) {
519 this.command = command;
520 }
521
522 private Action action;
523 private PropertyChangeListener actionPropertyChangeListener;
524
525 /**
526 * Sets the <code>Action</code> for the <code>ActionEvent</code> source.
527 * The new <code>Action</code> replaces
528 * any previously set <code>Action</code> but does not affect
529 * <code>ActionListeners</code> independently
530 * added with <code>addActionListener</code>.
531 * If the <code>Action</code> is already a registered
532 * <code>ActionListener</code>
533 * for the <code>ActionEvent</code> source, it is not re-registered.
534 * <p>
535 * Setting the <code>Action</code> results in immediately changing
536 * all the properties described in <a href="Action.html#buttonActions">
537 * Swing Components Supporting <code>Action</code></a>.
538 * Subsequently, the textfield's properties are automatically updated
539 * as the <code>Action</code>'s properties change.
540 * <p>
541 * This method uses three other methods to set
542 * and help track the <code>Action</code>'s property values.
543 * It uses the <code>configurePropertiesFromAction</code> method
544 * to immediately change the textfield's properties.
545 * To track changes in the <code>Action</code>'s property values,
546 * this method registers the <code>PropertyChangeListener</code>
547 * returned by <code>createActionPropertyChangeListener</code>. The
548 * default {@code PropertyChangeListener} invokes the
549 * {@code actionPropertyChanged} method when a property in the
550 * {@code Action} changes.
551 *
552 * @param a the <code>Action</code> for the <code>JTextField</code>,
553 * or <code>null</code>
554 * @since 1.3
555 * @see Action
556 * @see #getAction
557 * @see #configurePropertiesFromAction
558 * @see #createActionPropertyChangeListener
559 * @see #actionPropertyChanged
560 * @beaninfo
561 * bound: true
562 * attribute: visualUpdate true
563 * description: the Action instance connected with this ActionEvent source
564 */
565 public void setAction(Action a) {
566 Action oldValue = getAction();
567 if (action==null || !action.equals(a)) {
568 action = a;
569 if (oldValue!=null) {
570 removeActionListener(oldValue);
571 oldValue.removePropertyChangeListener(actionPropertyChangeListener);
572 actionPropertyChangeListener = null;
573 }
574 configurePropertiesFromAction(action);
575 if (action!=null) {
576 // Don't add if it is already a listener
577 if (!isListener(ActionListener.class, action)) {
578 addActionListener(action);
579 }
580 // Reverse linkage:
581 actionPropertyChangeListener = createActionPropertyChangeListener(action);
582 action.addPropertyChangeListener(actionPropertyChangeListener);
583 }
584 firePropertyChange("action", oldValue, action);
585 }
586 }
587
588 private boolean isListener(Class c, ActionListener a) {
589 boolean isListener = false;
590 Object[] listeners = listenerList.getListenerList();
591 for (int i = listeners.length-2; i>=0; i-=2) {
592 if (listeners[i]==c && listeners[i+1]==a) {
593 isListener=true;
594 }
595 }
596 return isListener;
597 }
598
599 /**
600 * Returns the currently set <code>Action</code> for this
601 * <code>ActionEvent</code> source, or <code>null</code>
602 * if no <code>Action</code> is set.
603 *
604 * @return the <code>Action</code> for this <code>ActionEvent</code> source,
605 * or <code>null</code>
606 * @since 1.3
607 * @see Action
608 * @see #setAction
609 */
610 public Action getAction() {
611 return action;
612 }
613
614 /**
615 * Sets the properties on this textfield to match those in the specified
616 * <code>Action</code>. Refer to <a href="Action.html#buttonActions">
617 * Swing Components Supporting <code>Action</code></a> for more
618 * details as to which properties this sets.
619 *
620 * @param a the <code>Action</code> from which to get the properties,
621 * or <code>null</code>
622 * @since 1.3
623 * @see Action
624 * @see #setAction
625 */
626 protected void configurePropertiesFromAction(Action a) {
627 AbstractAction.setEnabledFromAction(this, a);
628 AbstractAction.setToolTipTextFromAction(this, a);
629 setActionCommandFromAction(a);
630 }
631
632 /**
633 * Updates the textfield's state in response to property changes in
634 * associated action. This method is invoked from the
635 * {@code PropertyChangeListener} returned from
636 * {@code createActionPropertyChangeListener}. Subclasses do not normally
637 * need to invoke this. Subclasses that support additional {@code Action}
638 * properties should override this and
639 * {@code configurePropertiesFromAction}.
640 * <p>
641 * Refer to the table at <a href="Action.html#buttonActions">
642 * Swing Components Supporting <code>Action</code></a> for a list of
643 * the properties this method sets.
644 *
645 * @param action the <code>Action</code> associated with this textfield
646 * @param propertyName the name of the property that changed
647 * @since 1.6
648 * @see Action
649 * @see #configurePropertiesFromAction
650 */
651 protected void actionPropertyChanged(Action action, String propertyName) {
652 if (propertyName == Action.ACTION_COMMAND_KEY) {
653 setActionCommandFromAction(action);
654 } else if (propertyName == "enabled") {
655 AbstractAction.setEnabledFromAction(this, action);
656 } else if (propertyName == Action.SHORT_DESCRIPTION) {
657 AbstractAction.setToolTipTextFromAction(this, action);
658 }
659 }
660
661 private void setActionCommandFromAction(Action action) {
662 setActionCommand((action == null) ? null :
663 (String)action.getValue(Action.ACTION_COMMAND_KEY));
664 }
665
666 /**
667 * Creates and returns a <code>PropertyChangeListener</code> that is
668 * responsible for listening for changes from the specified
669 * <code>Action</code> and updating the appropriate properties.
670 * <p>
671 * <b>Warning:</b> If you subclass this do not create an anonymous
672 * inner class. If you do the lifetime of the textfield will be tied to
673 * that of the <code>Action</code>.
674 *
675 * @param a the textfield's action
676 * @since 1.3
677 * @see Action
678 * @see #setAction
679 */
680 protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
681 return new TextFieldActionPropertyChangeListener(this, a);
682 }
683
684 private static class TextFieldActionPropertyChangeListener extends
685 ActionPropertyChangeListener<JTextField> {
686 TextFieldActionPropertyChangeListener(JTextField tf, Action a) {
687 super(tf, a);
688 }
689
690 protected void actionPropertyChanged(JTextField textField,
691 Action action,
692 PropertyChangeEvent e) {
693 if (AbstractAction.shouldReconfigure(e)) {
694 textField.configurePropertiesFromAction(action);
695 } else {
696 textField.actionPropertyChanged(action, e.getPropertyName());
697 }
698 }
699 }
700
701 /**
702 * Fetches the command list for the editor. This is
703 * the list of commands supported by the plugged-in UI
704 * augmented by the collection of commands that the
705 * editor itself supports. These are useful for binding
706 * to events, such as in a keymap.
707 *
708 * @return the command list
709 */
710 public Action[] getActions() {
711 return TextAction.augmentList(super.getActions(), defaultActions);
712 }
713
714 /**
715 * Processes action events occurring on this textfield by
716 * dispatching them to any registered <code>ActionListener</code> objects.
717 * This is normally called by the controller registered with
718 * textfield.
719 */
720 public void postActionEvent() {
721 fireActionPerformed();
722 }
723
724 // --- Scrolling support -----------------------------------
725
726 /**
727 * Gets the visibility of the text field. This can
728 * be adjusted to change the location of the visible
729 * area if the size of the field is greater than
730 * the area that was allocated to the field.
731 *
732 * <p>
733 * The fields look-and-feel implementation manages
734 * the values of the minimum, maximum, and extent
735 * properties on the <code>BoundedRangeModel</code>.
736 *
737 * @return the visibility
738 * @see BoundedRangeModel
739 */
740 public BoundedRangeModel getHorizontalVisibility() {
741 return visibility;
742 }
743
744 /**
745 * Gets the scroll offset, in pixels.
746 *
747 * @return the offset >= 0
748 */
749 public int getScrollOffset() {
750 return visibility.getValue();
751 }
752
753 /**
754 * Sets the scroll offset, in pixels.
755 *
756 * @param scrollOffset the offset >= 0
757 */
758 public void setScrollOffset(int scrollOffset) {
759 visibility.setValue(scrollOffset);
760 }
761
762 /**
763 * Scrolls the field left or right.
764 *
765 * @param r the region to scroll
766 */
767 public void scrollRectToVisible(Rectangle r) {
768 // convert to coordinate system of the bounded range
769 Insets i = getInsets();
770 int x0 = r.x + visibility.getValue() - i.left;
771 int x1 = x0 + r.width;
772 if (x0 < visibility.getValue()) {
773 // Scroll to the left
774 visibility.setValue(x0);
775 } else if(x1 > visibility.getValue() + visibility.getExtent()) {
776 // Scroll to the right
777 visibility.setValue(x1 - visibility.getExtent());
778 }
779 }
780
781 /**
782 * Returns true if the receiver has an <code>ActionListener</code>
783 * installed.
784 */
785 boolean hasActionListener() {
786 // Guaranteed to return a non-null array
787 Object[] listeners = listenerList.getListenerList();
788 // Process the listeners last to first, notifying
789 // those that are interested in this event
790 for (int i = listeners.length-2; i>=0; i-=2) {
791 if (listeners[i]==ActionListener.class) {
792 return true;
793 }
794 }
795 return false;
796 }
797
798 // --- variables -------------------------------------------
799
800 /**
801 * Name of the action to send notification that the
802 * contents of the field have been accepted. Typically
803 * this is bound to a carriage-return.
804 */
805 public static final String notifyAction = "notify-field-accept";
806
807 private BoundedRangeModel visibility;
808 private int horizontalAlignment = LEADING;
809 private int columns;
810 private int columnWidth;
811 private String command;
812
813 private static final Action[] defaultActions = {
814 new NotifyAction()
815 };
816
817 /**
818 * @see #getUIClassID
819 * @see #readObject
820 */
821 private static final String uiClassID = "TextFieldUI";
822
823 // --- Action implementations -----------------------------------
824
825 // Note that JFormattedTextField.CommitAction extends this
826 static class NotifyAction extends TextAction {
827
828 NotifyAction() {
829 super(notifyAction);
830 }
831
832 public void actionPerformed(ActionEvent e) {
833 JTextComponent target = getFocusedComponent();
834 if (target instanceof JTextField) {
835 JTextField field = (JTextField) target;
836 field.postActionEvent();
837 }
838 }
839
840 public boolean isEnabled() {
841 JTextComponent target = getFocusedComponent();
842 if (target instanceof JTextField) {
843 return ((JTextField)target).hasActionListener();
844 }
845 return false;
846 }
847 }
848
849 class ScrollRepainter implements ChangeListener, Serializable {
850
851 public void stateChanged(ChangeEvent e) {
852 repaint();
853 }
854
855 }
856
857
858 /**
859 * See <code>readObject</code> and <code>writeObject</code> in
860 * <code>JComponent</code> for more
861 * information about serialization in Swing.
862 */
863 private void writeObject(ObjectOutputStream s) throws IOException {
864 s.defaultWriteObject();
865 if (getUIClassID().equals(uiClassID)) {
866 byte count = JComponent.getWriteObjCounter(this);
867 JComponent.setWriteObjCounter(this, --count);
868 if (count == 0 && ui != null) {
869 ui.installUI(this);
870 }
871 }
872 }
873
874
875 /**
876 * Returns a string representation of this <code>JTextField</code>.
877 * This method is intended to be used only for debugging purposes,
878 * and the content and format of the returned string may vary between
879 * implementations. The returned string may be empty but may not
880 * be <code>null</code>.
881 *
882 * @return a string representation of this <code>JTextField</code>
883 */
884 protected String paramString() {
885 String horizontalAlignmentString;
886 if (horizontalAlignment == LEFT) {
887 horizontalAlignmentString = "LEFT";
888 } else if (horizontalAlignment == CENTER) {
889 horizontalAlignmentString = "CENTER";
890 } else if (horizontalAlignment == RIGHT) {
891 horizontalAlignmentString = "RIGHT";
892 } else if (horizontalAlignment == LEADING) {
893 horizontalAlignmentString = "LEADING";
894 } else if (horizontalAlignment == TRAILING) {
895 horizontalAlignmentString = "TRAILING";
896 } else horizontalAlignmentString = "";
897 String commandString = (command != null ?
898 command : "");
899
900 return super.paramString() +
901 ",columns=" + columns +
902 ",columnWidth=" + columnWidth +
903 ",command=" + commandString +
904 ",horizontalAlignment=" + horizontalAlignmentString;
905 }
906
907
908/////////////////
909// Accessibility support
910////////////////
911
912
913 /**
914 * Gets the <code>AccessibleContext</code> associated with this
915 * <code>JTextField</code>. For <code>JTextFields</code>,
916 * the <code>AccessibleContext</code> takes the form of an
917 * <code>AccessibleJTextField</code>.
918 * A new <code>AccessibleJTextField</code> instance is created
919 * if necessary.
920 *
921 * @return an <code>AccessibleJTextField</code> that serves as the
922 * <code>AccessibleContext</code> of this <code>JTextField</code>
923 */
924 public AccessibleContext getAccessibleContext() {
925 if (accessibleContext == null) {
926 accessibleContext = new AccessibleJTextField();
927 }
928 return accessibleContext;
929 }
930
931 /**
932 * This class implements accessibility support for the
933 * <code>JTextField</code> class. It provides an implementation of the
934 * Java Accessibility API appropriate to text field user-interface
935 * elements.
936 * <p>
937 * <strong>Warning:</strong>
938 * Serialized objects of this class will not be compatible with
939 * future Swing releases. The current serialization support is
940 * appropriate for short term storage or RMI between applications running
941 * the same version of Swing. As of 1.4, support for long term storage
942 * of all JavaBeans<sup><font size="-2">TM</font></sup>
943 * has been added to the <code>java.beans</code> package.
944 * Please see {@link java.beans.XMLEncoder}.
945 */
946 protected class AccessibleJTextField extends AccessibleJTextComponent {
947
948 /**
949 * Gets the state set of this object.
950 *
951 * @return an instance of AccessibleStateSet describing the states
952 * of the object
953 * @see AccessibleState
954 */
955 public AccessibleStateSet getAccessibleStateSet() {
956 AccessibleStateSet states = super.getAccessibleStateSet();
957 states.add(AccessibleState.SINGLE_LINE);
958 return states;
959 }
960 }
961}