History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/SpinnerNumberModel.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/SpinnerNumberModel.java+450−0
@@ -0,0 +1,450 @@
1+/*
2+ * Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package javax.swing;
27+
28+import java.util.*;
29+import java.io.Serializable;
30+
31+
32+/**
33+ * A <code>SpinnerModel</code> for sequences of numbers.
34+ * The upper and lower bounds of the sequence are defined
35+ * by properties called <code>minimum</code> and
36+ * <code>maximum</code>. The size of the increase or decrease
37+ * computed by the <code>nextValue</code> and
38+ * <code>previousValue</code> methods is defined by a property called
39+ * <code>stepSize</code>. The <code>minimum</code> and
40+ * <code>maximum</code> properties can be <code>null</code>
41+ * to indicate that the sequence has no lower or upper limit.
42+ * All of the properties in this class are defined in terms of two
43+ * generic types: <code>Number</code> and
44+ * <code>Comparable</code>, so that all Java numeric types
45+ * may be accommodated. Internally, there's only support for
46+ * values whose type is one of the primitive <code>Number</code> types:
47+ * <code>Double</code>, <code>Float</code>, <code>Long</code>,
48+ * <code>Integer</code>, <code>Short</code>, or <code>Byte</code>.
49+ * <p>
50+ * To create a <code>SpinnerNumberModel</code> for the integer
51+ * range zero to one hundred, with
52+ * fifty as the initial value, one could write:
53+ * <pre>
54+ * Integer value = new Integer(50);
55+ * Integer min = new Integer(0);
56+ * Integer max = new Integer(100);
57+ * Integer step = new Integer(1);
58+ * SpinnerNumberModel model = new SpinnerNumberModel(value, min, max, step);
59+ * int fifty = model.getNumber().intValue();
60+ * </pre>
61+ * <p>
62+ * Spinners for integers and doubles are common, so special constructors
63+ * for these cases are provided. For example to create the model in
64+ * the previous example, one could also write:
65+ * <pre>
66+ * SpinnerNumberModel model = new SpinnerNumberModel(50, 0, 100, 1);
67+ * </pre>
68+ * <p>
69+ * This model inherits a <code>ChangeListener</code>.
70+ * The <code>ChangeListeners</code> are notified
71+ * whenever the model's <code>value</code>, <code>stepSize</code>,
72+ * <code>minimum</code>, or <code>maximum</code> properties changes.
73+ *
74+ * @see JSpinner
75+ * @see SpinnerModel
76+ * @see AbstractSpinnerModel
77+ * @see SpinnerListModel
78+ * @see SpinnerDateModel
79+ *
80+ * @author Hans Muller
81+ * @since 1.4
82+*/
83+public class SpinnerNumberModel extends AbstractSpinnerModel implements Serializable
84+{
85+ private Number stepSize, value;
86+ private Comparable minimum, maximum;
87+
88+
89+ /**
90+ * Constructs a <code>SpinnerModel</code> that represents
91+ * a closed sequence of
92+ * numbers from <code>minimum</code> to <code>maximum</code>. The
93+ * <code>nextValue</code> and <code>previousValue</code> methods
94+ * compute elements of the sequence by adding or subtracting
95+ * <code>stepSize</code> respectively. All of the parameters
96+ * must be mutually <code>Comparable</code>, <code>value</code>
97+ * and <code>stepSize</code> must be instances of <code>Integer</code>
98+ * <code>Long</code>, <code>Float</code>, or <code>Double</code>.
99+ * <p>
100+ * The <code>minimum</code> and <code>maximum</code> parameters
101+ * can be <code>null</code> to indicate that the range doesn't
102+ * have an upper or lower bound.
103+ * If <code>value</code> or <code>stepSize</code> is <code>null</code>,
104+ * or if both <code>minimum</code> and <code>maximum</code>
105+ * are specified and <code>mininum &gt; maximum</code> then an
106+ * <code>IllegalArgumentException</code> is thrown.
107+ * Similarly if <code>(minimum &lt;= value &lt;= maximum</code>) is false,
108+ * an <code>IllegalArgumentException</code> is thrown.
109+ *
110+ * @param value the current (non <code>null</code>) value of the model
111+ * @param minimum the first number in the sequence or <code>null</code>
112+ * @param maximum the last number in the sequence or <code>null</code>
113+ * @param stepSize the difference between elements of the sequence
114+ *
115+ * @throws IllegalArgumentException if stepSize or value is
116+ * <code>null</code> or if the following expression is false:
117+ * <code>minimum &lt;= value &lt;= maximum</code>
118+ */
119+ public SpinnerNumberModel(Number value, Comparable minimum, Comparable maximum, Number stepSize) {
120+ if ((value == null) || (stepSize == null)) {
121+ throw new IllegalArgumentException("value and stepSize must be non-null");
122+ }
123+ if (!(((minimum == null) || (minimum.compareTo(value) <= 0)) &&
124+ ((maximum == null) || (maximum.compareTo(value) >= 0)))) {
125+ throw new IllegalArgumentException("(minimum <= value <= maximum) is false");
126+ }
127+ this.value = value;
128+ this.minimum = minimum;
129+ this.maximum = maximum;
130+ this.stepSize = stepSize;
131+ }
132+
133+
134+ /**
135+ * Constructs a <code>SpinnerNumberModel</code> with the specified
136+ * <code>value</code>, <code>minimum</code>/<code>maximum</code> bounds,
137+ * and <code>stepSize</code>.
138+ *
139+ * @param value the current value of the model
140+ * @param minimum the first number in the sequence
141+ * @param maximum the last number in the sequence
142+ * @param stepSize the difference between elements of the sequence
143+ * @throws IllegalArgumentException if the following expression is false:
144+ * <code>minimum &lt;= value &lt;= maximum</code>
145+ */
146+ public SpinnerNumberModel(int value, int minimum, int maximum, int stepSize) {
147+ this(Integer.valueOf(value), Integer.valueOf(minimum), Integer.valueOf(maximum), Integer.valueOf(stepSize));
148+ }
149+
150+
151+ /**
152+ * Constructs a <code>SpinnerNumberModel</code> with the specified
153+ * <code>value</code>, <code>minimum</code>/<code>maximum</code> bounds,
154+ * and <code>stepSize</code>.
155+ *
156+ * @param value the current value of the model
157+ * @param minimum the first number in the sequence
158+ * @param maximum the last number in the sequence
159+ * @param stepSize the difference between elements of the sequence
160+ * @throws IllegalArgumentException if the following expression is false:
161+ * <code>minimum &lt;= value &lt;= maximum</code>
162+ */
163+ public SpinnerNumberModel(double value, double minimum, double maximum, double stepSize) {
164+ this(new Double(value), new Double(minimum), new Double(maximum), new Double(stepSize));
165+ }
166+
167+
168+ /**
169+ * Constructs a <code>SpinnerNumberModel</code> with no
170+ * <code>minimum</code> or <code>maximum</code> value,
171+ * <code>stepSize</code> equal to one, and an initial value of zero.
172+ */
173+ public SpinnerNumberModel() {
174+ this(Integer.valueOf(0), null, null, Integer.valueOf(1));
175+ }
176+
177+
178+ /**
179+ * Changes the lower bound for numbers in this sequence.
180+ * If <code>minimum</code> is <code>null</code>,
181+ * then there is no lower bound. No bounds checking is done here;
182+ * the new <code>minimum</code> value may invalidate the
183+ * <code>(minimum &lt;= value &lt= maximum)</code>
184+ * invariant enforced by the constructors. This is to simplify updating
185+ * the model, naturally one should ensure that the invariant is true
186+ * before calling the <code>getNextValue</code>,
187+ * <code>getPreviousValue</code>, or <code>setValue</code> methods.
188+ * <p>
189+ * Typically this property is a <code>Number</code> of the same type
190+ * as the <code>value</code> however it's possible to use any
191+ * <code>Comparable</code> with a <code>compareTo</code>
192+ * method for a <code>Number</code> with the same type as the value.
193+ * For example if value was a <code>Long</code>,
194+ * <code>minimum</code> might be a Date subclass defined like this:
195+ * <pre>
196+ * MyDate extends Date { // Date already implements Comparable
197+ * public int compareTo(Long o) {
198+ * long t = getTime();
199+ * return (t < o.longValue() ? -1 : (t == o.longValue() ? 0 : 1));
200+ * }
201+ * }
202+ * </pre>
203+ * <p>
204+ * This method fires a <code>ChangeEvent</code>
205+ * if the <code>minimum</code> has changed.
206+ *
207+ * @param minimum a <code>Comparable</code> that has a
208+ * <code>compareTo</code> method for <code>Number</code>s with
209+ * the same type as <code>value</code>
210+ * @see #getMinimum
211+ * @see #setMaximum
212+ * @see SpinnerModel#addChangeListener
213+ */
214+ public void setMinimum(Comparable minimum) {
215+ if ((minimum == null) ? (this.minimum != null) : !minimum.equals(this.minimum)) {
216+ this.minimum = minimum;
217+ fireStateChanged();
218+ }
219+ }
220+
221+
222+ /**
223+ * Returns the first number in this sequence.
224+ *
225+ * @return the value of the <code>minimum</code> property
226+ * @see #setMinimum
227+ */
228+ public Comparable getMinimum() {
229+ return minimum;
230+ }
231+
232+
233+ /**
234+ * Changes the upper bound for numbers in this sequence.
235+ * If <code>maximum</code> is <code>null</code>, then there
236+ * is no upper bound. No bounds checking is done here; the new
237+ * <code>maximum</code> value may invalidate the
238+ * <code>(minimum <= value < maximum)</code>
239+ * invariant enforced by the constructors. This is to simplify updating
240+ * the model, naturally one should ensure that the invariant is true
241+ * before calling the <code>next</code>, <code>previous</code>,
242+ * or <code>setValue</code> methods.
243+ * <p>
244+ * Typically this property is a <code>Number</code> of the same type
245+ * as the <code>value</code> however it's possible to use any
246+ * <code>Comparable</code> with a <code>compareTo</code>
247+ * method for a <code>Number</code> with the same type as the value.
248+ * See <a href="#setMinimum(java.lang.Comparable)">
249+ * <code>setMinimum</code></a> for an example.
250+ * <p>
251+ * This method fires a <code>ChangeEvent</code> if the
252+ * <code>maximum</code> has changed.
253+ *
254+ * @param maximum a <code>Comparable</code> that has a
255+ * <code>compareTo</code> method for <code>Number</code>s with
256+ * the same type as <code>value</code>
257+ * @see #getMaximum
258+ * @see #setMinimum
259+ * @see SpinnerModel#addChangeListener
260+ */
261+ public void setMaximum(Comparable maximum) {
262+ if ((maximum == null) ? (this.maximum != null) : !maximum.equals(this.maximum)) {
263+ this.maximum = maximum;
264+ fireStateChanged();
265+ }
266+ }
267+
268+
269+ /**
270+ * Returns the last number in the sequence.
271+ *
272+ * @return the value of the <code>maximum</code> property
273+ * @see #setMaximum
274+ */
275+ public Comparable getMaximum() {
276+ return maximum;
277+ }
278+
279+
280+ /**
281+ * Changes the size of the value change computed by the
282+ * <code>getNextValue</code> and <code>getPreviousValue</code>
283+ * methods. An <code>IllegalArgumentException</code>
284+ * is thrown if <code>stepSize</code> is <code>null</code>.
285+ * <p>
286+ * This method fires a <code>ChangeEvent</code> if the
287+ * <code>stepSize</code> has changed.
288+ *
289+ * @param stepSize the size of the value change computed by the
290+ * <code>getNextValue</code> and <code>getPreviousValue</code> methods
291+ * @see #getNextValue
292+ * @see #getPreviousValue
293+ * @see #getStepSize
294+ * @see SpinnerModel#addChangeListener
295+ */
296+ public void setStepSize(Number stepSize) {
297+ if (stepSize == null) {
298+ throw new IllegalArgumentException("null stepSize");
299+ }
300+ if (!stepSize.equals(this.stepSize)) {
301+ this.stepSize = stepSize;
302+ fireStateChanged();
303+ }
304+ }
305+
306+
307+ /**
308+ * Returns the size of the value change computed by the
309+ * <code>getNextValue</code>
310+ * and <code>getPreviousValue</code> methods.
311+ *
312+ * @return the value of the <code>stepSize</code> property
313+ * @see #setStepSize
314+ */
315+ public Number getStepSize() {
316+ return stepSize;
317+ }
318+
319+
320+ private Number incrValue(int dir)
321+ {
322+ Number newValue;
323+ if ((value instanceof Float) || (value instanceof Double)) {
324+ double v = value.doubleValue() + (stepSize.doubleValue() * (double)dir);
325+ if (value instanceof Double) {
326+ newValue = new Double(v);
327+ }
328+ else {
329+ newValue = new Float(v);
330+ }
331+ }
332+ else {
333+ long v = value.longValue() + (stepSize.longValue() * (long)dir);
334+
335+ if (value instanceof Long) {
336+ newValue = Long.valueOf(v);
337+ }
338+ else if (value instanceof Integer) {
339+ newValue = Integer.valueOf((int)v);
340+ }
341+ else if (value instanceof Short) {
342+ newValue = Short.valueOf((short)v);
343+ }
344+ else {
345+ newValue = Byte.valueOf((byte)v);
346+ }
347+ }
348+
349+ if ((maximum != null) && (maximum.compareTo(newValue) < 0)) {
350+ return null;
351+ }
352+ if ((minimum != null) && (minimum.compareTo(newValue) > 0)) {
353+ return null;
354+ }
355+ else {
356+ return newValue;
357+ }
358+ }
359+
360+
361+ /**
362+ * Returns the next number in the sequence.
363+ *
364+ * @return <code>value + stepSize</code> or <code>null</code> if the sum
365+ * exceeds <code>maximum</code>.
366+ *
367+ * @see SpinnerModel#getNextValue
368+ * @see #getPreviousValue
369+ * @see #setStepSize
370+ */
371+ public Object getNextValue() {
372+ return incrValue(+1);
373+ }
374+
375+
376+ /**
377+ * Returns the previous number in the sequence.
378+ *
379+ * @return <code>value - stepSize</code>, or
380+ * <code>null</code> if the sum is less
381+ * than <code>minimum</code>.
382+ *
383+ * @see SpinnerModel#getPreviousValue
384+ * @see #getNextValue
385+ * @see #setStepSize
386+ */
387+ public Object getPreviousValue() {
388+ return incrValue(-1);
389+ }
390+
391+
392+ /**
393+ * Returns the value of the current element of the sequence.
394+ *
395+ * @return the value property
396+ * @see #setValue
397+ */
398+ public Number getNumber() {
399+ return value;
400+ }
401+
402+
403+ /**
404+ * Returns the value of the current element of the sequence.
405+ *
406+ * @return the value property
407+ * @see #setValue
408+ * @see #getNumber
409+ */
410+ public Object getValue() {
411+ return value;
412+ }
413+
414+
415+ /**
416+ * Sets the current value for this sequence. If <code>value</code> is
417+ * <code>null</code>, or not a <code>Number</code>, an
418+ * <code>IllegalArgumentException</code> is thrown. No
419+ * bounds checking is done here; the new value may invalidate the
420+ * <code>(minimum &lt;= value &lt;= maximum)</code>
421+ * invariant enforced by the constructors. It's also possible to set
422+ * the value to be something that wouldn't naturally occur in the sequence,
423+ * i.e. a value that's not modulo the <code>stepSize</code>.
424+ * This is to simplify updating the model, and to accommodate
425+ * spinners that don't want to restrict values that have been
426+ * directly entered by the user. Naturally, one should ensure that the
427+ * <code>(minimum &lt;= value &lt;= maximum)</code> invariant is true
428+ * before calling the <code>next</code>, <code>previous</code>, or
429+ * <code>setValue</code> methods.
430+ * <p>
431+ * This method fires a <code>ChangeEvent</code> if the value has changed.
432+ *
433+ * @param value the current (non <code>null</code>) <code>Number</code>
434+ * for this sequence
435+ * @throws IllegalArgumentException if <code>value</code> is
436+ * <code>null</code> or not a <code>Number</code>
437+ * @see #getNumber
438+ * @see #getValue
439+ * @see SpinnerModel#addChangeListener
440+ */
441+ public void setValue(Object value) {
442+ if ((value == null) || !(value instanceof Number)) {
443+ throw new IllegalArgumentException("illegal value");
444+ }
445+ if (!value.equals(this.value)) {
446+ this.value = (Number)value;
447+ fireStateChanged();
448+ }
449+ }
450+}