/* JSpinner.java --
   Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.SpinnerUI;
import javax.swing.text.DateFormatter;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.NumberFormatter;

/**
 * A <code>JSpinner</code> is a component that displays a single value from
 * a sequence of values, and provides a convenient means for selecting the
 * previous and next values in the sequence.  Typically the spinner displays
 * a numeric value, but it is possible to display dates or arbitrary items
 * from a list.
 *
 * @author Ka-Hing Cheung
 * 
 * @since 1.4
 */
public class JSpinner extends JComponent
{
  /**
   * The base class for the editor used by the {@link JSpinner} component.  
   * The editor is in fact a panel containing a {@link JFormattedTextField}
   * component.
   */
  public static class DefaultEditor 
    extends JPanel 
    implements ChangeListener, PropertyChangeListener, LayoutManager
  {
    /** The spinner that the editor is allocated to. */
    private JSpinner spinner;

    /** The JFormattedTextField that backs the editor. */
    JFormattedTextField ftf;

    /**
     * For compatability with Sun's JDK 1.4.2 rev. 5
     */
    private static final long serialVersionUID = -5317788736173368172L;

    /**
     * Creates a new <code>DefaultEditor</code> object.  The editor is 
     * registered with the spinner as a {@link ChangeListener} here.
     *
     * @param spinner the <code>JSpinner</code> associated with this editor
     */
    public DefaultEditor(JSpinner spinner)
    {
      super();
      setLayout(this);
      this.spinner = spinner;
      ftf = new JFormattedTextField();
      add(ftf);
      ftf.setValue(spinner.getValue());
      ftf.addPropertyChangeListener(this);
      if (getComponentOrientation().isLeftToRight())
	ftf.setHorizontalAlignment(JTextField.RIGHT);
      else
	ftf.setHorizontalAlignment(JTextField.LEFT);
      spinner.addChangeListener(this);
    }

    /**
     * Returns the <code>JSpinner</code> component that the editor is assigned
     * to.
     * 
     * @return The spinner that the editor is assigned to.
     */
    public JSpinner getSpinner()
    {
      return spinner;
    }
    
    /**
     * DOCUMENT ME!
     */
    public void commitEdit() throws ParseException
    {
      // TODO: Implement this properly.
    }

    /**
     * Removes the editor from the {@link ChangeListener} list maintained by
     * the specified <code>spinner</code>.
     *
     * @param spinner  the spinner (<code>null</code> not permitted).
     */
    public void dismiss(JSpinner spinner)
    {
      spinner.removeChangeListener(this);
    }

    /**
     * Returns the text field used to display and edit the current value in 
     * the spinner.
     *
     * @return The text field.
     */
    public JFormattedTextField getTextField()
    {
      return ftf;
    }
    
    /**
     * Sets the bounds for the child components in this container.  In this
     * case, the text field is the only component to be laid out.
     *
     * @param parent the parent container.
     */
    public void layoutContainer(Container parent)
    {
      Insets insets = getInsets();
      Dimension size = getSize();
      ftf.setBounds(insets.left, insets.top,
                    size.width - insets.left - insets.right,
                    size.height - insets.top - insets.bottom);
    }
    
    /**
     * Calculates the minimum size for this component.  In this case, the
     * text field is the only subcomponent, so the return value is the minimum
     * size of the text field plus the insets of this component.
     *
     * @param parent  the parent container.
     *
     * @return The minimum size.
     */
    public Dimension minimumLayoutSize(Container parent)
    {
      Insets insets = getInsets();
      Dimension minSize = ftf.getMinimumSize();
      return new Dimension(minSize.width + insets.left + insets.right,
                            minSize.height + insets.top + insets.bottom);
    }
    
    /**
     * Calculates the preferred size for this component.  In this case, the
     * text field is the only subcomponent, so the return value is the 
     * preferred size of the text field plus the insets of this component.
     *
     * @param parent  the parent container.
     *
     * @return The preferred size.
     */
    public Dimension preferredLayoutSize(Container parent)
    {
      Insets insets = getInsets();
      Dimension prefSize = ftf.getPreferredSize();
      return new Dimension(prefSize.width + insets.left + insets.right,
                            prefSize.height + insets.top + insets.bottom);
    }
    
    /**
     * Receives notification of property changes.  If the text field's 'value' 
     * property changes, the spinner's model is updated accordingly.
     *
     * @param event the event.
     */
    public void propertyChange(PropertyChangeEvent event)
    {
      if (event.getSource() == ftf) 
        {
          if (event.getPropertyName().equals("value"))
            spinner.getModel().setValue(event.getNewValue());
        }
    }
    
    /**
     * Receives notification of changes in the state of the {@link JSpinner}
     * that the editor belongs to - the content of the text field is updated
     * accordingly.  
     *
     * @param event  the change event.
     */
    public void stateChanged(ChangeEvent event)
    {
      ftf.setValue(spinner.getValue());
    }
    
    /**
     * This method does nothing.  It is required by the {@link LayoutManager}
     * interface, but since this component has a single child, there is no
     * need to use this method.
     * 
     * @param child  the child component to remove.
     */
    public void removeLayoutComponent(Component child)
    {
      // Nothing to do here.
    }

    /**
     * This method does nothing.  It is required by the {@link LayoutManager}
     * interface, but since this component has a single child, there is no
     * need to use this method.
     * 
     * @param name  the name.
     * @param child  the child component to add.
     */
    public void addLayoutComponent(String name, Component child)
    {
      // Nothing to do here.
    }
  }

