jdk/src/share/classes/javax/swing/DefaultBoundedRangeModel.java
changeset 2 90ce3da70b43
child 1301 15e81207e1f2
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package javax.swing;
       
    27 
       
    28 import javax.swing.event.*;
       
    29 import java.io.Serializable;
       
    30 import java.util.EventListener;
       
    31 
       
    32 /**
       
    33  * A generic implementation of BoundedRangeModel.
       
    34  * <p>
       
    35  * <strong>Warning:</strong>
       
    36  * Serialized objects of this class will not be compatible with
       
    37  * future Swing releases. The current serialization support is
       
    38  * appropriate for short term storage or RMI between applications running
       
    39  * the same version of Swing.  As of 1.4, support for long term storage
       
    40  * of all JavaBeans<sup><font size="-2">TM</font></sup>
       
    41  * has been added to the <code>java.beans</code> package.
       
    42  * Please see {@link java.beans.XMLEncoder}.
       
    43  *
       
    44  * @author David Kloba
       
    45  * @author Hans Muller
       
    46  * @see BoundedRangeModel
       
    47  */
       
    48 public class DefaultBoundedRangeModel implements BoundedRangeModel, Serializable
       
    49 {
       
    50     /**
       
    51      * Only one <code>ChangeEvent</code> is needed per model instance since the
       
    52      * event's only (read-only) state is the source property.  The source
       
    53      * of events generated here is always "this".
       
    54      */
       
    55     protected transient ChangeEvent changeEvent = null;
       
    56 
       
    57     /** The listeners waiting for model changes. */
       
    58     protected EventListenerList listenerList = new EventListenerList();
       
    59 
       
    60     private int value = 0;
       
    61     private int extent = 0;
       
    62     private int min = 0;
       
    63     private int max = 100;
       
    64     private boolean isAdjusting = false;
       
    65 
       
    66 
       
    67     /**
       
    68      * Initializes all of the properties with default values.
       
    69      * Those values are:
       
    70      * <ul>
       
    71      * <li><code>value</code> = 0
       
    72      * <li><code>extent</code> = 0
       
    73      * <li><code>minimum</code> = 0
       
    74      * <li><code>maximum</code> = 100
       
    75      * <li><code>adjusting</code> = false
       
    76      * </ul>
       
    77      */
       
    78     public DefaultBoundedRangeModel() {
       
    79     }
       
    80 
       
    81 
       
    82     /**
       
    83      * Initializes value, extent, minimum and maximum. Adjusting is false.
       
    84      * Throws an <code>IllegalArgumentException</code> if the following
       
    85      * constraints aren't satisfied:
       
    86      * <pre>
       
    87      * min &lt;= value &lt;= value+extent &lt;= max
       
    88      * </pre>
       
    89      */
       
    90     public DefaultBoundedRangeModel(int value, int extent, int min, int max)
       
    91     {
       
    92         if ((max >= min) &&
       
    93             (value >= min) &&
       
    94             ((value + extent) >= value) &&
       
    95             ((value + extent) <= max)) {
       
    96             this.value = value;
       
    97             this.extent = extent;
       
    98             this.min = min;
       
    99             this.max = max;
       
   100         }
       
   101         else {
       
   102             throw new IllegalArgumentException("invalid range properties");
       
   103         }
       
   104     }
       
   105 
       
   106 
       
   107     /**
       
   108      * Returns the model's current value.
       
   109      * @return the model's current value
       
   110      * @see #setValue
       
   111      * @see BoundedRangeModel#getValue
       
   112      */
       
   113     public int getValue() {
       
   114       return value;
       
   115     }
       
   116 
       
   117 
       
   118     /**
       
   119      * Returns the model's extent.
       
   120      * @return the model's extent
       
   121      * @see #setExtent
       
   122      * @see BoundedRangeModel#getExtent
       
   123      */
       
   124     public int getExtent() {
       
   125       return extent;
       
   126     }
       
   127 
       
   128 
       
   129     /**
       
   130      * Returns the model's minimum.
       
   131      * @return the model's minimum
       
   132      * @see #setMinimum
       
   133      * @see BoundedRangeModel#getMinimum
       
   134      */
       
   135     public int getMinimum() {
       
   136       return min;
       
   137     }
       
   138 
       
   139 
       
   140     /**
       
   141      * Returns the model's maximum.
       
   142      * @return  the model's maximum
       
   143      * @see #setMaximum
       
   144      * @see BoundedRangeModel#getMaximum
       
   145      */
       
   146     public int getMaximum() {
       
   147         return max;
       
   148     }
       
   149 
       
   150 
       
   151     /**
       
   152      * Sets the current value of the model. For a slider, that
       
   153      * determines where the knob appears. Ensures that the new
       
   154      * value, <I>n</I> falls within the model's constraints:
       
   155      * <pre>
       
   156      *     minimum &lt;= value &lt;= value+extent &lt;= maximum
       
   157      * </pre>
       
   158      *
       
   159      * @see BoundedRangeModel#setValue
       
   160      */
       
   161     public void setValue(int n) {
       
   162         n = Math.min(n, Integer.MAX_VALUE - extent);
       
   163 
       
   164         int newValue = Math.max(n, min);
       
   165         if (newValue + extent > max) {
       
   166             newValue = max - extent;
       
   167         }
       
   168         setRangeProperties(newValue, extent, min, max, isAdjusting);
       
   169     }
       
   170 
       
   171 
       
   172     /**
       
   173      * Sets the extent to <I>n</I> after ensuring that <I>n</I>
       
   174      * is greater than or equal to zero and falls within the model's
       
   175      * constraints:
       
   176      * <pre>
       
   177      *     minimum &lt;= value &lt;= value+extent &lt;= maximum
       
   178      * </pre>
       
   179      * @see BoundedRangeModel#setExtent
       
   180      */
       
   181     public void setExtent(int n) {
       
   182         int newExtent = Math.max(0, n);
       
   183         if(value + newExtent > max) {
       
   184             newExtent = max - value;
       
   185         }
       
   186         setRangeProperties(value, newExtent, min, max, isAdjusting);
       
   187     }
       
   188 
       
   189 
       
   190     /**
       
   191      * Sets the minimum to <I>n</I> after ensuring that <I>n</I>
       
   192      * that the other three properties obey the model's constraints:
       
   193      * <pre>
       
   194      *     minimum &lt;= value &lt;= value+extent &lt;= maximum
       
   195      * </pre>
       
   196      * @see #getMinimum
       
   197      * @see BoundedRangeModel#setMinimum
       
   198      */
       
   199     public void setMinimum(int n) {
       
   200         int newMax = Math.max(n, max);
       
   201         int newValue = Math.max(n, value);
       
   202         int newExtent = Math.min(newMax - newValue, extent);
       
   203         setRangeProperties(newValue, newExtent, n, newMax, isAdjusting);
       
   204     }
       
   205 
       
   206 
       
   207     /**
       
   208      * Sets the maximum to <I>n</I> after ensuring that <I>n</I>
       
   209      * that the other three properties obey the model's constraints:
       
   210      * <pre>
       
   211      *     minimum &lt;= value &lt;= value+extent &lt;= maximum
       
   212      * </pre>
       
   213      * @see BoundedRangeModel#setMaximum
       
   214      */
       
   215     public void setMaximum(int n) {
       
   216         int newMin = Math.min(n, min);
       
   217         int newExtent = Math.min(n - newMin, extent);
       
   218         int newValue = Math.min(n - newExtent, value);
       
   219         setRangeProperties(newValue, newExtent, newMin, n, isAdjusting);
       
   220     }
       
   221 
       
   222 
       
   223     /**
       
   224      * Sets the <code>valueIsAdjusting</code> property.
       
   225      *
       
   226      * @see #getValueIsAdjusting
       
   227      * @see #setValue
       
   228      * @see BoundedRangeModel#setValueIsAdjusting
       
   229      */
       
   230     public void setValueIsAdjusting(boolean b) {
       
   231         setRangeProperties(value, extent, min, max, b);
       
   232     }
       
   233 
       
   234 
       
   235     /**
       
   236      * Returns true if the value is in the process of changing
       
   237      * as a result of actions being taken by the user.
       
   238      *
       
   239      * @return the value of the <code>valueIsAdjusting</code> property
       
   240      * @see #setValue
       
   241      * @see BoundedRangeModel#getValueIsAdjusting
       
   242      */
       
   243     public boolean getValueIsAdjusting() {
       
   244         return isAdjusting;
       
   245     }
       
   246 
       
   247 
       
   248     /**
       
   249      * Sets all of the <code>BoundedRangeModel</code> properties after forcing
       
   250      * the arguments to obey the usual constraints:
       
   251      * <pre>
       
   252      *     minimum &lt;= value &lt;= value+extent &lt;= maximum
       
   253      * </pre>
       
   254      * <p>
       
   255      * At most, one <code>ChangeEvent</code> is generated.
       
   256      *
       
   257      * @see BoundedRangeModel#setRangeProperties
       
   258      * @see #setValue
       
   259      * @see #setExtent
       
   260      * @see #setMinimum
       
   261      * @see #setMaximum
       
   262      * @see #setValueIsAdjusting
       
   263      */
       
   264     public void setRangeProperties(int newValue, int newExtent, int newMin, int newMax, boolean adjusting)
       
   265     {
       
   266         if (newMin > newMax) {
       
   267             newMin = newMax;
       
   268         }
       
   269         if (newValue > newMax) {
       
   270             newMax = newValue;
       
   271         }
       
   272         if (newValue < newMin) {
       
   273             newMin = newValue;
       
   274         }
       
   275 
       
   276         /* Convert the addends to long so that extent can be
       
   277          * Integer.MAX_VALUE without rolling over the sum.
       
   278          * A JCK test covers this, see bug 4097718.
       
   279          */
       
   280         if (((long)newExtent + (long)newValue) > newMax) {
       
   281             newExtent = newMax - newValue;
       
   282         }
       
   283 
       
   284         if (newExtent < 0) {
       
   285             newExtent = 0;
       
   286         }
       
   287 
       
   288         boolean isChange =
       
   289             (newValue != value) ||
       
   290             (newExtent != extent) ||
       
   291             (newMin != min) ||
       
   292             (newMax != max) ||
       
   293             (adjusting != isAdjusting);
       
   294 
       
   295         if (isChange) {
       
   296             value = newValue;
       
   297             extent = newExtent;
       
   298             min = newMin;
       
   299             max = newMax;
       
   300             isAdjusting = adjusting;
       
   301 
       
   302             fireStateChanged();
       
   303         }
       
   304     }
       
   305 
       
   306 
       
   307     /**
       
   308      * Adds a <code>ChangeListener</code>.  The change listeners are run each
       
   309      * time any one of the Bounded Range model properties changes.
       
   310      *
       
   311      * @param l the ChangeListener to add
       
   312      * @see #removeChangeListener
       
   313      * @see BoundedRangeModel#addChangeListener
       
   314      */
       
   315     public void addChangeListener(ChangeListener l) {
       
   316         listenerList.add(ChangeListener.class, l);
       
   317     }
       
   318 
       
   319 
       
   320     /**
       
   321      * Removes a <code>ChangeListener</code>.
       
   322      *
       
   323      * @param l the <code>ChangeListener</code> to remove
       
   324      * @see #addChangeListener
       
   325      * @see BoundedRangeModel#removeChangeListener
       
   326      */
       
   327     public void removeChangeListener(ChangeListener l) {
       
   328         listenerList.remove(ChangeListener.class, l);
       
   329     }
       
   330 
       
   331 
       
   332     /**
       
   333      * Returns an array of all the change listeners
       
   334      * registered on this <code>DefaultBoundedRangeModel</code>.
       
   335      *
       
   336      * @return all of this model's <code>ChangeListener</code>s
       
   337      *         or an empty
       
   338      *         array if no change listeners are currently registered
       
   339      *
       
   340      * @see #addChangeListener
       
   341      * @see #removeChangeListener
       
   342      *
       
   343      * @since 1.4
       
   344      */
       
   345     public ChangeListener[] getChangeListeners() {
       
   346         return (ChangeListener[])listenerList.getListeners(
       
   347                 ChangeListener.class);
       
   348     }
       
   349 
       
   350 
       
   351     /**
       
   352      * Runs each <code>ChangeListener</code>'s <code>stateChanged</code> method.
       
   353      *
       
   354      * @see #setRangeProperties
       
   355      * @see EventListenerList
       
   356      */
       
   357     protected void fireStateChanged()
       
   358     {
       
   359         Object[] listeners = listenerList.getListenerList();
       
   360         for (int i = listeners.length - 2; i >= 0; i -=2 ) {
       
   361             if (listeners[i] == ChangeListener.class) {
       
   362                 if (changeEvent == null) {
       
   363                     changeEvent = new ChangeEvent(this);
       
   364                 }
       
   365                 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
       
   366             }
       
   367         }
       
   368     }
       
   369 
       
   370 
       
   371     /**
       
   372      * Returns a string that displays all of the
       
   373      * <code>BoundedRangeModel</code> properties.
       
   374      */
       
   375     public String toString()  {
       
   376         String modelString =
       
   377             "value=" + getValue() + ", " +
       
   378             "extent=" + getExtent() + ", " +
       
   379             "min=" + getMinimum() + ", " +
       
   380             "max=" + getMaximum() + ", " +
       
   381             "adj=" + getValueIsAdjusting();
       
   382 
       
   383         return getClass().getName() + "[" + modelString + "]";
       
   384     }
       
   385 
       
   386     /**
       
   387      * Returns an array of all the objects currently registered as
       
   388      * <code><em>Foo</em>Listener</code>s
       
   389      * upon this model.
       
   390      * <code><em>Foo</em>Listener</code>s
       
   391      * are registered using the <code>add<em>Foo</em>Listener</code> method.
       
   392      * <p>
       
   393      * You can specify the <code>listenerType</code> argument
       
   394      * with a class literal, such as <code><em>Foo</em>Listener.class</code>.
       
   395      * For example, you can query a <code>DefaultBoundedRangeModel</code>
       
   396      * instance <code>m</code>
       
   397      * for its change listeners
       
   398      * with the following code:
       
   399      *
       
   400      * <pre>ChangeListener[] cls = (ChangeListener[])(m.getListeners(ChangeListener.class));</pre>
       
   401      *
       
   402      * If no such listeners exist,
       
   403      * this method returns an empty array.
       
   404      *
       
   405      * @param listenerType  the type of listeners requested;
       
   406      *          this parameter should specify an interface
       
   407      *          that descends from <code>java.util.EventListener</code>
       
   408      * @return an array of all objects registered as
       
   409      *          <code><em>Foo</em>Listener</code>s
       
   410      *          on this model,
       
   411      *          or an empty array if no such
       
   412      *          listeners have been added
       
   413      * @exception ClassCastException if <code>listenerType</code> doesn't
       
   414      *          specify a class or interface that implements
       
   415      *          <code>java.util.EventListener</code>
       
   416      *
       
   417      * @see #getChangeListeners
       
   418      *
       
   419      * @since 1.3
       
   420      */
       
   421     public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
       
   422         return listenerList.getListeners(listenerType);
       
   423     }
       
   424 }