1 /* JScrollBar.java -- 2 Copyright (C) 2002, 2004, 2005, 2006, 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., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 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 javax.swing; 40 41 import gnu.java.lang.CPStringBuilder; 42 43 import java.awt.Adjustable; 44 import java.awt.Dimension; 45 import java.awt.event.AdjustmentEvent; 46 import java.awt.event.AdjustmentListener; 47 import java.beans.PropertyChangeEvent; 48 49 import javax.accessibility.Accessible; 50 import javax.accessibility.AccessibleContext; 51 import javax.accessibility.AccessibleRole; 52 import javax.accessibility.AccessibleState; 53 import javax.accessibility.AccessibleStateSet; 54 import javax.accessibility.AccessibleValue; 55 import javax.swing.event.ChangeEvent; 56 import javax.swing.event.ChangeListener; 57 import javax.swing.plaf.ScrollBarUI; 58 59 /** 60 * The JScrollBar. Two buttons control how the values that the 61 * scroll bar can take. You can also drag the thumb or click the track 62 * to move the scroll bar. Typically, the JScrollBar is used with 63 * other components to translate the value of the bar to the viewable 64 * contents of the other components. 65 */ 66 public class JScrollBar extends JComponent implements Adjustable, Accessible 67 { 68 /** 69 * Provides the accessibility features for the <code>JScrollBar</code> 70 * component. 71 */ 72 protected class AccessibleJScrollBar extends JComponent.AccessibleJComponent 73 implements AccessibleValue 74 { 75 private static final long serialVersionUID = -7758162392045586663L; 76 77 /** 78 * Creates a new <code>AccessibleJScrollBar</code> instance. 79 */ AccessibleJScrollBar()80 protected AccessibleJScrollBar() 81 { 82 super(); 83 } 84 85 /** 86 * Returns a set containing the current state of the {@link JScrollBar} 87 * component. 88 * 89 * @return The accessible state set. 90 */ getAccessibleStateSet()91 public AccessibleStateSet getAccessibleStateSet() 92 { 93 AccessibleStateSet result = super.getAccessibleStateSet(); 94 if (orientation == JScrollBar.HORIZONTAL) 95 result.add(AccessibleState.HORIZONTAL); 96 else if (orientation == JScrollBar.VERTICAL) 97 result.add(AccessibleState.VERTICAL); 98 return result; 99 } 100 101 /** 102 * Returns the accessible role for the <code>JScrollBar</code> component. 103 * 104 * @return {@link AccessibleRole#SCROLL_BAR}. 105 */ getAccessibleRole()106 public AccessibleRole getAccessibleRole() 107 { 108 return AccessibleRole.SCROLL_BAR; 109 } 110 111 /** 112 * Returns an object that provides access to the current, minimum and 113 * maximum values. 114 * 115 * @return The accessible value. 116 */ getAccessibleValue()117 public AccessibleValue getAccessibleValue() 118 { 119 return this; 120 } 121 122 /** 123 * Returns the current value of the {@link JScrollBar} component, as an 124 * {@link Integer}. 125 * 126 * @return The current value of the {@link JScrollBar} component. 127 */ getCurrentAccessibleValue()128 public Number getCurrentAccessibleValue() 129 { 130 return new Integer(getValue()); 131 } 132 133 /** 134 * Sets the current value of the {@link JScrollBar} component and sends a 135 * {@link PropertyChangeEvent} (with the property name 136 * {@link AccessibleContext#ACCESSIBLE_VALUE_PROPERTY}) to all registered 137 * listeners. If the supplied value is <code>null</code>, this method 138 * does nothing and returns <code>false</code>. 139 * 140 * @param value the new slider value (<code>null</code> permitted). 141 * 142 * @return <code>true</code> if the slider value is updated, and 143 * <code>false</code> otherwise. 144 */ setCurrentAccessibleValue(Number value)145 public boolean setCurrentAccessibleValue(Number value) 146 { 147 if (value == null) 148 return false; 149 Number oldValue = getCurrentAccessibleValue(); 150 setValue(value.intValue()); 151 firePropertyChange(AccessibleContext.ACCESSIBLE_VALUE_PROPERTY, oldValue, 152 new Integer(getValue())); 153 return true; 154 } 155 156 /** 157 * Returns the minimum value of the {@link JScrollBar} component, as an 158 * {@link Integer}. 159 * 160 * @return The minimum value of the {@link JScrollBar} component. 161 */ getMinimumAccessibleValue()162 public Number getMinimumAccessibleValue() 163 { 164 return new Integer(getMinimum()); 165 } 166 167 /** 168 * Returns the maximum value of the {@link JScrollBar} component, as an 169 * {@link Integer}. 170 * 171 * @return The maximum value of the {@link JScrollBar} component. 172 */ getMaximumAccessibleValue()173 public Number getMaximumAccessibleValue() 174 { 175 return new Integer(getMaximum() - model.getExtent()); 176 } 177 } 178 179 /** 180 * Listens for changes on the model and fires them to interested 181 * listeners on the JScrollBar, after re-sourcing them. 182 */ 183 private class ScrollBarChangeListener 184 implements ChangeListener 185 { 186 stateChanged(ChangeEvent event)187 public void stateChanged(ChangeEvent event) 188 { 189 Object o = event.getSource(); 190 if (o instanceof BoundedRangeModel) 191 { 192 BoundedRangeModel m = (BoundedRangeModel) o; 193 fireAdjustmentValueChanged(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, 194 AdjustmentEvent.TRACK, m.getValue(), 195 m.getValueIsAdjusting()); 196 } 197 } 198 199 } 200 201 private static final long serialVersionUID = -8195169869225066566L; 202 203 /** How much the thumb moves when moving in a block. */ 204 protected int blockIncrement = 10; 205 206 /** The model that holds the scroll bar's data. */ 207 protected BoundedRangeModel model; 208 209 /** The orientation of the scroll bar. */ 210 protected int orientation = SwingConstants.VERTICAL; 211 212 /** How much the thumb moves when moving in a unit. */ 213 protected int unitIncrement = 1; 214 215 /** 216 * This ChangeListener forwards events fired from the model and re-sources 217 * them to originate from this JScrollBar. 218 */ 219 private ChangeListener sbChangeListener; 220 221 /** 222 * Creates a new horizontal JScrollBar object with a minimum 223 * of 0, a maxmium of 100, a value of 0 and an extent of 10. 224 */ JScrollBar()225 public JScrollBar() 226 { 227 this(SwingConstants.VERTICAL, 0, 10, 0, 100); 228 } 229 230 /** 231 * Creates a new JScrollBar object with a minimum of 0, a 232 * maximum of 100, a value of 0, an extent of 10 and the given 233 * orientation. 234 * 235 * @param orientation The orientation of the JScrollBar. 236 */ JScrollBar(int orientation)237 public JScrollBar(int orientation) 238 { 239 this(orientation, 0, 10, 0, 100); 240 } 241 242 /** 243 * Creates a new JScrollBar object with the given orientation, 244 * value, min, max, and extent. 245 * 246 * @param orientation The orientation to use. 247 * @param value The value to use. 248 * @param extent The extent to use. 249 * @param min The minimum value of the scrollbar. 250 * @param max The maximum value of the scrollbar. 251 */ JScrollBar(int orientation, int value, int extent, int min, int max)252 public JScrollBar(int orientation, int value, int extent, int min, int max) 253 { 254 model = new DefaultBoundedRangeModel(value, extent, min, max); 255 sbChangeListener = new ScrollBarChangeListener(); 256 model.addChangeListener(sbChangeListener); 257 if (orientation != SwingConstants.HORIZONTAL 258 && orientation != SwingConstants.VERTICAL) 259 throw new IllegalArgumentException(orientation 260 + " is not a legal orientation"); 261 this.orientation = orientation; 262 updateUI(); 263 } 264 265 /** 266 * This method sets the UI of this scrollbar to 267 * the given UI. 268 * 269 * @param ui The UI to use with this scrollbar. 270 */ setUI(ScrollBarUI ui)271 public void setUI(ScrollBarUI ui) 272 { 273 super.setUI(ui); 274 } 275 276 /** 277 * This method returns the UI that is being used 278 * with this scrollbar. 279 * 280 * @return The scrollbar's current UI. 281 */ getUI()282 public ScrollBarUI getUI() 283 { 284 return (ScrollBarUI) ui; 285 } 286 287 /** 288 * This method changes the UI to be the 289 * default for the current look and feel. 290 */ updateUI()291 public void updateUI() 292 { 293 setUI((ScrollBarUI) UIManager.getUI(this)); 294 } 295 296 /** 297 * This method returns an identifier to 298 * choose the correct UI delegate for the 299 * scrollbar. 300 * 301 * @return The identifer to choose the UI delegate; "ScrollBarUI" 302 */ getUIClassID()303 public String getUIClassID() 304 { 305 return "ScrollBarUI"; 306 } 307 308 /** 309 * This method returns the orientation of the scrollbar. 310 * 311 * @return The orientation of the scrollbar. 312 */ getOrientation()313 public int getOrientation() 314 { 315 return orientation; 316 } 317 318 /** 319 * This method sets the orientation of the scrollbar. 320 * 321 * @param orientation The orientation of the scrollbar. 322 */ setOrientation(int orientation)323 public void setOrientation(int orientation) 324 { 325 if (orientation != SwingConstants.HORIZONTAL 326 && orientation != SwingConstants.VERTICAL) 327 throw new IllegalArgumentException("orientation must be one of HORIZONTAL or VERTICAL"); 328 if (orientation != this.orientation) 329 { 330 int oldOrientation = this.orientation; 331 this.orientation = orientation; 332 firePropertyChange("orientation", oldOrientation, 333 this.orientation); 334 } 335 } 336 337 /** 338 * This method returns the model being used with 339 * the scrollbar. 340 * 341 * @return The scrollbar's model. 342 */ getModel()343 public BoundedRangeModel getModel() 344 { 345 return model; 346 } 347 348 /** 349 * This method sets the model to use with 350 * the scrollbar. 351 * 352 * @param newModel The new model to use with the scrollbar. 353 */ setModel(BoundedRangeModel newModel)354 public void setModel(BoundedRangeModel newModel) 355 { 356 BoundedRangeModel oldModel = model; 357 if (oldModel != null) 358 oldModel.removeChangeListener(sbChangeListener); 359 model = newModel; 360 if (model != null) 361 model.addChangeListener(sbChangeListener); 362 firePropertyChange("model", oldModel, model); 363 } 364 365 /** 366 * This method returns how much the scrollbar's value 367 * should change for a unit increment depending on the 368 * given direction. 369 * 370 * @param direction The direction to scroll in. 371 * 372 * @return The amount the scrollbar's value will change given the direction. 373 */ getUnitIncrement(int direction)374 public int getUnitIncrement(int direction) 375 { 376 return unitIncrement; 377 } 378 379 /** 380 * This method sets the unitIncrement property. 381 * 382 * @param unitIncrement The new unitIncrement. 383 */ setUnitIncrement(int unitIncrement)384 public void setUnitIncrement(int unitIncrement) 385 { 386 if (unitIncrement != this.unitIncrement) 387 { 388 int oldInc = this.unitIncrement; 389 this.unitIncrement = unitIncrement; 390 firePropertyChange("unitIncrement", oldInc, 391 this.unitIncrement); 392 } 393 } 394 395 /** 396 * The method returns how much the scrollbar's value 397 * should change for a block increment depending on 398 * the given direction. 399 * 400 * @param direction The direction to scroll in. 401 * 402 * @return The amount the scrollbar's value will change given the direction. 403 */ getBlockIncrement(int direction)404 public int getBlockIncrement(int direction) 405 { 406 return blockIncrement; 407 } 408 409 /** 410 * This method sets the blockIncrement property. 411 * 412 * @param blockIncrement The new blockIncrement. 413 */ setBlockIncrement(int blockIncrement)414 public void setBlockIncrement(int blockIncrement) 415 { 416 if (blockIncrement != this.blockIncrement) 417 { 418 int oldInc = this.blockIncrement; 419 this.blockIncrement = blockIncrement; 420 firePropertyChange("blockIncrement", oldInc, 421 this.blockIncrement); 422 } 423 } 424 425 /** 426 * This method returns the unitIncrement. 427 * 428 * @return The unitIncrement. 429 */ getUnitIncrement()430 public int getUnitIncrement() 431 { 432 return unitIncrement; 433 } 434 435 /** 436 * This method returns the blockIncrement. 437 * 438 * @return The blockIncrement. 439 */ getBlockIncrement()440 public int getBlockIncrement() 441 { 442 return blockIncrement; 443 } 444 445 /** 446 * This method returns the value of the scrollbar. 447 * 448 * @return The value of the scrollbar. 449 */ getValue()450 public int getValue() 451 { 452 return model.getValue(); 453 } 454 455 /** 456 * This method changes the value of the scrollbar. 457 * 458 * @param value The new value of the scrollbar. 459 */ setValue(int value)460 public void setValue(int value) 461 { 462 model.setValue(value); 463 } 464 465 /** 466 * This method returns the visible amount (AKA extent). 467 * The visible amount can be used by UI delegates to 468 * determine the size of the thumb. 469 * 470 * @return The visible amount (AKA extent). 471 */ getVisibleAmount()472 public int getVisibleAmount() 473 { 474 return model.getExtent(); 475 } 476 477 /** 478 * This method sets the visible amount (AKA extent). 479 * 480 * @param extent The visible amount (AKA extent). 481 */ setVisibleAmount(int extent)482 public void setVisibleAmount(int extent) 483 { 484 model.setExtent(extent); 485 } 486 487 /** 488 * This method returns the minimum value of the scrollbar. 489 * 490 * @return The minimum value of the scrollbar. 491 */ getMinimum()492 public int getMinimum() 493 { 494 return model.getMinimum(); 495 } 496 497 /** 498 * This method sets the minimum value of the scrollbar. 499 * 500 * @param minimum The minimum value of the scrollbar. 501 */ setMinimum(int minimum)502 public void setMinimum(int minimum) 503 { 504 model.setMinimum(minimum); 505 } 506 507 /** 508 * This method returns the maximum value of the scrollbar. 509 * 510 * @return The maximum value of the scrollbar. 511 */ getMaximum()512 public int getMaximum() 513 { 514 return model.getMaximum(); 515 } 516 517 /** 518 * This method sets the maximum value of the scrollbar. 519 * 520 * @param maximum The maximum value of the scrollbar. 521 */ setMaximum(int maximum)522 public void setMaximum(int maximum) 523 { 524 model.setMaximum(maximum); 525 } 526 527 /** 528 * This method returns the model's isAjusting value. 529 * 530 * @return The model's isAdjusting value. 531 */ getValueIsAdjusting()532 public boolean getValueIsAdjusting() 533 { 534 return model.getValueIsAdjusting(); 535 } 536 537 /** 538 * This method sets the model's isAdjusting value. 539 * 540 * @param b The new isAdjusting value. 541 */ setValueIsAdjusting(boolean b)542 public void setValueIsAdjusting(boolean b) 543 { 544 model.setValueIsAdjusting(b); 545 } 546 547 /** 548 * This method sets the value, extent, minimum and 549 * maximum. 550 * 551 * @param newValue The new value. 552 * @param newExtent The new extent. 553 * @param newMin The new minimum. 554 * @param newMax The new maximum. 555 */ setValues(int newValue, int newExtent, int newMin, int newMax)556 public void setValues(int newValue, int newExtent, int newMin, int newMax) 557 { 558 model.setRangeProperties(newValue, newExtent, newMin, newMax, 559 model.getValueIsAdjusting()); 560 } 561 562 /** 563 * This method adds an AdjustmentListener to the scroll bar. 564 * 565 * @param listener The listener to add. 566 */ addAdjustmentListener(AdjustmentListener listener)567 public void addAdjustmentListener(AdjustmentListener listener) 568 { 569 listenerList.add(AdjustmentListener.class, listener); 570 } 571 572 /** 573 * This method removes an AdjustmentListener from the scroll bar. 574 * 575 * @param listener The listener to remove. 576 */ removeAdjustmentListener(AdjustmentListener listener)577 public void removeAdjustmentListener(AdjustmentListener listener) 578 { 579 listenerList.remove(AdjustmentListener.class, listener); 580 } 581 582 /** 583 * This method returns an arry of all AdjustmentListeners listening to 584 * this scroll bar. 585 * 586 * @return An array of AdjustmentListeners listening to this scroll bar. 587 */ getAdjustmentListeners()588 public AdjustmentListener[] getAdjustmentListeners() 589 { 590 return (AdjustmentListener[]) listenerList.getListeners(AdjustmentListener.class); 591 } 592 593 /** 594 * This method is called to fired AdjustmentEvents to the listeners 595 * of this scroll bar. All AdjustmentEvents that are fired 596 * will have an ID of ADJUSTMENT_VALUE_CHANGED and a type of 597 * TRACK. 598 * 599 * @param id The ID of the adjustment event. 600 * @param type The Type of change. 601 * @param value The new value for the property that was changed.. 602 */ fireAdjustmentValueChanged(int id, int type, int value)603 protected void fireAdjustmentValueChanged(int id, int type, int value) 604 { 605 fireAdjustmentValueChanged(id, type, value, getValueIsAdjusting()); 606 } 607 608 /** 609 * Helper method for firing adjustment events that can have their 610 * isAdjusting field modified. 611 * 612 * This is package private to avoid an accessor method. 613 * 614 * @param id the ID of the event 615 * @param type the type of the event 616 * @param value the value 617 * @param isAdjusting if the scrollbar is adjusting or not 618 */ fireAdjustmentValueChanged(int id, int type, int value, boolean isAdjusting)619 void fireAdjustmentValueChanged(int id, int type, int value, 620 boolean isAdjusting) 621 { 622 Object[] adjustmentListeners = listenerList.getListenerList(); 623 AdjustmentEvent adjustmentEvent = new AdjustmentEvent(this, id, type, 624 value, isAdjusting); 625 for (int i = adjustmentListeners.length - 2; i >= 0; i -= 2) 626 { 627 if (adjustmentListeners[i] == AdjustmentListener.class) 628 ((AdjustmentListener) adjustmentListeners[i + 1]).adjustmentValueChanged(adjustmentEvent); 629 } 630 } 631 632 /** 633 * This method returns the minimum size for this scroll bar. 634 * 635 * @return The minimum size. 636 */ getMinimumSize()637 public Dimension getMinimumSize() 638 { 639 return ui.getMinimumSize(this); 640 } 641 642 /** 643 * This method returns the maximum size for this scroll bar. 644 * 645 * @return The maximum size. 646 */ getMaximumSize()647 public Dimension getMaximumSize() 648 { 649 return ui.getMaximumSize(this); 650 } 651 652 /** 653 * This method overrides the setEnabled in JComponent. 654 * When the scroll bar is disabled, the knob cannot 655 * be moved. 656 * 657 * @param x Whether the scrollbar is enabled. 658 */ setEnabled(boolean x)659 public void setEnabled(boolean x) 660 { 661 // nothing special needs to be done here since we 662 // just check the enabled setting before changing the value. 663 super.setEnabled(x); 664 } 665 666 /** 667 * Returns a string describing the attributes for the <code>JScrollBar</code> 668 * component, for use in debugging. The return value is guaranteed to be 669 * non-<code>null</code>, but the format of the string may vary between 670 * implementations. 671 * 672 * @return A string describing the attributes of the <code>JScrollBar</code>. 673 */ paramString()674 protected String paramString() 675 { 676 CPStringBuilder sb = new CPStringBuilder(super.paramString()); 677 sb.append(",blockIncrement=").append(blockIncrement); 678 sb.append(",orientation="); 679 if (this.orientation == JScrollBar.HORIZONTAL) 680 sb.append("HORIZONTAL"); 681 else 682 sb.append("VERTICAL"); 683 sb.append(",unitIncrement=").append(unitIncrement); 684 return sb.toString(); 685 } 686 687 /** 688 * Returns the object that provides accessibility features for this 689 * <code>JScrollBar</code> component. 690 * 691 * @return The accessible context (an instance of 692 * {@link AccessibleJScrollBar}). 693 */ getAccessibleContext()694 public AccessibleContext getAccessibleContext() 695 { 696 if (accessibleContext == null) 697 accessibleContext = new AccessibleJScrollBar(); 698 return accessibleContext; 699 } 700 } 701