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