/*
 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.swing;

import java.awt.*;
import java.awt.event.*;

import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.plaf.SpinnerUI;

import java.util.*;
import java.beans.*;
import java.text.*;
import java.io.*;
import java.util.HashMap;
import sun.util.resources.LocaleData;

import javax.accessibility.*;


/**
 * A single line input field that lets the user select a
 * number or an object value from an ordered sequence. Spinners typically
 * provide a pair of tiny arrow buttons for stepping through the elements
 * of the sequence. The keyboard up/down arrow keys also cycle through the
 * elements. The user may also be allowed to type a (legal) value directly
 * into the spinner. Although combo boxes provide similar functionality,
 * spinners are sometimes preferred because they don't require a drop down list
 * that can obscure important data.
 * <p>
 * A <code>JSpinner</code>'s sequence value is defined by its
 * <code>SpinnerModel</code>.
 * The <code>model</code> can be specified as a constructor argument and
 * changed with the <code>model</code> property.  <code>SpinnerModel</code>
 * classes for some common types are provided: <code>SpinnerListModel</code>,
 * <code>SpinnerNumberModel</code>, and <code>SpinnerDateModel</code>.
 * <p>
 * A <code>JSpinner</code> has a single child component that's
 * responsible for displaying
 * and potentially changing the current element or <i>value</i> of
 * the model, which is called the <code>editor</code>.  The editor is created
 * by the <code>JSpinner</code>'s constructor and can be changed with the
 * <code>editor</code> property.  The <code>JSpinner</code>'s editor stays
 * in sync with the model by listening for <code>ChangeEvent</code>s. If the
 * user has changed the value displayed by the <code>editor</code> it is
 * possible for the <code>model</code>'s value to differ from that of
 * the <code>editor</code>. To make sure the <code>model</code> has the same
 * value as the editor use the <code>commitEdit</code> method, eg:
 * <pre>
 *   try {
 *       spinner.commitEdit();
 *   }
 *   catch (ParseException pe) {{
 *       // Edited value is invalid, spinner.getValue() will return
 *       // the last valid value, you could revert the spinner to show that:
 *       JComponent editor = spinner.getEditor()
 *       if (editor instanceof DefaultEditor) {
 *           ((DefaultEditor)editor).getTextField().setValue(spinner.getValue();
 *       }
 *       // reset the value to some known value:
 *       spinner.setValue(fallbackValue);
 *       // or treat the last valid value as the current, in which
 *       // case you don't need to do anything.
 *   }
 *   return spinner.getValue();
 * </pre>
 * <p>
 * For information and examples of using spinner see
 * <a href="http://java.sun.com/doc/books/tutorial/uiswing/components/spinner.html">How to Use Spinners</a>,
 * a section in <em>The Java Tutorial.</em>
 * <p>
 * <strong>Warning:</strong> Swing is not thread safe. For more
 * information see <a
 * href="package-summary.html#threading">Swing's Threading
 * Policy</a>.
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases. The current serialization support is
 * appropriate for short term storage or RMI between applications running
 * the same version of Swing.  As of 1.4, support for long term storage
 * of all JavaBeans<sup><font size="-2">TM</font></sup>
 * has been added to the <code>java.beans</code> package.
 * Please see {@link java.beans.XMLEncoder}.
 *
 * @beaninfo
 *   attribute: isContainer false
 * description: A single line input field that lets the user select a
 *     number or an object value from an ordered set.
 *
 * @see SpinnerModel
 * @see AbstractSpinnerModel
 * @see SpinnerListModel
 * @see SpinnerNumberModel
 * @see SpinnerDateModel
 * @see JFormattedTextField
 *
 * @author Hans Muller
 * @author Lynn Monsanto (accessibility)
 * @since 1.4
 */
public class JSpinner extends JComponent implements Accessible
{
    /**
     * @see #getUIClassID
     * @see #readObject
     */
    private static final String uiClassID = "SpinnerUI";

    private static final Action DISABLED_ACTION = new DisabledAction();

    private SpinnerModel model;
    private JComponent editor;
    private ChangeListener modelListener;
    private transient ChangeEvent changeEvent;
    private boolean editorExplicitlySet = false;


    /**
     * Constructs a spinner for the given model. The spinner has
     * a set of previous/next buttons, and an editor appropriate
     * for the model.
     *
     * @throws NullPointerException if the model is {@code null}
     */
    public JSpinner(SpinnerModel model) {
        if (model == null) {
            throw new NullPointerException("model cannot be null");
        }
        this.model = model;
        this.editor = createEditor(model);
        setUIProperty("opaque",true);
        updateUI();
    }


    /**
     * Constructs a spinner with an <code>Integer SpinnerNumberModel</code>
     * with initial value 0 and no minimum or maximum limits.
     */
    public JSpinner() {
        this(new SpinnerNumberModel());
    }


    /**
     * Returns the look and feel (L&F) object that renders this component.
     *
     * @return the <code>SpinnerUI</code> object that renders this component
     */
    public SpinnerUI getUI() {
        return (SpinnerUI)ui;
    }


    /**
     * Sets the look and feel (L&F) object that renders this component.
     *
     * @param ui  the <code>SpinnerUI</code> L&F object
     * @see UIDefaults#getUI
     */
    public void setUI(SpinnerUI ui) {
        super.setUI(ui);
    }


    /**
     * Returns the suffix used to construct the name of the look and feel
     * (L&F) class used to render this component.
     *
     * @return the string "SpinnerUI"
     * @see JComponent#getUIClassID
     * @see UIDefaults#getUI
     */
    public String getUIClassID() {
        return uiClassID;
    }



    /**
     * Resets the UI property with the value from the current look and feel.
     *
     * @see UIManager#getUI
     */
    public void updateUI() {
        setUI((SpinnerUI)UIManager.getUI(this));
        invalidate();
    }


    /**
     * This method is called by the constructors to create the
     * <code>JComponent</code>
     * that displays the current value of the sequence.  The editor may
     * also allow the user to enter an element of the sequence directly.
     * An editor must listen for <code>ChangeEvents</code> on the
     * <code>model</code> and keep the value it displays
     * in sync with the value of the model.
     * <p>
     * Subclasses may override this method to add support for new
     * <code>SpinnerModel</code> classes.  Alternatively one can just
     * replace the editor created here with the <code>setEditor</code>
     * method.  The default mapping from model type to editor is:
     * <ul>
     * <li> <code>SpinnerNumberModel =&gt; JSpinner.NumberEditor</code>
     * <li> <code>SpinnerDateModel =&gt; JSpinner.DateEditor</code>
     * <li> <code>SpinnerListModel =&gt; JSpinner.ListEditor</code>
     * <li> <i>all others</i> =&gt; <code>JSpinner.DefaultEditor</code>
     * </ul>
     *
     * @return a component that displays the current value of the sequence
     * @param model the value of getModel
     * @see #getModel
     * @see #setEditor
     */
    protected JComponent createEditor(SpinnerModel model) {
        if (model instanceof SpinnerDateModel) {
            return new DateEditor(this);
        }
        else if (model instanceof SpinnerListModel) {
            return new ListEditor(this);
        }
        else if (model instanceof SpinnerNumberModel) {
            return new NumberEditor(this);
        }
        else {
            return new DefaultEditor(this);
        }
    }


