Source Code Cross Referenced for JFormattedTextField.java in  » 6.0-JDK-Core » swing » javax » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025        package javax.swing;
0026
0027        import java.awt.*;
0028        import java.awt.event.*;
0029        import java.awt.im.InputContext;
0030        import java.io.*;
0031        import java.text.*;
0032        import java.util.*;
0033        import javax.swing.UIManager;
0034        import javax.swing.event.*;
0035        import javax.swing.plaf.UIResource;
0036        import javax.swing.text.*;
0037
0038        /**
0039         * <code>JFormattedTextField</code> extends <code>JTextField</code> adding
0040         * support for formatting arbitrary values, as well as retrieving a particular
0041         * object once the user has edited the text. The following illustrates
0042         * configuring a <code>JFormattedTextField</code> to edit dates:
0043         * <pre>
0044         *   JFormattedTextField ftf = new JFormattedTextField();
0045         *   ftf.setValue(new Date());
0046         * </pre>
0047         * <p>
0048         * Once a <code>JFormattedTextField</code> has been created, you can
0049         * listen for editing changes by way of adding
0050         * a <code>PropertyChangeListener</code> and listening for
0051         * <code>PropertyChangeEvent</code>s with the property name <code>value</code>.
0052         * <p>
0053         * <code>JFormattedTextField</code> allows
0054         * configuring what action should be taken when focus is lost. The possible
0055         * configurations are:
0056         * <table summary="Possible JFormattedTextField configurations and their descriptions">
0057         * <tr><th><p align="left">Value</p></th><th><p align="left">Description</p></th></tr>
0058         * <tr><td>JFormattedTextField.REVERT
0059         *            <td>Revert the display to match that of <code>getValue</code>,
0060         *                possibly losing the current edit.
0061         *        <tr><td>JFormattedTextField.COMMIT
0062         *            <td>Commits the current value. If the value being edited
0063         *                isn't considered a legal value by the
0064         *                <code>AbstractFormatter</code> that is, a
0065         *                <code>ParseException</code> is thrown, then the value
0066         *                will not change, and then edited value will persist.
0067         *        <tr><td>JFormattedTextField.COMMIT_OR_REVERT
0068         *            <td>Similar to <code>COMMIT</code>, but if the value isn't
0069         *                legal, behave like <code>REVERT</code>.
0070         *        <tr><td>JFormattedTextField.PERSIST
0071         *            <td>Do nothing, don't obtain a new
0072         *                <code>AbstractFormatter</code>, and don't update the value.
0073         * </table>
0074         * The default is <code>JFormattedTextField.COMMIT_OR_REVERT</code>, 
0075         * refer to {@link #setFocusLostBehavior} for more information on this.
0076         * <p>
0077         * <code>JFormattedTextField</code> allows the focus to leave, even if
0078         * the currently edited value is invalid. To lock the focus down while the
0079         * <code>JFormattedTextField</code> is an invalid edit state
0080         * you can attach an <code>InputVerifier</code>. The following code snippet
0081         * shows a potential implementation of such an <code>InputVerifier</code>:
0082         * <pre>
0083         * public class FormattedTextFieldVerifier extends InputVerifier {
0084         *     public boolean verify(JComponent input) {
0085         *         if (input instanceof JFormattedTextField) {
0086         *             JFormattedTextField ftf = (JFormattedTextField)input;
0087         *             AbstractFormatter formatter = ftf.getFormatter();
0088         *             if (formatter != null) {
0089         *                 String text = ftf.getText();
0090         *                 try {
0091         *                      formatter.stringToValue(text);
0092         *                      return true;
0093         *                  } catch (ParseException pe) {
0094         *                      return false;
0095         *                  }
0096         *              }
0097         *          }
0098         *          return true;
0099         *      }
0100         *      public boolean shouldYieldFocus(JComponent input) {
0101         *          return verify(input);
0102         *      }
0103         *  }
0104         * </pre>
0105         * <p>
0106         * Alternatively, you could invoke <code>commitEdit</code>, which would also
0107         * commit the value.
0108         * <p>
0109         * <code>JFormattedTextField</code> does not do the formatting it self,
0110         * rather formatting is done through an instance of
0111         * <code>JFormattedTextField.AbstractFormatter</code> which is obtained from
0112         * an instance of <code>JFormattedTextField.AbstractFormatterFactory</code>.
0113         * Instances of <code>JFormattedTextField.AbstractFormatter</code> are
0114         * notified when they become active by way of the
0115         * <code>install</code> method, at which point the
0116         * <code>JFormattedTextField.AbstractFormatter</code> can install whatever
0117         * it needs to, typically a <code>DocumentFilter</code>. Similarly when
0118         * <code>JFormattedTextField</code> no longer
0119         * needs the <code>AbstractFormatter</code>, it will invoke
0120         * <code>uninstall</code>.
0121         * <p>
0122         * <code>JFormattedTextField</code> typically
0123         * queries the <code>AbstractFormatterFactory</code> for an
0124         * <code>AbstractFormat</code> when it gains or loses focus. Although this
0125         * can change based on the focus lost policy. If the focus lost
0126         * policy is <code>JFormattedTextField.PERSIST</code>
0127         * and the <code>JFormattedTextField</code> has been edited, the
0128         * <code>AbstractFormatterFactory</code> will not be queried until the
0129         * value has been commited. Similarly if the focus lost policy is
0130         * <code>JFormattedTextField.COMMIT</code> and an exception
0131         * is thrown from <code>stringToValue</code>, the
0132         * <code>AbstractFormatterFactory</code> will not be querired when focus is
0133         * lost or gained.
0134         * <p>
0135         * <code>JFormattedTextField.AbstractFormatter</code>
0136         * is also responsible for determining when values are commited to
0137         * the <code>JFormattedTextField</code>. Some
0138         * <code>JFormattedTextField.AbstractFormatter</code>s will make new values
0139         * available on every edit, and others will never commit the value. You can
0140         * force the current value to be obtained
0141         * from the current <code>JFormattedTextField.AbstractFormatter</code>
0142         * by way of invoking <code>commitEdit</code>. <code>commitEdit</code> will
0143         * be invoked whenever return is pressed in the
0144         * <code>JFormattedTextField</code>.
0145         * <p>
0146         * If an <code>AbstractFormatterFactory</code> has not been explicitly
0147         * set, one will be set based on the <code>Class</code> of the value type after
0148         * <code>setValue</code> has been invoked (assuming value is non-null).
0149         * For example, in the following code an appropriate
0150         * <code>AbstractFormatterFactory</code> and <code>AbstractFormatter</code>
0151         * will be created to handle formatting of numbers:
0152         * <pre>
0153         *   JFormattedTextField tf = new JFormattedTextField();
0154         *   tf.setValue(new Number(100));
0155         * </pre>
0156         * <p>
0157         * <strong>Warning:</strong> As the <code>AbstractFormatter</code> will
0158         * typically install a <code>DocumentFilter</code> on the
0159         * <code>Document</code>, and a <code>NavigationFilter</code> on the
0160         * <code>JFormattedTextField</code> you should not install your own. If you do,
0161         * you are likely to see odd behavior in that the editing policy of the
0162         * <code>AbstractFormatter</code> will not be enforced.
0163         * <p>
0164         * <strong>Warning:</strong> Swing is not thread safe. For more
0165         * information see <a
0166         * href="package-summary.html#threading">Swing's Threading
0167         * Policy</a>.
0168         * <p>
0169         * <strong>Warning:</strong>
0170         * Serialized objects of this class will not be compatible with
0171         * future Swing releases. The current serialization support is
0172         * appropriate for short term storage or RMI between applications running
0173         * the same version of Swing.  As of 1.4, support for long term storage
0174         * of all JavaBeans<sup><font size="-2">TM</font></sup>
0175         * has been added to the <code>java.beans</code> package.
0176         * Please see {@link java.beans.XMLEncoder}.
0177         *
0178         * @version 1.31 05/05/07
0179         * @since 1.4
0180         */
0181        public class JFormattedTextField extends JTextField {
0182            private static final String uiClassID = "FormattedTextFieldUI";
0183            private static final Action[] defaultActions = {
0184                    new CommitAction(), new CancelAction() };
0185
0186            /**
0187             * Constant identifying that when focus is lost,
0188             * <code>commitEdit</code> should be invoked. If in commiting the
0189             * new value a <code>ParseException</code> is thrown, the invalid
0190             * value will remain.
0191             *
0192             * @see #setFocusLostBehavior
0193             */
0194            public static final int COMMIT = 0;
0195
0196            /**
0197             * Constant identifying that when focus is lost,
0198             * <code>commitEdit</code> should be invoked. If in commiting the new
0199             * value a <code>ParseException</code> is thrown, the value will be
0200             * reverted.
0201             *
0202             * @see #setFocusLostBehavior
0203             */
0204            public static final int COMMIT_OR_REVERT = 1;
0205
0206            /**
0207             * Constant identifying that when focus is lost, editing value should
0208             * be reverted to current value set on the
0209             * <code>JFormattedTextField</code>.
0210             *
0211             * @see #setFocusLostBehavior
0212             */
0213            public static final int REVERT = 2;
0214
0215            /**
0216             * Constant identifying that when focus is lost, the edited value
0217             * should be left.
0218             *
0219             * @see #setFocusLostBehavior
0220             */
0221            public static final int PERSIST = 3;
0222
0223            /**
0224             * Factory used to obtain an instance of AbstractFormatter.
0225             */
0226            private AbstractFormatterFactory factory;
0227            /**
0228             * Object responsible for formatting the current value.
0229             */
0230            private AbstractFormatter format;
0231            /**
0232             * Last valid value.
0233             */
0234            private Object value;
0235            /**
0236             * True while the value being edited is valid.
0237             */
0238            private boolean editValid;
0239            /**
0240             * Behavior when focus is lost.
0241             */
0242            private int focusLostBehavior;
0243            /**
0244             * Indicates the current value has been edited.
0245             */
0246            private boolean edited;
0247            /**
0248             * Used to set the dirty state.
0249             */
0250            private DocumentListener documentListener;
0251            /**
0252             * Masked used to set the AbstractFormatterFactory.
0253             */
0254            private Object mask;
0255            /**
0256             * ActionMap that the TextFormatter Actions are added to.
0257             */
0258            private ActionMap textFormatterActionMap;
0259            /**
0260             * Indicates the input method composed text is in the document
0261             */
0262            private boolean composedTextExists = false;
0263            /**
0264             * A handler for FOCUS_LOST event
0265             */
0266            private FocusLostHandler focusLostHandler;
0267
0268            /**
0269             * Creates a <code>JFormattedTextField</code> with no
0270             * <code>AbstractFormatterFactory</code>. Use <code>setMask</code> or
0271             * <code>setFormatterFactory</code> to configure the
0272             * <code>JFormattedTextField</code> to edit a particular type of
0273             * value.
0274             */
0275            public JFormattedTextField() {
0276                super ();
0277                enableEvents(AWTEvent.FOCUS_EVENT_MASK);
0278                setFocusLostBehavior(COMMIT_OR_REVERT);
0279            }
0280
0281            /**
0282             * Creates a JFormattedTextField with the specified value. This will
0283             * create an <code>AbstractFormatterFactory</code> based on the
0284             * type of <code>value</code>.
0285             *
0286             * @param value Initial value for the JFormattedTextField
0287             */
0288            public JFormattedTextField(Object value) {
0289                this ();
0290                setValue(value);
0291            }
0292
0293            /**
0294             * Creates a <code>JFormattedTextField</code>. <code>format</code> is
0295             * wrapped in an appropriate <code>AbstractFormatter</code> which is
0296             * then wrapped in an <code>AbstractFormatterFactory</code>.
0297             *
0298             * @param format Format used to look up an AbstractFormatter
0299             */
0300            public JFormattedTextField(java.text.Format format) {
0301                this ();
0302                setFormatterFactory(getDefaultFormatterFactory(format));
0303            }
0304
0305            /**
0306             * Creates a <code>JFormattedTextField</code> with the specified
0307             * <code>AbstractFormatter</code>. The <code>AbstractFormatter</code>
0308             * is placed in an <code>AbstractFormatterFactory</code>.
0309             *
0310             * @param formatter AbstractFormatter to use for formatting.
0311             */
0312            public JFormattedTextField(AbstractFormatter formatter) {
0313                this (new DefaultFormatterFactory(formatter));
0314            }
0315
0316            /**
0317             * Creates a <code>JFormattedTextField</code> with the specified
0318             * <code>AbstractFormatterFactory</code>.
0319             *
0320             * @param factory AbstractFormatterFactory used for formatting.
0321             */
0322            public JFormattedTextField(AbstractFormatterFactory factory) {
0323                this ();
0324                setFormatterFactory(factory);
0325            }
0326
0327            /**
0328             * Creates a <code>JFormattedTextField</code> with the specified
0329             * <code>AbstractFormatterFactory</code> and initial value.
0330             *
0331             * @param factory <code>AbstractFormatterFactory</code> used for
0332             *        formatting.
0333             * @param currentValue Initial value to use
0334             */
0335            public JFormattedTextField(AbstractFormatterFactory factory,
0336                    Object currentValue) {
0337                this (currentValue);
0338                setFormatterFactory(factory);
0339            }
0340
0341            /**
0342             * Sets the behavior when focus is lost. This will be one of
0343             * <code>JFormattedTextField.COMMIT_OR_REVERT</code>,
0344             * <code>JFormattedTextField.REVERT</code>,
0345             * <code>JFormattedTextField.COMMIT</code> or
0346             * <code>JFormattedTextField.PERSIST</code>
0347             * Note that some <code>AbstractFormatter</code>s may push changes as
0348             * they occur, so that the value of this will have no effect.
0349             * <p>
0350             * This will throw an <code>IllegalArgumentException</code> if the object
0351             * passed in is not one of the afore mentioned values.
0352             * <p>
0353             * The default value of this property is
0354             * <code>JFormattedTextField.COMMIT_OR_REVERT</code>.
0355             *
0356             * @param behavior Identifies behavior when focus is lost
0357             * @throws IllegalArgumentException if behavior is not one of the known
0358             *         values
0359             * @beaninfo
0360             *  enum: COMMIT         JFormattedTextField.COMMIT
0361             *        COMMIT_OR_REVERT JFormattedTextField.COMMIT_OR_REVERT
0362             *        REVERT         JFormattedTextField.REVERT
0363             *        PERSIST        JFormattedTextField.PERSIST
0364             *  description: Behavior when component loses focus
0365             */
0366            public void setFocusLostBehavior(int behavior) {
0367                if (behavior != COMMIT && behavior != COMMIT_OR_REVERT
0368                        && behavior != PERSIST && behavior != REVERT) {
0369                    throw new IllegalArgumentException(
0370                            "setFocusLostBehavior must be one of: JFormattedTextField.COMMIT, JFormattedTextField.COMMIT_OR_REVERT, JFormattedTextField.PERSIST or JFormattedTextField.REVERT");
0371                }
0372                focusLostBehavior = behavior;
0373            }
0374
0375            /**
0376             * Returns the behavior when focus is lost. This will be one of
0377             * <code>COMMIT_OR_REVERT</code>,
0378             * <code>COMMIT</code>,
0379             * <code>REVERT</code> or
0380             * <code>PERSIST</code>
0381             * Note that some <code>AbstractFormatter</code>s may push changes as
0382             * they occur, so that the value of this will have no effect.
0383             *
0384             * @return returns behavior when focus is lost
0385             */
0386            public int getFocusLostBehavior() {
0387                return focusLostBehavior;
0388            }
0389
0390            /**
0391             * Sets the <code>AbstractFormatterFactory</code>.
0392             * <code>AbstractFormatterFactory</code> is
0393             * able to return an instance of <code>AbstractFormatter</code> that is
0394             * used to format a value for display, as well an enforcing an editing
0395             * policy.
0396             * <p>
0397             * If you have not explicitly set an <code>AbstractFormatterFactory</code>
0398             * by way of this method (or a constructor) an
0399             * <code>AbstractFormatterFactory</code> and consequently an
0400             * <code>AbstractFormatter</code> will be used based on the
0401             * <code>Class</code> of the value. <code>NumberFormatter</code> will
0402             * be used for <code>Number</code>s, <code>DateFormatter</code> will
0403             * be used for <code>Dates</code>, otherwise <code>DefaultFormatter</code>
0404             * will be used.
0405             * <p>
0406             * This is a JavaBeans bound property.
0407             *
0408             * @param tf <code>AbstractFormatterFactory</code> used to lookup
0409             *          instances of <code>AbstractFormatter</code>
0410             * @beaninfo
0411             *       bound: true
0412             *   attribute: visualUpdate true
0413             * description: AbstractFormatterFactory, responsible for returning an
0414             *              AbstractFormatter that can format the current value.
0415             */
0416            public void setFormatterFactory(AbstractFormatterFactory tf) {
0417                AbstractFormatterFactory oldFactory = factory;
0418
0419                factory = tf;
0420                firePropertyChange("formatterFactory", oldFactory, tf);
0421                setValue(getValue(), true, false);
0422            }
0423
0424            /**
0425             * Returns the current <code>AbstractFormatterFactory</code>.
0426             *
0427             * @see #setFormatterFactory
0428             * @return <code>AbstractFormatterFactory</code> used to determine
0429             *         <code>AbstractFormatter</code>s
0430             */
0431            public AbstractFormatterFactory getFormatterFactory() {
0432                return factory;
0433            }
0434
0435            /**
0436             * Sets the current <code>AbstractFormatter</code>.
0437             * <p>
0438             * You should not normally invoke this, instead set the
0439             * <code>AbstractFormatterFactory</code> or set the value.
0440             * <code>JFormattedTextField</code> will
0441             * invoke this as the state of the <code>JFormattedTextField</code>
0442             * changes and requires the value to be reset.
0443             * <code>JFormattedTextField</code> passes in the
0444             * <code>AbstractFormatter</code> obtained from the
0445             * <code>AbstractFormatterFactory</code>.
0446             * <p>
0447             * This is a JavaBeans bound property.
0448             *
0449             * @see #setFormatterFactory
0450             * @param format AbstractFormatter to use for formatting
0451             * @beaninfo
0452             *       bound: true
0453             *   attribute: visualUpdate true
0454             * description: TextFormatter, responsible for formatting the current value
0455             */
0456            protected void setFormatter(AbstractFormatter format) {
0457                AbstractFormatter oldFormat = this .format;
0458
0459                if (oldFormat != null) {
0460                    oldFormat.uninstall();
0461                }
0462                setEditValid(true);
0463                this .format = format;
0464                if (format != null) {
0465                    format.install(this );
0466                }
0467                setEdited(false);
0468                firePropertyChange("textFormatter", oldFormat, format);
0469            }
0470
0471            /**
0472             * Returns the <code>AbstractFormatter</code> that is used to format and
0473             * parse the current value.
0474             *
0475             * @return AbstractFormatter used for formatting
0476             */
0477            public AbstractFormatter getFormatter() {
0478                return format;
0479            }
0480
0481            /**
0482             * Sets the value that will be formatted by an
0483             * <code>AbstractFormatter</code> obtained from the current
0484             * <code>AbstractFormatterFactory</code>. If no
0485             * <code>AbstractFormatterFactory</code> has been specified, this will
0486             * attempt to create one based on the type of <code>value</code>.
0487             * <p>
0488             * The default value of this property is null.
0489             * <p>
0490             * This is a JavaBeans bound property.
0491             *
0492             * @param value Current value to display
0493             * @beaninfo
0494             *       bound: true
0495             *   attribute: visualUpdate true
0496             * description: The value to be formatted.
0497             */
0498            public void setValue(Object value) {
0499                if (value != null && getFormatterFactory() == null) {
0500                    setFormatterFactory(getDefaultFormatterFactory(value));
0501                }
0502                setValue(value, true, true);
0503            }
0504
0505            /**
0506             * Returns the last valid value. Based on the editing policy of
0507             * the <code>AbstractFormatter</code> this may not return the current
0508             * value. The currently edited value can be obtained by invoking
0509             * <code>commitEdit</code> followed by <code>getValue</code>.
0510             *
0511             * @return Last valid value
0512             */
0513            public Object getValue() {
0514                return value;
0515            }
0516
0517            /**
0518             * Forces the current value to be taken from the
0519             * <code>AbstractFormatter</code> and set as the current value.
0520             * This has no effect if there is no current
0521             * <code>AbstractFormatter</code> installed.
0522             *
0523             * @throws ParseException if the <code>AbstractFormatter</code> is not able
0524             *         to format the current value
0525             */
0526            public void commitEdit() throws ParseException {
0527                AbstractFormatter format = getFormatter();
0528
0529                if (format != null) {
0530                    setValue(format.stringToValue(getText()), false, true);
0531                }
0532            }
0533
0534            /**
0535             * Sets the validity of the edit on the receiver. You should not normally
0536             * invoke this. This will be invoked by the
0537             * <code>AbstractFormatter</code> as the user edits the value.
0538             * <p>
0539             * Not all formatters will allow the component to get into an invalid
0540             * state, and thus this may never be invoked.
0541             * <p>
0542             * Based on the look and feel this may visually change the state of
0543             * the receiver.
0544             *
0545             * @param isValid boolean indicating if the currently edited value is
0546             *        valid.
0547             * @beaninfo
0548             *       bound: true
0549             *   attribute: visualUpdate true
0550             * description: True indicates the edited value is valid
0551             */
0552            private void setEditValid(boolean isValid) {
0553                if (isValid != editValid) {
0554                    editValid = isValid;
0555                    firePropertyChange("editValid", Boolean.valueOf(!isValid),
0556                            Boolean.valueOf(isValid));
0557                }
0558            }
0559
0560            /**
0561             * Returns true if the current value being edited is valid. The value of
0562             * this is managed by the current <code>AbstractFormatter</code>, as such
0563             * there is no public setter for it.
0564             *
0565             * @return true if the current value being edited is valid.
0566             */
0567            public boolean isEditValid() {
0568                return editValid;
0569            }
0570
0571            /**
0572             * Invoked when the user inputs an invalid value. This gives the
0573             * component a chance to provide feedback. The default
0574             * implementation beeps.
0575             */
0576            protected void invalidEdit() {
0577                UIManager.getLookAndFeel().provideErrorFeedback(
0578                        JFormattedTextField.this );
0579            }
0580
0581            /**
0582             * Processes any input method events, such as
0583             * <code>InputMethodEvent.INPUT_METHOD_TEXT_CHANGED</code> or
0584             * <code>InputMethodEvent.CARET_POSITION_CHANGED</code>.
0585             *
0586             * @param e the <code>InputMethodEvent</code>
0587             * @see InputMethodEvent
0588             */
0589            protected void processInputMethodEvent(InputMethodEvent e) {
0590                AttributedCharacterIterator text = e.getText();
0591                int commitCount = e.getCommittedCharacterCount();
0592
0593                // Keep track of the composed text
0594                if (text != null) {
0595                    int begin = text.getBeginIndex();
0596                    int end = text.getEndIndex();
0597                    composedTextExists = ((end - begin) > commitCount);
0598                } else {
0599                    composedTextExists = false;
0600                }
0601
0602                super .processInputMethodEvent(e);
0603            }
0604
0605            /**
0606             * Processes any focus events, such as
0607             * <code>FocusEvent.FOCUS_GAINED</code> or
0608             * <code>FocusEvent.FOCUS_LOST</code>.
0609             *
0610             * @param e the <code>FocusEvent</code>
0611             * @see FocusEvent
0612             */
0613            protected void processFocusEvent(FocusEvent e) {
0614                super .processFocusEvent(e);
0615
0616                // ignore temporary focus event
0617                if (e.isTemporary()) {
0618                    return;
0619                }
0620
0621                if (isEdited() && e.getID() == FocusEvent.FOCUS_LOST) {
0622                    InputContext ic = getInputContext();
0623                    if (focusLostHandler == null) {
0624                        focusLostHandler = new FocusLostHandler();
0625                    }
0626
0627                    // if there is a composed text, process it first
0628                    if ((ic != null) && composedTextExists) {
0629                        ic.endComposition();
0630                        EventQueue.invokeLater(focusLostHandler);
0631                    } else {
0632                        focusLostHandler.run();
0633                    }
0634                } else if (!isEdited()) {
0635                    // reformat
0636                    setValue(getValue(), true, true);
0637                }
0638            }
0639
0640            /**
0641             * FOCUS_LOST behavior implementation
0642             */
0643            private class FocusLostHandler implements  Runnable, Serializable {
0644                public void run() {
0645                    int fb = JFormattedTextField.this .getFocusLostBehavior();
0646                    if (fb == JFormattedTextField.COMMIT
0647                            || fb == JFormattedTextField.COMMIT_OR_REVERT) {
0648                        try {
0649                            JFormattedTextField.this .commitEdit();
0650                            // Give it a chance to reformat.
0651                            JFormattedTextField.this .setValue(
0652                                    JFormattedTextField.this .getValue(), true,
0653                                    true);
0654                        } catch (ParseException pe) {
0655                            if (fb == JFormattedTextField.this .COMMIT_OR_REVERT) {
0656                                JFormattedTextField.this .setValue(
0657                                        JFormattedTextField.this .getValue(),
0658                                        true, true);
0659                            }
0660                        }
0661                    } else if (fb == JFormattedTextField.REVERT) {
0662                        JFormattedTextField.this 
0663                                .setValue(JFormattedTextField.this .getValue(),
0664                                        true, true);
0665                    }
0666                }
0667            }
0668
0669            /**
0670             * Fetches the command list for the editor.  This is
0671             * the list of commands supported by the plugged-in UI
0672             * augmented by the collection of commands that the
0673             * editor itself supports.  These are useful for binding
0674             * to events, such as in a keymap.
0675             *
0676             * @return the command list
0677             */
0678            public Action[] getActions() {
0679                return TextAction.augmentList(super .getActions(),
0680                        defaultActions);
0681            }
0682
0683            /**
0684             * Gets the class ID for a UI.
0685             *
0686             * @return the string "FormattedTextFieldUI"
0687             * @see JComponent#getUIClassID
0688             */
0689            public String getUIClassID() {
0690                return uiClassID;
0691            }
0692
0693            /**
0694             * Associates the editor with a text document.
0695             * The currently registered factory is used to build a view for
0696             * the document, which gets displayed by the editor after revalidation.
0697             * A PropertyChange event ("document") is propagated to each listener.
0698             *
0699             * @param doc  the document to display/edit
0700             * @see #getDocument
0701             * @beaninfo
0702             *  description: the text document model
0703             *        bound: true
0704             *       expert: true
0705             */
0706            public void setDocument(Document doc) {
0707                if (documentListener != null && getDocument() != null) {
0708                    getDocument().removeDocumentListener(documentListener);
0709                }
0710                super .setDocument(doc);
0711                if (documentListener == null) {
0712                    documentListener = new DocumentHandler();
0713                }
0714                doc.addDocumentListener(documentListener);
0715            }
0716
0717            /*
0718             * See readObject and writeObject in JComponent for more 
0719             * information about serialization in Swing.
0720             *
0721             * @param s Stream to write to
0722             */
0723            private void writeObject(ObjectOutputStream s) throws IOException {
0724                s.defaultWriteObject();
0725                if (getUIClassID().equals(uiClassID)) {
0726                    byte count = JComponent.getWriteObjCounter(this );
0727                    JComponent.setWriteObjCounter(this , --count);
0728                    if (count == 0 && ui != null) {
0729                        ui.installUI(this );
0730                    }
0731                }
0732            }
0733
0734            /**
0735             * Resets the Actions that come from the TextFormatter to
0736             * <code>actions</code>.
0737             */
0738            private void setFormatterActions(Action[] actions) {
0739                if (actions == null) {
0740                    if (textFormatterActionMap != null) {
0741                        textFormatterActionMap.clear();
0742                    }
0743                } else {
0744                    if (textFormatterActionMap == null) {
0745                        ActionMap map = getActionMap();
0746
0747                        textFormatterActionMap = new ActionMap();
0748                        while (map != null) {
0749                            ActionMap parent = map.getParent();
0750
0751                            if (parent instanceof  UIResource || parent == null) {
0752                                map.setParent(textFormatterActionMap);
0753                                textFormatterActionMap.setParent(parent);
0754                                break;
0755                            }
0756                            map = parent;
0757                        }
0758                    }
0759                    for (int counter = actions.length - 1; counter >= 0; counter--) {
0760                        Object key = actions[counter].getValue(Action.NAME);
0761
0762                        if (key != null) {
0763                            textFormatterActionMap.put(key, actions[counter]);
0764                        }
0765                    }
0766                }
0767            }
0768
0769            /**
0770             * Does the setting of the value. If <code>createFormat</code> is true,
0771             * this will also obtain a new <code>AbstractFormatter</code> from the
0772             * current factory. The property change event will be fired if
0773             * <code>firePC</code> is true.
0774             */
0775            private void setValue(Object value, boolean createFormat,
0776                    boolean firePC) {
0777                Object oldValue = this .value;
0778
0779                this .value = value;
0780
0781                if (createFormat) {
0782                    AbstractFormatterFactory factory = getFormatterFactory();
0783                    AbstractFormatter atf;
0784
0785                    if (factory != null) {
0786                        atf = factory.getFormatter(this );
0787                    } else {
0788                        atf = null;
0789                    }
0790                    setFormatter(atf);
0791                } else {
0792                    // Assumed to be valid
0793                    setEditValid(true);
0794                }
0795
0796                setEdited(false);
0797
0798                if (firePC) {
0799                    firePropertyChange("value", oldValue, value);
0800                }
0801            }
0802
0803            /**
0804             * Sets the edited state of the receiver.
0805             */
0806            private void setEdited(boolean edited) {
0807                this .edited = edited;
0808            }
0809
0810            /**
0811             * Returns true if the receiver has been edited.
0812             */
0813            private boolean isEdited() {
0814                return edited;
0815            }
0816
0817            /**
0818             * Returns an AbstractFormatterFactory suitable for the passed in
0819             * Object type.
0820             */
0821            private AbstractFormatterFactory getDefaultFormatterFactory(
0822                    Object type) {
0823                if (type instanceof  DateFormat) {
0824                    return new DefaultFormatterFactory(new DateFormatter(
0825                            (DateFormat) type));
0826                }
0827                if (type instanceof  NumberFormat) {
0828                    return new DefaultFormatterFactory(new NumberFormatter(
0829                            (NumberFormat) type));
0830                }
0831                if (type instanceof  Format) {
0832                    return new DefaultFormatterFactory(
0833                            new InternationalFormatter((Format) type));
0834                }
0835                if (type instanceof  Date) {
0836                    return new DefaultFormatterFactory(new DateFormatter());
0837                }
0838                if (type instanceof  Number) {
0839                    AbstractFormatter displayFormatter = new NumberFormatter();
0840                    ((NumberFormatter) displayFormatter).setValueClass(type
0841                            .getClass());
0842                    AbstractFormatter editFormatter = new NumberFormatter(
0843                            new DecimalFormat("#.#"));
0844                    ((NumberFormatter) editFormatter).setValueClass(type
0845                            .getClass());
0846
0847                    return new DefaultFormatterFactory(displayFormatter,
0848                            displayFormatter, editFormatter);
0849                }
0850                return new DefaultFormatterFactory(new DefaultFormatter());
0851            }
0852
0853            /**
0854             * Instances of <code>AbstractFormatterFactory</code> are used by
0855             * <code>JFormattedTextField</code> to obtain instances of
0856             * <code>AbstractFormatter</code> which in turn are used to format values.
0857             * <code>AbstractFormatterFactory</code> can return different
0858             * <code>AbstractFormatter</code>s based on the state of the
0859             * <code>JFormattedTextField</code>, perhaps returning different
0860             * <code>AbstractFormatter</code>s when the
0861             * <code>JFormattedTextField</code> has focus vs when it
0862             * doesn't have focus.
0863             * @since 1.4
0864             */
0865            public static abstract class AbstractFormatterFactory {
0866                /**
0867                 * Returns an <code>AbstractFormatter</code> that can handle formatting
0868                 * of the passed in <code>JFormattedTextField</code>.
0869                 *
0870                 * @param tf JFormattedTextField requesting AbstractFormatter
0871                 * @return AbstractFormatter to handle formatting duties, a null
0872                 *         return value implies the JFormattedTextField should behave
0873                 *         like a normal JTextField
0874                 */
0875                public abstract AbstractFormatter getFormatter(
0876                        JFormattedTextField tf);
0877            }
0878
0879            /**
0880             * Instances of <code>AbstractFormatter</code> are used by
0881             * <code>JFormattedTextField</code> to handle the conversion both
0882             * from an Object to a String, and back from a String to an Object.
0883             * <code>AbstractFormatter</code>s can also enfore editing policies,
0884             * or navigation policies, or manipulate the
0885             * <code>JFormattedTextField</code> in any way it sees fit to
0886             * enforce the desired policy.
0887             * <p>
0888             * An <code>AbstractFormatter</code> can only be active in
0889             * one <code>JFormattedTextField</code> at a time.
0890             * <code>JFormattedTextField</code> invokes
0891             * <code>install</code> when it is ready to use it followed
0892             * by <code>uninstall</code> when done. Subclasses
0893             * that wish to install additional state should override
0894             * <code>install</code> and message super appropriately.
0895             * <p>
0896             * Subclasses must override the conversion methods
0897             * <code>stringToValue</code> and <code>valueToString</code>. Optionally
0898             * they can override <code>getActions</code>,
0899             * <code>getNavigationFilter</code> and <code>getDocumentFilter</code>
0900             * to restrict the <code>JFormattedTextField</code> in a particular
0901             * way. 
0902             * <p>
0903             * Subclasses that allow the <code>JFormattedTextField</code> to be in
0904             * a temporarily invalid state should invoke <code>setEditValid</code>
0905             * at the appropriate times.
0906             * @since 1.4
0907             */
0908            public static abstract class AbstractFormatter implements 
0909                    Serializable {
0910                private JFormattedTextField ftf;
0911
0912                /**
0913                 * Installs the <code>AbstractFormatter</code> onto a particular
0914                 * <code>JFormattedTextField</code>.
0915                 * This will invoke <code>valueToString</code> to convert the
0916                 * current value from the <code>JFormattedTextField</code> to
0917                 * a String. This will then install the <code>Action</code>s from
0918                 * <code>getActions</code>, the <code>DocumentFilter</code>
0919                 * returned from <code>getDocumentFilter</code> and the
0920                 * <code>NavigationFilter</code> returned from
0921                 * <code>getNavigationFilter</code> onto the
0922                 * <code>JFormattedTextField</code>.
0923                 * <p>
0924                 * Subclasses will typically only need to override this if they
0925                 * wish to install additional listeners on the
0926                 * <code>JFormattedTextField</code>.
0927                 * <p>
0928                 * If there is a <code>ParseException</code> in converting the
0929                 * current value to a String, this will set the text to an empty
0930                 * String, and mark the <code>JFormattedTextField</code> as being
0931                 * in an invalid state.
0932                 * <p>
0933                 * While this is a public method, this is typically only useful
0934                 * for subclassers of <code>JFormattedTextField</code>.
0935                 * <code>JFormattedTextField</code> will invoke this method at
0936                 * the appropriate times when the value changes, or its internal
0937                 * state changes.  You will only need to invoke this yourself if
0938                 * you are subclassing <code>JFormattedTextField</code> and
0939                 * installing/uninstalling <code>AbstractFormatter</code> at a
0940                 * different time than <code>JFormattedTextField</code> does.
0941                 *
0942                 * @param ftf JFormattedTextField to format for, may be null indicating
0943                 *            uninstall from current JFormattedTextField.
0944                 */
0945                public void install(JFormattedTextField ftf) {
0946                    if (this .ftf != null) {
0947                        uninstall();
0948                    }
0949                    this .ftf = ftf;
0950                    if (ftf != null) {
0951                        try {
0952                            ftf.setText(valueToString(ftf.getValue()));
0953                        } catch (ParseException pe) {
0954                            ftf.setText("");
0955                            setEditValid(false);
0956                        }
0957                        installDocumentFilter(getDocumentFilter());
0958                        ftf.setNavigationFilter(getNavigationFilter());
0959                        ftf.setFormatterActions(getActions());
0960                    }
0961                }
0962
0963                /**
0964                 * Uninstalls any state the <code>AbstractFormatter</code> may have
0965                 * installed on the <code>JFormattedTextField</code>. This resets the
0966                 * <code>DocumentFilter</code>, <code>NavigationFilter</code>
0967                 * and additional <code>Action</code>s installed on the
0968                 * <code>JFormattedTextField</code>.
0969                 */
0970                public void uninstall() {
0971                    if (this .ftf != null) {
0972                        installDocumentFilter(null);
0973                        this .ftf.setNavigationFilter(null);
0974                        this .ftf.setFormatterActions(null);
0975                    }
0976                }
0977
0978                /**
0979                 * Parses <code>text</code> returning an arbitrary Object. Some
0980                 * formatters may return null.
0981                 *
0982                 * @throws ParseException if there is an error in the conversion
0983                 * @param text String to convert
0984                 * @return Object representation of text
0985                 */
0986                public abstract Object stringToValue(String text)
0987                        throws ParseException;
0988
0989                /**
0990                 * Returns the string value to display for <code>value</code>.
0991                 *
0992                 * @throws ParseException if there is an error in the conversion
0993                 * @param value Value to convert
0994                 * @return String representation of value
0995                 */
0996                public abstract String valueToString(Object value)
0997                        throws ParseException;
0998
0999                /**
1000                 * Returns the current <code>JFormattedTextField</code> the
1001                 * <code>AbstractFormatter</code> is installed on.
1002                 *
1003                 * @return JFormattedTextField formatting for.
1004                 */
1005                protected JFormattedTextField getFormattedTextField() {
1006                    return ftf;
1007                }
1008
1009                /**
1010                 * This should be invoked when the user types an invalid character.
1011                 * This forwards the call to the current JFormattedTextField.
1012                 */
1013                protected void invalidEdit() {
1014                    JFormattedTextField ftf = getFormattedTextField();
1015
1016                    if (ftf != null) {
1017                        ftf.invalidEdit();
1018                    }
1019                }
1020
1021                /**
1022                 * Invoke this to update the <code>editValid</code> property of the
1023                 * <code>JFormattedTextField</code>. If you an enforce a policy
1024                 * such that the <code>JFormattedTextField</code> is always in a
1025                 * valid state, you will never need to invoke this.
1026                 *
1027                 * @param valid Valid state of the JFormattedTextField
1028                 */
1029                protected void setEditValid(boolean valid) {
1030                    JFormattedTextField ftf = getFormattedTextField();
1031
1032                    if (ftf != null) {
1033                        ftf.setEditValid(valid);
1034                    }
1035                }
1036
1037                /**
1038                 * Subclass and override if you wish to provide a custom set of
1039                 * <code>Action</code>s. <code>install</code> will install these
1040                 * on the <code>JFormattedTextField</code>'s <code>ActionMap</code>.
1041                 *
1042                 * @return Array of Actions to install on JFormattedTextField
1043                 */
1044                protected Action[] getActions() {
1045                    return null;
1046                }
1047
1048                /**
1049                 * Subclass and override if you wish to provide a 
1050                 * <code>DocumentFilter</code> to restrict what can be input.
1051                 * <code>install</code> will install the returned value onto
1052                 * the <code>JFormattedTextField</code>.
1053                 *
1054                 * @return DocumentFilter to restrict edits
1055                 */
1056                protected DocumentFilter getDocumentFilter() {
1057                    return null;
1058                }
1059
1060                /**
1061                 * Subclass and override if you wish to provide a filter to restrict
1062                 * where the user can navigate to.
1063                 * <code>install</code> will install the returned value onto
1064                 * the <code>JFormattedTextField</code>.
1065                 *
1066                 * @return NavigationFilter to restrict navigation
1067                 */
1068                protected NavigationFilter getNavigationFilter() {
1069                    return null;
1070                }
1071
1072                /**
1073                 * Clones the <code>AbstractFormatter</code>. The returned instance
1074                 * is not associated with a <code>JFormattedTextField</code>.
1075                 *
1076                 * @return Copy of the AbstractFormatter
1077                 */
1078                protected Object clone() throws CloneNotSupportedException {
1079                    AbstractFormatter formatter = (AbstractFormatter) super 
1080                            .clone();
1081
1082                    formatter.ftf = null;
1083                    return formatter;
1084                }
1085
1086                /**
1087                 * Installs the <code>DocumentFilter</code> <code>filter</code>
1088                 * onto the current <code>JFormattedTextField</code>.
1089                 *
1090                 * @param filter DocumentFilter to install on the Document.
1091                 */
1092                private void installDocumentFilter(DocumentFilter filter) {
1093                    JFormattedTextField ftf = getFormattedTextField();
1094
1095                    if (ftf != null) {
1096                        Document doc = ftf.getDocument();
1097
1098                        if (doc instanceof  AbstractDocument) {
1099                            ((AbstractDocument) doc).setDocumentFilter(filter);
1100                        }
1101                        doc.putProperty(DocumentFilter.class, null);
1102                    }
1103                }
1104            }
1105
1106            /**
1107             * Used to commit the edit. This extends JTextField.NotifyAction
1108             * so that <code>isEnabled</code> is true while a JFormattedTextField
1109             * has focus, and extends <code>actionPerformed</code> to invoke
1110             * commitEdit.
1111             */
1112            static class CommitAction extends JTextField.NotifyAction {
1113                public void actionPerformed(ActionEvent e) {
1114                    JTextComponent target = getFocusedComponent();
1115
1116                    if (target instanceof  JFormattedTextField) {
1117                        // Attempt to commit the value
1118                        try {
1119                            ((JFormattedTextField) target).commitEdit();
1120                        } catch (ParseException pe) {
1121                            ((JFormattedTextField) target).invalidEdit();
1122                            // value not commited, don't notify ActionListeners
1123                            return;
1124                        }
1125                    }
1126                    // Super behavior.
1127                    super .actionPerformed(e);
1128                }
1129
1130                public boolean isEnabled() {
1131                    JTextComponent target = getFocusedComponent();
1132                    if (target instanceof  JFormattedTextField) {
1133                        JFormattedTextField ftf = (JFormattedTextField) target;
1134                        if (!ftf.isEdited()) {
1135                            return false;
1136                        }
1137                        return true;
1138                    }
1139                    return super .isEnabled();
1140                }
1141            }
1142
1143            /**
1144             * CancelAction will reset the value in the JFormattedTextField when
1145             * <code>actionPerformed</code> is invoked. It will only be
1146             * enabled if the focused component is an instance of
1147             * JFormattedTextField.
1148             */
1149            private static class CancelAction extends TextAction {
1150                public CancelAction() {
1151                    super ("reset-field-edit");
1152                }
1153
1154                public void actionPerformed(ActionEvent e) {
1155                    JTextComponent target = getFocusedComponent();
1156
1157                    if (target instanceof  JFormattedTextField) {
1158                        JFormattedTextField ftf = (JFormattedTextField) target;
1159                        ftf.setValue(ftf.getValue());
1160                    }
1161                }
1162
1163                public boolean isEnabled() {
1164                    JTextComponent target = getFocusedComponent();
1165                    if (target instanceof  JFormattedTextField) {
1166                        JFormattedTextField ftf = (JFormattedTextField) target;
1167                        if (!ftf.isEdited()) {
1168                            return false;
1169                        }
1170                        return true;
1171                    }
1172                    return super .isEnabled();
1173                }
1174            }
1175
1176            /**
1177             * Sets the dirty state as the document changes.
1178             */
1179            private class DocumentHandler implements  DocumentListener,
1180                    Serializable {
1181                public void insertUpdate(DocumentEvent e) {
1182                    setEdited(true);
1183                }
1184
1185                public void removeUpdate(DocumentEvent e) {
1186                    setEdited(true);
1187                }
1188
1189                public void changedUpdate(DocumentEvent e) {
1190                }
1191            }
1192        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.