001 /* JScrollBar.java --
002 Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.swing;
040
041 import java.awt.Adjustable;
042 import java.awt.Dimension;
043 import java.awt.event.AdjustmentEvent;
044 import java.awt.event.AdjustmentListener;
045 import java.beans.PropertyChangeEvent;
046
047 import javax.accessibility.Accessible;
048 import javax.accessibility.AccessibleContext;
049 import javax.accessibility.AccessibleRole;
050 import javax.accessibility.AccessibleState;
051 import javax.accessibility.AccessibleStateSet;
052 import javax.accessibility.AccessibleValue;
053 import javax.swing.event.ChangeEvent;
054 import javax.swing.event.ChangeListener;
055 import javax.swing.plaf.ScrollBarUI;
056
057 /**
058 * The JScrollBar. Two buttons control how the values that the
059 * scroll bar can take. You can also drag the thumb or click the track
060 * to move the scroll bar. Typically, the JScrollBar is used with
061 * other components to translate the value of the bar to the viewable
062 * contents of the other components.
063 */
064 public class JScrollBar extends JComponent implements Adjustable, Accessible
065 {
066 /**
067 * Provides the accessibility features for the <code>JScrollBar</code>
068 * component.
069 */
070 protected class AccessibleJScrollBar extends JComponent.AccessibleJComponent
071 implements AccessibleValue
072 {
073 private static final long serialVersionUID = -7758162392045586663L;
074
075 /**
076 * Creates a new <code>AccessibleJScrollBar</code> instance.
077 */
078 protected AccessibleJScrollBar()
079 {
080 super();
081 }
082
083 /**
084 * Returns a set containing the current state of the {@link JScrollBar}
085 * component.
086 *
087 * @return The accessible state set.
088 */
089 public AccessibleStateSet getAccessibleStateSet()
090 {
091 AccessibleStateSet result = super.getAccessibleStateSet();
092 if (orientation == JScrollBar.HORIZONTAL)
093 result.add(AccessibleState.HORIZONTAL);
094 else if (orientation == JScrollBar.VERTICAL)
095 result.add(AccessibleState.VERTICAL);
096 return result;
097 }
098
099 /**
100 * Returns the accessible role for the <code>JScrollBar</code> component.
101 *
102 * @return {@link AccessibleRole#SCROLL_BAR}.
103 */
104 public AccessibleRole getAccessibleRole()
105 {
106 return AccessibleRole.SCROLL_BAR;
107 }
108
109 /**
110 * Returns an object that provides access to the current, minimum and
111 * maximum values.
112 *
113 * @return The accessible value.
114 */
115 public AccessibleValue getAccessibleValue()
116 {
117 return this;
118 }
119
120 /**
121 * Returns the current value of the {@link JScrollBar} component, as an
122 * {@link Integer}.
123 *
124 * @return The current value of the {@link JScrollBar} component.
125 */
126 public Number getCurrentAccessibleValue()
127 {
128 return new Integer(getValue());
129 }
130
131 /**
132 * Sets the current value of the {@link JScrollBar} component and sends a
133 * {@link PropertyChangeEvent} (with the property name
134 * {@link AccessibleContext#ACCESSIBLE_VALUE_PROPERTY}) to all registered
135 * listeners. If the supplied value is <code>null</code>, this method
136 * does nothing and returns <code>false</code>.
137 *
138 * @param value the new slider value (<code>null</code> permitted).
139 *
140 * @return <code>true</code> if the slider value is updated, and
141 * <code>false</code> otherwise.
142 */
143 public boolean setCurrentAccessibleValue(Number value)
144 {
145 if (value == null)
146 return false;
147 Number oldValue = getCurrentAccessibleValue();
148 setValue(value.intValue());
149 firePropertyChange(AccessibleContext.ACCESSIBLE_VALUE_PROPERTY, oldValue,
150 new Integer(getValue()));
151 return true;
152 }
153
154 /**
155 * Returns the minimum value of the {@link JScrollBar} component, as an
156 * {@link Integer}.
157 *
158 * @return The minimum value of the {@link JScrollBar} component.
159 */
160 public Number getMinimumAccessibleValue()
161 {
162 return new Integer(getMinimum());
163 }
164
165 /**
166 * Returns the maximum value of the {@link JScrollBar} component, as an
167 * {@link Integer}.
168 *
169 * @return The maximum value of the {@link JScrollBar} component.
170 */
171 public Number getMaximumAccessibleValue()
172 {
173 return new Integer(getMaximum() - model.getExtent());
174 }
175 }
176
177 /**
178 * Listens for changes on the model and fires them to interested
179 * listeners on the JScrollBar, after re-sourcing them.
180 */
181 private class ScrollBarChangeListener
182 implements ChangeListener
183 {
184
185 public void stateChanged(ChangeEvent event)
186 {
187 Object o = event.getSource();
188 if (o instanceof BoundedRangeModel)
189 {
190 BoundedRangeModel m = (BoundedRangeModel) o;
191 fireAdjustmentValueChanged(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
192 AdjustmentEvent.TRACK, m.getValue(),
193 m.getValueIsAdjusting());
194 }
195 }
196
197 }
198
199 private static final long serialVersionUID = -8195169869225066566L;
200
201 /** How much the thumb moves when moving in a block. */
202 protected int blockIncrement = 10;
203
204 /** The model that holds the scroll bar's data. */
205 protected BoundedRangeModel model;
206
207 /** The orientation of the scroll bar. */
208 protected int orientation = SwingConstants.VERTICAL;
209
210 /** How much the thumb moves when moving in a unit. */
211 protected int unitIncrement = 1;
212
213 /**
214 * This ChangeListener forwards events fired from the model and re-sources
215 * them to originate from this JScrollBar.
216 */
217 private ChangeListener sbChangeListener;
218
219 /**
220 * Creates a new horizontal JScrollBar object with a minimum
221 * of 0, a maxmium of 100, a value of 0 and an extent of 10.
222 */
223 public JScrollBar()
224 {
225 this(SwingConstants.VERTICAL, 0, 10, 0, 100);
226 }
227
228 /**
229 * Creates a new JScrollBar object with a minimum of 0, a
230 * maximum of 100, a value of 0, an extent of 10 and the given
231 * orientation.
232 *
233 * @param orientation The orientation of the JScrollBar.
234 */
235 public JScrollBar(int orientation)
236 {
237 this(orientation, 0, 10, 0, 100);
238 }
239
240 /**
241 * Creates a new JScrollBar object with the given orientation,
242 * value, min, max, and extent.
243 *
244 * @param orientation The orientation to use.
245 * @param value The value to use.
246 * @param extent The extent to use.
247 * @param min The minimum value of the scrollbar.
248 * @param max The maximum value of the scrollbar.
249 */
250 public JScrollBar(int orientation, int value, int extent, int min, int max)
251 {
252 model = new DefaultBoundedRangeModel(value, extent, min, max);
253 sbChangeListener = new ScrollBarChangeListener();
254 model.addChangeListener(sbChangeListener);
255 if (orientation != SwingConstants.HORIZONTAL
256 && orientation != SwingConstants.VERTICAL)
257 throw new IllegalArgumentException(orientation
258 + " is not a legal orientation");
259 this.orientation = orientation;
260 updateUI();
261 }
262
263 /**
264 * This method sets the UI of this scrollbar to
265 * the given UI.
266 *
267 * @param ui The UI to use with this scrollbar.
268 */
269 public void setUI(ScrollBarUI ui)
270 {
271 super.setUI(ui);
272 }
273
274 /**
275 * This method returns the UI that is being used
276 * with this scrollbar.
277 *
278 * @return The scrollbar's current UI.
279 */
280 public ScrollBarUI getUI()
281 {
282 return (ScrollBarUI) ui;
283 }
284
285 /**
286 * This method changes the UI to be the
287 * default for the current look and feel.
288 */
289 public void updateUI()
290 {
291 setUI((ScrollBarUI) UIManager.getUI(this));
292 }
293
294 /**
295 * This method returns an identifier to
296 * choose the correct UI delegate for the
297 * scrollbar.
298 *
299 * @return The identifer to choose the UI delegate; "ScrollBarUI"
300 */
301 public String getUIClassID()
302 {
303 return "ScrollBarUI";
304 }
305
306 /**
307 * This method returns the orientation of the scrollbar.
308 *
309 * @return The orientation of the scrollbar.
310 */
311 public int getOrientation()
312 {
313 return orientation;
314 }
315
316 /**
317 * This method sets the orientation of the scrollbar.
318 *
319 * @param orientation The orientation of the scrollbar.
320 */
321 public void setOrientation(int orientation)
322 {
323 if (orientation != SwingConstants.HORIZONTAL
324 && orientation != SwingConstants.VERTICAL)
325 throw new IllegalArgumentException("orientation must be one of HORIZONTAL or VERTICAL");
326 if (orientation != this.orientation)
327 {
328 int oldOrientation = this.orientation;
329 this.orientation = orientation;
330 firePropertyChange("orientation", oldOrientation,
331 this.orientation);
332 }
333 }
334
335 /**
336 * This method returns the model being used with
337 * the scrollbar.
338 *
339 * @return The scrollbar's model.
340 */
341 public BoundedRangeModel getModel()
342 {
343 return model;
344 }
345
346 /**
347 * This method sets the model to use with
348 * the scrollbar.
349 *
350 * @param newModel The new model to use with the scrollbar.
351 */
352 public void setModel(BoundedRangeModel newModel)
353 {
354 BoundedRangeModel oldModel = model;
355 if (oldModel != null)
356 oldModel.removeChangeListener(sbChangeListener);
357 model = newModel;
358 if (model != null)
359 model.addChangeListener(sbChangeListener);
360 firePropertyChange("model", oldModel, model);
361 }
362
363 /**
364 * This method returns how much the scrollbar's value
365 * should change for a unit increment depending on the
366 * given direction.
367 *
368 * @param direction The direction to scroll in.
369 *
370 * @return The amount the scrollbar's value will change given the direction.
371 */
372 public int getUnitIncrement(int direction)
373 {
374 return unitIncrement;
375 }
376
377 /**
378 * This method sets the unitIncrement property.
379 *
380 * @param unitIncrement The new unitIncrement.
381 */
382 public void setUnitIncrement(int unitIncrement)
383 {
384 if (unitIncrement != this.unitIncrement)
385 {
386 int oldInc = this.unitIncrement;
387 this.unitIncrement = unitIncrement;
388 firePropertyChange("unitIncrement", oldInc,
389 this.unitIncrement);
390 }
391 }
392
393 /**
394 * The method returns how much the scrollbar's value
395 * should change for a block increment depending on
396 * the given direction.
397 *
398 * @param direction The direction to scroll in.
399 *
400 * @return The amount the scrollbar's value will change given the direction.
401 */
402 public int getBlockIncrement(int direction)
403 {
404 return blockIncrement;
405 }
406
407 /**
408 * This method sets the blockIncrement property.
409 *
410 * @param blockIncrement The new blockIncrement.
411 */
412 public void setBlockIncrement(int blockIncrement)
413 {
414 if (blockIncrement != this.blockIncrement)
415 {
416 int oldInc = this.blockIncrement;
417 this.blockIncrement = blockIncrement;
418 firePropertyChange("blockIncrement", oldInc,
419 this.blockIncrement);
420 }
421 }
422
423 /**
424 * This method returns the unitIncrement.
425 *
426 * @return The unitIncrement.
427 */
428 public int getUnitIncrement()
429 {
430 return unitIncrement;
431 }
432
433 /**
434 * This method returns the blockIncrement.
435 *
436 * @return The blockIncrement.
437 */
438 public int getBlockIncrement()
439 {
440 return blockIncrement;
441 }
442
443 /**
444 * This method returns the value of the scrollbar.
445 *
446 * @return The value of the scrollbar.
447 */
448 public int getValue()
449 {
450 return model.getValue();
451 }
452
453 /**
454 * This method changes the value of the scrollbar.
455 *
456 * @param value The new value of the scrollbar.
457 */
458 public void setValue(int value)
459 {
460 model.setValue(value);
461 }
462
463 /**
464 * This method returns the visible amount (AKA extent).
465 * The visible amount can be used by UI delegates to
466 * determine the size of the thumb.
467 *
468 * @return The visible amount (AKA extent).
469 */
470 public int getVisibleAmount()
471 {
472 return model.getExtent();
473 }
474
475 /**
476 * This method sets the visible amount (AKA extent).
477 *
478 * @param extent The visible amount (AKA extent).
479 */
480 public void setVisibleAmount(int extent)
481 {
482 model.setExtent(extent);
483 }
484
485 /**
486 * This method returns the minimum value of the scrollbar.
487 *
488 * @return The minimum value of the scrollbar.
489 */
490 public int getMinimum()
491 {
492 return model.getMinimum();
493 }
494
495 /**
496 * This method sets the minimum value of the scrollbar.
497 *
498 * @param minimum The minimum value of the scrollbar.
499 */
500 public void setMinimum(int minimum)
501 {
502 model.setMinimum(minimum);
503 }
504
505 /**
506 * This method returns the maximum value of the scrollbar.
507 *
508 * @return The maximum value of the scrollbar.
509 */
510 public int getMaximum()
511 {
512 return model.getMaximum();
513 }
514
515 /**
516 * This method sets the maximum value of the scrollbar.
517 *
518 * @param maximum The maximum value of the scrollbar.
519 */
520 public void setMaximum(int maximum)
521 {
522 model.setMaximum(maximum);
523 }
524
525 /**
526 * This method returns the model's isAjusting value.
527 *
528 * @return The model's isAdjusting value.
529 */
530 public boolean getValueIsAdjusting()
531 {
532 return model.getValueIsAdjusting();
533 }
534
535 /**
536 * This method sets the model's isAdjusting value.
537 *
538 * @param b The new isAdjusting value.
539 */
540 public void setValueIsAdjusting(boolean b)
541 {
542 model.setValueIsAdjusting(b);
543 }
544
545 /**
546 * This method sets the value, extent, minimum and
547 * maximum.
548 *
549 * @param newValue The new value.
550 * @param newExtent The new extent.
551 * @param newMin The new minimum.
552 * @param newMax The new maximum.
553 */
554 public void setValues(int newValue, int newExtent, int newMin, int newMax)
555 {
556 model.setRangeProperties(newValue, newExtent, newMin, newMax,
557 model.getValueIsAdjusting());
558 }
559
560 /**
561 * This method adds an AdjustmentListener to the scroll bar.
562 *
563 * @param listener The listener to add.
564 */
565 public void addAdjustmentListener(AdjustmentListener listener)
566 {
567 listenerList.add(AdjustmentListener.class, listener);
568 }
569
570 /**
571 * This method removes an AdjustmentListener from the scroll bar.
572 *
573 * @param listener The listener to remove.
574 */
575 public void removeAdjustmentListener(AdjustmentListener listener)
576 {
577 listenerList.remove(AdjustmentListener.class, listener);
578 }
579
580 /**
581 * This method returns an arry of all AdjustmentListeners listening to
582 * this scroll bar.
583 *
584 * @return An array of AdjustmentListeners listening to this scroll bar.
585 */
586 public AdjustmentListener[] getAdjustmentListeners()
587 {
588 return (AdjustmentListener[]) listenerList.getListeners(AdjustmentListener.class);
589 }
590
591 /**
592 * This method is called to fired AdjustmentEvents to the listeners
593 * of this scroll bar. All AdjustmentEvents that are fired
594 * will have an ID of ADJUSTMENT_VALUE_CHANGED and a type of
595 * TRACK.
596 *
597 * @param id The ID of the adjustment event.
598 * @param type The Type of change.
599 * @param value The new value for the property that was changed..
600 */
601 protected void fireAdjustmentValueChanged(int id, int type, int value)
602 {
603 fireAdjustmentValueChanged(id, type, value, getValueIsAdjusting());
604 }
605
606 /**
607 * Helper method for firing adjustment events that can have their
608 * isAdjusting field modified.
609 *
610 * This is package private to avoid an accessor method.
611 *
612 * @param id the ID of the event
613 * @param type the type of the event
614 * @param value the value
615 * @param isAdjusting if the scrollbar is adjusting or not
616 */
617 void fireAdjustmentValueChanged(int id, int type, int value,
618 boolean isAdjusting)
619 {
620 Object[] adjustmentListeners = listenerList.getListenerList();
621 AdjustmentEvent adjustmentEvent = new AdjustmentEvent(this, id, type,
622 value, isAdjusting);
623 for (int i = adjustmentListeners.length - 2; i >= 0; i -= 2)
624 {
625 if (adjustmentListeners[i] == AdjustmentListener.class)
626 ((AdjustmentListener) adjustmentListeners[i + 1]).adjustmentValueChanged(adjustmentEvent);
627 }
628 }
629
630 /**
631 * This method returns the minimum size for this scroll bar.
632 *
633 * @return The minimum size.
634 */
635 public Dimension getMinimumSize()
636 {
637 return ui.getMinimumSize(this);
638 }
639
640 /**
641 * This method returns the maximum size for this scroll bar.
642 *
643 * @return The maximum size.
644 */
645 public Dimension getMaximumSize()
646 {
647 return ui.getMaximumSize(this);
648 }
649
650 /**
651 * This method overrides the setEnabled in JComponent.
652 * When the scroll bar is disabled, the knob cannot
653 * be moved.
654 *
655 * @param x Whether the scrollbar is enabled.
656 */
657 public void setEnabled(boolean x)
658 {
659 // nothing special needs to be done here since we
660 // just check the enabled setting before changing the value.
661 super.setEnabled(x);
662 }
663
664 /**
665 * Returns a string describing the attributes for the <code>JScrollBar</code>
666 * component, for use in debugging. The return value is guaranteed to be
667 * non-<code>null</code>, but the format of the string may vary between
668 * implementations.
669 *
670 * @return A string describing the attributes of the <code>JScrollBar</code>.
671 */
672 protected String paramString()
673 {
674 StringBuffer sb = new StringBuffer(super.paramString());
675 sb.append(",blockIncrement=").append(blockIncrement);
676 sb.append(",orientation=");
677 if (this.orientation == JScrollBar.HORIZONTAL)
678 sb.append("HORIZONTAL");
679 else
680 sb.append("VERTICAL");
681 sb.append(",unitIncrement=").append(unitIncrement);
682 return sb.toString();
683 }
684
685 /**
686 * Returns the object that provides accessibility features for this
687 * <code>JScrollBar</code> component.
688 *
689 * @return The accessible context (an instance of
690 * {@link AccessibleJScrollBar}).
691 */
692 public AccessibleContext getAccessibleContext()
693 {
694 if (accessibleContext == null)
695 accessibleContext = new AccessibleJScrollBar();
696 return accessibleContext;
697 }
698 }