SpinnerNumberModel.java 11.2 KB
Newer Older
Tom Tromey committed
1
/* SpinnerNumberModel.java --
2
   Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
Tom Tromey committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

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;

42 43
import javax.swing.event.ChangeEvent;

Tom Tromey committed
44
/**
45
 * A model used by the {@link JSpinner} component.
Tom Tromey committed
46 47
 *
 * @author Ka-Hing Cheung
48
 * @since 1.4
Tom Tromey committed
49 50 51 52 53 54 55 56 57
 */
public class SpinnerNumberModel extends AbstractSpinnerModel
  implements Serializable
{
  /**
   * For compatability with Sun's JDK
   */
  private static final long serialVersionUID = 7279176385485777821L;

58
  /** The current value. */
Tom Tromey committed
59 60
  private Number value;

61
  /** The minimum value (or <code>null</code>). */
Tom Tromey committed
62 63
  private Comparable minimum;

64
  /** The maximum value (or <code>null</code>). */
Tom Tromey committed
65 66
  private Comparable maximum;

67
  /** The step size. */
Tom Tromey committed
68 69 70 71 72 73 74 75 76 77 78 79
  private Number stepSize;

  /**
   * Creates a <code>SpinnerNumberModel</code> with initial value 0, step 1,
   * and no maximum nor minimum.
   */
  public SpinnerNumberModel()
  {
    this(new Integer(0), null, null, new Integer(1));
  }

  /**
80
   * Creates a <code>SpinnerNumberModel</code> with double precision.
Tom Tromey committed
81 82 83 84 85
   *
   * @param value the initial value
   * @param minimum the minimum value
   * @param maximum the maximum value
   * @param stepSize the step size
86 87
   * @throws IllegalArgumentException if minimum &lt;= value &lt;= maximum does 
   *         not hold.
Tom Tromey committed
88 89 90 91 92 93 94 95 96
   */
  public SpinnerNumberModel(double value, double minimum, double maximum,
                            double stepSize)
  {
    this(new Double(value), new Double(minimum), new Double(maximum),
         new Double(stepSize));
  }

  /**
97
   * Creates a <code>SpinnerNumberModel</code> with integer precision.
Tom Tromey committed
98 99 100 101 102
   *
   * @param value the initial value
   * @param minimum the minimum value
   * @param maximum the maximum value
   * @param stepSize the step size
103 104
   * @throws IllegalArgumentException if minimum &lt;= value &lt;= maximum does 
   *         not hold.
Tom Tromey committed
105 106 107 108 109 110 111 112
   */
  public SpinnerNumberModel(int value, int minimum, int maximum, int stepSize)
  {
    this(new Integer(value), new Integer(minimum), new Integer(maximum),
         new Integer(stepSize));
  }

  /**
113 114 115
   * Creates a <code>SpinnerNumberModel</code> with the given attributes.  The
   * caller should ensure that both <code>minimum</code> and 
   * <code>maximum</code> are serializable.
Tom Tromey committed
116
   *
117
   * @param value the initial value (<code>null</code> not permitted).
118 119
   * @param minimum the minimum value (<code>null</code> permitted).
   * @param maximum the maximum value (<code>null</code> permitted).
120
   * @param stepSize the step size  (<code>null</code> not permitted).
Tom Tromey committed
121 122 123
   *
   * @throws IllegalArgumentException if minimum &lt;= value &lt;= maximum
   *         does not hold
124 125 126 127
   * @throws IllegalArgumentException if <code>value</code> is 
   *         <code>null</code>.
   * @throws IllegalArgumentException if <code>stepSize</code> is 
   *         <code>null</code>.
Tom Tromey committed
128 129 130 131 132 133 134 135 136 137
   */
  public SpinnerNumberModel(Number value, Comparable minimum,
                            Comparable maximum, Number stepSize)
  {
    if (stepSize == null)
      throw new IllegalArgumentException("stepSize may not be null");
    if (value == null)
      throw new IllegalArgumentException("value may not be null");
    if (minimum != null)
      {
138 139
        if (minimum.compareTo(value) > 0)
          throw new IllegalArgumentException("minimum is not <= value");
Tom Tromey committed
140 141 142
      }
    if (maximum != null)
      {
143 144
        if (maximum.compareTo(value) < 0)
          throw new IllegalArgumentException("maximum is not >= value");
Tom Tromey committed
145 146 147 148 149 150 151 152 153
      }

    this.value = value;
    this.stepSize = stepSize;
    this.minimum = minimum;
    this.maximum = maximum;
  }

  /**
154 155
   * Sets the current value and, if the new value is different to the old
   * value, sends a {@link ChangeEvent} to all registered listeners.
Tom Tromey committed
156
   *
157 158
   * @param value the new value (<code>null</code> not permitted, must be an
   *              instance of <code>Number</code>).
Tom Tromey committed
159
   *
160 161
   * @throws IllegalArgumentException if <code>value</code> is not an instance
   *         of <code>Number</code>.
Tom Tromey committed
162 163 164 165 166 167
   */
  public void setValue(Object value)
  {
    if (! (value instanceof Number))
      throw new IllegalArgumentException("value must be a Number");

168 169 170 171 172
    if (!this.value.equals(value)) 
      {
        this.value = (Number) value;
        fireStateChanged();
      }
Tom Tromey committed
173 174 175
  }

  /**
176 177
   * Returns the current value, which for this class is always an instance of
   * {@link Number}.
Tom Tromey committed
178
   *
179
   * @return The current value.
180 181
   * 
   * @see #getNumber()
Tom Tromey committed
182 183 184 185 186 187 188
   */
  public Object getValue()
  {
    return value;
  }

  /**
189 190 191
   * Returns the next value, or <code>null</code> if adding the step size to
   * the current value results in a value greater than the maximum value.  
   * The current value is not changed.
Tom Tromey committed
192
   *
193 194
   * @return The next value, or <code>null</code> if the current value is the 
   *         maximum value represented by this model.
Tom Tromey committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
   */
  public Object getNextValue()
  {
    Number num;

    if (value instanceof Double)
      num = new Double(value.doubleValue() + stepSize.doubleValue());
    else if (value instanceof Float)
      num = new Double(value.floatValue() + stepSize.floatValue());
    else if (value instanceof Long)
      num = new Long(value.longValue() + stepSize.longValue());
    else if (value instanceof Integer)
      num = new Integer(value.intValue() + stepSize.intValue());
    else if (value instanceof Short)
      num = new Short((short) (value.shortValue() + stepSize.shortValue()));
    else
      num = new Byte((byte) (value.byteValue() + stepSize.byteValue()));
212 213 214 215 216 217
    
    // check upper bound if set
    if ((maximum != null) && maximum.compareTo(num) < 0)
      num = null;
    
    return num;
Tom Tromey committed
218 219 220
  }

  /**
221 222 223
   * Returns the previous value, or <code>null</code> if subtracting the
   * step size from the current value results in a value less than the minimum
   * value.  The current value is not changed.
Tom Tromey committed
224
   *
225 226
   * @return The previous value, or <code>null</code> if the current value
   *         is the minimum value represented by this model.
Tom Tromey committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
   */
  public Object getPreviousValue()
  {
    Number num;

    if (value instanceof Double)
      num = new Double(value.doubleValue() - stepSize.doubleValue());
    else if (value instanceof Float)
      num = new Double(value.floatValue() - stepSize.floatValue());
    else if (value instanceof Long)
      num = new Long(value.longValue() - stepSize.longValue());
    else if (value instanceof Integer)
      num = new Integer(value.intValue() - stepSize.intValue());
    else if (value instanceof Short)
      num = new Short((short) (value.shortValue() - stepSize.shortValue()));
    else
      num = new Byte((byte) (value.byteValue() - stepSize.byteValue()));
244 245 246 247
    
    // check lower bound if set
    if ((minimum != null) && minimum.compareTo(num) > 0)
      num = null;
Tom Tromey committed
248

249
    return num;
Tom Tromey committed
250 251 252
  }

  /**
253
   * Returns the current value.
Tom Tromey committed
254
   *
255
   * @return The current value.
Tom Tromey committed
256 257 258 259 260 261
   */
  public Number getNumber()
  {
    return value;
  }

262 263 264 265
  /**
   * Returns the minimum value, or <code>null</code> if there is no minimum.
   * 
   * @return The minimum value.
266 267
   * 
   * @see #setMinimum(Comparable)
268
   */
Tom Tromey committed
269 270 271 272 273
  public Comparable getMinimum()
  {
    return minimum;
  }

274 275 276 277 278 279
  /**
   * Sets the minimum value and, if the new value is different to the old
   * value, sends a {@link ChangeEvent} to all registered listeners.  A 
   * <code>null</code> value is interpreted as "no minimum value".  No check
   * is made to ensure that the new minimum is less than or equal to the 
   * current value, the caller is responsible for ensuring that this 
280 281
   * relationship holds.  In addition, the caller should ensure that
   * <code>newMinimum</code> is {@link Serializable}.
282 283
   * 
   * @param newMinimum  the new minimum value (<code>null</code> permitted).
284 285
   * 
   * @see #getMinimum()
286
   */
Tom Tromey committed
287 288
  public void setMinimum(Comparable newMinimum)
  {
289
    if (minimum != null ? !minimum.equals(newMinimum) : newMinimum != null)
Tom Tromey committed
290
      {
291 292
        minimum = newMinimum;
        fireStateChanged();
Tom Tromey committed
293 294 295
      }
  }

296 297 298 299
  /**
   * Returns the maximum value, or <code>null</code> if there is no maximum.
   * 
   * @return The maximum value.
300 301 302
   * 
   * @see #getMinimum()
   * @see #setMaximum(Comparable)
303
   */
Tom Tromey committed
304 305 306 307 308
  public Comparable getMaximum()
  {
    return maximum;
  }

309 310 311 312 313 314
  /**
   * Sets the maximum value and, if the new value is different to the old
   * value, sends a {@link ChangeEvent} to all registered listeners.  A 
   * <code>null</code> value is interpreted as "no maximum value".  No check
   * is made to ensure that the new maximum is greater than or equal to the 
   * current value, the caller is responsible for ensuring that this 
315 316
   * relationship holds. In addition, the caller should ensure that
   * <code>newMaximum</code> is {@link Serializable}.
317 318
   * 
   * @param newMaximum  the new maximum (<code>null</code> permitted).
319 320
   * 
   * @see #getMaximum()
321
   */
Tom Tromey committed
322 323
  public void setMaximum(Comparable newMaximum)
  {
324
    if (maximum != null ? !maximum.equals(newMaximum) : newMaximum != null)
Tom Tromey committed
325
      {
326 327
        maximum = newMaximum;
        fireStateChanged();
Tom Tromey committed
328 329 330
      }
  }

331 332 333
  /**
   * Returns the step size.
   * 
334
   * @return The step size (never <code>null</code>).
335
   */
Tom Tromey committed
336 337 338 339 340
  public Number getStepSize()
  {
    return stepSize;
  }

341 342 343 344 345 346 347 348 349
  /**
   * Sets the step size and, if the new step size is different to the old
   * step size, sends a {@link ChangeEvent} to all registered listeners.
   * 
   * @param newStepSize  the new step size (<code>null</code> not permitted).
   * 
   * @throws IllegalArgumentException if <code>newStepSize</code> is 
   *         <code>null</code>.
   */
Tom Tromey committed
350 351 352 353 354
  public void setStepSize(Number newStepSize)
  {
    if (newStepSize == null)
      throw new IllegalArgumentException();

355
    if (!stepSize.equals(newStepSize))
Tom Tromey committed
356
      {
357 358
        stepSize = newStepSize;
        fireStateChanged();
Tom Tromey committed
359 360 361
      }
  }
}