Frames | No Frames |
1: /* SpinnerNumberModel.java -- 2: Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package javax.swing; 39: 40: import java.io.Serializable; 41: 42: import javax.swing.event.ChangeEvent; 43: 44: /** 45: * A model used by the {@link JSpinner} component. 46: * 47: * @author Ka-Hing Cheung 48: * @since 1.4 49: */ 50: public class SpinnerNumberModel extends AbstractSpinnerModel 51: implements Serializable 52: { 53: /** 54: * For compatability with Sun's JDK 55: */ 56: private static final long serialVersionUID = 7279176385485777821L; 57: 58: /** The current value. */ 59: private Number value; 60: 61: /** The minimum value (or <code>null</code>). */ 62: private Comparable minimum; 63: 64: /** The maximum value (or <code>null</code>). */ 65: private Comparable maximum; 66: 67: /** The step size. */ 68: private Number stepSize; 69: 70: /** 71: * Creates a <code>SpinnerNumberModel</code> with initial value 0, step 1, 72: * and no maximum nor minimum. 73: */ 74: public SpinnerNumberModel() 75: { 76: this(new Integer(0), null, null, new Integer(1)); 77: } 78: 79: /** 80: * Creates a <code>SpinnerNumberModel</code> with double precision. 81: * 82: * @param value the initial value 83: * @param minimum the minimum value 84: * @param maximum the maximum value 85: * @param stepSize the step size 86: * @throws IllegalArgumentException if minimum <= value <= maximum does 87: * not hold. 88: */ 89: public SpinnerNumberModel(double value, double minimum, double maximum, 90: double stepSize) 91: { 92: this(new Double(value), new Double(minimum), new Double(maximum), 93: new Double(stepSize)); 94: } 95: 96: /** 97: * Creates a <code>SpinnerNumberModel</code> with integer precision. 98: * 99: * @param value the initial value 100: * @param minimum the minimum value 101: * @param maximum the maximum value 102: * @param stepSize the step size 103: * @throws IllegalArgumentException if minimum <= value <= maximum does 104: * not hold. 105: */ 106: public SpinnerNumberModel(int value, int minimum, int maximum, int stepSize) 107: { 108: this(new Integer(value), new Integer(minimum), new Integer(maximum), 109: new Integer(stepSize)); 110: } 111: 112: /** 113: * Creates a <code>SpinnerNumberModel</code> with the given attributes. The 114: * caller should ensure that both <code>minimum</code> and 115: * <code>maximum</code> are serializable. 116: * 117: * @param value the initial value (<code>null</code> not permitted). 118: * @param minimum the minimum value (<code>null</code> permitted). 119: * @param maximum the maximum value (<code>null</code> permitted). 120: * @param stepSize the step size (<code>null</code> not permitted). 121: * 122: * @throws IllegalArgumentException if minimum <= value <= maximum 123: * does not hold 124: * @throws IllegalArgumentException if <code>value</code> is 125: * <code>null</code>. 126: * @throws IllegalArgumentException if <code>stepSize</code> is 127: * <code>null</code>. 128: */ 129: public SpinnerNumberModel(Number value, Comparable minimum, 130: Comparable maximum, Number stepSize) 131: { 132: if (stepSize == null) 133: throw new IllegalArgumentException("stepSize may not be null"); 134: if (value == null) 135: throw new IllegalArgumentException("value may not be null"); 136: if (minimum != null) 137: { 138: if (minimum.compareTo(value) > 0) 139: throw new IllegalArgumentException("minimum is not <= value"); 140: } 141: if (maximum != null) 142: { 143: if (maximum.compareTo(value) < 0) 144: throw new IllegalArgumentException("maximum is not >= value"); 145: } 146: 147: this.value = value; 148: this.stepSize = stepSize; 149: this.minimum = minimum; 150: this.maximum = maximum; 151: } 152: 153: /** 154: * Sets the current value and, if the new value is different to the old 155: * value, sends a {@link ChangeEvent} to all registered listeners. 156: * 157: * @param value the new value (<code>null</code> not permitted, must be an 158: * instance of <code>Number</code>). 159: * 160: * @throws IllegalArgumentException if <code>value</code> is not an instance 161: * of <code>Number</code>. 162: */ 163: public void setValue(Object value) 164: { 165: if (! (value instanceof Number)) 166: throw new IllegalArgumentException("value must be a Number"); 167: 168: if (!this.value.equals(value)) 169: { 170: this.value = (Number) value; 171: fireStateChanged(); 172: } 173: } 174: 175: /** 176: * Returns the current value, which for this class is always an instance of 177: * {@link Number}. 178: * 179: * @return The current value. 180: * 181: * @see #getNumber() 182: */ 183: public Object getValue() 184: { 185: return value; 186: } 187: 188: /** 189: * Returns the next value, or <code>null</code> if adding the step size to 190: * the current value results in a value greater than the maximum value. 191: * The current value is not changed. 192: * 193: * @return The next value, or <code>null</code> if the current value is the 194: * maximum value represented by this model. 195: */ 196: public Object getNextValue() 197: { 198: Number num; 199: 200: if (value instanceof Double) 201: num = new Double(value.doubleValue() + stepSize.doubleValue()); 202: else if (value instanceof Float) 203: num = new Double(value.floatValue() + stepSize.floatValue()); 204: else if (value instanceof Long) 205: num = new Long(value.longValue() + stepSize.longValue()); 206: else if (value instanceof Integer) 207: num = new Integer(value.intValue() + stepSize.intValue()); 208: else if (value instanceof Short) 209: num = new Short((short) (value.shortValue() + stepSize.shortValue())); 210: else 211: num = new Byte((byte) (value.byteValue() + stepSize.byteValue())); 212: 213: // check upper bound if set 214: if ((maximum != null) && maximum.compareTo(num) < 0) 215: num = null; 216: 217: return num; 218: } 219: 220: /** 221: * Returns the previous value, or <code>null</code> if subtracting the 222: * step size from the current value results in a value less than the minimum 223: * value. The current value is not changed. 224: * 225: * @return The previous value, or <code>null</code> if the current value 226: * is the minimum value represented by this model. 227: */ 228: public Object getPreviousValue() 229: { 230: Number num; 231: 232: if (value instanceof Double) 233: num = new Double(value.doubleValue() - stepSize.doubleValue()); 234: else if (value instanceof Float) 235: num = new Double(value.floatValue() - stepSize.floatValue()); 236: else if (value instanceof Long) 237: num = new Long(value.longValue() - stepSize.longValue()); 238: else if (value instanceof Integer) 239: num = new Integer(value.intValue() - stepSize.intValue()); 240: else if (value instanceof Short) 241: num = new Short((short) (value.shortValue() - stepSize.shortValue())); 242: else 243: num = new Byte((byte) (value.byteValue() - stepSize.byteValue())); 244: 245: // check lower bound if set 246: if ((minimum != null) && minimum.compareTo(num) > 0) 247: num = null; 248: 249: return num; 250: } 251: 252: /** 253: * Returns the current value. 254: * 255: * @return The current value. 256: */ 257: public Number getNumber() 258: { 259: return value; 260: } 261: 262: /** 263: * Returns the minimum value, or <code>null</code> if there is no minimum. 264: * 265: * @return The minimum value. 266: * 267: * @see #setMinimum(Comparable) 268: */ 269: public Comparable getMinimum() 270: { 271: return minimum; 272: } 273: 274: /** 275: * Sets the minimum value and, if the new value is different to the old 276: * value, sends a {@link ChangeEvent} to all registered listeners. A 277: * <code>null</code> value is interpreted as "no minimum value". No check 278: * is made to ensure that the new minimum is less than or equal to the 279: * current value, the caller is responsible for ensuring that this 280: * relationship holds. In addition, the caller should ensure that 281: * <code>newMinimum</code> is {@link Serializable}. 282: * 283: * @param newMinimum the new minimum value (<code>null</code> permitted). 284: * 285: * @see #getMinimum() 286: */ 287: public void setMinimum(Comparable newMinimum) 288: { 289: if (minimum != null ? !minimum.equals(newMinimum) : newMinimum != null) 290: { 291: minimum = newMinimum; 292: fireStateChanged(); 293: } 294: } 295: 296: /** 297: * Returns the maximum value, or <code>null</code> if there is no maximum. 298: * 299: * @return The maximum value. 300: * 301: * @see #getMinimum() 302: * @see #setMaximum(Comparable) 303: */ 304: public Comparable getMaximum() 305: { 306: return maximum; 307: } 308: 309: /** 310: * Sets the maximum value and, if the new value is different to the old 311: * value, sends a {@link ChangeEvent} to all registered listeners. A 312: * <code>null</code> value is interpreted as "no maximum value". No check 313: * is made to ensure that the new maximum is greater than or equal to the 314: * current value, the caller is responsible for ensuring that this 315: * relationship holds. In addition, the caller should ensure that 316: * <code>newMaximum</code> is {@link Serializable}. 317: * 318: * @param newMaximum the new maximum (<code>null</code> permitted). 319: * 320: * @see #getMaximum() 321: */ 322: public void setMaximum(Comparable newMaximum) 323: { 324: if (maximum != null ? !maximum.equals(newMaximum) : newMaximum != null) 325: { 326: maximum = newMaximum; 327: fireStateChanged(); 328: } 329: } 330: 331: /** 332: * Returns the step size. 333: * 334: * @return The step size (never <code>null</code>). 335: */ 336: public Number getStepSize() 337: { 338: return stepSize; 339: } 340: 341: /** 342: * Sets the step size and, if the new step size is different to the old 343: * step size, sends a {@link ChangeEvent} to all registered listeners. 344: * 345: * @param newStepSize the new step size (<code>null</code> not permitted). 346: * 347: * @throws IllegalArgumentException if <code>newStepSize</code> is 348: * <code>null</code>. 349: */ 350: public void setStepSize(Number newStepSize) 351: { 352: if (newStepSize == null) 353: throw new IllegalArgumentException(); 354: 355: if (!stepSize.equals(newStepSize)) 356: { 357: stepSize = newStepSize; 358: fireStateChanged(); 359: } 360: } 361: }