/Users/lyon/j4p/src/gui/run/ObservableSlider.java
|
1 // Glenn Josefiak
2 // Fairfield University
3 // SW513
4 // Spring 2003
5
6 package gui.run;
7
8
9 import javax.swing.*;
10 import javax.swing.event.ChangeEvent;
11 import javax.swing.event.ChangeListener;
12 import java.awt.*;
13 import java.text.DecimalFormat;
14 import java.util.Hashtable;
15 import java.util.Observer;
16
17 /**
18 * A slider with floating point values, a name label, and built-in
19 * tick labels.
20 */
21 public final class ObservableSlider extends JPanel {
22 private final int JSLIDER_MIN = 0;
23 private final int JSLIDER_MAX = 1000;
24
25 private final JSlider js;
26 private final JLabel lblDescription;
27 private JLabel lblValue;
28 private final JPanel pnlLabels;
29
30 private final Hashtable hshLabelTable;
31 private final ObservableFloat sliderPosition;
32 private final DecimalFormat df;
33 private float sliderMin = 0.0f;
34 private float sliderMax = 100.0f;
35 private boolean isLogScale = false;
36
37 /**
38 * Construct a new ObservableSlider ranging from 0.0f to 100.0f
39 */
40 public ObservableSlider() {
41 hshLabelTable = new Hashtable();
42 sliderPosition = new ObservableFloat();
43 df = new DecimalFormat("##0.000");
44 setLayout(new BorderLayout());
45
46 js = new JSlider(SwingConstants.VERTICAL, JSLIDER_MIN,
47 JSLIDER_MAX, JSLIDER_MIN);
48 js.addChangeListener(new ChangeListener() {
49 public void stateChanged(final ChangeEvent e) {
50 final float val = intToDouble(js.getValue());
51 sliderPosition.setValue(val);
52 lblValue.setText(df.format(val));
53 }
54 });
55 add(js, BorderLayout.CENTER);
56
57 lblDescription = new JLabel("", SwingConstants.CENTER);
58 lblValue = new JLabel(df.format(sliderMin));
59 pnlLabels = new JPanel(new GridLayout(0, 1));
60 pnlLabels.add(lblDescription);
61 pnlLabels.add(lblValue);
62 add(pnlLabels, BorderLayout.SOUTH);
63 sliderPosition.setValue(intToDouble(JSLIDER_MIN));
64 }
65
66 /**
67 * Construct a ObservableSlider ranging from min to max.
68 *
69 * @param min The minimum value of the slider
70 * @param max The maximum value of the slider
71 */
72 public ObservableSlider(final float min, final float max) {
73 this();
74 setMinimum(min);
75 setMaximum(max);
76 }
77
78 /**
79 * Set the text of the label.
80 *
81 * @param s The string which will appear below the slider.
82 */
83 public void setLabel(final String s) {
84 lblDescription.setText(s);
85 }
86
87 /**
88 * Set the label of a tick
89 *
90 * @param value The tick at which the label will appear.
91 * @param label The text of the label.
92 */
93 public void setTickLabel(final float value, final String label) {
94 hshLabelTable.put(new Integer(doubleToInt(value)), new JLabel(label));
95 js.setLabelTable(hshLabelTable);
96 js.setPaintLabels(true);
97 }
98
99 /**
100 * Get the minimum value of the slider.
101 *
102 * @return Minimum slider value
103 */
104 public float getMinimum() {
105 return sliderMin;
106 }
107
108 /**
109 * Set the minimum value of the slider.
110 *
111 * @param newValue New minimum slider value
112 */
113 public void setMinimum(final float newValue) {
114 final float position;
115 sliderMin = newValue;
116 position = Math.max(sliderPosition.getValue(), newValue);
117 js.setValue(doubleToInt(position));
118 sliderPosition.setValue(position);
119 lblValue.setText(df.format(position));
120 }
121
122 /**
123 * Get the maximum value of the slider.
124 *
125 * @return Maximum slider value
126 */
127 public float getMaximum() {
128 return sliderMax;
129 }
130
131 /**
132 * Set the maximum value of the slider.
133 *
134 * @param newValue New maximum slider value
135 */
136 public void setMaximum(final float newValue) {
137 final float position;
138 sliderMax = newValue;
139 position = Math.min(sliderPosition.getValue(), newValue);
140 js.setValue(doubleToInt(position));
141 sliderPosition.setValue(position);
142 lblValue.setText(df.format(position));
143 }
144
145 /**
146 * Determine whether the slider has a log scale.
147 *
148 * @return True = log; false = linear
149 */
150 public boolean isLogScale() {
151 return isLogScale;
152 }
153
154 /**
155 * Set whether the slider has a log scale.
156 *
157 * @param state True = log; false = linear
158 */
159 public void setLogScale(final boolean state) {
160 isLogScale = state;
161 }
162
163 /**
164 * Get the current value of the slider.
165 *
166 * @return The floating point value of the slider.
167 */
168 public float getValue() {
169 return sliderPosition.getValue();
170 }
171
172 /**
173 * Set the current value of the slider.
174 *
175 * @param newValue The new floating point position value.
176 */
177 public void setValue(final float newValue) {
178 js.setValue(doubleToInt(newValue));
179 }
180
181 /**
182 * Change enabled/disabled state.
183 *
184 * @param state True = enabled, false = disabled
185 */
186 public void setEnabled(final boolean state) {
187 js.setEnabled(state);
188 lblDescription.setEnabled(state);
189 lblValue.setEnabled(state);
190 }
191
192 /**
193 * Add the specified Observer to the list of parties notified
194 * if the slider is moved.
195 *
196 * @param o The Observer to be added.
197 */
198 public void addObserver(final Observer o) {
199 sliderPosition.addObserver(o);
200 }
201
202 /**
203 * Convert the integer index of the JSlider to a floating point
204 * number in the user's specified range.
205 *
206 * @param in A position on the underlying JSlider.
207 * @return The position in the user-specified range.
208 */
209 private float intToDouble(final int in) {
210 if (!isLogScale) {
211 return sliderMin + (sliderMax - sliderMin) / (JSLIDER_MAX - JSLIDER_MIN) *
212 (in - JSLIDER_MIN);
213 } else {
214 return 0;
215 }
216 }
217
218 /**
219 * Convert a floating point number in the user's specified range
220 * to an integer index on the underlying JSlider.
221 *
222 * @param in A position in the user-specified range.
223 * @return The position on the underlying JSlider.
224 */
225 private int doubleToInt(final float in) {
226 if (!isLogScale) {
227 return JSLIDER_MIN + (int) (((float) JSLIDER_MAX - JSLIDER_MIN)
228 / (sliderMax - sliderMin) * (in - sliderMin));
229 } else {
230 return 0;
231 }
232 }
233 }