001 /*
002 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package java.awt;
026
027 import java.awt.event.AdjustmentEvent;
028 import java.awt.event.AdjustmentListener;
029 import java.awt.peer.ScrollPanePeer;
030 import java.io.Serializable;
031
032 /**
033 * This class represents the state of a horizontal or vertical
034 * scrollbar of a <code>ScrollPane</code>. Objects of this class are
035 * returned by <code>ScrollPane</code> methods.
036 *
037 * @version 1.17 05/05/07
038 * @since 1.4
039 */
040 public class ScrollPaneAdjustable implements Adjustable, Serializable {
041
042 /**
043 * The <code>ScrollPane</code> this object is a scrollbar of.
044 * @serial
045 */
046 private ScrollPane sp;
047
048 /**
049 * Orientation of this scrollbar.
050 *
051 * @serial
052 * @see #getOrientation
053 * @see java.awt.Adjustable#HORIZONTAL
054 * @see java.awt.Adjustable#VERTICAL
055 */
056 private int orientation;
057
058 /**
059 * The value of this scrollbar.
060 * <code>value</code> should be greater than <code>minimum</code>
061 * and less than <code>maximum</code>
062 *
063 * @serial
064 * @see #getValue
065 * @see #setValue
066 */
067 private int value;
068
069 /**
070 * The minimum value of this scrollbar.
071 * This value can only be set by the <code>ScrollPane</code>.
072 * <p>
073 * <strong>ATTN:</strong> In current implementation
074 * <code>minimum</code> is always <code>0</code>. This field can
075 * only be altered via <code>setSpan</code> method and
076 * <code>ScrollPane</code> always calls that method with
077 * <code>0</code> for the minimum. <code>getMinimum</code> method
078 * always returns <code>0</code> without checking this field.
079 *
080 * @serial
081 * @see #getMinimum
082 * @see #setSpan(int, int, int)
083 */
084 private int minimum;
085
086 /**
087 * The maximum value of this scrollbar.
088 * This value can only be set by the <code>ScrollPane</code>.
089 *
090 * @serial
091 * @see #getMaximum
092 * @see #setSpan(int, int, int)
093 */
094 private int maximum;
095
096 /**
097 * The size of the visible portion of this scrollbar.
098 * This value can only be set by the <code>ScrollPane</code>.
099 *
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 = "Can be set by scrollpane only";
146
147 /**
148 * Initialize JNI field and method ids.
149 */
150 private static native void initIDs();
151
152 static {
153 Toolkit.loadLibraries();
154 if (!GraphicsEnvironment.isHeadless()) {
155 initIDs();
156 }
157 }
158
159 /**
160 * JDK 1.1 serialVersionUID.
161 */
162 private static final long serialVersionUID = -3359745691033257079L;
163
164 /**
165 * Constructs a new object to represent specified scrollabar
166 * of the specified <code>ScrollPane</code>.
167 * Only ScrollPane creates instances of this class.
168 * @param sp <code>ScrollPane</code>
169 * @param l <code>AdjustmentListener</code> to add upon creation.
170 * @param orientation specifies which scrollbar this object represents,
171 * can be either <code>Adjustable.HORIZONTAL</code>
172 * or <code>Adjustable.VERTICAL</code>.
173 */
174 ScrollPaneAdjustable(ScrollPane sp, AdjustmentListener l,
175 int orientation) {
176 this .sp = sp;
177 this .orientation = orientation;
178 addAdjustmentListener(l);
179 }
180
181 /**
182 * This is called by the scrollpane itself to update the
183 * <code>minimum</code>, <code>maximum</code> and
184 * <code>visible</code> values. The scrollpane is the only one
185 * that should be changing these since it is the source of these
186 * values.
187 */
188 void setSpan(int min, int max, int visible) {
189 // adjust the values to be reasonable
190 minimum = min;
191 maximum = Math.max(max, minimum + 1);
192 visibleAmount = Math.min(visible, maximum - minimum);
193 visibleAmount = Math.max(visibleAmount, 1);
194 blockIncrement = Math.max((int) (visible * .90), 1);
195 setValue(value);
196 }
197
198 /**
199 * Returns the orientation of this scrollbar.
200 * @return the orientation of this scrollbar, either
201 * <code>Adjustable.HORIZONTAL</code> or
202 * <code>Adjustable.VERTICAL</code>
203 */
204 public int getOrientation() {
205 return orientation;
206 }
207
208 /**
209 * This method should <strong>NOT</strong> be called by user code.
210 * This method is public for this class to properly implement
211 * <code>Adjustable</code> interface.
212 *
213 * @throws <code>AWTError</code> Always throws an error when called.
214 */
215 public void setMinimum(int min) {
216 throw new AWTError(SCROLLPANE_ONLY);
217 }
218
219 public int getMinimum() {
220 // XXX: This relies on setSpan always being called with 0 for
221 // the minimum (which is currently true).
222 return 0;
223 }
224
225 /**
226 * This method should <strong>NOT</strong> be called by user code.
227 * This method is public for this class to properly implement
228 * <code>Adjustable</code> interface.
229 *
230 * @throws <code>AWTError</code> Always throws an error when called.
231 */
232 public void setMaximum(int max) {
233 throw new AWTError(SCROLLPANE_ONLY);
234 }
235
236 public int getMaximum() {
237 return maximum;
238 }
239
240 public synchronized void setUnitIncrement(int u) {
241 if (u != unitIncrement) {
242 unitIncrement = u;
243 if (sp.peer != null) {
244 ScrollPanePeer peer = (ScrollPanePeer) sp.peer;
245 peer.setUnitIncrement(this , u);
246 }
247 }
248 }
249
250 public int getUnitIncrement() {
251 return unitIncrement;
252 }
253
254 public synchronized void setBlockIncrement(int b) {
255 blockIncrement = b;
256 }
257
258 public int getBlockIncrement() {
259 return blockIncrement;
260 }
261
262 /**
263 * This method should <strong>NOT</strong> be called by user code.
264 * This method is public for this class to properly implement
265 * <code>Adjustable</code> interface.
266 *
267 * @throws <code>AWTError</code> Always throws an error when called.
268 */
269 public void setVisibleAmount(int v) {
270 throw new AWTError(SCROLLPANE_ONLY);
271 }
272
273 public int getVisibleAmount() {
274 return visibleAmount;
275 }
276
277 /**
278 * Sets the <code>valueIsAdjusting</code> property.
279 *
280 * @param b new adjustment-in-progress status
281 * @see #getValueIsAdjusting
282 * @since 1.4
283 */
284 public void setValueIsAdjusting(boolean b) {
285 if (isAdjusting != b) {
286 isAdjusting = b;
287 AdjustmentEvent e = new AdjustmentEvent(this ,
288 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
289 AdjustmentEvent.TRACK, value, b);
290 adjustmentListener.adjustmentValueChanged(e);
291 }
292 }
293
294 /**
295 * Returns true if the value is in the process of changing as a
296 * result of actions being taken by the user.
297 *
298 * @return the value of the <code>valueIsAdjusting</code> property
299 * @see #setValueIsAdjusting
300 */
301 public boolean getValueIsAdjusting() {
302 return isAdjusting;
303 }
304
305 /**
306 * Sets the value of this scrollbar to the specified value.
307 * <p>
308 * If the value supplied is less than the current minimum or
309 * greater than the current maximum, then one of those values is
310 * substituted, as appropriate.
311 *
312 * @param v the new value of the scrollbar
313 */
314 public void setValue(int v) {
315 setTypedValue(v, AdjustmentEvent.TRACK);
316 }
317
318 /**
319 * Sets the value of this scrollbar to the specified value.
320 * <p>
321 * If the value supplied is less than the current minimum or
322 * greater than the current maximum, then one of those values is
323 * substituted, as appropriate. Also, creates and dispatches
324 * the AdjustementEvent with specified type and value.
325 *
326 * @param v the new value of the scrollbar
327 * @param type the type of the scrolling operation occured
328 */
329 private void setTypedValue(int v, int type) {
330 v = Math.max(v, minimum);
331 v = Math.min(v, maximum - visibleAmount);
332
333 if (v != value) {
334 value = v;
335 // Synchronously notify the listeners so that they are
336 // guaranteed to be up-to-date with the Adjustable before
337 // it is mutated again.
338 AdjustmentEvent e = new AdjustmentEvent(this ,
339 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, type,
340 value, isAdjusting);
341 adjustmentListener.adjustmentValueChanged(e);
342 }
343 }
344
345 public int getValue() {
346 return value;
347 }
348
349 /**
350 * Adds the specified adjustment listener to receive adjustment
351 * events from this <code>ScrollPaneAdjustable</code>.
352 * If <code>l</code> is <code>null</code>, no exception is thrown
353 * and no action is performed.
354 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
355 * >AWT Threading Issues</a> for details on AWT's threading model.
356 *
357 * @param l the adjustment listener.
358 * @see #removeAdjustmentListener
359 * @see #getAdjustmentListeners
360 * @see java.awt.event.AdjustmentListener
361 * @see java.awt.event.AdjustmentEvent
362 */
363 public synchronized void addAdjustmentListener(AdjustmentListener l) {
364 if (l == null) {
365 return;
366 }
367 adjustmentListener = AWTEventMulticaster.add(
368 adjustmentListener, l);
369 }
370
371 /**
372 * Removes the specified adjustment listener so that it no longer
373 * receives adjustment events from this <code>ScrollPaneAdjustable</code>.
374 * If <code>l</code> is <code>null</code>, no exception is thrown
375 * and no action is performed.
376 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
377 * >AWT Threading Issues</a> for details on AWT's threading model.
378 *
379 * @param l the adjustment listener.
380 * @see #addAdjustmentListener
381 * @see #getAdjustmentListeners
382 * @see java.awt.event.AdjustmentListener
383 * @see java.awt.event.AdjustmentEvent
384 * @since JDK1.1
385 */
386 public synchronized void removeAdjustmentListener(
387 AdjustmentListener l) {
388 if (l == null) {
389 return;
390 }
391 adjustmentListener = AWTEventMulticaster.remove(
392 adjustmentListener, l);
393 }
394
395 /**
396 * Returns an array of all the adjustment listeners
397 * registered on this <code>ScrollPaneAdjustable</code>.
398 *
399 * @return all of this <code>ScrollPaneAdjustable</code>'s
400 * <code>AdjustmentListener</code>s
401 * or an empty array if no adjustment
402 * listeners are currently registered
403 *
404 * @see #addAdjustmentListener
405 * @see #removeAdjustmentListener
406 * @see java.awt.event.AdjustmentListener
407 * @see java.awt.event.AdjustmentEvent
408 * @since 1.4
409 */
410 public synchronized AdjustmentListener[] getAdjustmentListeners() {
411 return (AdjustmentListener[]) (AWTEventMulticaster
412 .getListeners(adjustmentListener,
413 AdjustmentListener.class));
414 }
415
416 /**
417 * Returns a string representation of this scrollbar and its values.
418 * @return a string representation of this scrollbar.
419 */
420 public String toString() {
421 return getClass().getName() + "[" + paramString() + "]";
422 }
423
424 /**
425 * Returns a string representing the state of this scrollbar.
426 * This method is intended to be used only for debugging purposes,
427 * and the content and format of the returned string may vary
428 * between implementations. The returned string may be empty but
429 * may not be <code>null</code>.
430 *
431 * @return the parameter string of this scrollbar.
432 */
433 public String paramString() {
434 return ((orientation == Adjustable.VERTICAL ? "vertical,"
435 : "horizontal,")
436 + "[0.."
437 + maximum
438 + "]"
439 + ",val="
440 + value
441 + ",vis="
442 + visibleAmount
443 + ",unit="
444 + unitIncrement
445 + ",block="
446 + blockIncrement + ",isAdjusting=" + isAdjusting);
447 }
448 }
|