001    /*
002     * $Id: JXDatePickerFormatterFactory.java,v 1.4 2005/10/26 14:29:57 kleopatra Exp $
003     * 
004     * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    package org.jdesktop.swingx.calendar;
022    
023    import java.text.ParseException;
024    import java.text.SimpleDateFormat;
025    
026    import javax.swing.JFormattedTextField;
027    import javax.swing.UIManager;
028    import javax.swing.JFormattedTextField.AbstractFormatter;
029    import javax.swing.JFormattedTextField.AbstractFormatterFactory;
030    
031    /**
032     * Default formatter factory for the JXDatePicker component.  This factory
033     * creates and returns a formatter that can handle a variety of date formats.
034     *
035     * @author Joshua Outwater
036     */
037    public class JXDatePickerFormatterFactory extends AbstractFormatterFactory {
038        /** Cached formatter */
039        protected AbstractFormatter formatter = null;
040    
041        /**
042         * {@inheritDoc}
043         */
044        @Override
045        public AbstractFormatter getFormatter(JFormattedTextField ftf) {
046            if (formatter == null) {
047                formatter = new JXDatePickerFormatter();
048            }
049            return formatter;
050        }
051    
052        /**
053         * Default formatter class for the JXDatePicker component.  This formatter
054         * supports the following three default formats:
055         * <ul>
056         * <li>EEE MM/dd/yyyy (Fri 04/09/2004)
057         * <li>MM/dd/yyyy     (04/09/2004)
058         * <li>dd/yy          (04/09)
059         * </ul>
060         * These formats are localizable and fields may be re-arranged, such as
061         * swapping the month and day fields.  The keys for localizing these fields
062         * are:
063         * <ul>
064         * <li>JXDatePicker.longFormat
065         * <li>JXDatePicker.mediumFormat
066         * <li>JXDatePicker.shortFormat
067         * </ul>
068         * It is important to order the formats in the order of most complex to
069         * least complex as it is possible for less complex formats to match more
070         * complex strings.
071         */
072        private class JXDatePickerFormatter extends
073                JFormattedTextField.AbstractFormatter {
074            private SimpleDateFormat _formats[] = null;
075            private int _formatIndex = 0;
076            
077            public JXDatePickerFormatter() {
078                _formats = new SimpleDateFormat[3];
079                String format = UIManager.getString("JXDatePicker.longFormat");
080                if (format == null) {
081                    format = "EEE MM/dd/yyyy";
082                }
083                _formats[0] = new SimpleDateFormat(format);
084    
085                format = UIManager.getString("JXDatePicker.mediumFormat");
086                if (format == null) {
087                    format = "MM/dd/yyyy";
088                }
089                _formats[1] = new SimpleDateFormat(format);
090    
091                format = UIManager.getString("JXDatePicker.shortFormat");
092                if (format == null) {
093                    format = "MM/dd";
094                }
095                _formats[2] = new SimpleDateFormat(format);
096            }
097    
098            /**
099             * {@inheritDoc}
100             */
101            @Override
102            public Object stringToValue(String text) throws ParseException {
103                Object result = null;
104                ParseException pex = null;
105    
106                if (text == null || text.trim().length() == 0) {
107                    return null;
108                }
109    
110                // If the current formatter did not work loop through the other
111                // formatters and see if any of them can parse the string passed
112                // in.
113                if (result == null) {
114                    for (int i = 0; i < _formats.length; i++) {
115                        try {
116                            result = _formats[i].parse(text);
117    
118                            // We got a successful formatter.  Update the current
119                            // formatter index.
120                            _formatIndex = i;
121                            pex = null;
122                            break;
123                        } catch (ParseException ex) {
124                            pex = ex;
125                        }
126                    }
127                }
128    
129                if (pex != null) {
130                    throw pex;
131                }
132    
133                return result;
134            }
135    
136            /**
137             * {@inheritDoc}
138             */
139            @Override
140            public String valueToString(Object value) {
141                if (value != null) {
142                    return _formats[_formatIndex].format(value);
143                }
144                return null;
145            }
146        }
147    }