1 /*
   2  * Copyright (c) 2000, 2014, 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 javax.swing;
  26 
  27 import java.awt.*;
  28 import java.awt.event.*;
  29 import java.awt.im.InputContext;
  30 import java.io.*;
  31 import java.text.*;
  32 import java.util.*;
  33 import javax.swing.UIManager;
  34 import javax.swing.event.*;
  35 import javax.swing.plaf.UIResource;
  36 import javax.swing.text.*;
  37 
  38 /**
  39  * <code>JFormattedTextField</code> extends <code>JTextField</code> adding
  40  * support for formatting arbitrary values, as well as retrieving a particular
  41  * object once the user has edited the text. The following illustrates
  42  * configuring a <code>JFormattedTextField</code> to edit dates:
  43  * <pre>
  44  *   JFormattedTextField ftf = new JFormattedTextField();
  45  *   ftf.setValue(new Date());
  46  * </pre>
  47  * <p>
  48  * Once a <code>JFormattedTextField</code> has been created, you can
  49  * listen for editing changes by way of adding
  50  * a <code>PropertyChangeListener</code> and listening for
  51  * <code>PropertyChangeEvent</code>s with the property name <code>value</code>.
  52  * <p>
  53  * <code>JFormattedTextField</code> allows
  54  * configuring what action should be taken when focus is lost. The possible
  55  * configurations are:
  56  * <table summary="Possible JFormattedTextField configurations and their descriptions">
  57  * <tr><th><p style="text-align:left">Value</p></th><th><p style="text-align:left">Description</p></th></tr>
  58  * <tr><td>JFormattedTextField.REVERT
  59  *            <td>Revert the display to match that of <code>getValue</code>,
  60  *                possibly losing the current edit.
  61  *        <tr><td>JFormattedTextField.COMMIT
  62  *            <td>Commits the current value. If the value being edited
  63  *                isn't considered a legal value by the
  64  *                <code>AbstractFormatter</code> that is, a
  65  *                <code>ParseException</code> is thrown, then the value
  66  *                will not change, and then edited value will persist.
  67  *        <tr><td>JFormattedTextField.COMMIT_OR_REVERT
  68  *            <td>Similar to <code>COMMIT</code>, but if the value isn't
  69  *                legal, behave like <code>REVERT</code>.
  70  *        <tr><td>JFormattedTextField.PERSIST
  71  *            <td>Do nothing, don't obtain a new
  72  *                <code>AbstractFormatter</code>, and don't update the value.
  73  * </table>
  74  * The default is <code>JFormattedTextField.COMMIT_OR_REVERT</code>,
  75  * refer to {@link #setFocusLostBehavior} for more information on this.
  76  * <p>
  77  * <code>JFormattedTextField</code> allows the focus to leave, even if
  78  * the currently edited value is invalid. To lock the focus down while the
  79  * <code>JFormattedTextField</code> is an invalid edit state
  80  * you can attach an <code>InputVerifier</code>. The following code snippet
  81  * shows a potential implementation of such an <code>InputVerifier</code>:
  82  * <pre>
  83  * public class FormattedTextFieldVerifier extends InputVerifier {
  84  *     public boolean verify(JComponent input) {
  85  *         if (input instanceof JFormattedTextField) {
  86  *             JFormattedTextField ftf = (JFormattedTextField)input;
  87  *             AbstractFormatter formatter = ftf.getFormatter();
  88  *             if (formatter != null) {
  89  *                 String text = ftf.getText();
  90  *                 try {
  91  *                      formatter.stringToValue(text);
  92  *                      return true;
  93  *                  } catch (ParseException pe) {
  94  *                      return false;
  95  *                  }
  96  *              }
  97  *          }
  98  *          return true;
  99  *      }
 100  *      public boolean shouldYieldFocus(JComponent input) {
 101  *          return verify(input);
 102  *      }
 103  *  }
 104  * </pre>
 105  * <p>
 106  * Alternatively, you could invoke <code>commitEdit</code>, which would also
 107  * commit the value.
 108  * <p>
 109  * <code>JFormattedTextField</code> does not do the formatting it self,
 110  * rather formatting is done through an instance of
 111  * <code>JFormattedTextField.AbstractFormatter</code> which is obtained from
 112  * an instance of <code>JFormattedTextField.AbstractFormatterFactory</code>.
 113  * Instances of <code>JFormattedTextField.AbstractFormatter</code> are
 114  * notified when they become active by way of the
 115  * <code>install</code> method, at which point the
 116  * <code>JFormattedTextField.AbstractFormatter</code> can install whatever
 117  * it needs to, typically a <code>DocumentFilter</code>. Similarly when
 118  * <code>JFormattedTextField</code> no longer
 119  * needs the <code>AbstractFormatter</code>, it will invoke
 120  * <code>uninstall</code>.
 121  * <p>
 122  * <code>JFormattedTextField</code> typically
 123  * queries the <code>AbstractFormatterFactory</code> for an
 124  * <code>AbstractFormat</code> when it gains or loses focus. Although this
 125  * can change based on the focus lost policy. If the focus lost
 126  * policy is <code>JFormattedTextField.PERSIST</code>
 127  * and the <code>JFormattedTextField</code> has been edited, the
 128  * <code>AbstractFormatterFactory</code> will not be queried until the
 129  * value has been committed. Similarly if the focus lost policy is
 130  * <code>JFormattedTextField.COMMIT</code> and an exception
 131  * is thrown from <code>stringToValue</code>, the
 132  * <code>AbstractFormatterFactory</code> will not be queried when focus is
 133  * lost or gained.
 134  * <p>
 135  * <code>JFormattedTextField.AbstractFormatter</code>
 136  * is also responsible for determining when values are committed to
 137  * the <code>JFormattedTextField</code>. Some
 138  * <code>JFormattedTextField.AbstractFormatter</code>s will make new values
 139  * available on every edit, and others will never commit the value. You can
 140  * force the current value to be obtained
 141  * from the current <code>JFormattedTextField.AbstractFormatter</code>
 142  * by way of invoking <code>commitEdit</code>. <code>commitEdit</code> will
 143  * be invoked whenever return is pressed in the
 144  * <code>JFormattedTextField</code>.
 145  * <p>
 146  * If an <code>AbstractFormatterFactory</code> has not been explicitly
 147  * set, one will be set based on the <code>Class</code> of the value type after
 148  * <code>setValue</code> has been invoked (assuming value is non-null).
 149  * For example, in the following code an appropriate
 150  * <code>AbstractFormatterFactory</code> and <code>AbstractFormatter</code>
 151  * will be created to handle formatting of numbers:
 152  * <pre>
 153  *   JFormattedTextField tf = new JFormattedTextField();
 154  *   tf.setValue(new Number(100));
 155  * </pre>
 156  * <p>
 157  * <strong>Warning:</strong> As the <code>AbstractFormatter</code> will
 158  * typically install a <code>DocumentFilter</code> on the
 159  * <code>Document</code>, and a <code>NavigationFilter</code> on the
 160  * <code>JFormattedTextField</code> you should not install your own. If you do,
 161  * you are likely to see odd behavior in that the editing policy of the
 162  * <code>AbstractFormatter</code> will not be enforced.
 163  * <p>
 164  * <strong>Warning:</strong> Swing is not thread safe. For more
 165  * information see <a
 166  * href="package-summary.html#threading">Swing's Threading
 167  * Policy</a>.
 168  * <p>
 169  * <strong>Warning:</strong>
 170  * Serialized objects of this class will not be compatible with
 171  * future Swing releases. The current serialization support is
 172  * appropriate for short term storage or RMI between applications running
 173  * the same version of Swing.  As of 1.4, support for long term storage
 174  * of all JavaBeans&trade;
 175  * has been added to the <code>java.beans</code> package.
 176  * Please see {@link java.beans.XMLEncoder}.
 177  *
 178  * @since 1.4
 179  */
 180 @SuppressWarnings("serial") // Same-version serialization only
 181 public class JFormattedTextField extends JTextField {
 182     private static final String uiClassID = "FormattedTextFieldUI";
 183     private static final Action[] defaultActions =
 184             { new CommitAction(), new CancelAction() };
 185 
 186     /**
 187      * Constant identifying that when focus is lost,
 188      * <code>commitEdit</code> should be invoked. If in committing the
 189      * new value a <code>ParseException</code> is thrown, the invalid
 190      * value will remain.
 191      *
 192      * @see #setFocusLostBehavior
 193      */
 194     public static final int COMMIT = 0;
 195 
 196     /**
 197      * Constant identifying that when focus is lost,
 198      * <code>commitEdit</code> should be invoked. If in committing the new
 199      * value a <code>ParseException</code> is thrown, the value will be
 200      * reverted.
 201      *
 202      * @see #setFocusLostBehavior
 203      */
 204     public static final int COMMIT_OR_REVERT = 1;
 205 
 206     /**
 207      * Constant identifying that when focus is lost, editing value should
 208      * be reverted to current value set on the
 209      * <code>JFormattedTextField</code>.
 210      *
 211      * @see #setFocusLostBehavior
 212      */
 213     public static final int REVERT = 2;
 214 
 215     /**
 216      * Constant identifying that when focus is lost, the edited value
 217      * should be left.
 218      *
 219      * @see #setFocusLostBehavior
 220      */
 221     public static final int PERSIST = 3;
 222 
 223 
 224     /**
 225      * Factory used to obtain an instance of AbstractFormatter.
 226      */
 227     private AbstractFormatterFactory factory;
 228     /**
 229      * Object responsible for formatting the current value.
 230      */
 231     private AbstractFormatter format;
 232     /**
 233      * Last valid value.
 234      */
 235     private Object value;
 236     /**
 237      * True while the value being edited is valid.
 238      */
 239     private boolean editValid;
 240     /**
 241      * Behavior when focus is lost.
 242      */
 243     private int focusLostBehavior;
 244     /**
 245      * Indicates the current value has been edited.
 246      */
 247     private boolean edited;
 248     /**
 249      * Used to set the dirty state.
 250      */
 251     private DocumentListener documentListener;
 252     /**
 253      * Masked used to set the AbstractFormatterFactory.
 254      */
 255     private Object mask;
 256     /**
 257      * ActionMap that the TextFormatter Actions are added to.
 258      */
 259     private ActionMap textFormatterActionMap;
 260     /**
 261      * Indicates the input method composed text is in the document
 262      */
 263     private boolean composedTextExists = false;
 264     /**
 265      * A handler for FOCUS_LOST event
 266      */
 267     private FocusLostHandler focusLostHandler;
 268 
 269 
 270     /**
 271      * Creates a <code>JFormattedTextField</code> with no
 272      * <code>AbstractFormatterFactory</code>. Use <code>setMask</code> or
 273      * <code>setFormatterFactory</code> to configure the
 274      * <code>JFormattedTextField</code> to edit a particular type of
 275      * value.
 276      */
 277     public JFormattedTextField() {
 278         super();
 279         enableEvents(AWTEvent.FOCUS_EVENT_MASK);
 280         setFocusLostBehavior(COMMIT_OR_REVERT);
 281     }
 282 
 283     /**
 284      * Creates a JFormattedTextField with the specified value. This will
 285      * create an <code>AbstractFormatterFactory</code> based on the
 286      * type of <code>value</code>.
 287      *
 288      * @param value Initial value for the JFormattedTextField
 289      */
 290     public JFormattedTextField(Object value) {
 291         this();
 292         setValue(value);
 293     }
 294 
 295     /**
 296      * Creates a <code>JFormattedTextField</code>. <code>format</code> is
 297      * wrapped in an appropriate <code>AbstractFormatter</code> which is
 298      * then wrapped in an <code>AbstractFormatterFactory</code>.
 299      *
 300      * @param format Format used to look up an AbstractFormatter
 301      */
 302     public JFormattedTextField(java.text.Format format) {
 303         this();
 304         setFormatterFactory(getDefaultFormatterFactory(format));
 305     }
 306 
 307     /**
 308      * Creates a <code>JFormattedTextField</code> with the specified
 309      * <code>AbstractFormatter</code>. The <code>AbstractFormatter</code>
 310      * is placed in an <code>AbstractFormatterFactory</code>.
 311      *
 312      * @param formatter AbstractFormatter to use for formatting.
 313      */
 314     public JFormattedTextField(AbstractFormatter formatter) {
 315         this(new DefaultFormatterFactory(formatter));
 316     }
 317 
 318     /**
 319      * Creates a <code>JFormattedTextField</code> with the specified
 320      * <code>AbstractFormatterFactory</code>.
 321      *
 322      * @param factory AbstractFormatterFactory used for formatting.
 323      */
 324     public JFormattedTextField(AbstractFormatterFactory factory) {
 325         this();
 326         setFormatterFactory(factory);
 327     }
 328 
 329     /**
 330      * Creates a <code>JFormattedTextField</code> with the specified
 331      * <code>AbstractFormatterFactory</code> and initial value.
 332      *
 333      * @param factory <code>AbstractFormatterFactory</code> used for
 334      *        formatting.
 335      * @param currentValue Initial value to use
 336      */
 337     public JFormattedTextField(AbstractFormatterFactory factory,
 338                                Object currentValue) {
 339         this(currentValue);
 340         setFormatterFactory(factory);
 341     }
 342 
 343     /**
 344      * Sets the behavior when focus is lost. This will be one of
 345      * <code>JFormattedTextField.COMMIT_OR_REVERT</code>,
 346      * <code>JFormattedTextField.REVERT</code>,
 347      * <code>JFormattedTextField.COMMIT</code> or
 348      * <code>JFormattedTextField.PERSIST</code>
 349      * Note that some <code>AbstractFormatter</code>s may push changes as
 350      * they occur, so that the value of this will have no effect.
 351      * <p>
 352      * This will throw an <code>IllegalArgumentException</code> if the object
 353      * passed in is not one of the afore mentioned values.
 354      * <p>
 355      * The default value of this property is
 356      * <code>JFormattedTextField.COMMIT_OR_REVERT</code>.
 357      *
 358      * @param behavior Identifies behavior when focus is lost
 359      * @throws IllegalArgumentException if behavior is not one of the known
 360      *         values
 361      * @beaninfo
 362      *  enum: COMMIT         JFormattedTextField.COMMIT
 363      *        COMMIT_OR_REVERT JFormattedTextField.COMMIT_OR_REVERT
 364      *        REVERT         JFormattedTextField.REVERT
 365      *        PERSIST        JFormattedTextField.PERSIST
 366      *  description: Behavior when component loses focus
 367      */
 368     public void setFocusLostBehavior(int behavior) {
 369         if (behavior != COMMIT && behavior != COMMIT_OR_REVERT &&
 370             behavior != PERSIST && behavior != REVERT) {
 371             throw new IllegalArgumentException("setFocusLostBehavior must be one of: JFormattedTextField.COMMIT, JFormattedTextField.COMMIT_OR_REVERT, JFormattedTextField.PERSIST or JFormattedTextField.REVERT");
 372         }
 373         focusLostBehavior = behavior;
 374     }
 375 
 376     /**
 377      * Returns the behavior when focus is lost. This will be one of
 378      * <code>COMMIT_OR_REVERT</code>,
 379      * <code>COMMIT</code>,
 380      * <code>REVERT</code> or
 381      * <code>PERSIST</code>
 382      * Note that some <code>AbstractFormatter</code>s may push changes as
 383      * they occur, so that the value of this will have no effect.
 384      *
 385      * @return returns behavior when focus is lost
 386      */
 387     public int getFocusLostBehavior() {
 388         return focusLostBehavior;
 389     }
 390 
 391     /**
 392      * Sets the <code>AbstractFormatterFactory</code>.
 393      * <code>AbstractFormatterFactory</code> is
 394      * able to return an instance of <code>AbstractFormatter</code> that is
 395      * used to format a value for display, as well an enforcing an editing
 396      * policy.
 397      * <p>
 398      * If you have not explicitly set an <code>AbstractFormatterFactory</code>
 399      * by way of this method (or a constructor) an
 400      * <code>AbstractFormatterFactory</code> and consequently an
 401      * <code>AbstractFormatter</code> will be used based on the
 402      * <code>Class</code> of the value. <code>NumberFormatter</code> will
 403      * be used for <code>Number</code>s, <code>DateFormatter</code> will
 404      * be used for <code>Dates</code>, otherwise <code>DefaultFormatter</code>
 405      * will be used.
 406      * <p>
 407      * This is a JavaBeans bound property.
 408      *
 409      * @param tf <code>AbstractFormatterFactory</code> used to lookup
 410      *          instances of <code>AbstractFormatter</code>
 411      * @beaninfo
 412      *       bound: true
 413      *   attribute: visualUpdate true
 414      * description: AbstractFormatterFactory, responsible for returning an
 415      *              AbstractFormatter that can format the current value.
 416      */
 417     public void setFormatterFactory(AbstractFormatterFactory tf) {
 418         AbstractFormatterFactory oldFactory = factory;
 419 
 420         factory = tf;
 421         firePropertyChange("formatterFactory", oldFactory, tf);
 422         setValue(getValue(), true, false);
 423     }
 424 
 425     /**
 426      * Returns the current <code>AbstractFormatterFactory</code>.
 427      *
 428      * @see #setFormatterFactory
 429      * @return <code>AbstractFormatterFactory</code> used to determine
 430      *         <code>AbstractFormatter</code>s
 431      */
 432     public AbstractFormatterFactory getFormatterFactory() {
 433         return factory;
 434     }
 435 
 436     /**
 437      * Sets the current <code>AbstractFormatter</code>.
 438      * <p>
 439      * You should not normally invoke this, instead set the
 440      * <code>AbstractFormatterFactory</code> or set the value.
 441      * <code>JFormattedTextField</code> will
 442      * invoke this as the state of the <code>JFormattedTextField</code>
 443      * changes and requires the value to be reset.
 444      * <code>JFormattedTextField</code> passes in the
 445      * <code>AbstractFormatter</code> obtained from the
 446      * <code>AbstractFormatterFactory</code>.
 447      * <p>
 448      * This is a JavaBeans bound property.
 449      *
 450      * @see #setFormatterFactory
 451      * @param format AbstractFormatter to use for formatting
 452      * @beaninfo
 453      *       bound: true
 454      *   attribute: visualUpdate true
 455      * description: TextFormatter, responsible for formatting the current value
 456      */
 457     protected void setFormatter(AbstractFormatter format) {
 458         AbstractFormatter oldFormat = this.format;
 459 
 460         if (oldFormat != null) {
 461             oldFormat.uninstall();
 462         }
 463         setEditValid(true);
 464         this.format = format;
 465         if (format != null) {
 466             format.install(this);
 467         }
 468         setEdited(false);
 469         firePropertyChange("textFormatter", oldFormat, format);
 470     }
 471 
 472     /**
 473      * Returns the <code>AbstractFormatter</code> that is used to format and
 474      * parse the current value.
 475      *
 476      * @return AbstractFormatter used for formatting
 477      */
 478     public AbstractFormatter getFormatter() {
 479         return format;
 480     }
 481 
 482     /**
 483      * Sets the value that will be formatted by an
 484      * <code>AbstractFormatter</code> obtained from the current
 485      * <code>AbstractFormatterFactory</code>. If no
 486      * <code>AbstractFormatterFactory</code> has been specified, this will
 487      * attempt to create one based on the type of <code>value</code>.
 488      * <p>
 489      * The default value of this property is null.
 490      * <p>
 491      * This is a JavaBeans bound property.
 492      *
 493      * @param value Current value to display
 494      * @beaninfo
 495      *       bound: true
 496      *   attribute: visualUpdate true
 497      * description: The value to be formatted.
 498      */
 499     public void setValue(Object value) {
 500         if (value != null && getFormatterFactory() == null) {
 501             setFormatterFactory(getDefaultFormatterFactory(value));
 502         }
 503         setValue(value, true, true);
 504     }
 505 
 506     /**
 507      * Returns the last valid value. Based on the editing policy of
 508      * the <code>AbstractFormatter</code> this may not return the current
 509      * value. The currently edited value can be obtained by invoking
 510      * <code>commitEdit</code> followed by <code>getValue</code>.
 511      *
 512      * @return Last valid value
 513      */
 514     public Object getValue() {
 515         return value;
 516     }
 517 
 518     /**
 519      * Forces the current value to be taken from the
 520      * <code>AbstractFormatter</code> and set as the current value.
 521      * This has no effect if there is no current
 522      * <code>AbstractFormatter</code> installed.
 523      *
 524      * @throws ParseException if the <code>AbstractFormatter</code> is not able
 525      *         to format the current value
 526      */
 527     public void commitEdit() throws ParseException {
 528         AbstractFormatter format = getFormatter();
 529 
 530         if (format != null) {
 531             setValue(format.stringToValue(getText()), false, true);
 532         }
 533     }
 534 
 535     /**
 536      * Sets the validity of the edit on the receiver. You should not normally
 537      * invoke this. This will be invoked by the
 538      * <code>AbstractFormatter</code> as the user edits the value.
 539      * <p>
 540      * Not all formatters will allow the component to get into an invalid
 541      * state, and thus this may never be invoked.
 542      * <p>
 543      * Based on the look and feel this may visually change the state of
 544      * the receiver.
 545      *
 546      * @param isValid boolean indicating if the currently edited value is
 547      *        valid.
 548      * @beaninfo
 549      *       bound: true
 550      *   attribute: visualUpdate true
 551      * description: True indicates the edited value is valid
 552      */
 553     private void setEditValid(boolean isValid) {
 554         if (isValid != editValid) {
 555             editValid = isValid;
 556             firePropertyChange("editValid", Boolean.valueOf(!isValid),
 557                                Boolean.valueOf(isValid));
 558         }
 559     }
 560 
 561     /**
 562      * Returns true if the current value being edited is valid. The value of
 563      * this is managed by the current <code>AbstractFormatter</code>, as such
 564      * there is no public setter for it.
 565      *
 566      * @return true if the current value being edited is valid.
 567      */
 568     public boolean isEditValid() {
 569         return editValid;
 570     }
 571 
 572     /**
 573      * Invoked when the user inputs an invalid value. This gives the
 574      * component a chance to provide feedback. The default
 575      * implementation beeps.
 576      */
 577     protected void invalidEdit() {
 578         UIManager.getLookAndFeel().provideErrorFeedback(JFormattedTextField.this);
 579     }
 580 
 581     /**
 582      * Processes any input method events, such as
 583      * <code>InputMethodEvent.INPUT_METHOD_TEXT_CHANGED</code> or
 584      * <code>InputMethodEvent.CARET_POSITION_CHANGED</code>.
 585      *
 586      * @param e the <code>InputMethodEvent</code>
 587      * @see InputMethodEvent
 588      */
 589     protected void processInputMethodEvent(InputMethodEvent e) {
 590         AttributedCharacterIterator text = e.getText();
 591         int commitCount = e.getCommittedCharacterCount();
 592 
 593         // Keep track of the composed text
 594         if (text != null) {
 595             int begin = text.getBeginIndex();
 596             int end = text.getEndIndex();
 597             composedTextExists = ((end - begin) > commitCount);
 598         } else {
 599             composedTextExists = false;
 600         }
 601 
 602         super.processInputMethodEvent(e);
 603     }
 604 
 605     /**
 606      * Processes any focus events, such as
 607      * <code>FocusEvent.FOCUS_GAINED</code> or
 608      * <code>FocusEvent.FOCUS_LOST</code>.
 609      *
 610      * @param e the <code>FocusEvent</code>
 611      * @see FocusEvent
 612      */
 613     protected void processFocusEvent(FocusEvent e) {
 614         super.processFocusEvent(e);
 615 
 616         // ignore temporary focus event
 617         if (e.isTemporary()) {
 618             return;
 619         }
 620 
 621         if (isEdited() && e.getID() == FocusEvent.FOCUS_LOST) {
 622             InputContext ic = getInputContext();
 623             if (focusLostHandler == null) {
 624                 focusLostHandler = new FocusLostHandler();
 625             }
 626 
 627             // if there is a composed text, process it first
 628             if ((ic != null) && composedTextExists) {
 629                 ic.endComposition();
 630                 EventQueue.invokeLater(focusLostHandler);
 631             } else {
 632                 focusLostHandler.run();
 633             }
 634         }
 635         else if (!isEdited()) {
 636             // reformat
 637             setValue(getValue(), true, true);
 638         }
 639     }
 640 
 641     /**
 642      * FOCUS_LOST behavior implementation
 643      */
 644     private class FocusLostHandler implements Runnable, Serializable {
 645         public void run() {
 646             int fb = JFormattedTextField.this.getFocusLostBehavior();
 647             if (fb == JFormattedTextField.COMMIT ||
 648                 fb == JFormattedTextField.COMMIT_OR_REVERT) {
 649                 try {
 650                     JFormattedTextField.this.commitEdit();
 651                     // Give it a chance to reformat.
 652                     JFormattedTextField.this.setValue(
 653                         JFormattedTextField.this.getValue(), true, true);
 654                 } catch (ParseException pe) {
 655                     if (fb == JFormattedTextField.COMMIT_OR_REVERT) {
 656                         JFormattedTextField.this.setValue(
 657                             JFormattedTextField.this.getValue(), true, true);
 658                     }
 659                 }
 660             }
 661             else if (fb == JFormattedTextField.REVERT) {
 662                 JFormattedTextField.this.setValue(
 663                     JFormattedTextField.this.getValue(), true, true);
 664             }
 665         }
 666     }
 667 
 668     /**
 669      * Fetches the command list for the editor.  This is
 670      * the list of commands supported by the plugged-in UI
 671      * augmented by the collection of commands that the
 672      * editor itself supports.  These are useful for binding
 673      * to events, such as in a keymap.
 674      *
 675      * @return the command list
 676      */
 677     public Action[] getActions() {
 678         return TextAction.augmentList(super.getActions(), defaultActions);
 679     }
 680 
 681     /**
 682      * Gets the class ID for a UI.
 683      *
 684      * @return the string "FormattedTextFieldUI"
 685      * @see JComponent#getUIClassID
 686      */
 687     public String getUIClassID() {
 688         return uiClassID;
 689     }
 690 
 691     /**
 692      * Associates the editor with a text document.
 693      * The currently registered factory is used to build a view for
 694      * the document, which gets displayed by the editor after revalidation.
 695      * A PropertyChange event ("document") is propagated to each listener.
 696      *
 697      * @param doc  the document to display/edit
 698      * @see #getDocument
 699      * @beaninfo
 700      *  description: the text document model
 701      *        bound: true
 702      *       expert: true
 703      */
 704     public void setDocument(Document doc) {
 705         if (documentListener != null && getDocument() != null) {
 706             getDocument().removeDocumentListener(documentListener);
 707         }
 708         super.setDocument(doc);
 709         if (documentListener == null) {
 710             documentListener = new DocumentHandler();
 711         }
 712         doc.addDocumentListener(documentListener);
 713     }
 714 
 715     /*
 716      * See readObject and writeObject in JComponent for more
 717      * information about serialization in Swing.
 718      *
 719      * @param s Stream to write to
 720      */
 721     private void writeObject(ObjectOutputStream s) throws IOException {
 722         s.defaultWriteObject();
 723         if (getUIClassID().equals(uiClassID)) {
 724             byte count = JComponent.getWriteObjCounter(this);
 725             JComponent.setWriteObjCounter(this, --count);
 726             if (count == 0 && ui != null) {
 727                 ui.installUI(this);
 728             }
 729         }
 730     }
 731 
 732     /**
 733      * Resets the Actions that come from the TextFormatter to
 734      * <code>actions</code>.
 735      */
 736     private void setFormatterActions(Action[] actions) {
 737         if (actions == null) {
 738             if (textFormatterActionMap != null) {
 739                 textFormatterActionMap.clear();
 740             }
 741         }
 742         else {
 743             if (textFormatterActionMap == null) {
 744                 ActionMap map = getActionMap();
 745 
 746                 textFormatterActionMap = new ActionMap();
 747                 while (map != null) {
 748                     ActionMap parent = map.getParent();
 749 
 750                     if (parent instanceof UIResource || parent == null) {
 751                         map.setParent(textFormatterActionMap);
 752                         textFormatterActionMap.setParent(parent);
 753                         break;
 754                     }
 755                     map = parent;
 756                 }
 757             }
 758             for (int counter = actions.length - 1; counter >= 0;
 759                  counter--) {
 760                 Object key = actions[counter].getValue(Action.NAME);
 761 
 762                 if (key != null) {
 763                     textFormatterActionMap.put(key, actions[counter]);
 764                 }
 765             }
 766         }
 767     }
 768 
 769     /**
 770      * Does the setting of the value. If <code>createFormat</code> is true,
 771      * this will also obtain a new <code>AbstractFormatter</code> from the
 772      * current factory. The property change event will be fired if
 773      * <code>firePC</code> is true.
 774      */
 775     private void setValue(Object value, boolean createFormat, boolean firePC) {
 776         Object oldValue = this.value;
 777 
 778         this.value = value;
 779 
 780         if (createFormat) {
 781             AbstractFormatterFactory factory = getFormatterFactory();
 782             AbstractFormatter atf;
 783 
 784             if (factory != null) {
 785                 atf = factory.getFormatter(this);
 786             }
 787             else {
 788                 atf = null;
 789             }
 790             setFormatter(atf);
 791         }
 792         else {
 793             // Assumed to be valid
 794             setEditValid(true);
 795         }
 796 
 797         setEdited(false);
 798 
 799         if (firePC) {
 800             firePropertyChange("value", oldValue, value);
 801         }
 802     }
 803 
 804     /**
 805      * Sets the edited state of the receiver.
 806      */
 807     private void setEdited(boolean edited) {
 808         this.edited = edited;
 809     }
 810 
 811     /**
 812      * Returns true if the receiver has been edited.
 813      */
 814     private boolean isEdited() {
 815         return edited;
 816     }
 817 
 818     /**
 819      * Returns an AbstractFormatterFactory suitable for the passed in
 820      * Object type.
 821      */
 822     private AbstractFormatterFactory getDefaultFormatterFactory(Object type) {
 823         if (type instanceof DateFormat) {
 824             return new DefaultFormatterFactory(new DateFormatter
 825                                                ((DateFormat)type));
 826         }
 827         if (type instanceof NumberFormat) {
 828             return new DefaultFormatterFactory(new NumberFormatter(
 829                                                (NumberFormat)type));
 830         }
 831         if (type instanceof Format) {
 832             return new DefaultFormatterFactory(new InternationalFormatter(
 833                                                (Format)type));
 834         }
 835         if (type instanceof Date) {
 836             return new DefaultFormatterFactory(new DateFormatter());
 837         }
 838         if (type instanceof Number) {
 839             AbstractFormatter displayFormatter = new NumberFormatter();
 840             ((NumberFormatter)displayFormatter).setValueClass(type.getClass());
 841             AbstractFormatter editFormatter = new NumberFormatter(
 842                                   new DecimalFormat("#.#"));
 843             ((NumberFormatter)editFormatter).setValueClass(type.getClass());
 844 
 845             return new DefaultFormatterFactory(displayFormatter,
 846                                                displayFormatter,editFormatter);
 847         }
 848         return new DefaultFormatterFactory(new DefaultFormatter());
 849     }
 850 
 851 
 852     /**
 853      * Instances of <code>AbstractFormatterFactory</code> are used by
 854      * <code>JFormattedTextField</code> to obtain instances of
 855      * <code>AbstractFormatter</code> which in turn are used to format values.
 856      * <code>AbstractFormatterFactory</code> can return different
 857      * <code>AbstractFormatter</code>s based on the state of the
 858      * <code>JFormattedTextField</code>, perhaps returning different
 859      * <code>AbstractFormatter</code>s when the
 860      * <code>JFormattedTextField</code> has focus vs when it
 861      * doesn't have focus.
 862      * @since 1.4
 863      */
 864     public static abstract class AbstractFormatterFactory {
 865         /**
 866          * Returns an <code>AbstractFormatter</code> that can handle formatting
 867          * of the passed in <code>JFormattedTextField</code>.
 868          *
 869          * @param tf JFormattedTextField requesting AbstractFormatter
 870          * @return AbstractFormatter to handle formatting duties, a null
 871          *         return value implies the JFormattedTextField should behave
 872          *         like a normal JTextField
 873          */
 874         public abstract AbstractFormatter getFormatter(JFormattedTextField tf);
 875     }
 876 
 877 
 878     /**
 879      * Instances of <code>AbstractFormatter</code> are used by
 880      * <code>JFormattedTextField</code> to handle the conversion both
 881      * from an Object to a String, and back from a String to an Object.
 882      * <code>AbstractFormatter</code>s can also enforce editing policies,
 883      * or navigation policies, or manipulate the
 884      * <code>JFormattedTextField</code> in any way it sees fit to
 885      * enforce the desired policy.
 886      * <p>
 887      * An <code>AbstractFormatter</code> can only be active in
 888      * one <code>JFormattedTextField</code> at a time.
 889      * <code>JFormattedTextField</code> invokes
 890      * <code>install</code> when it is ready to use it followed
 891      * by <code>uninstall</code> when done. Subclasses
 892      * that wish to install additional state should override
 893      * <code>install</code> and message super appropriately.
 894      * <p>
 895      * Subclasses must override the conversion methods
 896      * <code>stringToValue</code> and <code>valueToString</code>. Optionally
 897      * they can override <code>getActions</code>,
 898      * <code>getNavigationFilter</code> and <code>getDocumentFilter</code>
 899      * to restrict the <code>JFormattedTextField</code> in a particular
 900      * way.
 901      * <p>
 902      * Subclasses that allow the <code>JFormattedTextField</code> to be in
 903      * a temporarily invalid state should invoke <code>setEditValid</code>
 904      * at the appropriate times.
 905      * @since 1.4
 906      */
 907     public static abstract class AbstractFormatter implements Serializable {
 908         private JFormattedTextField ftf;
 909 
 910         /**
 911          * Installs the <code>AbstractFormatter</code> onto a particular
 912          * <code>JFormattedTextField</code>.
 913          * This will invoke <code>valueToString</code> to convert the
 914          * current value from the <code>JFormattedTextField</code> to
 915          * a String. This will then install the <code>Action</code>s from
 916          * <code>getActions</code>, the <code>DocumentFilter</code>
 917          * returned from <code>getDocumentFilter</code> and the
 918          * <code>NavigationFilter</code> returned from
 919          * <code>getNavigationFilter</code> onto the
 920          * <code>JFormattedTextField</code>.
 921          * <p>
 922          * Subclasses will typically only need to override this if they
 923          * wish to install additional listeners on the
 924          * <code>JFormattedTextField</code>.
 925          * <p>
 926          * If there is a <code>ParseException</code> in converting the
 927          * current value to a String, this will set the text to an empty
 928          * String, and mark the <code>JFormattedTextField</code> as being
 929          * in an invalid state.
 930          * <p>
 931          * While this is a public method, this is typically only useful
 932          * for subclassers of <code>JFormattedTextField</code>.
 933          * <code>JFormattedTextField</code> will invoke this method at
 934          * the appropriate times when the value changes, or its internal
 935          * state changes.  You will only need to invoke this yourself if
 936          * you are subclassing <code>JFormattedTextField</code> and
 937          * installing/uninstalling <code>AbstractFormatter</code> at a
 938          * different time than <code>JFormattedTextField</code> does.
 939          *
 940          * @param ftf JFormattedTextField to format for, may be null indicating
 941          *            uninstall from current JFormattedTextField.
 942          */
 943         public void install(JFormattedTextField ftf) {
 944             if (this.ftf != null) {
 945                 uninstall();
 946             }
 947             this.ftf = ftf;
 948             if (ftf != null) {
 949                 try {
 950                     ftf.setText(valueToString(ftf.getValue()));
 951                 } catch (ParseException pe) {
 952                     ftf.setText("");
 953                     setEditValid(false);
 954                 }
 955                 installDocumentFilter(getDocumentFilter());
 956                 ftf.setNavigationFilter(getNavigationFilter());
 957                 ftf.setFormatterActions(getActions());
 958             }
 959         }
 960 
 961         /**
 962          * Uninstalls any state the <code>AbstractFormatter</code> may have
 963          * installed on the <code>JFormattedTextField</code>. This resets the
 964          * <code>DocumentFilter</code>, <code>NavigationFilter</code>
 965          * and additional <code>Action</code>s installed on the
 966          * <code>JFormattedTextField</code>.
 967          */
 968         public void uninstall() {
 969             if (this.ftf != null) {
 970                 installDocumentFilter(null);
 971                 this.ftf.setNavigationFilter(null);
 972                 this.ftf.setFormatterActions(null);
 973             }
 974         }
 975 
 976         /**
 977          * Parses <code>text</code> returning an arbitrary Object. Some
 978          * formatters may return null.
 979          *
 980          * @throws ParseException if there is an error in the conversion
 981          * @param text String to convert
 982          * @return Object representation of text
 983          */
 984         public abstract Object stringToValue(String text) throws
 985                                      ParseException;
 986 
 987         /**
 988          * Returns the string value to display for <code>value</code>.
 989          *
 990          * @throws ParseException if there is an error in the conversion
 991          * @param value Value to convert
 992          * @return String representation of value
 993          */
 994         public abstract String valueToString(Object value) throws
 995                         ParseException;
 996 
 997         /**
 998          * Returns the current <code>JFormattedTextField</code> the
 999          * <code>AbstractFormatter</code> is installed on.
1000          *
1001          * @return JFormattedTextField formatting for.
1002          */
1003         protected JFormattedTextField getFormattedTextField() {
1004             return ftf;
1005         }
1006 
1007         /**
1008          * This should be invoked when the user types an invalid character.
1009          * This forwards the call to the current JFormattedTextField.
1010          */
1011         protected void invalidEdit() {
1012             JFormattedTextField ftf = getFormattedTextField();
1013 
1014             if (ftf != null) {
1015                 ftf.invalidEdit();
1016             }
1017         }
1018 
1019         /**
1020          * Invoke this to update the <code>editValid</code> property of the
1021          * <code>JFormattedTextField</code>. If you an enforce a policy
1022          * such that the <code>JFormattedTextField</code> is always in a
1023          * valid state, you will never need to invoke this.
1024          *
1025          * @param valid Valid state of the JFormattedTextField
1026          */
1027         protected void setEditValid(boolean valid) {
1028             JFormattedTextField ftf = getFormattedTextField();
1029 
1030             if (ftf != null) {
1031                 ftf.setEditValid(valid);
1032             }
1033         }
1034 
1035         /**
1036          * Subclass and override if you wish to provide a custom set of
1037          * <code>Action</code>s. <code>install</code> will install these
1038          * on the <code>JFormattedTextField</code>'s <code>ActionMap</code>.
1039          *
1040          * @return Array of Actions to install on JFormattedTextField
1041          */
1042         protected Action[] getActions() {
1043             return null;
1044         }
1045 
1046         /**
1047          * Subclass and override if you wish to provide a
1048          * <code>DocumentFilter</code> to restrict what can be input.
1049          * <code>install</code> will install the returned value onto
1050          * the <code>JFormattedTextField</code>.
1051          *
1052          * @return DocumentFilter to restrict edits
1053          */
1054         protected DocumentFilter getDocumentFilter() {
1055             return null;
1056         }
1057 
1058         /**
1059          * Subclass and override if you wish to provide a filter to restrict
1060          * where the user can navigate to.
1061          * <code>install</code> will install the returned value onto
1062          * the <code>JFormattedTextField</code>.
1063          *
1064          * @return NavigationFilter to restrict navigation
1065          */
1066         protected NavigationFilter getNavigationFilter() {
1067             return null;
1068         }
1069 
1070         /**
1071          * Clones the <code>AbstractFormatter</code>. The returned instance
1072          * is not associated with a <code>JFormattedTextField</code>.
1073          *
1074          * @return Copy of the AbstractFormatter
1075          */
1076         protected Object clone() throws CloneNotSupportedException {
1077             AbstractFormatter formatter = (AbstractFormatter)super.clone();
1078 
1079             formatter.ftf = null;
1080             return formatter;
1081         }
1082 
1083         /**
1084          * Installs the <code>DocumentFilter</code> <code>filter</code>
1085          * onto the current <code>JFormattedTextField</code>.
1086          *
1087          * @param filter DocumentFilter to install on the Document.
1088          */
1089         private void installDocumentFilter(DocumentFilter filter) {
1090             JFormattedTextField ftf = getFormattedTextField();
1091 
1092             if (ftf != null) {
1093                 Document doc = ftf.getDocument();
1094 
1095                 if (doc instanceof AbstractDocument) {
1096                     ((AbstractDocument)doc).setDocumentFilter(filter);
1097                 }
1098                 doc.putProperty(DocumentFilter.class, null);
1099             }
1100         }
1101     }
1102 
1103 
1104     /**
1105      * Used to commit the edit. This extends JTextField.NotifyAction
1106      * so that <code>isEnabled</code> is true while a JFormattedTextField
1107      * has focus, and extends <code>actionPerformed</code> to invoke
1108      * commitEdit.
1109      */
1110     static class CommitAction extends JTextField.NotifyAction {
1111         public void actionPerformed(ActionEvent e) {
1112             JTextComponent target = getFocusedComponent();
1113 
1114             if (target instanceof JFormattedTextField) {
1115                 // Attempt to commit the value
1116                 try {
1117                     ((JFormattedTextField)target).commitEdit();
1118                 } catch (ParseException pe) {
1119                     ((JFormattedTextField)target).invalidEdit();
1120                     // value not committed, don't notify ActionListeners
1121                     return;
1122                 }
1123             }
1124             // Super behavior.
1125             super.actionPerformed(e);
1126         }
1127 
1128         public boolean isEnabled() {
1129             JTextComponent target = getFocusedComponent();
1130             if (target instanceof JFormattedTextField) {
1131                 JFormattedTextField ftf = (JFormattedTextField)target;
1132                 if (!ftf.isEdited()) {
1133                     return false;
1134                 }
1135                 return true;
1136             }
1137             return super.isEnabled();
1138         }
1139     }
1140 
1141 
1142     /**
1143      * CancelAction will reset the value in the JFormattedTextField when
1144      * <code>actionPerformed</code> is invoked. It will only be
1145      * enabled if the focused component is an instance of
1146      * JFormattedTextField.
1147      */
1148     private static class CancelAction extends TextAction {
1149         public CancelAction() {
1150             super("reset-field-edit");
1151         }
1152 
1153         public void actionPerformed(ActionEvent e) {
1154             JTextComponent target = getFocusedComponent();
1155 
1156             if (target instanceof JFormattedTextField) {
1157                 JFormattedTextField ftf = (JFormattedTextField)target;
1158                 ftf.setValue(ftf.getValue());
1159             }
1160         }
1161 
1162         public boolean isEnabled() {
1163             JTextComponent target = getFocusedComponent();
1164             if (target instanceof JFormattedTextField) {
1165                 JFormattedTextField ftf = (JFormattedTextField)target;
1166                 if (!ftf.isEdited()) {
1167                     return false;
1168                 }
1169                 return true;
1170             }
1171             return super.isEnabled();
1172         }
1173     }
1174 
1175 
1176     /**
1177      * Sets the dirty state as the document changes.
1178      */
1179     private class DocumentHandler implements DocumentListener, Serializable {
1180         public void insertUpdate(DocumentEvent e) {
1181             setEdited(true);
1182         }
1183         public void removeUpdate(DocumentEvent e) {
1184             setEdited(true);
1185         }
1186         public void changedUpdate(DocumentEvent e) {}
1187     }
1188 }