  /**
   * A panel containing a {@link JFormattedTextField} that is configured for
   * displaying and editing numbers.  The panel is used as a subcomponent of
   * a {@link JSpinner}.
   * 
   * @see JSpinner#createEditor(SpinnerModel)
   */
  public static class NumberEditor extends DefaultEditor
  {
    /**
     * For compatability with Sun's JDK
     */
    private static final long serialVersionUID = 3791956183098282942L;

    /**
     * Creates a new <code>NumberEditor</code> object for the specified 
     * <code>spinner</code>.  The editor is registered with the spinner as a 
     * {@link ChangeListener}.
     *
     * @param spinner the component the editor will be used with.
     */
    public NumberEditor(JSpinner spinner)
    {
      super(spinner);
      NumberEditorFormatter nef = new NumberEditorFormatter();
      nef.setMinimum(getModel().getMinimum());
      nef.setMaximum(getModel().getMaximum());
      ftf.setFormatterFactory(new DefaultFormatterFactory(nef));
    }

    /**
     * Creates a new <code>NumberEditor</code> object.
     *
     * @param spinner  the spinner.
     * @param decimalFormatPattern  the number format pattern.
     */
    public NumberEditor(JSpinner spinner, String decimalFormatPattern)
    {
      super(spinner);
      NumberEditorFormatter nef 
          = new NumberEditorFormatter(decimalFormatPattern);
      nef.setMinimum(getModel().getMinimum());
      nef.setMaximum(getModel().getMaximum());
      ftf.setFormatterFactory(new DefaultFormatterFactory(nef));
    }

    /**
     * Returns the format used by the text field.
     *
     * @return The format used by the text field.
     */
    public DecimalFormat getFormat()
    {
      NumberFormatter formatter = (NumberFormatter) ftf.getFormatter();
      return (DecimalFormat) formatter.getFormat();
    }

    /**
     * Returns the model used by the editor's {@link JSpinner} component,
     * cast to a {@link SpinnerNumberModel}.
     * 
     * @return The model.
     */
    public SpinnerNumberModel getModel()
    {
      return (SpinnerNumberModel) getSpinner().getModel();
    }
  }
  
  static class NumberEditorFormatter 
    extends NumberFormatter
  {
    public NumberEditorFormatter() 
    {
      super(NumberFormat.getInstance());
    }
    public NumberEditorFormatter(String decimalFormatPattern)
    {
      super(new DecimalFormat(decimalFormatPattern));
    }
  }

  /**
   * A <code>JSpinner</code> editor used for the {@link SpinnerListModel}.
   * This editor uses a <code>JFormattedTextField</code> to edit the values
   * of the spinner.
   *
   * @author Roman Kennke (kennke@aicas.com)
   */
  public static class ListEditor extends DefaultEditor
  {
    /**
     * Creates a new instance of <code>ListEditor</code>.
     *
     * @param spinner the spinner for which this editor is used
     */
    public ListEditor(JSpinner spinner)
    {
      super(spinner);
    }

    /**
     * Returns the spinner's model cast as a {@link SpinnerListModel}.
     * 
     * @return The spinner's model.
     */
    public SpinnerListModel getModel()
    {
      return (SpinnerListModel) getSpinner().getModel();
    }
  }

  /**
   * An editor class for a <code>JSpinner</code> that is used
   * for displaying and editing dates (e.g. that uses
   * <code>SpinnerDateModel</code> as model).
   *
   * The editor uses a {@link JTextField} with the value
   * displayed by a {@link DateFormatter} instance.
   */
  public static class DateEditor extends DefaultEditor
  {

    /** The serialVersionUID. */
    private static final long serialVersionUID = -4279356973770397815L;

