/* BasicSpinnerUI.java --
   Copyright (C) 2003, 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.plaf.basic;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JSpinner;
import javax.swing.LookAndFeel;
import javax.swing.Timer;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SpinnerUI;

/**
 * A UI delegate for the {@link JSpinner} component.
 *
 * @author Ka-Hing Cheung
 *
 * @since 1.4
 */
public class BasicSpinnerUI extends SpinnerUI
{
  /**
   * Creates a new <code>BasicSpinnerUI</code> for the specified
   * <code>JComponent</code>
   *
   * @param c  the component (ignored).
   *
   * @return A new instance of {@link BasicSpinnerUI}.
   */
  public static ComponentUI createUI(JComponent c)
  {
    return new BasicSpinnerUI();
  }

  /**
   * Creates an editor component. Really, it just returns
   * <code>JSpinner.getEditor()</code>
   *
   * @return a JComponent as an editor
   *
   * @see javax.swing.JSpinner#getEditor
   */
  protected JComponent createEditor()
  {
    return spinner.getEditor();
  }

  /**
   * Creates a <code>LayoutManager</code> that layouts the sub components. The
   * subcomponents are identifies by the constraint "Next", "Previous" and
   * "Editor"
   *
   * @return a LayoutManager
   *
   * @see java.awt.LayoutManager
   */
  protected LayoutManager createLayout()
  {
    return new DefaultLayoutManager();
  }

  /**
   * Creates the "Next" button
   *
   * @return the next button component
   */
  protected Component createNextButton()
  {
    JButton button = new BasicArrowButton(BasicArrowButton.NORTH);
    return button;
  }

  /**
   * Creates the "Previous" button
   *
   * @return the previous button component
   */
  protected Component createPreviousButton()
  {
    JButton button = new BasicArrowButton(BasicArrowButton.SOUTH);
    return button;
  }

  /**
   * Creates the <code>PropertyChangeListener</code> that will be attached by
   * <code>installListeners</code>. It should watch for the "editor"
   * property, when it's changed, replace the old editor with the new one,
   * probably by calling <code>replaceEditor</code>
   *
   * @return a PropertyChangeListener
   *
   * @see #replaceEditor
   */
  protected PropertyChangeListener createPropertyChangeListener()
  {
    return new PropertyChangeListener()
      {
        public void propertyChange(PropertyChangeEvent event)
        {
          // FIXME: Add check for enabled property change. Need to
          // disable the buttons.
          if ("editor".equals(event.getPropertyName()))
            BasicSpinnerUI.this.replaceEditor((JComponent) event.getOldValue(),
                (JComponent) event.getNewValue());
          // FIXME: Handle 'font' property change
        }
      };
  }

  /**
   * Called by <code>installUI</code>. This should set various defaults
   * obtained from <code>UIManager.getLookAndFeelDefaults</code>, as well as
   * set the layout obtained from <code>createLayout</code>
   *
   * @see javax.swing.UIManager#getLookAndFeelDefaults
   * @see #createLayout
   * @see #installUI
   */
  protected void installDefaults()
  {
    LookAndFeel.installColorsAndFont(spinner, "Spinner.background",
                                     "Spinner.foreground", "Spinner.font");
    LookAndFeel.installBorder(spinner, "Spinner.border");
    JComponent e = spinner.getEditor();
    if (e instanceof JSpinner.DefaultEditor)
      {
        JSpinner.DefaultEditor de = (JSpinner.DefaultEditor) e;
        de.getTextField().setBorder(null);  
      }
    spinner.setLayout(createLayout());
    spinner.setOpaque(true);
  }

  /*
   * Called by <code>installUI</code>, which basically adds the
   * <code>PropertyChangeListener</code> created by
   * <code>createPropertyChangeListener</code>
   *
   * @see #createPropertyChangeListener
   * @see #installUI
   */
  protected void installListeners()
  {
    spinner.addPropertyChangeListener(listener);
  }

