1 /* Scrollbar.java -- AWT Scrollbar widget
2    Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package java.awt;
40 
41 import java.awt.event.AdjustmentListener;
42 import java.awt.event.AdjustmentEvent;
43 import java.awt.peer.ScrollbarPeer;
44 import java.util.EventListener;
45 import javax.accessibility.Accessible;
46 
47 /**
48   * This class implements a scrollbar widget.
49   *
50   * @author Aaron M. Renn (arenn@urbanophile.com)
51   * @author Tom Tromey <tromey@cygnus.com>
52   */
53 public class Scrollbar extends Component implements Accessible,
54                                                     Adjustable
55 {
56 
57 // FIXME: Serialization readObject/writeObject
58 
59 /*
60  * Static Variables
61  */
62 
63 /**
64   * Constant indicating that a scrollbar is horizontal.
65   */
66 public static final int HORIZONTAL = 0;
67 
68 /**
69   * Constant indicating that a scrollbar is vertical.
70   */
71 public static final int VERTICAL = 1;
72 
73 // Serialization Constant
74 private static final long serialVersionUID = 8451667562882310543L;
75 
76 /*************************************************************************/
77 
78 /**
79   * @serial The amount by which the value of the scrollbar is changed
80   * when incrementing in line mode.
81   */
82 private int lineIncrement;
83 
84 /**
85   * @serial The amount by which the value of the scrollbar is changed
86   * when incrementing in page mode.
87   */
88 private int pageIncrement;
89 
90 /**
91   * @serial The maximum value for this scrollbar
92   */
93 private int maximum;
94 
95 /**
96   * @serial The minimum value for this scrollbar
97   */
98 private int minimum;
99 
100 /**
101   * @serial The orientation of this scrollbar, which will be either
102   * the <code>HORIZONTAL</code> or <code>VERTICAL</code> constant
103   * from this class.
104   */
105 private int orientation;
106 
107 /**
108   * @serial The current value of this scrollbar.
109   */
110 private int value;
111 
112 /**
113   * @serial The width of the scrollbar's thumb, which is relative
114   * to the minimum and maximum value of the scrollbar.
115   */
116 private int visibleAmount;
117 
118 // List of AdjustmentListener's.
119 private AdjustmentListener adjustment_listeners;
120 
121 private transient boolean valueIsAdjusting = false;
122 
123 /*************************************************************************/
124 
125 /*
126  * Constructors
127  */
128 
129 /**
130   * Initializes a new instance of <code>Scrollbar</code> with a
131   * vertical orientation and default values for all other parameters.
132   *
133   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
134   */
135 public
Scrollbar()136 Scrollbar()
137 {
138   this(VERTICAL);
139 }
140 
141 /*************************************************************************/
142 
143 /**
144   * Initializes a new instance of <code>Scrollbar</code> with the
145   * specified orientation and default values for all other parameters.
146   * The orientation must be either the constant <code>HORIZONTAL</code> or
147   * <code>VERTICAL</code> from this class.  An incorrect value will throw
148   * an exception.
149   *
150   * @param orientation The orientation of this scrollbar.
151   *
152   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
153   * @exception IllegalArgumentException If the orientation value is not valid.
154   */
155 public
Scrollbar(int orientation)156 Scrollbar(int orientation) throws IllegalArgumentException
157 {
158   this(orientation, 0, 10, 0, 100);
159 }
160 
161 /*************************************************************************/
162 
163 /**
164   * Initializes a new instance of <code>Scrollbar</code> with the
165   * specified parameters.  The orientation must be either the constant
166   * <code>HORIZONTAL</code> or <code>VERTICAL</code>.  An incorrect value
167   * will throw an exception.  Inconsistent values for other parameters
168   * are silently corrected to valid values.
169   *
170   * @param orientation The orientation of this scrollbar.
171   * @param value The initial value of the scrollbar.
172   * @param visibleAmount The width of the scrollbar thumb.
173   * @param minimum The minimum value of the scrollbar.
174   * @param maximum The maximum value of the scrollbar.
175   *
176   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
177   * @exception IllegalArgumentException If the orientation value is not valid.
178   */
179 public
Scrollbar(int orientation, int value, int visibleAmount, int minimum, int maximum)180 Scrollbar(int orientation, int value, int visibleAmount, int minimum,
181           int maximum) throws IllegalArgumentException
182 {
183   if (GraphicsEnvironment.isHeadless())
184     throw new HeadlessException ();
185 
186   if ((orientation != HORIZONTAL) && (orientation != VERTICAL))
187     throw new IllegalArgumentException("Bad orientation value: "
188 				       + orientation);
189 
190   this.orientation = orientation;
191 
192   setValues(value, visibleAmount, minimum, maximum);
193 
194   // Default is 1 according to online docs.
195   lineIncrement = 1;
196 
197   pageIncrement = (maximum - minimum) / 5;
198   if (pageIncrement == 0)
199     pageIncrement = 1;
200 }
201 
202 /*************************************************************************/
203 
204 /*
205  * Instance Methods
206  */
207 
208 /**
209   * Returns the orientation constant for this object.
210   *
211   * @return The orientation constant for this object.
212   */
213 public int
getOrientation()214 getOrientation()
215 {
216   return(orientation);
217 }
218 
219 /*************************************************************************/
220 
221 /**
222   * Sets the orientation of this scrollbar to the specified value.  This
223   * value must be either the constant <code>HORIZONTAL</code> or
224   * <code>VERTICAL</code> from this class or an exception will be thrown.
225   *
226   * @param orientation The new orientation value.
227   *
228   * @exception IllegalArgumentException If the orientation value is not valid.
229   */
230 public void
setOrientation(int orientation)231 setOrientation(int orientation)
232 {
233   if ((orientation != HORIZONTAL) && (orientation != VERTICAL))
234     throw new IllegalArgumentException("Bad orientation value: "
235 				       + orientation);
236 
237   // FIXME: Communicate to peer?  Or must this be called before peer creation?
238   this.orientation = orientation;
239 }
240 
241 /*************************************************************************/
242 
243 /**
244   * Returns the current value for this scrollbar.
245   *
246   * @return The current value for this scrollbar.
247   */
248 public int
getValue()249 getValue()
250 {
251   return(value);
252 }
253 
254 /*************************************************************************/
255 
256 /**
257   * Sets the current value for this scrollbar to the specified value.
258   * If this is inconsistent with the minimum and maximum values for this
259   * scrollbar, the value is silently adjusted.
260   *
261   * @param value The new value for this scrollbar.
262   */
263 public void
setValue(int value)264 setValue(int value)
265 {
266   setValues(value, visibleAmount, minimum, maximum);
267 }
268 
269 /*************************************************************************/
270 
271 /**
272   * Returns the maximum value for this scrollbar.
273   *
274   * @return The maximum value for this scrollbar.
275   */
276 public int
getMaximum()277 getMaximum()
278 {
279   return(maximum);
280 }
281 
282 /*************************************************************************/
283 
284 /**
285   * Sets the maximum value for this scrollbar to the specified value.
286   * If the value is less than the current minimum value, it is silent
287   * set to equal the minimum value.
288   *
289   * @param maximum The new maximum value for this scrollbar.
290   */
291 public void
setMaximum(int maximum)292 setMaximum(int maximum)
293 {
294   setValues(value, visibleAmount, minimum, maximum);
295 }
296 
297 /*************************************************************************/
298 
299 /**
300   * Returns the minimum value for this scrollbar.
301   *
302   * @return The minimum value for this scrollbar.
303   */
304 public int
getMinimum()305 getMinimum()
306 {
307   return(minimum);
308 }
309 
310 /*************************************************************************/
311 
312 /**
313   * Sets the minimum value for this scrollbar to the specified value.  If
314   * this is not consistent with the current value and maximum, it is
315   * silently adjusted to be consistent.
316   *
317   * @param minimum The new minimum value for this scrollbar.
318   */
319 public void
setMinimum(int minimum)320 setMinimum(int minimum)
321 {
322   setValues(value, visibleAmount, minimum, maximum);
323 }
324 
325 /*************************************************************************/
326 
327 /**
328   * Returns the width of the scrollbar's thumb, in units relative to the
329   * maximum and minimum value of the scrollbar.
330   *
331   * @return The width of the scrollbar's thumb.
332   */
333 public int
getVisibleAmount()334 getVisibleAmount()
335 {
336   return(visibleAmount);
337 }
338 
339 /*************************************************************************/
340 
341 /**
342   * Returns the width of the scrollbar's thumb, in units relative to the
343   * maximum and minimum value of the scrollbar.
344   *
345   * @return The width of the scrollbar's thumb.
346   *
347   * @deprecated This method is deprecated in favor of
348   * <code>getVisibleAmount()</code>.
349   */
350 public int
getVisible()351 getVisible()
352 {
353   return(getVisibleAmount());
354 }
355 
356 /*************************************************************************/
357 
358 /**
359   * Sets the width of the scrollbar's thumb, in units relative to the
360   * maximum and minimum value of the scrollbar.
361   *
362   * @param visibileAmount The new visible amount value of the scrollbar.
363   */
364 public void
setVisibleAmount(int visibleAmount)365 setVisibleAmount(int visibleAmount)
366 {
367   setValues(value, visibleAmount, minimum, maximum);
368 }
369 
370 /*************************************************************************/
371 
372 /**
373   * Sets the current value, visible amount, minimum, and maximum for this
374   * scrollbar.  These values are adjusted to be internally consistent
375   * if necessary.
376   *
377   * @param value The new value for this scrollbar.
378   * @param visibleAmount The new visible amount for this scrollbar.
379   * @param minimum The new minimum value for this scrollbar.
380   * @param maximum The new maximum value for this scrollbar.
381   */
382 public synchronized void
setValues(int value, int visibleAmount, int minimum, int maximum)383 setValues(int value, int visibleAmount, int minimum, int maximum)
384 {
385   if (maximum < minimum)
386     maximum = minimum;
387 
388   if (value < minimum)
389     value = minimum;
390 
391   if (value > maximum)
392     value = maximum;
393 
394   if (visibleAmount > maximum - minimum)
395     visibleAmount = maximum - minimum;
396 
397   this.value = value;
398   this.visibleAmount = visibleAmount;
399   this.minimum = minimum;
400   this.maximum = maximum;
401 
402   ScrollbarPeer sp = (ScrollbarPeer)getPeer();
403   if (sp != null)
404     sp.setValues(value, visibleAmount, minimum, maximum);
405 
406   int range = maximum - minimum;
407   if (lineIncrement > range)
408     {
409       if (range == 0)
410         lineIncrement = 1;
411       else
412         lineIncrement = range;
413 
414       if (sp != null)
415         sp.setLineIncrement(lineIncrement);
416     }
417 
418   if (pageIncrement > range)
419     {
420       if (range == 0)
421         pageIncrement = 1;
422       else
423         pageIncrement = range;
424 
425       if (sp != null)
426         sp.setPageIncrement(pageIncrement);
427     }
428 }
429 
430 /*************************************************************************/
431 
432 /**
433   * Returns the value added or subtracted when the user activates the scrollbar
434   * scroll by a "unit" amount.
435   *
436   * @return The unit increment value.
437   */
438 public int
getUnitIncrement()439 getUnitIncrement()
440 {
441   return(lineIncrement);
442 }
443 
444 /*************************************************************************/
445 
446 /**
447   * Returns the value added or subtracted when the user selects the scrollbar
448   * scroll by a "unit" amount control.
449   *
450   * @return The unit increment value.
451   *
452   * @deprecated This method is deprecated in favor of
453   * <code>getUnitIncrement()</code>.
454   */
455 public int
getLineIncrement()456 getLineIncrement()
457 {
458   return(lineIncrement);
459 }
460 
461 /*************************************************************************/
462 
463 /**
464   * Sets the value added or subtracted to the scrollbar value when the
465   * user selects the scroll by a "unit" amount control.
466   *
467   * @param unitIncrement The new unit increment amount.
468   */
469 public synchronized void
setUnitIncrement(int unitIncrement)470 setUnitIncrement(int unitIncrement)
471 {
472   if (unitIncrement < 0)
473     throw new IllegalArgumentException("Unit increment less than zero.");
474 
475   int range = maximum - minimum;
476   if (unitIncrement > range)
477     {
478       if (range == 0)
479         unitIncrement = 1;
480       else
481         unitIncrement = range;
482     }
483 
484   if (unitIncrement == lineIncrement)
485     return;
486 
487   lineIncrement = unitIncrement;
488 
489   ScrollbarPeer sp = (ScrollbarPeer)getPeer();
490   if (sp != null)
491     sp.setLineIncrement(lineIncrement);
492 }
493 
494 /*************************************************************************/
495 
496 /**
497   * Sets the value added or subtracted to the scrollbar value when the
498   * user selects the scroll by a "unit" amount control.
499   *
500   * @param lineIncrement The new unit increment amount.
501   *
502   * @deprecated This method is deprecated in favor of
503   * <code>setUnitIncrement()</code>.
504   */
505 public void
setLineIncrement(int lineIncrement)506 setLineIncrement(int lineIncrement)
507 {
508   setUnitIncrement(lineIncrement);
509 }
510 
511 /*************************************************************************/
512 
513 /**
514   * Returns the value added or subtracted when the user activates the scrollbar
515   * scroll by a "block" amount.
516   *
517   * @return The block increment value.
518   */
519 public int
getBlockIncrement()520 getBlockIncrement()
521 {
522   return(pageIncrement);
523 }
524 
525 /*************************************************************************/
526 
527 /**
528   * Returns the value added or subtracted when the user selects the scrollbar
529   * scroll by a "block" amount control.
530   *
531   * @return The block increment value.
532   *
533   * @deprecated This method is deprecated in favor of
534   * <code>getBlockIncrement()</code>.
535   */
536 public int
getPageIncrement()537 getPageIncrement()
538 {
539   return(pageIncrement);
540 }
541 
542 /*************************************************************************/
543 
544 /**
545   * Sets the value added or subtracted to the scrollbar value when the
546   * user selects the scroll by a "block" amount control.
547   *
548   * @param blockIncrement The new block increment amount.
549   */
550 public synchronized void
setBlockIncrement(int blockIncrement)551 setBlockIncrement(int blockIncrement)
552 {
553   if (blockIncrement < 0)
554     throw new IllegalArgumentException("Block increment less than zero.");
555 
556   int range = maximum - minimum;
557   if (blockIncrement > range)
558     {
559       if (range == 0)
560         blockIncrement = 1;
561       else
562         blockIncrement = range;
563     }
564 
565   if (blockIncrement == pageIncrement)
566     return;
567 
568   pageIncrement = blockIncrement;
569 
570   ScrollbarPeer sp = (ScrollbarPeer)getPeer();
571   if (sp != null)
572     sp.setPageIncrement(pageIncrement);
573 }
574 
575 /*************************************************************************/
576 
577 /**
578   * Sets the value added or subtracted to the scrollbar value when the
579   * user selects the scroll by a "block" amount control.
580   *
581   * @param pageIncrement The new block increment amount.
582   *
583   * @deprecated This method is deprecated in favor of
584   * <code>setBlockIncrement()</code>.
585   */
586 public void
setPageIncrement(int pageIncrement)587 setPageIncrement(int pageIncrement)
588 {
589   setBlockIncrement(pageIncrement);
590 }
591 
592 /*************************************************************************/
593 
594 /**
595   * Notifies this object to create its native peer.
596   */
597 public synchronized void
addNotify()598 addNotify()
599 {
600   if (peer == null)
601     peer = getToolkit ().createScrollbar (this);
602   super.addNotify ();
603 }
604 
605 /*************************************************************************/
606 
607 /**
608   * Adds a new adjustment listener to the list of registered listeners
609   * for this object.
610   *
611   * @param listener The listener to add.
612   */
613 public synchronized void
addAdjustmentListener(AdjustmentListener listener)614 addAdjustmentListener(AdjustmentListener listener)
615 {
616   adjustment_listeners = AWTEventMulticaster.add(adjustment_listeners, listener);
617   enableEvents(AWTEvent.ADJUSTMENT_EVENT_MASK);
618 }
619 
620 /*************************************************************************/
621 
622 /**
623   * Removes the specified listener from the list of registered listeners
624   * for this object.
625   *
626   * @param listener The listener to remove.
627   */
628 public synchronized void
removeAdjustmentListener(AdjustmentListener listener)629 removeAdjustmentListener(AdjustmentListener listener)
630 {
631   adjustment_listeners = AWTEventMulticaster.remove(adjustment_listeners,
632                                                     listener);
633 }
634 
635 /*************************************************************************/
636 
637 /**
638   * Processes events for this scrollbar.  It does this by calling
639   * <code>processAdjustmentEvent()</code> if the event is an instance of
640   * <code>AdjustmentEvent</code>, otherwise it calls the superclass to
641   * process the event.
642   *
643   * @param event The event to process.
644   */
645 protected void
processEvent(AWTEvent event)646 processEvent(AWTEvent event)
647 {
648   if (event instanceof AdjustmentEvent)
649     processAdjustmentEvent((AdjustmentEvent)event);
650   else
651     super.processEvent(event);
652 }
653 
654 /*************************************************************************/
655 
656 /**
657   * Processes adjustment events for this object by dispatching them to
658   * any registered listeners.  Note that this method will only be called
659   * if adjustment events are enabled.  This will happen automatically if
660   * any listeners are registered.  Otherwise, it can be enabled by a
661   * call to <code>enableEvents()</code>.
662   *
663   * @param event The event to process.
664   */
665 protected void
processAdjustmentEvent(AdjustmentEvent event)666 processAdjustmentEvent(AdjustmentEvent event)
667 {
668   value = event.getValue();
669   if (adjustment_listeners != null)
670     adjustment_listeners.adjustmentValueChanged(event);
671 }
672 
673 void
dispatchEventImpl(AWTEvent e)674 dispatchEventImpl(AWTEvent e)
675 {
676   if (e.id <= AdjustmentEvent.ADJUSTMENT_LAST
677       && e.id >= AdjustmentEvent.ADJUSTMENT_FIRST
678       && (adjustment_listeners != null
679 	  || (eventMask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0))
680     processEvent(e);
681   else
682     super.dispatchEventImpl(e);
683 }
684 
685 /*************************************************************************/
686 
687 /**
688   * Returns a debugging string for this object.
689   *
690   * @return A debugging string for this object.
691   */
692 protected String
paramString()693 paramString()
694 {
695   return("value=" + getValue() + ",visibleAmount=" +
696          getVisibleAmount() + ",minimum=" + getMinimum()
697 	 + ",maximum=" + getMaximum()
698 	 + ",pageIncrement=" + pageIncrement
699 	 + ",lineIncrement=" + lineIncrement
700 	 + ",orientation=" + (orientation == HORIZONTAL
701 			      ? "HORIZONTAL" : "VERTICAL")
702 	 + super.paramString());
703 }
704 
705   /**
706    * Returns an array of all the objects currently registered as FooListeners
707    * upon this <code>Scrollbar</code>. FooListeners are registered using the
708    * addFooListener method.
709    *
710    * @exception ClassCastException If listenerType doesn't specify a class or
711    * interface that implements java.util.EventListener.
712    */
getListeners(Class listenerType)713   public EventListener[] getListeners (Class listenerType)
714   {
715     if (listenerType == AdjustmentListener.class)
716       return AWTEventMulticaster.getListeners (adjustment_listeners,
717                                                listenerType);
718 
719     return super.getListeners (listenerType);
720   }
721 
722   /**
723    * Returns an array of all registered adjustment listeners.
724    */
getAdjustmentListeners()725   public AdjustmentListener[] getAdjustmentListeners ()
726   {
727     return (AdjustmentListener[]) getListeners (AdjustmentListener.class);
728   }
729 
730   /**
731    * Returns true if the value is in the process of changing.
732    *
733    * @since 1.4
734    */
getValueIsAdjusting()735   public boolean getValueIsAdjusting ()
736   {
737     return valueIsAdjusting;
738   }
739 
740   /**
741    * Sets the value of valueIsAdjusting.
742    *
743    * @since 1.4
744    */
setValueIsAdjusting(boolean valueIsAdjusting)745   public void setValueIsAdjusting (boolean valueIsAdjusting)
746   {
747     this.valueIsAdjusting = valueIsAdjusting;
748   }
749 } // class Scrollbar
750 
751