    /**
     * Creates a new instance of DateEditor for the specified
     * <code>JSpinner</code>.
     *
     * @param spinner the <code>JSpinner</code> for which to
     *     create a <code>DateEditor</code> instance
     */
    public DateEditor(JSpinner spinner)
    {
      super(spinner);
      DateEditorFormatter nef = new DateEditorFormatter();
      nef.setMinimum(getModel().getStart());
      nef.setMaximum(getModel().getEnd());
      ftf.setFormatterFactory(new DefaultFormatterFactory(nef));
    }

    /**
     * Creates a new instance of DateEditor for the specified
     * <code>JSpinner</code> using the specified date format
     * pattern.
     *
     * @param spinner the <code>JSpinner</code> for which to
     *     create a <code>DateEditor</code> instance
     * @param dateFormatPattern the date format to use
     *
     * @see SimpleDateFormat#SimpleDateFormat(String)
     */
    public DateEditor(JSpinner spinner, String dateFormatPattern)
    {
      super(spinner);
      DateEditorFormatter nef = new DateEditorFormatter(dateFormatPattern);
      nef.setMinimum(getModel().getStart());
      nef.setMaximum(getModel().getEnd());
      ftf.setFormatterFactory(new DefaultFormatterFactory(nef));
    }

    /**
     * Returns the <code>SimpleDateFormat</code> instance that is used to
     * format the date value.
     *
     * @return the <code>SimpleDateFormat</code> instance that is used to
     *     format the date value
     */
    public SimpleDateFormat getFormat()
    {
      DateFormatter formatter = (DateFormatter) ftf.getFormatter();
      return (SimpleDateFormat) formatter.getFormat();
    }

    /**
     * Returns the {@link SpinnerDateModel} that is edited by this editor.
     *
     * @return the <code>SpinnerDateModel</code> that is edited by this editor
     */
    public SpinnerDateModel getModel()
    {
      return (SpinnerDateModel) getSpinner().getModel();
    }
  }

  static class DateEditorFormatter 
    extends DateFormatter
  {
    public DateEditorFormatter() 
    {
      super(DateFormat.getInstance());
    }
    public DateEditorFormatter(String dateFormatPattern)
    {
      super(new SimpleDateFormat(dateFormatPattern));
    }
  }

  /** 
   * A listener that forwards {@link ChangeEvent} notifications from the model
   * to the {@link JSpinner}'s listeners. 
   */
  class ModelListener implements ChangeListener
  {
    /**
     * Creates a new listener.
     */
    public ModelListener()
    {
      // nothing to do here
    }
    
    /**
     * Receives notification from the model that its state has changed.
     * 
     * @param event  the event (ignored).
     */
    public void stateChanged(ChangeEvent event)
    {
      fireStateChanged();
    }
  }

  /** 
   * The model that defines the current value and permitted values for the 
   * spinner. 
   */
  private SpinnerModel model;

  /** The current editor. */
  private JComponent editor;

  private static final long serialVersionUID = 3412663575706551720L;

  /**
   * Creates a new <code>JSpinner</code> with default instance of 
   * {@link SpinnerNumberModel} (that is, a model with value 0, step size 1, 
   * and no upper or lower limit).
   *
   * @see javax.swing.SpinnerNumberModel
   */
  public JSpinner()
  {
    this(new SpinnerNumberModel());
  }

  /**
   * Creates a new <code>JSpinner with the specified model.  The 
   * {@link #createEditor(SpinnerModel)} method is used to create an editor
   * that is suitable for the model.
   *
   * @param model the model (<code>null</code> not permitted).
   * 
   * @throws NullPointerException if <code>model</code> is <code>null</code>.
   */
  public JSpinner(SpinnerModel model)
  {
    this.model = model;
    this.editor = createEditor(model);
    model.addChangeListener(new ModelListener());
    updateUI();
  }

  /**
   * If the editor is <code>JSpinner.DefaultEditor</code>, then forwards the
   * call to it, otherwise do nothing.
   *
   * @throws ParseException DOCUMENT ME!
   */
  public void commitEdit() throws ParseException
  {
    if (editor instanceof DefaultEditor)
      ((DefaultEditor) editor).commitEdit();
  }

  /**
   * Gets the current editor
   *
   * @return the current editor
   *
   * @see #setEditor
   */
  public JComponent getEditor()
  {
    return editor;
  }