    /**
     * Changes the model that represents the value of this spinner.
     * If the editor property has not been explicitly set,
     * the editor property is (implicitly) set after the <code>"model"</code>
     * <code>PropertyChangeEvent</code> has been fired.  The editor
     * property is set to the value returned by <code>createEditor</code>,
     * as in:
     * <pre>
     * setEditor(createEditor(model));
     * </pre>
     *
     * @param model the new <code>SpinnerModel</code>
     * @see #getModel
     * @see #getEditor
     * @see #setEditor
     * @throws IllegalArgumentException if model is <code>null</code>
     *
     * @beaninfo
     *        bound: true
     *    attribute: visualUpdate true
     *  description: Model that represents the value of this spinner.
     */
    public void setModel(SpinnerModel model) {
        if (model == null) {
            throw new IllegalArgumentException("null model");
        }
        if (!model.equals(this.model)) {
            SpinnerModel oldModel = this.model;
            this.model = model;
            if (modelListener != null) {
                oldModel.removeChangeListener(modelListener);
                this.model.addChangeListener(modelListener);
            }
            firePropertyChange("model", oldModel, model);
            if (!editorExplicitlySet) {
                setEditor(createEditor(model)); // sets editorExplicitlySet true
                editorExplicitlySet = false;
            }
            repaint();
            revalidate();
        }
    }


    /**
     * Returns the <code>SpinnerModel</code> that defines
     * this spinners sequence of values.
     *
     * @return the value of the model property
     * @see #setModel
     */
    public SpinnerModel getModel() {
        return model;
    }


    /**
     * Returns the current value of the model, typically
     * this value is displayed by the <code>editor</code>. If the
     * user has changed the value displayed by the <code>editor</code> it is
     * possible for the <code>model</code>'s value to differ from that of
     * the <code>editor</code>, refer to the class level javadoc for examples
     * of how to deal with this.
     * <p>
     * This method simply delegates to the <code>model</code>.
     * It is equivalent to:
     * <pre>
     * getModel().getValue()
     * </pre>
     *
     * @see #setValue
     * @see SpinnerModel#getValue
     */
    public Object getValue() {
        return getModel().getValue();
    }


    /**
     * Changes current value of the model, typically
     * this value is displayed by the <code>editor</code>.
     * If the <code>SpinnerModel</code> implementation
     * doesn't support the specified value then an
     * <code>IllegalArgumentException</code> is thrown.
     * <p>
     * This method simply delegates to the <code>model</code>.
     * It is equivalent to:
     * <pre>
     * getModel().setValue(value)
     * </pre>
     *
     * @throws IllegalArgumentException if <code>value</code> isn't allowed
     * @see #getValue
     * @see SpinnerModel#setValue
     */
    public void setValue(Object value) {
        getModel().setValue(value);
    }


    /**
     * Returns the object in the sequence that comes after the object returned
     * by <code>getValue()</code>. If the end of the sequence has been reached
     * then return <code>null</code>.
     * Calling this method does not effect <code>value</code>.
     * <p>
     * This method simply delegates to the <code>model</code>.
     * It is equivalent to:
     * <pre>
     * getModel().getNextValue()
     * </pre>
     *
     * @return the next legal value or <code>null</code> if one doesn't exist
     * @see #getValue
     * @see #getPreviousValue
     * @see SpinnerModel#getNextValue
     */
    public Object getNextValue() {
        return getModel().getNextValue();
    }


    /**
     * We pass <code>Change</code> events along to the listeners with the
     * the slider (instead of the model itself) as the event source.
     */
    private class ModelListener implements ChangeListener, Serializable {
        public void stateChanged(ChangeEvent e) {
            fireStateChanged();
        }
    }


    /**
     * Adds a listener to the list that is notified each time a change
     * to the model occurs.  The source of <code>ChangeEvents</code>
     * delivered to <code>ChangeListeners</code> will be this
     * <code>JSpinner</code>.  Note also that replacing the model
     * will not affect listeners added directly to JSpinner.
     * Applications can add listeners to  the model directly.  In that
     * case is that the source of the event would be the
     * <code>SpinnerModel</code>.
     *
     * @param listener the <code>ChangeListener</code> to add
     * @see #removeChangeListener
     * @see #getModel
     */
    public void addChangeListener(ChangeListener listener) {
        if (modelListener == null) {
            modelListener = new ModelListener();
            getModel().addChangeListener(modelListener);
        }
        listenerList.add(ChangeListener.class, listener);
    }



    /**
     * Removes a <code>ChangeListener</code> from this spinner.
     *
     * @param listener the <code>ChangeListener</code> to remove
     * @see #fireStateChanged
     * @see #addChangeListener
     */
    public void removeChangeListener(ChangeListener listener) {
        listenerList.remove(ChangeListener.class, listener);
    }


    /**
     * Returns an array of all the <code>ChangeListener</code>s added
     * to this JSpinner with addChangeListener().
     *
     * @return all of the <code>ChangeListener</code>s added or an empty
     *         array if no listeners have been added
     * @since 1.4
     */
    public ChangeListener[] getChangeListeners() {
        return listenerList.getListeners(ChangeListener.class);
    }


