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