  /*
   * Install listeners to the next button so that it increments the model
   */
  protected void installNextButtonListeners(Component c)
  {
    c.addMouseListener(new MouseAdapter()
        {
	  public void mousePressed(MouseEvent evt)
	  {
	    if (! spinner.isEnabled())
	      return;
	    increment();
	    timer.setInitialDelay(500);
	    timer.start();
	  }

	  public void mouseReleased(MouseEvent evt)
	  {
	    timer.stop();
	  }

	  void increment()
	  {
	    Object next = BasicSpinnerUI.this.spinner.getNextValue();
	    if (next != null)
	      BasicSpinnerUI.this.spinner.getModel().setValue(next);
	  }

	  volatile boolean mouseDown;
	  Timer timer = new Timer(50,
	                          new ActionListener()
	      {
		public void actionPerformed(ActionEvent event)
		{
		  increment();
		}
	      });
        });
  }

  /*
   * Install listeners to the previous button so that it decrements the model
   */
  protected void installPreviousButtonListeners(Component c)
  {
    c.addMouseListener(new MouseAdapter()
        {
	  public void mousePressed(MouseEvent evt)
	  {
	    if (! spinner.isEnabled())
	      return;
	    decrement();
	    timer.setInitialDelay(500);
	    timer.start();
	  }

	  public void mouseReleased(MouseEvent evt)
	  {
	    timer.stop();
	  }

	  void decrement()
	  {
	    Object prev = BasicSpinnerUI.this.spinner.getPreviousValue();
	    if (prev != null)
	      BasicSpinnerUI.this.spinner.getModel().setValue(prev);
	  }

	  volatile boolean mouseDown;
	  Timer timer = new Timer(50,
	                          new ActionListener()
	      {
		public void actionPerformed(ActionEvent event)
		{
		  decrement();
		}
	      });
        });
  }

  /**
   * Install this UI to the <code>JComponent</code>, which in reality, is a
   * <code>JSpinner</code>. Calls <code>installDefaults</code>,
   * <code>installListeners</code>, and also adds the buttons and editor.
   *
   * @param c DOCUMENT ME!
   *
   * @see #installDefaults
   * @see #installListeners
   * @see #createNextButton
   * @see #createPreviousButton
   * @see #createEditor
   */
  public void installUI(JComponent c)
  {
    super.installUI(c);

    spinner = (JSpinner) c;

    installDefaults();
    installListeners();

    Component next = createNextButton();
    Component previous = createPreviousButton();

    installNextButtonListeners(next);
    installPreviousButtonListeners(previous);

    c.add(createEditor(), "Editor");
    c.add(next, "Next");
    c.add(previous, "Previous");
  }

  /**
   * Replace the old editor with the new one
   *
   * @param oldEditor the old editor
   * @param newEditor the new one to replace with
   */
  protected void replaceEditor(JComponent oldEditor, JComponent newEditor)
  {
    spinner.remove(oldEditor);
    spinner.add(newEditor);
  }

  /**
   * The reverse of <code>installDefaults</code>. Called by
   * <code>uninstallUI</code>
   */
  protected void uninstallDefaults()
  {
    spinner.setLayout(null);
  }

  /**
   * The reverse of <code>installListeners</code>, called by
   * <code>uninstallUI</code>
   */
  protected void uninstallListeners()
  {
    spinner.removePropertyChangeListener(listener);
  }

  /**
   * Called when the current L&F is replaced with another one, should call
   * <code>uninstallDefaults</code> and <code>uninstallListeners</code> as
   * well as remove the next/previous buttons and the editor
   *
   * @param c DOCUMENT ME!
   */
  public void uninstallUI(JComponent c)
  {
    super.uninstallUI(c);

    uninstallDefaults();
    uninstallListeners();
    c.removeAll();
  }

  /** The spinner for this UI */
  protected JSpinner spinner;

  /** DOCUMENT ME! */
  private PropertyChangeListener listener = createPropertyChangeListener();