    /**
     * Sends a <code>ChangeEvent</code>, whose source is this
     * <code>JSpinner</code>, to each <code>ChangeListener</code>.
     * When a <code>ChangeListener</code> has been added
     * to the spinner, this method method is called each time
     * a <code>ChangeEvent</code> is received from the model.
     *
     * @see #addChangeListener
     * @see #removeChangeListener
     * @see EventListenerList
     */
    protected void fireStateChanged() {
        Object[] listeners = listenerList.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == ChangeListener.class) {
                if (changeEvent == null) {
                    changeEvent = new ChangeEvent(this);
                }
                ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
            }
        }
    }


    /**
     * Returns the object in the sequence that comes
     * before the object returned by <code>getValue()</code>.
     * If the end of the sequence has been reached then
     * return <code>null</code>. Calling this method does
     * not effect <code>value</code>.
     * <p>
     * This method simply delegates to the <code>model</code>.
     * It is equivalent to:
     * <pre>
     * getModel().getPreviousValue()
     * </pre>
     *
     * @return the previous legal value or <code>null</code>
     *   if one doesn't exist
     * @see #getValue
     * @see #getNextValue
     * @see SpinnerModel#getPreviousValue
     */
    public Object getPreviousValue() {
        return getModel().getPreviousValue();
    }


    /**
     * Changes the <code>JComponent</code> that displays the current value
     * of the <code>SpinnerModel</code>.  It is the responsibility of this
     * method to <i>disconnect</i> the old editor from the model and to
     * connect the new editor.  This may mean removing the
     * old editors <code>ChangeListener</code> from the model or the
     * spinner itself and adding one for the new editor.
     *
     * @param editor the new editor
     * @see #getEditor
     * @see #createEditor
     * @see #getModel
     * @throws IllegalArgumentException if editor is <code>null</code>
     *
     * @beaninfo
     *        bound: true
     *    attribute: visualUpdate true
     *  description: JComponent that displays the current value of the model
     */
    public void setEditor(JComponent editor) {
        if (editor == null) {
            throw new IllegalArgumentException("null editor");
        }
        if (!editor.equals(this.editor)) {
            JComponent oldEditor = this.editor;
            this.editor = editor;
            if (oldEditor instanceof DefaultEditor) {
                ((DefaultEditor)oldEditor).dismiss(this);
            }
            editorExplicitlySet = true;
            firePropertyChange("editor", oldEditor, editor);
            revalidate();
            repaint();
        }
    }


    /**
     * Returns the component that displays and potentially
     * changes the model's value.
     *
     * @return the component that displays and potentially
     *    changes the model's value
     * @see #setEditor
     * @see #createEditor
     */
    public JComponent getEditor() {
        return editor;
    }


    /**
     * Commits the currently edited value to the <code>SpinnerModel</code>.
     * <p>
     * If the editor is an instance of <code>DefaultEditor</code>, the
     * call if forwarded to the editor, otherwise this does nothing.
     *
     * @throws ParseException if the currently edited value couldn't
     *         be commited.
     */
    public void commitEdit() throws ParseException {
        JComponent editor = getEditor();
        if (editor instanceof DefaultEditor) {
            ((DefaultEditor)editor).commitEdit();
        }
    }


    /*
     * See readObject and writeObject in JComponent for more
     * information about serialization in Swing.
     *
     * @param s Stream to write to
     */
    private void writeObject(ObjectOutputStream s) throws IOException {
        s.defaultWriteObject();
        if (getUIClassID().equals(uiClassID)) {
            byte count = JComponent.getWriteObjCounter(this);
            JComponent.setWriteObjCounter(this, --count);
            if (count == 0 && ui != null) {
                ui.installUI(this);
            }
        }
    }


    /**
     * A simple base class for more specialized editors
     * that displays a read-only view of the model's current
     * value with a <code>JFormattedTextField</code>.  Subclasses
     * can configure the <code>JFormattedTextField</code> to create
     * an editor that's appropriate for the type of model they
     * support and they may want to override
     * the <code>stateChanged</code> and <code>propertyChanged</code>
     * methods, which keep the model and the text field in sync.
     * <p>
     * This class defines a <code>dismiss</code> method that removes the
     * editors <code>ChangeListener</code> from the <code>JSpinner</code>
     * that it's part of.   The <code>setEditor</code> method knows about
     * <code>DefaultEditor.dismiss</code>, so if the developer
     * replaces an editor that's derived from <code>JSpinner.DefaultEditor</code>
     * its <code>ChangeListener</code> connection back to the
     * <code>JSpinner</code> will be removed.  However after that,
     * it's up to the developer to manage their editor listeners.
     * Similarly, if a subclass overrides <code>createEditor</code>,
     * it's up to the subclasser to deal with their editor
     * subsequently being replaced (with <code>setEditor</code>).
     * We expect that in most cases, and in editor installed
     * with <code>setEditor</code> or created by a <code>createEditor</code>
     * override, will not be replaced anyway.
     * <p>
     * This class is the <code>LayoutManager</code> for it's single
     * <code>JFormattedTextField</code> child.   By default the
     * child is just centered with the parents insets.
     * @since 1.4
     */
    public static class DefaultEditor extends JPanel
        implements ChangeListener, PropertyChangeListener, LayoutManager
    {
        /**
         * Constructs an editor component for the specified <code>JSpinner</code>.
         * This <code>DefaultEditor</code> is it's own layout manager and
         * it is added to the spinner's <code>ChangeListener</code> list.
         * The constructor creates a single <code>JFormattedTextField</code> child,
         * initializes it's value to be the spinner model's current value
         * and adds it to <code>this</code> <code>DefaultEditor</code>.
         *
         * @param spinner the spinner whose model <code>this</code> editor will monitor
         * @see #getTextField
         * @see JSpinner#addChangeListener
         */
        public DefaultEditor(JSpinner spinner) {
            super(null);

            JFormattedTextField ftf = new JFormattedTextField();
            ftf.setName("Spinner.formattedTextField");
            ftf.setValue(spinner.getValue());
            ftf.addPropertyChangeListener(this);
            ftf.setEditable(false);
            ftf.setInheritsPopupMenu(true);

            String toolTipText = spinner.getToolTipText();
            if (toolTipText != null) {
                ftf.setToolTipText(toolTipText);
            }

            add(ftf);

            setLayout(this);
            spinner.addChangeListener(this);

            // We want the spinner's increment/decrement actions to be
            // active vs those of the JFormattedTextField. As such we
            // put disabled actions in the JFormattedTextField's actionmap.
            // A binding to a disabled action is treated as a nonexistant
            // binding.
            ActionMap ftfMap = ftf.getActionMap();

            if (ftfMap != null) {
                ftfMap.put("increment", DISABLED_ACTION);
                ftfMap.put("decrement", DISABLED_ACTION);
            }
        }


        /**
         * Disconnect <code>this</code> editor from the specified
         * <code>JSpinner</code>.  By default, this method removes
         * itself from the spinners <code>ChangeListener</code> list.
         *
         * @param spinner the <code>JSpinner</code> to disconnect this
         *    editor from; the same spinner as was passed to the constructor.
         */
        public void dismiss(JSpinner spinner) {
            spinner.removeChangeListener(this);
        }


        /**
         * Returns the <code>JSpinner</code> ancestor of this editor or
         * <code>null</code> if none of the ancestors are a
         * <code>JSpinner</code>.
         * Typically the editor's parent is a <code>JSpinner</code> however
         * subclasses of <code>JSpinner</code> may override the
         * the <code>createEditor</code> method and insert one or more containers
         * between the <code>JSpinner</code> and it's editor.
         *
         * @return <code>JSpinner</code> ancestor; <code>null</code>
         *         if none of the ancestors are a <code>JSpinner</code>
         *
         * @see JSpinner#createEditor
         */
        public JSpinner getSpinner() {
            for (Component c = this; c != null; c = c.getParent()) {
                if (c instanceof JSpinner) {
                    return (JSpinner)c;
                }
            }
            return null;
        }


        /**
         * Returns the <code>JFormattedTextField</code> child of this
         * editor.  By default the text field is the first and only
         * child of editor.
         *
         * @return the <code>JFormattedTextField</code> that gives the user
         *     access to the <code>SpinnerDateModel's</code> value.
         * @see #getSpinner
         * @see #getModel
         */
        public JFormattedTextField getTextField() {
            return (JFormattedTextField)getComponent(0);
        }


        /**
         * This method is called when the spinner's model's state changes.
         * It sets the <code>value</code> of the text field to the current
         * value of the spinners model.
         *
         * @param e the <code>ChangeEvent</code> whose source is the
         * <code>JSpinner</code> whose model has changed.
         * @see #getTextField
         * @see JSpinner#getValue
         */
        public void stateChanged(ChangeEvent e) {
            JSpinner spinner = (JSpinner)(e.getSource());
            getTextField().setValue(spinner.getValue());
        }


        /**
         * Called by the <code>JFormattedTextField</code>
         * <code>PropertyChangeListener</code>.  When the <code>"value"</code>
         * property changes, which implies that the user has typed a new
         * number, we set the value of the spinners model.
         * <p>
         * This class ignores <code>PropertyChangeEvents</code> whose
         * source is not the <code>JFormattedTextField</code>, so subclasses
         * may safely make <code>this</code> <code>DefaultEditor</code> a
         * <code>PropertyChangeListener</code> on other objects.
         *
         * @param e the <code>PropertyChangeEvent</code> whose source is
         *    the <code>JFormattedTextField</code> created by this class.
         * @see #getTextField
         */
        public void propertyChange(PropertyChangeEvent e)
        {
            JSpinner spinner = getSpinner();

            if (spinner == null) {
                // Indicates we aren't installed anywhere.
                return;
            }

            Object source = e.getSource();
            String name = e.getPropertyName();
            if ((source instanceof JFormattedTextField) && "value".equals(name)) {
                Object lastValue = spinner.getValue();

                // Try to set the new value
                try {
                    spinner.setValue(getTextField().getValue());
                } catch (IllegalArgumentException iae) {
                    // SpinnerModel didn't like new value, reset
                    try {
                        ((JFormattedTextField)source).setValue(lastValue);
                    } catch (IllegalArgumentException iae2) {
                        // Still bogus, nothing else we can do, the
                        // SpinnerModel and JFormattedTextField are now out
                        // of sync.
                    }
                }
            }
        }


        /**
         * This <code>LayoutManager</code> method does nothing.  We're
         * only managing a single child and there's no support
         * for layout constraints.
         *
         * @param name ignored
         * @param child ignored
         */
        public void addLayoutComponent(String name, Component child) {
        }


        /**
         * This <code>LayoutManager</code> method does nothing.  There
         * isn't any per-child state.
         *
         * @param child ignored
         */
        public void removeLayoutComponent(Component child) {
        }


        /**
         * Returns the size of the parents insets.
         */
        private Dimension insetSize(Container parent) {
            Insets insets = parent.getInsets();
            int w = insets.left + insets.right;
            int h = insets.top + insets.bottom;
            return new Dimension(w, h);
        }


        /**
         * Returns the preferred size of first (and only) child plus the
         * size of the parents insets.
         *
         * @param parent the Container that's managing the layout
         * @return the preferred dimensions to lay out the subcomponents
         *          of the specified container.
         */
        public Dimension preferredLayoutSize(Container parent) {
            Dimension preferredSize = insetSize(parent);
            if (parent.getComponentCount() > 0) {
                Dimension childSize = getComponent(0).getPreferredSize();
                preferredSize.width += childSize.width;
                preferredSize.height += childSize.height;
            }
            return preferredSize;
        }


        /**
         * Returns the minimum size of first (and only) child plus the
         * size of the parents insets.
         *
         * @param parent the Container that's managing the layout
         * @return  the minimum dimensions needed to lay out the subcomponents
         *          of the specified container.
         */
        public Dimension minimumLayoutSize(Container parent) {
            Dimension minimumSize = insetSize(parent);
            if (parent.getComponentCount() > 0) {
                Dimension childSize = getComponent(0).getMinimumSize();
                minimumSize.width += childSize.width;
                minimumSize.height += childSize.height;
            }
            return minimumSize;
        }


        /**
         * Resize the one (and only) child to completely fill the area
         * within the parents insets.
         */
        public void layoutContainer(Container parent) {
            if (parent.getComponentCount() > 0) {
                Insets insets = parent.getInsets();
                int w = parent.getWidth() - (insets.left + insets.right);
                int h = parent.getHeight() - (insets.top + insets.bottom);
                getComponent(0).setBounds(insets.left, insets.top, w, h);
            }
        }

        /**
         * Pushes the currently edited value to the <code>SpinnerModel</code>.
         * <p>
         * The default implementation invokes <code>commitEdit</code> on the
         * <code>JFormattedTextField</code>.
         *
         * @throws ParseException if the edited value is not legal
         */
        public void commitEdit()  throws ParseException {
            // If the value in the JFormattedTextField is legal, this will have
            // the result of pushing the value to the SpinnerModel
            // by way of the <code>propertyChange</code> method.
            JFormattedTextField ftf = getTextField();

            ftf.commitEdit();
        }

        /**
         * Returns the baseline.
         *
         * @throws IllegalArgumentException {@inheritDoc}
         * @see javax.swing.JComponent#getBaseline(int,int)
         * @see javax.swing.JComponent#getBaselineResizeBehavior()
         * @since 1.6
         */
        public int getBaseline(int width, int height) {
            // check size.
            super.getBaseline(width, height);
            Insets insets = getInsets();
            width = width - insets.left - insets.right;
            height = height - insets.top - insets.bottom;
            int baseline = getComponent(0).getBaseline(width, height);
            if (baseline >= 0) {
                return baseline + insets.top;
            }
            return -1;
        }

        /**
         * Returns an enum indicating how the baseline of the component
         * changes as the size changes.
         *
         * @throws NullPointerException {@inheritDoc}
         * @see javax.swing.JComponent#getBaseline(int, int)
         * @since 1.6
         */
        public BaselineResizeBehavior getBaselineResizeBehavior() {
            return getComponent(0).getBaselineResizeBehavior();
        }
    }




    /**
     * This subclass of javax.swing.DateFormatter maps the minimum/maximum
     * properties to te start/end properties of a SpinnerDateModel.
     */
    private static class DateEditorFormatter extends DateFormatter {
        private final SpinnerDateModel model;

        DateEditorFormatter(SpinnerDateModel model, DateFormat format) {
            super(format);
            this.model = model;
        }

        public void setMinimum(Comparable min) {
            model.setStart(min);
        }

        public Comparable getMinimum() {
            return  model.getStart();
        }

        public void setMaximum(Comparable max) {
            model.setEnd(max);
        }

        public Comparable getMaximum() {
            return model.getEnd();
        }
    }


    /**
     * An editor for a <code>JSpinner</code> whose model is a
     * <code>SpinnerDateModel</code>.  The value of the editor is
     * displayed with a <code>JFormattedTextField</code> whose format
     * is defined by a <code>DateFormatter</code> instance whose
     * <code>minimum</code> and <code>maximum</code> properties
     * are mapped to the <code>SpinnerDateModel</code>.
     * @since 1.4
     */
    // PENDING(hmuller): more example javadoc
    public static class DateEditor extends DefaultEditor
    {
        // This is here until SimpleDateFormat gets a constructor that
        // takes a Locale: 4923525
        private static String getDefaultPattern(Locale loc) {
            ResourceBundle r = LocaleData.getDateFormatData(loc);
            String[] dateTimePatterns = r.getStringArray("DateTimePatterns");
            Object[] dateTimeArgs = {dateTimePatterns[DateFormat.SHORT],
                                     dateTimePatterns[DateFormat.SHORT + 4]};
            return MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
        }

        /**
         * Construct a <code>JSpinner</code> editor that supports displaying
         * and editing the value of a <code>SpinnerDateModel</code>
         * with a <code>JFormattedTextField</code>.  <code>This</code>
         * <code>DateEditor</code> becomes both a <code>ChangeListener</code>
         * on the spinners model and a <code>PropertyChangeListener</code>
         * on the new <code>JFormattedTextField</code>.
         *
         * @param spinner the spinner whose model <code>this</code> editor will monitor
         * @exception IllegalArgumentException if the spinners model is not
         *     an instance of <code>SpinnerDateModel</code>
         *
         * @see #getModel
         * @see #getFormat
         * @see SpinnerDateModel
         */
        public DateEditor(JSpinner spinner) {
            this(spinner, getDefaultPattern(spinner.getLocale()));
        }


        /**
         * Construct a <code>JSpinner</code> editor that supports displaying
         * and editing the value of a <code>SpinnerDateModel</code>
         * with a <code>JFormattedTextField</code>.  <code>This</code>
         * <code>DateEditor</code> becomes both a <code>ChangeListener</code>
         * on the spinner and a <code>PropertyChangeListener</code>
         * on the new <code>JFormattedTextField</code>.
         *
         * @param spinner the spinner whose model <code>this</code> editor will monitor
         * @param dateFormatPattern the initial pattern for the
         *     <code>SimpleDateFormat</code> object that's used to display
         *     and parse the value of the text field.
         * @exception IllegalArgumentException if the spinners model is not
         *     an instance of <code>SpinnerDateModel</code>
         *
         * @see #getModel
         * @see #getFormat
         * @see SpinnerDateModel
         * @see java.text.SimpleDateFormat
         */
        public DateEditor(JSpinner spinner, String dateFormatPattern) {
            this(spinner, new SimpleDateFormat(dateFormatPattern,
                                               spinner.getLocale()));
        }

        /**
         * Construct a <code>JSpinner</code> editor that supports displaying
         * and editing the value of a <code>SpinnerDateModel</code>
         * with a <code>JFormattedTextField</code>.  <code>This</code>
         * <code>DateEditor</code> becomes both a <code>ChangeListener</code>
         * on the spinner and a <code>PropertyChangeListener</code>
         * on the new <code>JFormattedTextField</code>.
         *
         * @param spinner the spinner whose model <code>this</code> editor
         *        will monitor
         * @param format <code>DateFormat</code> object that's used to display
         *     and parse the value of the text field.
         * @exception IllegalArgumentException if the spinners model is not
         *     an instance of <code>SpinnerDateModel</code>
         *
         * @see #getModel
         * @see #getFormat
         * @see SpinnerDateModel
         * @see java.text.SimpleDateFormat
         */
        private DateEditor(JSpinner spinner, DateFormat format) {
            super(spinner);
            if (!(spinner.getModel() instanceof SpinnerDateModel)) {
                throw new IllegalArgumentException(
                                 "model not a SpinnerDateModel");
            }

            SpinnerDateModel model = (SpinnerDateModel)spinner.getModel();
            DateFormatter formatter = new DateEditorFormatter(model, format);
            DefaultFormatterFactory factory = new DefaultFormatterFactory(
                                                  formatter);
            JFormattedTextField ftf = getTextField();
            ftf.setEditable(true);
            ftf.setFormatterFactory(factory);

            /* TBD - initializing the column width of the text field
             * is imprecise and doing it here is tricky because
             * the developer may configure the formatter later.
             */
            try {
                String maxString = formatter.valueToString(model.getStart());
                String minString = formatter.valueToString(model.getEnd());
                ftf.setColumns(Math.max(maxString.length(),
                                        minString.length()));
            }
            catch (ParseException e) {
                // PENDING: hmuller
            }
        }

        /**
         * Returns the <code>java.text.SimpleDateFormat</code> object the
         * <code>JFormattedTextField</code> uses to parse and format
         * numbers.
         *
         * @return the value of <code>getTextField().getFormatter().getFormat()</code>.
         * @see #getTextField
         * @see java.text.SimpleDateFormat
         */
        public SimpleDateFormat getFormat() {
            return (SimpleDateFormat)((DateFormatter)(getTextField().getFormatter())).getFormat();
        }


        /**
         * Return our spinner ancestor's <code>SpinnerDateModel</code>.
         *
         * @return <code>getSpinner().getModel()</code>
         * @see #getSpinner
         * @see #getTextField
         */
        public SpinnerDateModel getModel() {
            return (SpinnerDateModel)(getSpinner().getModel());
        }
    }


    /**
     * This subclass of javax.swing.NumberFormatter maps the minimum/maximum
     * properties to a SpinnerNumberModel and initializes the valueClass
     * of the NumberFormatter to match the type of the initial models value.
     */
    private static class NumberEditorFormatter extends NumberFormatter {
        private final SpinnerNumberModel model;

        NumberEditorFormatter(SpinnerNumberModel model, NumberFormat format) {
            super(format);
            this.model = model;
            setValueClass(model.getValue().getClass());
        }

        public void setMinimum(Comparable min) {
            model.setMinimum(min);
        }

        public Comparable getMinimum() {
            return  model.getMinimum();
        }

        public void setMaximum(Comparable max) {
            model.setMaximum(max);
        }

        public Comparable getMaximum() {
            return model.getMaximum();
        }
    }



    /**
     * An editor for a <code>JSpinner</code> whose model is a
     * <code>SpinnerNumberModel</code>.  The value of the editor is
     * displayed with a <code>JFormattedTextField</code> whose format
     * is defined by a <code>NumberFormatter</code> instance whose
     * <code>minimum</code> and <code>maximum</code> properties
     * are mapped to the <code>SpinnerNumberModel</code>.
     * @since 1.4
     */
    // PENDING(hmuller): more example javadoc
    public static class NumberEditor extends DefaultEditor
    {
        // This is here until DecimalFormat gets a constructor that
        // takes a Locale: 4923525
        private static String getDefaultPattern(Locale locale) {
            // Get the pattern for the default locale.
            ResourceBundle rb = LocaleData.getNumberFormatData(locale);
            String[] all = rb.getStringArray("NumberPatterns");
            return all[0];
        }

        /**
         * Construct a <code>JSpinner</code> editor that supports displaying
         * and editing the value of a <code>SpinnerNumberModel</code>
         * with a <code>JFormattedTextField</code>.  <code>This</code>
         * <code>NumberEditor</code> becomes both a <code>ChangeListener</code>
         * on the spinner and a <code>PropertyChangeListener</code>
         * on the new <code>JFormattedTextField</code>.
         *
         * @param spinner the spinner whose model <code>this</code> editor will monitor
         * @exception IllegalArgumentException if the spinners model is not
         *     an instance of <code>SpinnerNumberModel</code>
         *
         * @see #getModel
         * @see #getFormat
         * @see SpinnerNumberModel
         */
        public NumberEditor(JSpinner spinner) {
            this(spinner, getDefaultPattern(spinner.getLocale()));
        }

        /**
         * Construct a <code>JSpinner</code> editor that supports displaying
         * and editing the value of a <code>SpinnerNumberModel</code>
         * with a <code>JFormattedTextField</code>.  <code>This</code>
         * <code>NumberEditor</code> becomes both a <code>ChangeListener</code>
         * on the spinner and a <code>PropertyChangeListener</code>
         * on the new <code>JFormattedTextField</code>.
         *
         * @param spinner the spinner whose model <code>this</code> editor will monitor
         * @param decimalFormatPattern the initial pattern for the
         *     <code>DecimalFormat</code> object that's used to display
         *     and parse the value of the text field.
         * @exception IllegalArgumentException if the spinners model is not
         *     an instance of <code>SpinnerNumberModel</code> or if
         *     <code>decimalFormatPattern</code> is not a legal
         *     argument to <code>DecimalFormat</code>
         *
         * @see #getTextField
         * @see SpinnerNumberModel
         * @see java.text.DecimalFormat
         */
        public NumberEditor(JSpinner spinner, String decimalFormatPattern) {
            this(spinner, new DecimalFormat(decimalFormatPattern));
        }


        /**
         * Construct a <code>JSpinner</code> editor that supports displaying
         * and editing the value of a <code>SpinnerNumberModel</code>
         * with a <code>JFormattedTextField</code>.  <code>This</code>
         * <code>NumberEditor</code> becomes both a <code>ChangeListener</code>
         * on the spinner and a <code>PropertyChangeListener</code>
         * on the new <code>JFormattedTextField</code>.
         *
         * @param spinner the spinner whose model <code>this</code> editor will monitor
         * @param decimalFormatPattern the initial pattern for the
         *     <code>DecimalFormat</code> object that's used to display
         *     and parse the value of the text field.
         * @exception IllegalArgumentException if the spinners model is not
         *     an instance of <code>SpinnerNumberModel</code>
         *
         * @see #getTextField
         * @see SpinnerNumberModel
         * @see java.text.DecimalFormat
         */
        private NumberEditor(JSpinner spinner, DecimalFormat format) {
            super(spinner);
            if (!(spinner.getModel() instanceof SpinnerNumberModel)) {
                throw new IllegalArgumentException(
                          "model not a SpinnerNumberModel");
            }

            SpinnerNumberModel model = (SpinnerNumberModel)spinner.getModel();
            NumberFormatter formatter = new NumberEditorFormatter(model,
                                                                  format);
            DefaultFormatterFactory factory = new DefaultFormatterFactory(
                                                  formatter);
            JFormattedTextField ftf = getTextField();
            ftf.setEditable(true);
            ftf.setFormatterFactory(factory);
            ftf.setHorizontalAlignment(JTextField.RIGHT);

            /* TBD - initializing the column width of the text field
             * is imprecise and doing it here is tricky because
             * the developer may configure the formatter later.
             */
            try {
                String maxString = formatter.valueToString(model.getMinimum());
                String minString = formatter.valueToString(model.getMaximum());
                ftf.setColumns(Math.max(maxString.length(),
                                        minString.length()));
            }
            catch (ParseException e) {
                // TBD should throw a chained error here
            }

        }


        /**
         * Returns the <code>java.text.DecimalFormat</code> object the
         * <code>JFormattedTextField</code> uses to parse and format
         * numbers.
         *
         * @return the value of <code>getTextField().getFormatter().getFormat()</code>.
         * @see #getTextField
         * @see java.text.DecimalFormat
         */
        public DecimalFormat getFormat() {
            return (DecimalFormat)((NumberFormatter)(getTextField().getFormatter())).getFormat();
        }


        /**
         * Return our spinner ancestor's <code>SpinnerNumberModel</code>.
         *
         * @return <code>getSpinner().getModel()</code>
         * @see #getSpinner
         * @see #getTextField
         */
        public SpinnerNumberModel getModel() {
            return (SpinnerNumberModel)(getSpinner().getModel());
        }
    }


    /**
     * An editor for a <code>JSpinner</code> whose model is a
     * <code>SpinnerListModel</code>.
     * @since 1.4
     */
    public static class ListEditor extends DefaultEditor
    {
        /**
         * Construct a <code>JSpinner</code> editor that supports displaying
         * and editing the value of a <code>SpinnerListModel</code>
         * with a <code>JFormattedTextField</code>.  <code>This</code>
         * <code>ListEditor</code> becomes both a <code>ChangeListener</code>
         * on the spinner and a <code>PropertyChangeListener</code>
         * on the new <code>JFormattedTextField</code>.
         *
         * @param spinner the spinner whose model <code>this</code> editor will monitor
         * @exception IllegalArgumentException if the spinners model is not
         *     an instance of <code>SpinnerListModel</code>
         *
         * @see #getModel
         * @see SpinnerListModel
         */
        public ListEditor(JSpinner spinner) {
            super(spinner);
            if (!(spinner.getModel() instanceof SpinnerListModel)) {
                throw new IllegalArgumentException("model not a SpinnerListModel");
            }
            getTextField().setEditable(true);
            getTextField().setFormatterFactory(new
                              DefaultFormatterFactory(new ListFormatter()));
        }

        /**
         * Return our spinner ancestor's <code>SpinnerNumberModel</code>.
         *
         * @return <code>getSpinner().getModel()</code>
         * @see #getSpinner
         * @see #getTextField
         */
        public SpinnerListModel getModel() {
            return (SpinnerListModel)(getSpinner().getModel());
        }


        /**
         * ListFormatter provides completion while text is being input
         * into the JFormattedTextField. Completion is only done if the
         * user is inserting text at the end of the document. Completion
         * is done by way of the SpinnerListModel method findNextMatch.
         */
        private class ListFormatter extends
                          JFormattedTextField.AbstractFormatter {
            private DocumentFilter filter;

            public String valueToString(Object value) throws ParseException {
                if (value == null) {
                    return "";
                }
                return value.toString();
            }

            public Object stringToValue(String string) throws ParseException {
                return string;
            }

            protected DocumentFilter getDocumentFilter() {
                if (filter == null) {
                    filter = new Filter();
                }
                return filter;
            }


            private class Filter extends DocumentFilter {
                public void replace(FilterBypass fb, int offset, int length,
                                    String string, AttributeSet attrs) throws
                                           BadLocationException {
                    if (string != null && (offset + length) ==
                                          fb.getDocument().getLength()) {
                        Object next = getModel().findNextMatch(
                                         fb.getDocument().getText(0, offset) +
                                         string);
                        String value = (next != null) ? next.toString() : null;

                        if (value != null) {
                            fb.remove(0, offset + length);
                            fb.insertString(0, value, null);
                            getFormattedTextField().select(offset +
                                                           string.length(),
                                                           value.length());
                            return;
                        }
                    }
                    super.replace(fb, offset, length, string, attrs);
                }

                public void insertString(FilterBypass fb, int offset,
                                     String string, AttributeSet attr)
                       throws BadLocationException {
                    replace(fb, offset, 0, string, attr);
                }
            }
        }
    }


    /**
     * An Action implementation that is always disabled.
     */
    private static class DisabledAction implements Action {
        public Object getValue(String key) {
            return null;
        }
        public void putValue(String key, Object value) {
        }
        public void setEnabled(boolean b) {
        }
        public boolean isEnabled() {
            return false;
        }
        public void addPropertyChangeListener(PropertyChangeListener l) {
        }
        public void removePropertyChangeListener(PropertyChangeListener l) {
        }
        public void actionPerformed(ActionEvent ae) {
        }
    }

    /////////////////
    // Accessibility support
    ////////////////

    /**
     * Gets the <code>AccessibleContext</code> for the <code>JSpinner</code>
     *
     * @return the <code>AccessibleContext</code> for the <code>JSpinner</code>
     * @since 1.5
     */
    public AccessibleContext getAccessibleContext() {
        if (accessibleContext == null) {
            accessibleContext = new AccessibleJSpinner();
        }
        return accessibleContext;
    }

    /**
     * <code>AccessibleJSpinner</code> implements accessibility
     * support for the <code>JSpinner</code> class.
     * @since 1.5
     */
    protected class AccessibleJSpinner extends AccessibleJComponent
        implements AccessibleValue, AccessibleAction, AccessibleText,
                   AccessibleEditableText, ChangeListener {

        private Object oldModelValue = null;

        /**
         * AccessibleJSpinner constructor
         */
        protected AccessibleJSpinner() {
            // model is guaranteed to be non-null
            oldModelValue = model.getValue();
            JSpinner.this.addChangeListener(this);
        }

        /**
         * Invoked when the target of the listener has changed its state.
         *
         * @param e  a <code>ChangeEvent</code> object. Must not be null.
         * @throws NullPointerException if the parameter is null.
         */
        public void stateChanged(ChangeEvent e) {
            if (e == null) {
                throw new NullPointerException();
            }
            Object newModelValue = model.getValue();
            firePropertyChange(ACCESSIBLE_VALUE_PROPERTY,
                               oldModelValue,
                               newModelValue);
            firePropertyChange(ACCESSIBLE_TEXT_PROPERTY,
                               null,
                               0); // entire text may have changed

            oldModelValue = newModelValue;
        }

        /* ===== Begin AccessibleContext methods ===== */

        /**
         * Gets the role of this object.  The role of the object is the generic
         * purpose or use of the class of this object.  For example, the role
         * of a push button is AccessibleRole.PUSH_BUTTON.  The roles in
         * AccessibleRole are provided so component developers can pick from
         * a set of predefined roles.  This enables assistive technologies to
         * provide a consistent interface to various tweaked subclasses of
         * components (e.g., use AccessibleRole.PUSH_BUTTON for all components
         * that act like a push button) as well as distinguish between sublasses
         * that behave differently (e.g., AccessibleRole.CHECK_BOX for check boxes
         * and AccessibleRole.RADIO_BUTTON for radio buttons).
         * <p>Note that the AccessibleRole class is also extensible, so
         * custom component developers can define their own AccessibleRole's
         * if the set of predefined roles is inadequate.
         *
         * @return an instance of AccessibleRole describing the role of the object
         * @see AccessibleRole
         */
        public AccessibleRole getAccessibleRole() {
            return AccessibleRole.SPIN_BOX;
        }

        /**
         * Returns the number of accessible children of the object.
         *
         * @return the number of accessible children of the object.
         */
        public int getAccessibleChildrenCount() {
            // the JSpinner has one child, the editor
            if (editor.getAccessibleContext() != null) {
                return 1;
            }
            return 0;
        }

        /**
         * Returns the specified Accessible child of the object.  The Accessible
         * children of an Accessible object are zero-based, so the first child
         * of an Accessible child is at index 0, the second child is at index 1,
         * and so on.
         *
         * @param i zero-based index of child
         * @return the Accessible child of the object
         * @see #getAccessibleChildrenCount
         */
        public Accessible getAccessibleChild(int i) {
            // the JSpinner has one child, the editor
            if (i != 0) {
                return null;
            }
            if (editor.getAccessibleContext() != null) {
                return (Accessible)editor;
            }
            return null;
        }

        /* ===== End AccessibleContext methods ===== */

        /**
         * Gets the AccessibleAction associated with this object that supports
         * one or more actions.
         *
         * @return AccessibleAction if supported by object; else return null
         * @see AccessibleAction
         */
        public AccessibleAction getAccessibleAction() {
            return this;
        }

        /**
         * Gets the AccessibleText associated with this object presenting
         * text on the display.
         *
         * @return AccessibleText if supported by object; else return null
         * @see AccessibleText
         */
        public AccessibleText getAccessibleText() {
            return this;
        }

        /*
         * Returns the AccessibleContext for the JSpinner editor
         */
        private AccessibleContext getEditorAccessibleContext() {
            if (editor instanceof DefaultEditor) {
                JTextField textField = ((DefaultEditor)editor).getTextField();
                if (textField != null) {
                    return textField.getAccessibleContext();
                }
            } else if (editor instanceof Accessible) {
                return editor.getAccessibleContext();
            }
            return null;
        }

        /*
         * Returns the AccessibleText for the JSpinner editor
         */
        private AccessibleText getEditorAccessibleText() {
            AccessibleContext ac = getEditorAccessibleContext();
            if (ac != null) {
                return ac.getAccessibleText();
            }
            return null;
        }

        /*
         * Returns the AccessibleEditableText for the JSpinner editor
         */
        private AccessibleEditableText getEditorAccessibleEditableText() {
            AccessibleText at = getEditorAccessibleText();
            if (at instanceof AccessibleEditableText) {
                return (AccessibleEditableText)at;
            }
            return null;
        }

        /**
         * Gets the AccessibleValue associated with this object.
         *
         * @return AccessibleValue if supported by object; else return null
         * @see AccessibleValue
         *
         */
        public AccessibleValue getAccessibleValue() {
            return this;
        }

        /* ===== Begin AccessibleValue impl ===== */

        /**
         * Get the value of this object as a Number.  If the value has not been
         * set, the return value will be null.
         *
         * @return value of the object
         * @see #setCurrentAccessibleValue
         */
        public Number getCurrentAccessibleValue() {
            Object o = model.getValue();
            if (o instanceof Number) {
                return (Number)o;
            }
            return null;
        }

        /**
         * Set the value of this object as a Number.
         *
         * @param n the value to set for this object
         * @return true if the value was set; else False
         * @see #getCurrentAccessibleValue
         */
        public boolean setCurrentAccessibleValue(Number n) {
            // try to set the new value
            try {
                model.setValue(n);
                return true;
            } catch (IllegalArgumentException iae) {
                // SpinnerModel didn't like new value
            }
            return false;
        }

        /**
         * Get the minimum value of this object as a Number.
         *
         * @return Minimum value of the object; null if this object does not
         * have a minimum value
         * @see #getMaximumAccessibleValue
         */
        public Number getMinimumAccessibleValue() {
            if (model instanceof SpinnerNumberModel) {
                SpinnerNumberModel numberModel = (SpinnerNumberModel)model;
                Object o = numberModel.getMinimum();
                if (o instanceof Number) {
                    return (Number)o;
                }
            }
            return null;
        }

        /**
         * Get the maximum value of this object as a Number.
         *
         * @return Maximum value of the object; null if this object does not
         * have a maximum value
         * @see #getMinimumAccessibleValue
         */
        public Number getMaximumAccessibleValue() {
            if (model instanceof SpinnerNumberModel) {
                SpinnerNumberModel numberModel = (SpinnerNumberModel)model;
                Object o = numberModel.getMaximum();
                if (o instanceof Number) {
                    return (Number)o;
                }
            }
            return null;
        }

        /* ===== End AccessibleValue impl ===== */

        /* ===== Begin AccessibleAction impl ===== */

        /**
         * Returns the number of accessible actions available in this object
         * If there are more than one, the first one is considered the "default"
         * action of the object.
         *
         * Two actions are supported: AccessibleAction.INCREMENT which
         * increments the spinner value and AccessibleAction.DECREMENT
         * which decrements the spinner value
         *
         * @return the zero-based number of Actions in this object
         */
        public int getAccessibleActionCount() {
            return 2;
        }

        /**
         * Returns a description of the specified action of the object.
         *
         * @param i zero-based index of the actions
         * @return a String description of the action
         * @see #getAccessibleActionCount
         */
        public String getAccessibleActionDescription(int i) {
            if (i == 0) {
                return AccessibleAction.INCREMENT;
            } else if (i == 1) {
                return AccessibleAction.DECREMENT;
            }
            return null;
        }

        /**
         * Performs the specified Action on the object
         *
         * @param i zero-based index of actions. The first action
         * (index 0) is AccessibleAction.INCREMENT and the second
         * action (index 1) is AccessibleAction.DECREMENT.
         * @return true if the action was performed; otherwise false.
         * @see #getAccessibleActionCount
         */
        public boolean doAccessibleAction(int i) {
            if (i < 0 || i > 1) {
                return false;
            }
            Object o;
            if (i == 0) {
                o = getNextValue(); // AccessibleAction.INCREMENT
            } else {
                o = getPreviousValue(); // AccessibleAction.DECREMENT
            }
            // try to set the new value
            try {
                model.setValue(o);
                return true;
            } catch (IllegalArgumentException iae) {
                // SpinnerModel didn't like new value
            }
            return false;
        }

        /* ===== End AccessibleAction impl ===== */

        /* ===== Begin AccessibleText impl ===== */

        /*
         * Returns whether source and destination components have the
         * same window ancestor
         */
        private boolean sameWindowAncestor(Component src, Component dest) {
            if (src == null || dest == null) {
                return false;
            }
            return SwingUtilities.getWindowAncestor(src) ==
                SwingUtilities.getWindowAncestor(dest);
        }

        /**
         * Given a point in local coordinates, return the zero-based index
         * of the character under that Point.  If the point is invalid,
         * this method returns -1.
         *
         * @param p the Point in local coordinates
         * @return the zero-based index of the character under Point p; if
         * Point is invalid return -1.
         */
        public int getIndexAtPoint(Point p) {
            AccessibleText at = getEditorAccessibleText();
            if (at != null && sameWindowAncestor(JSpinner.this, editor)) {
                // convert point from the JSpinner bounds (source) to
                // editor bounds (destination)
                Point editorPoint = SwingUtilities.convertPoint(JSpinner.this,
                                                                p,
                                                                editor);
                if (editorPoint != null) {
                    return at.getIndexAtPoint(editorPoint);
                }
            }
            return -1;
        }

        /**
         * Determines the bounding box of the character at the given
         * index into the string.  The bounds are returned in local
         * coordinates.  If the index is invalid an empty rectangle is
         * returned.
         *
         * @param i the index into the String
         * @return the screen coordinates of the character's bounding box,
         * if index is invalid return an empty rectangle.
         */
        public Rectangle getCharacterBounds(int i) {
            AccessibleText at = getEditorAccessibleText();
            if (at != null ) {
                Rectangle editorRect = at.getCharacterBounds(i);
                if (editorRect != null &&
                    sameWindowAncestor(JSpinner.this, editor)) {
                    // return rectangle in the the JSpinner bounds
                    return SwingUtilities.convertRectangle(editor,
                                                           editorRect,
                                                           JSpinner.this);
                }
            }
            return null;
        }

        /**
         * Returns the number of characters (valid indicies)
         *
         * @return the number of characters
         */
        public int getCharCount() {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getCharCount();
            }
            return -1;
        }

        /**
         * Returns the zero-based offset of the caret.
         *
         * Note: That to the right of the caret will have the same index
         * value as the offset (the caret is between two characters).
         * @return the zero-based offset of the caret.
         */
        public int getCaretPosition() {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getCaretPosition();
            }
            return -1;
        }

        /**
         * Returns the String at a given index.
         *
         * @param part the CHARACTER, WORD, or SENTENCE to retrieve
         * @param index an index within the text
         * @return the letter, word, or sentence
         */
        public String getAtIndex(int part, int index) {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getAtIndex(part, index);
            }
            return null;
        }

        /**
         * Returns the String after a given index.
         *
         * @param part the CHARACTER, WORD, or SENTENCE to retrieve
         * @param index an index within the text
         * @return the letter, word, or sentence
         */
        public String getAfterIndex(int part, int index) {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getAfterIndex(part, index);
            }
            return null;
        }

        /**
         * Returns the String before a given index.
         *
         * @param part the CHARACTER, WORD, or SENTENCE to retrieve
         * @param index an index within the text
         * @return the letter, word, or sentence
         */
        public String getBeforeIndex(int part, int index) {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getBeforeIndex(part, index);
            }
            return null;
        }

        /**
         * Returns the AttributeSet for a given character at a given index
         *
         * @param i the zero-based index into the text
         * @return the AttributeSet of the character
         */
        public AttributeSet getCharacterAttribute(int i) {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getCharacterAttribute(i);
            }
            return null;
        }

        /**
         * Returns the start offset within the selected text.
         * If there is no selection, but there is
         * a caret, the start and end offsets will be the same.
         *
         * @return the index into the text of the start of the selection
         */
        public int getSelectionStart() {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getSelectionStart();
            }
            return -1;
        }

        /**
         * Returns the end offset within the selected text.
         * If there is no selection, but there is
         * a caret, the start and end offsets will be the same.
         *
         * @return the index into teh text of the end of the selection
         */
        public int getSelectionEnd() {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getSelectionEnd();
            }
            return -1;
        }

        /**
         * Returns the portion of the text that is selected.
         *
         * @return the String portion of the text that is selected
         */
        public String getSelectedText() {
            AccessibleText at = getEditorAccessibleText();
            if (at != null) {
                return at.getSelectedText();
            }
            return null;
        }

        /* ===== End AccessibleText impl ===== */


        /* ===== Begin AccessibleEditableText impl ===== */

        /**
         * Sets the text contents to the specified string.
         *
         * @param s the string to set the text contents
         */
        public void setTextContents(String s) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                at.setTextContents(s);
            }
        }

        /**
         * Inserts the specified string at the given index/
         *
         * @param index the index in the text where the string will
         * be inserted
         * @param s the string to insert in the text
         */
        public void insertTextAtIndex(int index, String s) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                at.insertTextAtIndex(index, s);
            }
        }

        /**
         * Returns the text string between two indices.
         *
         * @param startIndex the starting index in the text
         * @param endIndex the ending index in the text
         * @return the text string between the indices
         */
        public String getTextRange(int startIndex, int endIndex) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                return at.getTextRange(startIndex, endIndex);
            }
            return null;
        }

        /**
         * Deletes the text between two indices
         *
         * @param startIndex the starting index in the text
         * @param endIndex the ending index in the text
         */
        public void delete(int startIndex, int endIndex) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                at.delete(startIndex, endIndex);
            }
        }

        /**
         * Cuts the text between two indices into the system clipboard.
         *
         * @param startIndex the starting index in the text
         * @param endIndex the ending index in the text
         */
        public void cut(int startIndex, int endIndex) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                at.cut(startIndex, endIndex);
            }
        }

        /**
         * Pastes the text from the system clipboard into the text
         * starting at the specified index.
         *
         * @param startIndex the starting index in the text
         */
        public void paste(int startIndex) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                at.paste(startIndex);
            }
        }

        /**
         * Replaces the text between two indices with the specified
         * string.
         *
         * @param startIndex the starting index in the text
         * @param endIndex the ending index in the text
         * @param s the string to replace the text between two indices
         */
        public void replaceText(int startIndex, int endIndex, String s) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                at.replaceText(startIndex, endIndex, s);
            }
        }

        /**
         * Selects the text between two indices.
         *
         * @param startIndex the starting index in the text
         * @param endIndex the ending index in the text
         */
        public void selectText(int startIndex, int endIndex) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                at.selectText(startIndex, endIndex);
            }
        }

        /**
         * Sets attributes for the text between two indices.
         *
         * @param startIndex the starting index in the text
         * @param endIndex the ending index in the text
         * @param as the attribute set
         * @see AttributeSet
         */
        public void setAttributes(int startIndex, int endIndex, AttributeSet as) {
            AccessibleEditableText at = getEditorAccessibleEditableText();
            if (at != null) {
                at.setAttributes(startIndex, endIndex, as);
            }
        }
    }  /* End AccessibleJSpinner */
}
