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