/* DefaultBoundedRangeModel.java -- Default implementation
   of BoundedRangeModel.
   Copyright (C) 2002, 2004, 2005  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.io.Serializable;
import java.util.EventListener;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;

/**
 * The default implementation of <code>BoundedRangeModel</code>.
 *
 * @author Andrew Selkirk (aselkirk@sympatico.ca)
 * @author Sascha Brawer (brawer@dandelis.ch)
 */
public class DefaultBoundedRangeModel
  implements BoundedRangeModel, Serializable
{
  /**
   * The identifier of this class in object serialization. Verified
   * using the serialver tool of Sun J2SE 1.4.1_01.
   */
  private static final long serialVersionUID = 5034068491295259790L;

  /**
   * An event that is sent to all registered {@link ChangeListener}s
   * when the state of this range model has changed.
   *
   * <p>The event object is created on demand, the first time it
   * is actually needed.</p>
   *
   * @see #fireStateChanged()
   */
  protected transient ChangeEvent changeEvent;

  /**
   * The list of the currently registered EventListeners.
   */
  protected EventListenerList listenerList = new EventListenerList();

  /**
   * The current value of the range model, which is always between
   * {@link #minimum} and ({@link #maximum} - {@link #extent}). In a
   * scroll bar visualization of a {@link BoundedRangeModel}, the
   * <code>value</code> is displayed as the position of the thumb.
   */
  private int value;

  /**
   * The current extent of the range model, which is a number greater
   * than or equal to zero. In a scroll bar visualization of a {@link
   * BoundedRangeModel}, the <code>extent</code> is displayed as the
   * size of the thumb.
   */
  private int extent;

  /**
   * The current minimum value of the range model, which is always
   * less than or equal to {@link #maximum}.
   */
  private int minimum;

  /**
   * The current maximum value of the range model, which is always
   * greater than or equal to {@link #minimum}.
   */
  private int maximum;

  /**
   * A property that indicates whether the value of this {@link
   * BoundedRangeModel} is going to change in the immediate future.
   */
  private boolean isAdjusting;

  /**
   * Constructs a <code>DefaultBoundedRangeModel</code> with default
   * values for the properties. The properties <code>value</code>,
   * <code>extent</code> and <code>minimum</code> will be initialized
   * to zero; <code>maximum</code> will be set to 100; the property
   * <code>valueIsAdjusting</code> will be <code>false</code>.
   */
  public DefaultBoundedRangeModel()
  {
    // The fields value, extent, minimum have the default value 0, and
    // isAdjusting is already false. These fields no not need to be
    // set explicitly.
    maximum = 100;
  }

  /**
   * Constructs a <code>DefaultBoundedRangeModel</code> with the
   * specified values for some properties.
   *
   * @param value the initial value of the range model, which must be
   *     a number between <code>minimum</code> and <code>(maximum -
   *     extent)</code>. In a scroll bar visualization of a {@link
   *     BoundedRangeModel}, the <code>value</code> is displayed as the
   *     position of the thumb.
   * @param extent the initial extent of the range model, which is a
   *     number greater than or equal to zero. In a scroll bar
   *     visualization of a {@link BoundedRangeModel}, the
   *     <code>extent</code> is displayed as the size of the thumb.
   * @param minimum the initial minimal value of the range model.
   * @param maximum the initial maximal value of the range model.
   *
   * @throws IllegalArgumentException if the following condition is
   *     not satisfied: <code>minimum &lt;= value &lt;= value + extent &lt;=
   *     maximum</code>.
   */
  public DefaultBoundedRangeModel(int value, int extent, int minimum,
                                  int maximum)
  {
    if (!(minimum <= value && extent >= 0 && (value + extent) <= maximum))
      throw new IllegalArgumentException();

    this.value = value;
    this.extent = extent;
    this.minimum = minimum;
    this.maximum = maximum;

    // The isAdjusting field already has a false value by default.
  }

  /**
   * Returns a string with all relevant properties of this range
   * model.
   *
   * @return a string representing the object
   */
  public String toString()
  {
    return getClass().getName()
      + "[value=" + value
      + ", extent=" + extent
      + ", min=" + minimum
      + ", max=" + maximum
      + ", adj=" + isAdjusting
      + ']';
  }

  /**
   * Returns the current value of this bounded range model.  In a
   * scroll bar visualization of a {@link BoundedRangeModel}, the
   * <code>value</code> is displayed as the position of the thumb.
   *
   * @return the value
   */
  public int getValue()
  {
    return value;
  }

  /**
   * Changes the current value of this bounded range model. In a
   * scroll bar visualization of a {@link BoundedRangeModel}, the
   * <code>value</code> is displayed as the position of the thumb;
   * changing the <code>value</code> of a scroll bar's model
   * thus moves the thumb to a different position.
   *
   * @param value the value
   */
  public void setValue(int value)
  {
    value = Math.max(minimum, value);
    if (value + extent > maximum)
      value = maximum - extent;

    if (value != this.value)
      {
        this.value = value;
        fireStateChanged();
      }
  }

  /**
   * Returns the current extent of this bounded range model, which is
   * a number greater than or equal to zero. In a scroll bar
   * visualization of a {@link BoundedRangeModel}, the
   * <code>extent</code> is displayed as the size of the thumb.
   *
   * @return the extent
   */
  public int getExtent()
  {
    return extent;
  }

  /**
   * Changes the current extent of this bounded range model. In a
   * scroll bar visualization of a {@link BoundedRangeModel}, the
   * <code>extent</code> is displayed as the size of the thumb.
   *
   * @param extent the new extent of the range model, which is a
   *     number greater than or equal to zero.
   */
  public void setExtent(int extent)
  {
    extent = Math.max(extent, 0);
    if (value + extent > maximum)
      extent = maximum - value;

    if (extent != this.extent)
      {
        this.extent = extent;
        fireStateChanged();
      }
  }

  /**
   * Returns the current minimal value of this bounded range model.
   */
  public int getMinimum()
  {
    return minimum;
  }

  /**
   * Changes the current minimal value of this bounded range model.
   *
   * @param minimum the new minimal value.
   */
  public void setMinimum(int minimum)
  {
    int value, maximum;

    maximum = Math.max(minimum, this.maximum);
    value = Math.max(minimum, this.value);

    setRangeProperties(value, extent, minimum, maximum, isAdjusting);
  }

  /**
   * Returns the current maximal value of this bounded range model.
   *
   * @return the maximum
   */
  public int getMaximum()
  {
    return maximum;
  }

  /**
   * Changes the current maximal value of this bounded range model.
   *
   * @param maximum the new maximal value.
   */
  public void setMaximum(int maximum)
  {
    int value, extent, minimum;

    minimum = Math.min(this.minimum, maximum);
    extent = Math.min(this.extent, maximum - minimum);
    value = Math.min(this.value, maximum - extent);

    setRangeProperties(value, extent, minimum, maximum, isAdjusting);
  }

  /**
   * Returns whether or not the value of this bounded range model is
   * going to change in the immediate future. Scroll bars set this
   * property to <code>true</code> while the thumb is being dragged
   * around; when the mouse is relased, they set the property to
   * <code>false</code> and post a final {@link ChangeEvent}.
   *
   * @return <code>true</code> if the value will change soon again;
   *     <code>false</code> if the value will probably not change soon.
   */
  public boolean getValueIsAdjusting()
  {
    return isAdjusting;
  }

  /**
   * Specifies whether or not the value of this bounded range model is
   * going to change in the immediate future. Scroll bars set this
   * property to <code>true</code> while the thumb is being dragged
   * around; when the mouse is relased, they set the property to
   * <code>false</code>.
   *
   * @param isAdjusting <code>true</code> if the value will change
   *     soon again; <code>false</code> if the value will probably not
   *     change soon.
   */
  public void setValueIsAdjusting(boolean isAdjusting)
  {
    if (isAdjusting == this.isAdjusting)
      return;

    this.isAdjusting = isAdjusting;
    fireStateChanged();
  }

  /**
   * Sets all properties.
   *
   * @param value the new value of the range model.  In a scroll bar
   *     visualization of a {@link BoundedRangeModel}, the
   *     <code>value</code> is displayed as the position of the thumb.
   * @param extent the new extent of the range model, which is a
   *     number greater than or equal to zero. In a scroll bar
   *     visualization of a {@link BoundedRangeModel}, the
   *     <code>extent</code> is displayed as the size of the thumb.
   * @param minimum the new minimal value of the range model.
   * @param maximum the new maximal value of the range model.
   * @param isAdjusting whether or not the value of this bounded range
   *     model is going to change in the immediate future. Scroll bars set
   *     this property to <code>true</code> while the thumb is being
   *     dragged around; when the mouse is relased, they set the property
   *     to <code>false</code>.
   */
  public void setRangeProperties(int value, int extent, int minimum,
                                 int maximum, boolean isAdjusting)
  {
    minimum = Math.min(Math.min(minimum, maximum), value);
    maximum = Math.max(value, maximum);
    if (extent + value > maximum)
      extent = maximum - value;
    extent = Math.max(0, extent);

    if ((value == this.value)
        && (extent == this.extent)
        && (minimum == this.minimum)
        && (maximum == this.maximum)
        && (isAdjusting == this.isAdjusting))
      return;

    this.value = value;
    this.extent = extent;
    this.minimum = minimum;
    this.maximum = maximum;
    this.isAdjusting = isAdjusting;
		
    fireStateChanged();
  }

  /**
   * Subscribes a ChangeListener to state changes.
   *
   * @param listener the listener to be subscribed.
   */
  public void addChangeListener(ChangeListener listener)
  {
    listenerList.add(ChangeListener.class, listener);
  }

  /**
   * Cancels the subscription of a ChangeListener.
   *
   * @param listener the listener to be unsubscribed.
   */
  public void removeChangeListener(ChangeListener listener)
  {
    listenerList.remove(ChangeListener.class, listener);
  }

  /**
   * Sends a {@link ChangeEvent} to any registered {@link
   * ChangeListener}s.
   *
   * @see #addChangeListener(ChangeListener)
   * @see #removeChangeListener(ChangeListener)
   */
  protected void fireStateChanged()
  {
    ChangeListener[] listeners = getChangeListeners();
    
    if (changeEvent == null)
      changeEvent = new ChangeEvent(this);

    for (int i = listeners.length - 1; i >= 0; --i)
      listeners[i].stateChanged(changeEvent);
  }

  /**
   * Retrieves the current listeners of the specified class.
   *
   * @param listenerType the class of listeners; usually {@link
   *     ChangeListener}<code>.class</code>.
   *
   * @return an array with the currently subscribed listeners, or
   *     an empty array if there are currently no listeners.
   *
   * @since 1.3
   */
  public EventListener[] getListeners(Class listenerType)
  {
    return listenerList.getListeners(listenerType);
  }

  /**
   * Returns all <code>ChangeListeners</code> that are currently
   * subscribed for changes to this
   * <code>DefaultBoundedRangeModel</code>.
   *
   * @return an array with the currently subscribed listeners, or
   *     an empty array if there are currently no listeners.
   *
   * @since 1.4
   */
  public ChangeListener[] getChangeListeners()
  {
    return (ChangeListener[]) getListeners(ChangeListener.class);
  }
}