  /**
   * A layout manager for the {@link JSpinner} component.  The spinner has
   * three subcomponents: an editor, a 'next' button and a 'previous' button.
   */
  private class DefaultLayoutManager implements LayoutManager
  {
    /**
     * Layout the spinners inner parts.
     *
     * @param parent The parent container
     */
    public void layoutContainer(Container parent)
    {
      synchronized (parent.getTreeLock())
        {
          Insets i = parent.getInsets();
          boolean l2r = parent.getComponentOrientation().isLeftToRight();
          /*
            --------------    --------------
            |        | n |    | n |        |
            |   e    | - | or | - |   e    |
            |        | p |    | p |        |
            --------------    --------------
          */
          Dimension e = prefSize(editor);
          Dimension n = prefSize(next);
          Dimension p = prefSize(previous);
	  Dimension s = parent.getSize();

          int x = l2r ? i.left : i.right;
          int y = i.top;
          int w = Math.max(p.width, n.width);
          int h = (s.height - i.bottom) / 2;
          int e_width = s.width - w - i.left - i.right;

          if (l2r)
            {
              setBounds(editor, x, y, e_width, 2 * h);
              x += e_width;
              setBounds(next, x, y, w, h);
              y += h;
              setBounds(previous, x, y, w, h);
            }
          else
            {
              setBounds(next, x, y + (s.height - e.height) / 2, w, h);
              y += h;
              setBounds(previous, x, y + (s.height - e.height) / 2, w, h);
              x += w;
              y -= h;
              setBounds(editor, x, y, e_width, e.height);
            }
        }
    }

    /**
     * Calculates the minimum layout size.
     *
     * @param parent  the parent.
     *
     * @return The minimum layout size.
     */
    public Dimension minimumLayoutSize(Container parent)
    {
      Dimension d = new Dimension();

      if (editor != null)
        {
          Dimension tmp = editor.getMinimumSize();
          d.width += tmp.width;
          d.height = tmp.height;
        }

      int nextWidth = 0;
      int previousWidth = 0;

      if (next != null)
        {
          Dimension tmp = next.getMinimumSize();
          nextWidth = tmp.width;
        }
      if (previous != null)
        {
          Dimension tmp = previous.getMinimumSize();
          previousWidth = tmp.width;
        }

      d.width += Math.max(nextWidth, previousWidth);

      return d;
    }

    /**
     * Returns the preferred layout size of the container.
     *
     * @param parent DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public Dimension preferredLayoutSize(Container parent)
    {
      Dimension d = new Dimension();

      if (editor != null)
        {
          Dimension tmp = editor.getPreferredSize();
          d.width += Math.max(tmp.width, 40);
          d.height = tmp.height;
        }

      int nextWidth = 0;
      int previousWidth = 0;

      if (next != null)
        {
          Dimension tmp = next.getPreferredSize();
          nextWidth = tmp.width;
        }
      if (previous != null)
        {
          Dimension tmp = previous.getPreferredSize();
          previousWidth = tmp.width;
        }

      d.width += Math.max(nextWidth, previousWidth);
      Insets insets = parent.getInsets();
      d.width = d.width + insets.left + insets.right;
      d.height = d.height + insets.top + insets.bottom;
      return d;
    }

    /**
     * DOCUMENT ME!
     *
     * @param child DOCUMENT ME!
     */
    public void removeLayoutComponent(Component child)
    {
      if (child == editor)
        editor = null;
      else if (child == next)
        next = null;
      else if (previous == child)
        previous = null;
    }

    /**
     * DOCUMENT ME!
     *
     * @param name DOCUMENT ME!
     * @param child DOCUMENT ME!
     */
    public void addLayoutComponent(String name, Component child)
    {
      if ("Editor".equals(name))
        editor = child;
      else if ("Next".equals(name))
        next = child;
      else if ("Previous".equals(name))
        previous = child;
    }

    /**
     * DOCUMENT ME!
     *
     * @param c DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    private Dimension prefSize(Component c)
    {
      if (c == null)
        return new Dimension();
      else
        return c.getPreferredSize();
    }

    /**
     * Sets the bounds for the specified component.
     *
     * @param c  the component.
     * @param x  the x-coordinate for the top-left of the component bounds.
     * @param y  the y-coordinate for the top-left of the component bounds.
     * @param w  the width of the bounds.
     * @param h  the height of the bounds.
     */
    private void setBounds(Component c, int x, int y, int w, int h)
    {
      if (c != null)
        c.setBounds(x, y, w, h);
    }

    /** The editor component. */
    private Component editor;

    /** The next button. */
    private Component next;

    /** The previous button. */
    private Component previous;
  }
}
