2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
41
package org.openide.awt;
44
import java.awt.event.MouseAdapter;
45
import java.awt.event.MouseEvent;
47
import java.beans.PropertyChangeListener;
48
import java.beans.PropertyChangeSupport;
50
import java.util.Vector;
54
* A class that produces a Spin Button.
57
* <TABLE BORDER COLS=3 WIDTH=100%>
58
* <TR><TH WIDTH=15%>Property<TH WIDTH=15%>Property Type<TH>Description
59
* <TR><TD> Orientation <TD> boolean <TD> Orientation of SpinButton (Left-right or Up-down)
60
* <TR><TD> Minimum <TD> int <TD> Minimum value.
61
* <TR><TD> Maximum <TD> int <TD> Maximum value.
62
* <TR><TD> Step <TD> int <TD> Step.
63
* <TR><TD> Value <TD> int <TD> Current value.
64
* <TR><TD> RepeatDelay <TD> int <TD> Delay time after press SpinButton [ms]
65
* <TR><TD> RepeatRate <TD> int <TD> Repeat rate while holding PressButton [ms]
68
* @deprecated Obsoleted by <code>javax.swing.JSpinner</code> in JDK 1.4
69
* @version 3.06, November 17, 1997
70
* @author Petr Hamernik, Jan Jancura
72
public class SpinButton extends Canvas {
73
/** generated Serialized Version UID */
74
static final long serialVersionUID = -3525959415481788776L;
76
/** Default orientation of SpinButton. Currently false (UP-DOWN).
77
* @see #DEFAULT_ORIENTATION
78
* @see #setOrientation
79
* @see #getOrientation
81
public static final boolean DEFAULT_ORIENTATION = false;
83
/** Default minimum. Currently 0.
88
public static final int DEFAULT_MINIMUM = 0;
90
/** Default maximum. Currently 100.
95
public static final int DEFAULT_MAXIMUM = 100;
97
/** Default step. Currently 1.
102
public static final int DEFAULT_STEP = 1;
104
/** Default value of repeatDelay. Currently 300 ms.
109
public static final int DEFAULT_REPEAT_DELAY = 300;
111
/** Default value of repeatRate. Currently 70 ms.
116
public static final int DEFAULT_REPEAT_RATE = 70;
118
/** Helper constant */
119
private static final boolean SPIN_UP = true;
121
/** Helper constant */
122
private static final boolean SPIN_DOWN = false;
124
/** Current orientation of SpinButton.
125
* True = LEFT-RIGHT, False = UP-DOWN
126
* @see #DEFAULT_ORIENTATION
127
* @see #setOrientation
128
* @see #getOrientation
130
protected boolean orientation = DEFAULT_ORIENTATION;
132
/** Current orientation of arrows of SpinButton.
133
* True = LEFT-RIGHT, False = UP-DOWN
134
* @see #DEFAULT_ORIENTATION
135
* @see #setOrientation
136
* @see #getOrientation
138
protected boolean arrowsOrientation = DEFAULT_ORIENTATION;
140
/** Minimum of the range of the SpinButton.
141
* @see #DEFAULT_MINIMUM
145
protected int minimum = DEFAULT_MINIMUM;
147
/** Maximum of the range of the SpinButton.
148
* @see #DEFAULT_MAXIMUM
152
protected int maximum = DEFAULT_MAXIMUM;
154
/** Step of the SpinButton.
159
protected int step = DEFAULT_STEP;
161
/** Value of the SpinButton. Default 0.
165
protected int value = 0;
167
/** Adjusts the amount of time that elapses before a increment
168
* (or decrement) begins repeating when you hold down a mouse
172
* @see #DEFAULT_REPEAT_DELAY
174
protected int repeatDelay = DEFAULT_REPEAT_DELAY;
176
/** Adjusts the speed at which a increment (or decrement)
177
* repeats when you hold down a mouse button. [ms]
180
* @see #DEFAULT_REPEAT_RATE
182
protected int repeatRate = DEFAULT_REPEAT_RATE;
184
/** Spin repeat thread. When the SpinButton is holded this thread
185
* runs and regulary sends the events to SpinButton.
187
protected RepeatThread rt = null;
189
/** Flag if the SpinRepeatThread is currently running. */
190
protected boolean running = false;
192
/** Flag if the SpinRepeatThread is currently running. */
193
protected boolean repeating = true;
195
/** Current direction of the run of the SpinRepeatThread. */
196
protected boolean runningDir = SPIN_DOWN;
197
protected boolean boundsIgnored = false;
199
/** Property change listeners storage */
200
private PropertyChangeSupport valueSupport = new PropertyChangeSupport(this);
202
/** SpinButton change listeners storage */
203
private Vector<SpinButtonListener> spinButtonListeners = new Vector<SpinButtonListener>(3, 3);
205
/** Create new SpinButton. */
206
public SpinButton() {
207
setBackground(SystemColor.control);
208
setForeground(SystemColor.controlText);
212
public void mousePressed(MouseEvent evt) {
213
Dimension d = getSize();
214
boolean newDir = SPIN_UP;
217
if (evt.getX() <= ((d.width - 1) / 2)) {
223
if (evt.getY() <= ((d.height - 1) / 2)) {
231
(((newDir == SPIN_UP) && (value >= maximum)) || ((newDir == SPIN_DOWN) && (value <= minimum))) &&
241
public void mouseReleased(MouseEvent evt) {
254
* Setter method for foreground color.
256
* @param color New foreground color.
258
public void setForeground(Color color) {
259
super.setForeground(color);
263
/** Sets the new orientation.
264
* @param aDir new value of orientation.
266
* @see #DEFAULT_ORIENTATION
267
* @see #getOrientation
269
public void setOrientation(boolean aDir) {
275
/** Sets the new orientation of arows.
276
* @param aDir new value of orientation of arows.
278
* @see #DEFAULT_ORIENTATION
279
* @see #getOrientation
281
public void setArrowsOrientation(boolean aDir) {
282
arrowsOrientation = aDir;
287
/** Gets the current orientation of SpinButton.
288
* @return value of orientation.
290
* @see #DEFAULT_ORIENTATION
291
* @see #setOrientation
293
public boolean getOrientation() {
297
/** Gets the current orientation of Arrows of SpinButton.
298
* @return value of orientation of Arrows.
300
* @see #DEFAULT_ORIENTATION
301
* @see #setOrientation
303
public boolean getArrowsOrientation() {
304
return arrowsOrientation;
307
/** Sets a minimum of the range of the SpinButton. If value
308
* or maximum fall out of acceptable values they are adjusted.
309
* @param aMin New minimum.
312
public void setMinimum(int aMin) {
315
if (maximum < minimum) {
319
if (value < minimum) {
327
/** Gets the current minimum of the range of SpinButton.
331
public int getMinimum() {
335
/** Sets a maximum of the range of the SpinButton. If value
336
* or minimum fall out of acceptable values they are adjusted.
337
* @param aMax New maximum.
340
public void setMaximum(int aMax) {
343
if (maximum < minimum) {
347
if (value > maximum) {
355
/** Gets the current maximum of the range of SpinButton.
359
public int getMaximum() {
363
/** Sets a new value of the SpinButton. If value is outside
364
* the ranges it is set to nearest acceptable value.
365
* @param aValue New value.
368
public void setValue(int aValue) {
369
int oldValue = value;
373
if (!boundsIgnored) {
374
if (value < minimum) {
378
if (value > maximum) {
383
if (value != oldValue) {
384
valueSupport.firePropertyChange("value", new Integer(oldValue), new Integer(value)); // NOI18N
387
if ((getValue() == minimum) || (getValue() == maximum) || (oldValue == minimum) || (oldValue == maximum)) {
392
/** Gets the current value of the SpinButton.
396
public int getValue() {
400
/** Sets a new step of the SpinButton.
401
* @param aStep New step.
404
public void setStep(int aStep) {
410
/** Gets the current step of the SpinButton.
414
public int getStep() {
418
/** Sets new value of repeatDelay variable.
419
* @param aDelay New delay.
423
public void setDelay(int aDelay) {
424
repeatDelay = aDelay;
429
/** Gets the current value of repeatDelay variable.
434
public int getDelay() {
438
/** Sets new value of repeatRate variable.
439
* @param aRate New rate.
443
public void setRate(int aRate) {
449
/** Gets the current value of rate variable.
454
public int getRate() {
458
public boolean isBoundsIgnored() {
459
return boundsIgnored;
462
public void setBoundsIgnored(boolean ignored) {
463
boundsIgnored = ignored;
466
public boolean isRepeating() {
470
public void setRepeating(boolean aRepeating) {
471
repeating = aRepeating;
474
public void paint(Graphics g) {
475
Dimension d = getSize();
480
int h = d.height - 1;
482
g.setColor(getBackground());
483
g.fillRect(left, top, w, h);
487
paintBorder(g, left, top, w, h, running && (runningDir == SPIN_DOWN), SPIN_DOWN);
489
w = d.width - 1 - left;
490
paintBorder(g, left, top, w, h, running && (runningDir == SPIN_UP), SPIN_UP);
493
paintBorder(g, left, top, w, h, running && (runningDir == SPIN_UP), SPIN_UP);
495
h = d.height - 1 - top;
496
paintBorder(g, left, top, w, h, running && (runningDir == SPIN_DOWN), SPIN_DOWN);
500
private void paintBorder(Graphics g, int x, int y, int w, int h, boolean isDown, boolean aDir) {
501
g.setColor(Color.black);
504
g.drawLine(x, y + h, x + w, y + h);
505
g.drawLine(x + w, y, x + w, y + h);
507
g.drawLine(x, y, x + w, y);
508
g.drawLine(x, y, x, y + h);
515
g.setColor(SystemColor.controlHighlight);
516
g.draw3DRect(x, y, w, h, !isDown);
517
paintArrow(g, x, y, w, h, aDir);
520
private void paintArrow(Graphics g, int x, int y, int w, int h, boolean aDir) {
521
if ((w <= 0) || (h <= 0)) {
527
int[] xP = new int[3];
528
int[] yP = new int[3];
530
if (arrowsOrientation) {
531
if (aDir == SPIN_UP) {
533
xP[2] = (x + w) - wd;
535
xP[0] = (x + w) - wd;
541
yP[1] = (y + h) - hd;
544
if (aDir == SPIN_UP) {
545
yP[0] = (y + h) - hd;
549
yP[2] = (y + h) - hd;
554
xP[1] = (x + w) - wd;
559
(((aDir == SPIN_UP) && (value >= maximum)) || ((aDir == SPIN_DOWN) && (value <= minimum))) &&
562
Color fg = getForeground();
563
Color bg = getBackground();
566
(fg.getRed() + (2 * bg.getRed())) / 3, (fg.getGreen() + (2 * bg.getGreen())) / 3,
567
(fg.getBlue() + (2 * bg.getBlue())) / 3
571
g.setColor(getForeground());
574
g.fillPolygon(xP, yP, 3);
577
protected synchronized void switchRun(boolean aDirect) {
582
rt = new RepeatThread();
584
runningDir = aDirect;
588
public synchronized void switchStop() {
597
public Dimension getMinimumSize() {
601
public Dimension getPreferredSize() {
605
private Dimension countSize() {
615
return new Dimension(x, y);
618
public void addPropertyChangeListener(PropertyChangeListener l) {
619
valueSupport.addPropertyChangeListener(l);
622
public void removePropertyChangeListener(PropertyChangeListener l) {
623
valueSupport.removePropertyChangeListener(l);
626
public void addSpinButtonListener(SpinButtonListener spinButtonListener) {
627
spinButtonListeners.addElement(spinButtonListener);
630
public void removeSpinButtonListener(SpinButtonListener spinButtonListener) {
631
spinButtonListeners.removeElement(spinButtonListener);
634
public void notifySpinButtonListenersAboutUpMove() {
636
int k = spinButtonListeners.size();
638
for (i = 0; i < k; i++)
639
spinButtonListeners.elementAt(i).moveUp();
642
public void notifySpinButtonListenersAboutDownMove() {
644
int k = spinButtonListeners.size();
646
for (i = 0; i < k; i++)
647
spinButtonListeners.elementAt(i).moveDown();
650
protected void repeatThreadNotify() {
651
int old_val = getValue();
654
setValue(getValue() + step);
656
if (value != old_val) {
657
notifySpinButtonListenersAboutUpMove();
660
setValue(getValue() - step);
662
if (value != old_val) {
663
notifySpinButtonListenersAboutDownMove();
667
if ((getValue() == old_val) && !boundsIgnored) {
673
class RepeatThread extends Thread {
674
boolean finish = false;
676
public RepeatThread() {
681
repeatThreadNotify();
685
} catch (InterruptedException e) {
697
repeatThreadNotify();
705
} catch (InterruptedException e) {