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 }