  /**
   * Changes the current editor to the new editor. The old editor is
   * removed from the spinner's {@link ChangeEvent} list.
   *
   * @param editor the new editor (<code>null</code> not permitted.
   *
   * @throws IllegalArgumentException if <code>editor</code> is 
   *                                  <code>null</code>.
   *
   * @see #getEditor
   */
  public void setEditor(JComponent editor)
  {
    if (editor == null)
      throw new IllegalArgumentException("editor may not be null");

    JComponent oldEditor = this.editor;
    if (oldEditor instanceof DefaultEditor)
      ((DefaultEditor) oldEditor).dismiss(this);
    else if (oldEditor instanceof ChangeListener)
      removeChangeListener((ChangeListener) oldEditor);
    
    this.editor = editor;
    firePropertyChange("editor", oldEditor, editor);
  }

  /**
   * Returns the model used by the {@link JSpinner} component.
   *
   * @return The model.
   * 
   * @see #setModel(SpinnerModel)
   */
  public SpinnerModel getModel()
  {
    return model;
  }

  /**
   * Sets a new underlying model.
   *
   * @param newModel the new model to set
   *
   * @exception IllegalArgumentException if newModel is <code>null</code>
   */
  public void setModel(SpinnerModel newModel)
  {
    if (newModel == null)
      throw new IllegalArgumentException();
    
    if (model == newModel)
      return;

    SpinnerModel oldModel = model;
    model = newModel;
    firePropertyChange("model", oldModel, newModel);
    setEditor(createEditor(model));
  }

  /**
   * Gets the next value without changing the current value.
   *
   * @return the next value
   *
   * @see javax.swing.SpinnerModel#getNextValue
   */
  public Object getNextValue()
  {
    return model.getNextValue();
  }

  /**
   * Gets the previous value without changing the current value.
   *
   * @return the previous value
   *
   * @see javax.swing.SpinnerModel#getPreviousValue
   */
  public Object getPreviousValue()
  {
    return model.getPreviousValue();
  }

  /**
   * Gets the <code>SpinnerUI</code> that handles this spinner
   *
   * @return the <code>SpinnerUI</code>
   */
  public SpinnerUI getUI()
  {
    return (SpinnerUI) ui;
  }

  /**
   * Gets the current value of the spinner, according to the underly model,
   * not the UI.
   *
   * @return the current value
   *
   * @see javax.swing.SpinnerModel#getValue
   */
  public Object getValue()
  {
    return model.getValue();
  }

  /**
   * Sets the value in the model.
   *
   * @param value the new value.
   */
  public void setValue(Object value)
  {
    model.setValue(value);
  }

  /**
   * Returns the ID that identifies which look and feel class will be
   * the UI delegate for this spinner.
   *
   * @return <code>"SpinnerUI"</code>.
   */
  public String getUIClassID()
  {
    return "SpinnerUI";
  }

  /**
   * This method resets the spinner's UI delegate to the default UI for the
   * current look and feel.
   */
  public void updateUI()
  {
    setUI((SpinnerUI) UIManager.getUI(this));
  }

  /**
   * Sets the UI delegate for the component.
   *
   * @param ui The spinner's UI delegate.
   */
  public void setUI(SpinnerUI ui)
  {
    super.setUI(ui);
  }

  /**
   * Adds a <code>ChangeListener</code>
   *
   * @param listener the listener to add
   */
  public void addChangeListener(ChangeListener listener)
  {
    listenerList.add(ChangeListener.class, listener);
  }

  /**
   * Remove a particular listener
   *
   * @param listener the listener to remove
   */
  public void removeChangeListener(ChangeListener listener)
  {
    listenerList.remove(ChangeListener.class, listener);
  }

  /**
   * Gets all the <code>ChangeListener</code>s
   *
   * @return all the <code>ChangeListener</code>s
   */
  public ChangeListener[] getChangeListeners()
  {
    return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
  }

  /**
   * Fires a <code>ChangeEvent</code> to all the <code>ChangeListener</code>s
   * added to this <code>JSpinner</code>
   */
  protected void fireStateChanged()
  {
    ChangeEvent evt = new ChangeEvent(this);
    ChangeListener[] listeners = getChangeListeners();

    for (int i = 0; i < listeners.length; ++i)
      listeners[i].stateChanged(evt);
  }

  /**
   * Creates an editor that is appropriate for the specified <code>model</code>.
   *
   * @param model the model.
   *
   * @return The editor.
   */
  protected JComponent createEditor(SpinnerModel model)
  {
    if (model instanceof SpinnerDateModel)
      return new DateEditor(this);
    else if (model instanceof SpinnerNumberModel)
      return new NumberEditor(this);
    else if (model instanceof SpinnerListModel)
      return new ListEditor(this);
    else
      return new DefaultEditor(this);
  }
}
