1 /*
2 * Copyright 2000-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 package java.awt;
26
27 import java.awt.event.AdjustmentEvent;
28 import java.awt.event.AdjustmentListener;
29 import java.awt.peer.ScrollPanePeer;
30 import java.io.Serializable;
31
32
33 /**
34 * This class represents the state of a horizontal or vertical
35 * scrollbar of a <code>ScrollPane</code>. Objects of this class are
36 * returned by <code>ScrollPane</code> methods.
37 *
38 * @since 1.4
39 */
40 public class ScrollPaneAdjustable implements Adjustable, Serializable {
41
42 /**
43 * The <code>ScrollPane</code> this object is a scrollbar of.
44 * @serial
45 */
46 private ScrollPane sp;
47
48 /**
49 * Orientation of this scrollbar.
50 *
51 * @serial
52 * @see #getOrientation
53 * @see java.awt.Adjustable#HORIZONTAL
54 * @see java.awt.Adjustable#VERTICAL
55 */
56 private int orientation;
57
58 /**
59 * The value of this scrollbar.
60 * <code>value</code> should be greater than <code>minimum</code>
61 * and less than <code>maximum</code>
62 *
63 * @serial
64 * @see #getValue
65 * @see #setValue
66 */
67 private int value;
68
69 /**
70 * The minimum value of this scrollbar.
71 * This value can only be set by the <code>ScrollPane</code>.
72 * <p>
73 * <strong>ATTN:</strong> In current implementation
74 * <code>minimum</code> is always <code>0</code>. This field can
75 * only be altered via <code>setSpan</code> method and
76 * <code>ScrollPane</code> always calls that method with
77 * <code>0</code> for the minimum. <code>getMinimum</code> method
78 * always returns <code>0</code> without checking this field.
79 *
80 * @serial
81 * @see #getMinimum
82 * @see #setSpan(int, int, int)
83 */
84 private int minimum;
85
86 /**
87 * The maximum value of this scrollbar.
88 * This value can only be set by the <code>ScrollPane</code>.
89 *
90 * @serial
91 * @see #getMaximum
92 * @see #setSpan(int, int, int)
93 */
94 private int maximum;
95
96 /**
97 * The size of the visible portion of this scrollbar.
98 * This value can only be set by the <code>ScrollPane</code>.
99 *
100 * @serial
101 * @see #getVisibleAmount
102 * @see #setSpan(int, int, int)
103 */
104 private int visibleAmount;
105
106 /**
107 * The adjusting status of the <code>Scrollbar</code>.
108 * True if the value is in the process of changing as a result of
109 * actions being taken by the user.
110 *
111 * @see #getValueIsAdjusting
112 * @see #setValueIsAdjusting
113 * @since 1.4
114 */
115 private transient boolean isAdjusting;
116
117 /**
118 * The amount by which the scrollbar value will change when going
119 * up or down by a line.
120 * This value should be a non negative integer.
121 *
122 * @serial
123 * @see #getUnitIncrement
124 * @see #setUnitIncrement
125 */
126 private int unitIncrement = 1;
127
128 /**
129 * The amount by which the scrollbar value will change when going
130 * up or down by a page.
131 * This value should be a non negative integer.
132 *
133 * @serial
134 * @see #getBlockIncrement
135 * @see #setBlockIncrement
136 */
137 private int blockIncrement = 1;
138
139 private AdjustmentListener adjustmentListener;
140
141 /**
142 * Error message for <code>AWTError</code> reported when one of
143 * the public but unsupported methods is called.
144 */
145 private static final String SCROLLPANE_ONLY =
146 "Can be set by scrollpane only";
147
148
149 /**
150 * Initialize JNI field and method ids.
151 */
152 private static native void initIDs();
153
154 static {
155 Toolkit.loadLibraries();
156 if (!GraphicsEnvironment.isHeadless()) {
157 initIDs();
158 }
159 }
160
161 /**
162 * JDK 1.1 serialVersionUID.
163 */
164 private static final long serialVersionUID = -3359745691033257079L;
165
166
167 /**
168 * Constructs a new object to represent specified scrollabar
169 * of the specified <code>ScrollPane</code>.
170 * Only ScrollPane creates instances of this class.
171 * @param sp <code>ScrollPane</code>
172 * @param l <code>AdjustmentListener</code> to add upon creation.
173 * @param orientation specifies which scrollbar this object represents,
174 * can be either <code>Adjustable.HORIZONTAL</code>
175 * or <code>Adjustable.VERTICAL</code>.
176 */
177 ScrollPaneAdjustable(ScrollPane sp, AdjustmentListener l, int orientation) {
178 this.sp = sp;
179 this.orientation = orientation;
180 addAdjustmentListener(l);
181 }
182
183 /**
184 * This is called by the scrollpane itself to update the
185 * <code>minimum</code>, <code>maximum</code> and
186 * <code>visible</code> values. The scrollpane is the only one
187 * that should be changing these since it is the source of these
188 * values.
189 */
190 void setSpan(int min, int max, int visible) {
191 // adjust the values to be reasonable
192 minimum = min;
193 maximum = Math.max(max, minimum + 1);
194 visibleAmount = Math.min(visible, maximum - minimum);
195 visibleAmount = Math.max(visibleAmount, 1);
196 blockIncrement = Math.max((int)(visible * .90), 1);
197 setValue(value);
198 }
199
200 /**
201 * Returns the orientation of this scrollbar.
202 * @return the orientation of this scrollbar, either
203 * <code>Adjustable.HORIZONTAL</code> or
204 * <code>Adjustable.VERTICAL</code>
205 */
206 public int getOrientation() {
207 return orientation;
208 }
209
210 /**
211 * This method should <strong>NOT</strong> be called by user code.
212 * This method is public for this class to properly implement
213 * <code>Adjustable</code> interface.
214 *
215 * @throws <code>AWTError</code> Always throws an error when called.
216 */
217 public void setMinimum(int min) {
218 throw new AWTError(SCROLLPANE_ONLY);
219 }
220
221 public int getMinimum() {
222 // XXX: This relies on setSpan always being called with 0 for
223 // the minimum (which is currently true).
224 return 0;
225 }
226
227 /**
228 * This method should <strong>NOT</strong> be called by user code.
229 * This method is public for this class to properly implement
230 * <code>Adjustable</code> interface.
231 *
232 * @throws <code>AWTError</code> Always throws an error when called.
233 */
234 public void setMaximum(int max) {
235 throw new AWTError(SCROLLPANE_ONLY);
236 }
237
238 public int getMaximum() {
239 return maximum;
240 }
241
242 public synchronized void setUnitIncrement(int u) {
243 if (u != unitIncrement) {
244 unitIncrement = u;
245 if (sp.peer != null) {
246 ScrollPanePeer peer = (ScrollPanePeer) sp.peer;
247 peer.setUnitIncrement(this, u);
248 }
249 }
250 }
251
252 public int getUnitIncrement() {
253 return unitIncrement;
254 }
255
256 public synchronized void setBlockIncrement(int b) {
257 blockIncrement = b;
258 }
259
260 public int getBlockIncrement() {
261 return blockIncrement;
262 }
263
264 /**
265 * This method should <strong>NOT</strong> be called by user code.
266 * This method is public for this class to properly implement
267 * <code>Adjustable</code> interface.
268 *
269 * @throws <code>AWTError</code> Always throws an error when called.
270 */
271 public void setVisibleAmount(int v) {
272 throw new AWTError(SCROLLPANE_ONLY);
273 }
274
275 public int getVisibleAmount() {
276 return visibleAmount;
277 }
278
279
280 /**
281 * Sets the <code>valueIsAdjusting</code> property.
282 *
283 * @param b new adjustment-in-progress status
284 * @see #getValueIsAdjusting
285 * @since 1.4
286 */
287 public void setValueIsAdjusting(boolean b) {
288 if (isAdjusting != b) {
289 isAdjusting = b;
290 AdjustmentEvent e =
291 new AdjustmentEvent(this,
292 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
293 AdjustmentEvent.TRACK, value, b);
294 adjustmentListener.adjustmentValueChanged(e);
295 }
296 }
297
298 /**
299 * Returns true if the value is in the process of changing as a
300 * result of actions being taken by the user.
301 *
302 * @return the value of the <code>valueIsAdjusting</code> property
303 * @see #setValueIsAdjusting
304 */
305 public boolean getValueIsAdjusting() {
306 return isAdjusting;
307 }
308
309 /**
310 * Sets the value of this scrollbar to the specified value.
311 * <p>
312 * If the value supplied is less than the current minimum or
313 * greater than the current maximum, then one of those values is
314 * substituted, as appropriate.
315 *
316 * @param v the new value of the scrollbar
317 */
318 public void setValue(int v) {
319 setTypedValue(v, AdjustmentEvent.TRACK);
320 }
321
322 /**
323 * Sets the value of this scrollbar to the specified value.
324 * <p>
325 * If the value supplied is less than the current minimum or
326 * greater than the current maximum, then one of those values is
327 * substituted, as appropriate. Also, creates and dispatches
328 * the AdjustementEvent with specified type and value.
329 *
330 * @param v the new value of the scrollbar
331 * @param type the type of the scrolling operation occured
332 */
333 private void setTypedValue(int v, int type) {
334 v = Math.max(v, minimum);
335 v = Math.min(v, maximum - visibleAmount);
336
337 if (v != value) {
338 value = v;
339 // Synchronously notify the listeners so that they are
340 // guaranteed to be up-to-date with the Adjustable before
341 // it is mutated again.
342 AdjustmentEvent e =
343 new AdjustmentEvent(this,
344 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
345 type, value, isAdjusting);
346 adjustmentListener.adjustmentValueChanged(e);
347 }
348 }
349
350 public int getValue() {
351 return value;
352 }
353
354 /**
355 * Adds the specified adjustment listener to receive adjustment
356 * events from this <code>ScrollPaneAdjustable</code>.
357 * If <code>l</code> is <code>null</code>, no exception is thrown
358 * and no action is performed.
359 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
360 * >AWT Threading Issues</a> for details on AWT's threading model.
361 *
362 * @param l the adjustment listener.
363 * @see #removeAdjustmentListener
364 * @see #getAdjustmentListeners
365 * @see java.awt.event.AdjustmentListener
366 * @see java.awt.event.AdjustmentEvent
367 */
368 public synchronized void addAdjustmentListener(AdjustmentListener l) {
369 if (l == null) {
370 return;
371 }
372 adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l);
373 }
374
375 /**
376 * Removes the specified adjustment listener so that it no longer
377 * receives adjustment events from this <code>ScrollPaneAdjustable</code>.
378 * If <code>l</code> is <code>null</code>, no exception is thrown
379 * and no action is performed.
380 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
381 * >AWT Threading Issues</a> for details on AWT's threading model.
382 *
383 * @param l the adjustment listener.
384 * @see #addAdjustmentListener
385 * @see #getAdjustmentListeners
386 * @see java.awt.event.AdjustmentListener
387 * @see java.awt.event.AdjustmentEvent
388 * @since JDK1.1
389 */
390 public synchronized void removeAdjustmentListener(AdjustmentListener l){
391 if (l == null) {
392 return;
393 }
394 adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l);
395 }
396
397 /**
398 * Returns an array of all the adjustment listeners
399 * registered on this <code>ScrollPaneAdjustable</code>.
400 *
401 * @return all of this <code>ScrollPaneAdjustable</code>'s
402 * <code>AdjustmentListener</code>s
403 * or an empty array if no adjustment
404 * listeners are currently registered
405 *
406 * @see #addAdjustmentListener
407 * @see #removeAdjustmentListener
408 * @see java.awt.event.AdjustmentListener
409 * @see java.awt.event.AdjustmentEvent
410 * @since 1.4
411 */
412 public synchronized AdjustmentListener[] getAdjustmentListeners() {
413 return (AdjustmentListener[])(AWTEventMulticaster.getListeners(
414 adjustmentListener,
415 AdjustmentListener.class));
416 }
417
418 /**
419 * Returns a string representation of this scrollbar and its values.
420 * @return a string representation of this scrollbar.
421 */
422 public String toString() {
423 return getClass().getName() + "[" + paramString() + "]";
424 }
425
426 /**
427 * Returns a string representing the state of this scrollbar.
428 * This method is intended to be used only for debugging purposes,
429 * and the content and format of the returned string may vary
430 * between implementations. The returned string may be empty but
431 * may not be <code>null</code>.
432 *
433 * @return the parameter string of this scrollbar.
434 */
435 public String paramString() {
436 return ((orientation == Adjustable.VERTICAL ? "vertical,"
437 :"horizontal,")
438 + "[0.."+maximum+"]"
439 + ",val=" + value
440 + ",vis=" + visibleAmount
441 + ",unit=" + unitIncrement
442 + ",block=" + blockIncrement
443 + ",isAdjusting=" + isAdjusting);
444 }
445 }