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