1 7 package javax.swing.plaf.basic; 8 9 10 import sun.swing.DefaultLookup; 11 import sun.swing.UIAction; 12 13 import java.awt.*; 14 import java.awt.event.*; 15 16 import java.beans.*; 17 18 import javax.swing.*; 19 import javax.swing.event.*; 20 import javax.swing.plaf.*; 21 22 23 31 public class BasicScrollBarUI 32 extends ScrollBarUI implements LayoutManager, SwingConstants 33 { 34 private static final int POSITIVE_SCROLL = 1; 35 private static final int NEGATIVE_SCROLL = -1; 36 37 private static final int MIN_SCROLL = 2; 38 private static final int MAX_SCROLL = 3; 39 40 protected Dimension minimumThumbSize; 41 protected Dimension maximumThumbSize; 42 43 protected Color thumbHighlightColor; 44 protected Color thumbLightShadowColor; 45 protected Color thumbDarkShadowColor; 46 protected Color thumbColor; 47 protected Color trackColor; 48 protected Color trackHighlightColor; 49 50 protected JScrollBar scrollbar; 51 protected JButton incrButton; 52 protected JButton decrButton; 53 protected boolean isDragging; 54 protected TrackListener trackListener; 55 protected ArrowButtonListener buttonListener; 56 protected ModelListener modelListener; 57 58 protected Rectangle thumbRect; 59 protected Rectangle trackRect; 60 61 protected int trackHighlight; 62 63 protected static final int NO_HIGHLIGHT = 0; 64 protected static final int DECREASE_HIGHLIGHT = 1; 65 protected static final int INCREASE_HIGHLIGHT = 2; 66 67 protected ScrollListener scrollListener; 68 protected PropertyChangeListener propertyChangeListener; 69 protected Timer scrollTimer; 70 71 private final static int scrollSpeedThrottle = 60; 73 75 private boolean supportsAbsolutePositioning; 76 77 80 private int scrollBarWidth; 81 82 private Handler handler; 83 84 private boolean thumbActive; 85 86 90 private boolean useCachedValue = false; 91 94 private int scrollBarValue; 95 96 static void loadActionMap(LazyActionMap map) { 97 map.put(new Actions(Actions.POSITIVE_UNIT_INCREMENT)); 98 map.put(new Actions(Actions.POSITIVE_BLOCK_INCREMENT)); 99 map.put(new Actions(Actions.NEGATIVE_UNIT_INCREMENT)); 100 map.put(new Actions(Actions.NEGATIVE_BLOCK_INCREMENT)); 101 map.put(new Actions(Actions.MIN_SCROLL)); 102 map.put(new Actions(Actions.MAX_SCROLL)); 103 } 104 105 106 public static ComponentUI createUI(JComponent c) { 107 return new BasicScrollBarUI (); 108 } 109 110 111 protected void configureScrollBarColors() 112 { 113 LookAndFeel.installColors(scrollbar, "ScrollBar.background", 114 "ScrollBar.foreground"); 115 thumbHighlightColor = UIManager.getColor("ScrollBar.thumbHighlight"); 116 thumbLightShadowColor = UIManager.getColor("ScrollBar.thumbShadow"); 117 thumbDarkShadowColor = UIManager.getColor("ScrollBar.thumbDarkShadow"); 118 thumbColor = UIManager.getColor("ScrollBar.thumb"); 119 trackColor = UIManager.getColor("ScrollBar.track"); 120 trackHighlightColor = UIManager.getColor("ScrollBar.trackHighlight"); 121 } 122 123 124 public void installUI(JComponent c) { 125 scrollbar = (JScrollBar)c; 126 thumbRect = new Rectangle(0, 0, 0, 0); 127 trackRect = new Rectangle(0, 0, 0, 0); 128 installDefaults(); 129 installComponents(); 130 installListeners(); 131 installKeyboardActions(); 132 } 133 134 public void uninstallUI(JComponent c) { 135 scrollbar = (JScrollBar)c; 136 uninstallListeners(); 137 uninstallDefaults(); 138 uninstallComponents(); 139 uninstallKeyboardActions(); 140 thumbRect = null; 141 scrollbar = null; 142 incrButton = null; 143 decrButton = null; 144 } 145 146 147 protected void installDefaults() 148 { 149 scrollBarWidth = UIManager.getInt("ScrollBar.width"); 150 if (scrollBarWidth <= 0) { 151 scrollBarWidth = 16; 152 } 153 minimumThumbSize = (Dimension)UIManager.get("ScrollBar.minimumThumbSize"); 154 maximumThumbSize = (Dimension)UIManager.get("ScrollBar.maximumThumbSize"); 155 156 Boolean absB = (Boolean )UIManager.get("ScrollBar.allowsAbsolutePositioning"); 157 supportsAbsolutePositioning = (absB != null) ? absB.booleanValue() : 158 false; 159 160 trackHighlight = NO_HIGHLIGHT; 161 if (scrollbar.getLayout() == null || 162 (scrollbar.getLayout() instanceof UIResource)) { 163 scrollbar.setLayout(this); 164 } 165 configureScrollBarColors(); 166 LookAndFeel.installBorder(scrollbar, "ScrollBar.border"); 167 LookAndFeel.installProperty(scrollbar, "opaque", Boolean.TRUE); 168 169 scrollBarValue = scrollbar.getValue(); 170 } 171 172 173 protected void installComponents(){ 174 switch (scrollbar.getOrientation()) { 175 case JScrollBar.VERTICAL: 176 incrButton = createIncreaseButton(SOUTH); 177 decrButton = createDecreaseButton(NORTH); 178 break; 179 180 case JScrollBar.HORIZONTAL: 181 if (scrollbar.getComponentOrientation().isLeftToRight()) { 182 incrButton = createIncreaseButton(EAST); 183 decrButton = createDecreaseButton(WEST); 184 } else { 185 incrButton = createIncreaseButton(WEST); 186 decrButton = createDecreaseButton(EAST); 187 } 188 break; 189 } 190 scrollbar.add(incrButton); 191 scrollbar.add(decrButton); 192 scrollbar.setEnabled(scrollbar.isEnabled()); 194 } 195 196 protected void uninstallComponents(){ 197 scrollbar.remove(incrButton); 198 scrollbar.remove(decrButton); 199 } 200 201 202 protected void installListeners(){ 203 trackListener = createTrackListener(); 204 buttonListener = createArrowButtonListener(); 205 modelListener = createModelListener(); 206 propertyChangeListener = createPropertyChangeListener(); 207 208 scrollbar.addMouseListener(trackListener); 209 scrollbar.addMouseMotionListener(trackListener); 210 scrollbar.getModel().addChangeListener(modelListener); 211 scrollbar.addPropertyChangeListener(propertyChangeListener); 212 scrollbar.addFocusListener(getHandler()); 213 214 if (incrButton != null) { 215 incrButton.addMouseListener(buttonListener); 216 } 217 if (decrButton != null) { 218 decrButton.addMouseListener(buttonListener); 219 } 220 221 scrollListener = createScrollListener(); 222 scrollTimer = new Timer(scrollSpeedThrottle, scrollListener); 223 scrollTimer.setInitialDelay(300); } 225 226 227 protected void installKeyboardActions(){ 228 LazyActionMap.installLazyActionMap(scrollbar, BasicScrollBarUI .class, 229 "ScrollBar.actionMap"); 230 231 InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); 232 SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED, 233 inputMap); 234 inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 235 SwingUtilities.replaceUIInputMap(scrollbar, 236 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap); 237 } 238 239 protected void uninstallKeyboardActions(){ 240 SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED, 241 null); 242 SwingUtilities.replaceUIActionMap(scrollbar, null); 243 } 244 245 private InputMap getInputMap(int condition) { 246 if (condition == JComponent.WHEN_FOCUSED) { 247 InputMap keyMap = (InputMap)DefaultLookup.get( 248 scrollbar, this, "ScrollBar.focusInputMap"); 249 InputMap rtlKeyMap; 250 251 if (scrollbar.getComponentOrientation().isLeftToRight() || 252 ((rtlKeyMap = (InputMap)DefaultLookup.get(scrollbar, this, "ScrollBar.focusInputMap.RightToLeft")) == null)) { 253 return keyMap; 254 } else { 255 rtlKeyMap.setParent(keyMap); 256 return rtlKeyMap; 257 } 258 } 259 else if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { 260 InputMap keyMap = (InputMap)DefaultLookup.get( 261 scrollbar, this, "ScrollBar.ancestorInputMap"); 262 InputMap rtlKeyMap; 263 264 if (scrollbar.getComponentOrientation().isLeftToRight() || 265 ((rtlKeyMap = (InputMap)DefaultLookup.get(scrollbar, this, "ScrollBar.ancestorInputMap.RightToLeft")) == null)) { 266 return keyMap; 267 } else { 268 rtlKeyMap.setParent(keyMap); 269 return rtlKeyMap; 270 } 271 } 272 return null; 273 } 274 275 276 protected void uninstallListeners() { 277 scrollTimer.stop(); 278 scrollTimer = null; 279 280 if (decrButton != null){ 281 decrButton.removeMouseListener(buttonListener); 282 } 283 if (incrButton != null){ 284 incrButton.removeMouseListener(buttonListener); 285 } 286 287 scrollbar.getModel().removeChangeListener(modelListener); 288 scrollbar.removeMouseListener(trackListener); 289 scrollbar.removeMouseMotionListener(trackListener); 290 scrollbar.removePropertyChangeListener(propertyChangeListener); 291 scrollbar.removeFocusListener(getHandler()); 292 handler = null; 293 } 294 295 296 protected void uninstallDefaults(){ 297 LookAndFeel.uninstallBorder(scrollbar); 298 if (scrollbar.getLayout() == this) { 299 scrollbar.setLayout(null); 300 } 301 } 302 303 304 private Handler getHandler() { 305 if (handler == null) { 306 handler = new Handler(); 307 } 308 return handler; 309 } 310 311 protected TrackListener createTrackListener(){ 312 return new TrackListener(); 313 } 314 315 protected ArrowButtonListener createArrowButtonListener(){ 316 return new ArrowButtonListener(); 317 } 318 319 protected ModelListener createModelListener(){ 320 return new ModelListener(); 321 } 322 323 protected ScrollListener createScrollListener(){ 324 return new ScrollListener(); 325 } 326 327 protected PropertyChangeListener createPropertyChangeListener() { 328 return getHandler(); 329 } 330 331 private void updateThumbState(int x, int y) { 332 Rectangle rect = getThumbBounds(); 333 334 setThumbRollover(rect.contains(x, y)); 335 } 336 337 343 protected void setThumbRollover(boolean active) { 344 if (thumbActive != active) { 345 thumbActive = active; 346 scrollbar.repaint(getThumbBounds()); 347 } 348 } 349 350 356 public boolean isThumbRollover() { 357 return thumbActive; 358 } 359 360 public void paint(Graphics g, JComponent c) { 361 paintTrack(g, c, getTrackBounds()); 362 Rectangle thumbBounds = getThumbBounds(); 363 if (thumbBounds.intersects(g.getClipBounds())) { 364 paintThumb(g, c, thumbBounds); 365 } 366 } 367 368 369 385 public Dimension getPreferredSize(JComponent c) { 386 return (scrollbar.getOrientation() == JScrollBar.VERTICAL) 387 ? new Dimension(scrollBarWidth, 48) 388 : new Dimension(48, scrollBarWidth); 389 } 390 391 392 398 public Dimension getMaximumSize(JComponent c) { 399 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 400 } 401 402 protected JButton createDecreaseButton(int orientation) { 403 return new BasicArrowButton (orientation, 404 UIManager.getColor("ScrollBar.thumb"), 405 UIManager.getColor("ScrollBar.thumbShadow"), 406 UIManager.getColor("ScrollBar.thumbDarkShadow"), 407 UIManager.getColor("ScrollBar.thumbHighlight")); 408 } 409 410 protected JButton createIncreaseButton(int orientation) { 411 return new BasicArrowButton (orientation, 412 UIManager.getColor("ScrollBar.thumb"), 413 UIManager.getColor("ScrollBar.thumbShadow"), 414 UIManager.getColor("ScrollBar.thumbDarkShadow"), 415 UIManager.getColor("ScrollBar.thumbHighlight")); 416 } 417 418 419 protected void paintDecreaseHighlight(Graphics g) 420 { 421 Insets insets = scrollbar.getInsets(); 422 Rectangle thumbR = getThumbBounds(); 423 g.setColor(trackHighlightColor); 424 425 if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { 426 int x = insets.left; 427 int y = decrButton.getY() + decrButton.getHeight(); 428 int w = scrollbar.getWidth() - (insets.left + insets.right); 429 int h = thumbR.y - y; 430 g.fillRect(x, y, w, h); 431 } 432 else { 433 int x, w; 434 if (scrollbar.getComponentOrientation().isLeftToRight()) { 435 x = decrButton.getX() + decrButton.getWidth(); 436 w = thumbR.x - x; 437 } else { 438 x = thumbR.x + thumbR.width; 439 w = decrButton.getX() - x; 440 } 441 int y = insets.top; 442 int h = scrollbar.getHeight() - (insets.top + insets.bottom); 443 g.fillRect(x, y, w, h); 444 } 445 } 446 447 448 protected void paintIncreaseHighlight(Graphics g) 449 { 450 Insets insets = scrollbar.getInsets(); 451 Rectangle thumbR = getThumbBounds(); 452 g.setColor(trackHighlightColor); 453 454 if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { 455 int x = insets.left; 456 int y = thumbR.y + thumbR.height; 457 int w = scrollbar.getWidth() - (insets.left + insets.right); 458 int h = incrButton.getY() - y; 459 g.fillRect(x, y, w, h); 460 } 461 else { 462 int x, w; 463 if (scrollbar.getComponentOrientation().isLeftToRight()) { 464 x = thumbR.x + thumbR.width; 465 w = incrButton.getX() - x; 466 } else { 467 x = incrButton.getX() + incrButton.getWidth(); 468 w = thumbR.x - x; 469 } 470 int y = insets.top; 471 int h = scrollbar.getHeight() - (insets.top + insets.bottom); 472 g.fillRect(x, y, w, h); 473 } 474 } 475 476 477 protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) 478 { 479 g.setColor(trackColor); 480 g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width, trackBounds.height); 481 482 if(trackHighlight == DECREASE_HIGHLIGHT) { 483 paintDecreaseHighlight(g); 484 } 485 else if(trackHighlight == INCREASE_HIGHLIGHT) { 486 paintIncreaseHighlight(g); 487 } 488 } 489 490 491 protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) 492 { 493 if(thumbBounds.isEmpty() || !scrollbar.isEnabled()) { 494 return; 495 } 496 497 int w = thumbBounds.width; 498 int h = thumbBounds.height; 499 500 g.translate(thumbBounds.x, thumbBounds.y); 501 502 g.setColor(thumbDarkShadowColor); 503 g.drawRect(0, 0, w-1, h-1); 504 g.setColor(thumbColor); 505 g.fillRect(0, 0, w-1, h-1); 506 507 g.setColor(thumbHighlightColor); 508 g.drawLine(1, 1, 1, h-2); 509 g.drawLine(2, 1, w-3, 1); 510 511 g.setColor(thumbLightShadowColor); 512 g.drawLine(2, h-2, w-2, h-2); 513 g.drawLine(w-2, 1, w-2, h-3); 514 515 g.translate(-thumbBounds.x, -thumbBounds.y); 516 } 517 518 519 530 protected Dimension getMinimumThumbSize() { 531 return minimumThumbSize; 532 } 533 534 545 protected Dimension getMaximumThumbSize() { 546 return maximumThumbSize; 547 } 548 549 550 553 554 public void addLayoutComponent(String name, Component child) {} 555 public void removeLayoutComponent(Component child) {} 556 557 public Dimension preferredLayoutSize(Container scrollbarContainer) { 558 return getPreferredSize((JComponent)scrollbarContainer); 559 } 560 561 public Dimension minimumLayoutSize(Container scrollbarContainer) { 562 return getMinimumSize((JComponent)scrollbarContainer); 563 } 564 565 private int getValue(JScrollBar sb) { 566 return (useCachedValue) ? scrollBarValue : sb.getValue(); 567 } 568 569 protected void layoutVScrollbar(JScrollBar sb) 570 { 571 Dimension sbSize = sb.getSize(); 572 Insets sbInsets = sb.getInsets(); 573 574 577 int itemW = sbSize.width - (sbInsets.left + sbInsets.right); 578 int itemX = sbInsets.left; 579 580 583 boolean squareButtons = DefaultLookup.getBoolean( 584 scrollbar, this, "ScrollBar.squareButtons", false); 585 int decrButtonH = squareButtons ? itemW : 586 decrButton.getPreferredSize().height; 587 int decrButtonY = sbInsets.top; 588 589 int incrButtonH = squareButtons ? itemW : 590 incrButton.getPreferredSize().height; 591 int incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH); 592 593 596 int sbInsetsH = sbInsets.top + sbInsets.bottom; 597 int sbButtonsH = decrButtonH + incrButtonH; 598 float trackH = sbSize.height - (sbInsetsH + sbButtonsH); 599 600 606 float min = sb.getMinimum(); 607 float extent = sb.getVisibleAmount(); 608 float range = sb.getMaximum() - min; 609 float value = getValue(sb); 610 611 int thumbH = (range <= 0) 612 ? getMaximumThumbSize().height : (int)(trackH * (extent / range)); 613 thumbH = Math.max(thumbH, getMinimumThumbSize().height); 614 thumbH = Math.min(thumbH, getMaximumThumbSize().height); 615 616 int thumbY = incrButtonY - thumbH; 617 if (value < (sb.getMaximum() - sb.getVisibleAmount())) { 618 float thumbRange = trackH - thumbH; 619 thumbY = (int)(0.5f + (thumbRange * ((value - min) / (range - extent)))); 620 thumbY += decrButtonY + decrButtonH; 621 } 622 623 626 int sbAvailButtonH = (sbSize.height - sbInsetsH); 627 if (sbAvailButtonH < sbButtonsH) { 628 incrButtonH = decrButtonH = sbAvailButtonH / 2; 629 incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH); 630 } 631 decrButton.setBounds(itemX, decrButtonY, itemW, decrButtonH); 632 incrButton.setBounds(itemX, incrButtonY, itemW, incrButtonH); 633 634 636 int itrackY = decrButtonY + decrButtonH; 637 int itrackH = incrButtonY - itrackY; 638 trackRect.setBounds(itemX, itrackY, itemW, itrackH); 639 640 644 if(thumbH >= (int)trackH) { 645 setThumbBounds(0, 0, 0, 0); 646 } 647 else { 648 if ((thumbY + thumbH) > incrButtonY) { 649 thumbY = incrButtonY - thumbH; 650 } 651 if (thumbY < (decrButtonY + decrButtonH)) { 652 thumbY = decrButtonY + decrButtonH + 1; 653 } 654 setThumbBounds(itemX, thumbY, itemW, thumbH); 655 } 656 } 657 658 659 protected void layoutHScrollbar(JScrollBar sb) 660 { 661 Dimension sbSize = sb.getSize(); 662 Insets sbInsets = sb.getInsets(); 663 664 666 int itemH = sbSize.height - (sbInsets.top + sbInsets.bottom); 667 int itemY = sbInsets.top; 668 669 boolean ltr = sb.getComponentOrientation().isLeftToRight(); 670 671 674 boolean squareButtons = DefaultLookup.getBoolean( 675 scrollbar, this, "ScrollBar.squareButtons", false); 676 int leftButtonW = squareButtons ? itemH : 677 decrButton.getPreferredSize().width; 678 int rightButtonW = squareButtons ? itemH : 679 incrButton.getPreferredSize().width; 680 if (!ltr) { 681 int temp = leftButtonW; 682 leftButtonW = rightButtonW; 683 rightButtonW = temp; 684 } 685 int leftButtonX = sbInsets.left; 686 int rightButtonX = sbSize.width - (sbInsets.right + rightButtonW); 687 688 691 int sbInsetsW = sbInsets.left + sbInsets.right; 692 int sbButtonsW = leftButtonW + rightButtonW; 693 float trackW = sbSize.width - (sbInsetsW + sbButtonsW); 694 695 701 float min = sb.getMinimum(); 702 float max = sb.getMaximum(); 703 float extent = sb.getVisibleAmount(); 704 float range = max - min; 705 float value = getValue(sb); 706 707 int thumbW = (range <= 0) 708 ? getMaximumThumbSize().width : (int)(trackW * (extent / range)); 709 thumbW = Math.max(thumbW, getMinimumThumbSize().width); 710 thumbW = Math.min(thumbW, getMaximumThumbSize().width); 711 712 int thumbX = ltr ? rightButtonX - thumbW : leftButtonX + leftButtonW; 713 if (value < (max - sb.getVisibleAmount())) { 714 float thumbRange = trackW - thumbW; 715 if( ltr ) { 716 thumbX = (int)(0.5f + (thumbRange * ((value - min) / (range - extent)))); 717 } else { 718 thumbX = (int)(0.5f + (thumbRange * ((max - extent - value) / (range - extent)))); 719 } 720 thumbX += leftButtonX + leftButtonW; 721 } 722 723 726 int sbAvailButtonW = (sbSize.width - sbInsetsW); 727 if (sbAvailButtonW < sbButtonsW) { 728 rightButtonW = leftButtonW = sbAvailButtonW / 2; 729 rightButtonX = sbSize.width - (sbInsets.right + rightButtonW); 730 } 731 732 (ltr ? decrButton : incrButton).setBounds(leftButtonX, itemY, leftButtonW, itemH); 733 (ltr ? incrButton : decrButton).setBounds(rightButtonX, itemY, rightButtonW, itemH); 734 735 737 int itrackX = leftButtonX + leftButtonW; 738 int itrackW = rightButtonX - itrackX; 739 trackRect.setBounds(itrackX, itemY, itrackW, itemH); 740 741 744 if (thumbW >= (int)trackW) { 745 setThumbBounds(0, 0, 0, 0); 746 } 747 else { 748 if (thumbX + thumbW > rightButtonX) { 749 thumbX = rightButtonX - thumbW; 750 } 751 if (thumbX < leftButtonX + leftButtonW) { 752 thumbX = leftButtonX + leftButtonW + 1; 753 } 754 setThumbBounds(thumbX, itemY, thumbW, itemH); 755 } 756 } 757 758 public void layoutContainer(Container scrollbarContainer) 759 { 760 764 if (isDragging) { 765 return; 766 } 767 768 JScrollBar scrollbar = (JScrollBar)scrollbarContainer; 769 switch (scrollbar.getOrientation()) { 770 case JScrollBar.VERTICAL: 771 layoutVScrollbar(scrollbar); 772 break; 773 774 case JScrollBar.HORIZONTAL: 775 layoutHScrollbar(scrollbar); 776 break; 777 } 778 } 779 780 781 787 protected void setThumbBounds(int x, int y, int width, int height) 788 { 789 791 if ((thumbRect.x == x) && 792 (thumbRect.y == y) && 793 (thumbRect.width == width) && 794 (thumbRect.height == height)) { 795 return; 796 } 797 798 801 int minX = Math.min(x, thumbRect.x); 802 int minY = Math.min(y, thumbRect.y); 803 int maxX = Math.max(x + width, thumbRect.x + thumbRect.width); 804 int maxY = Math.max(y + height, thumbRect.y + thumbRect.height); 805 806 thumbRect.setBounds(x, y, width, height); 807 scrollbar.repaint(minX, minY, maxX - minX, maxY - minY); 808 809 setThumbRollover(false); 812 } 813 814 815 824 protected Rectangle getThumbBounds() { 825 return thumbRect; 826 } 827 828 829 841 protected Rectangle getTrackBounds() { 842 return trackRect; 843 } 844 845 849 static void scrollByBlock(JScrollBar scrollbar, int direction) { 850 int oldValue = scrollbar.getValue(); 853 int blockIncrement = scrollbar.getBlockIncrement(direction); 854 int delta = blockIncrement * ((direction > 0) ? +1 : -1); 855 int newValue = oldValue + delta; 856 857 if (delta > 0 && newValue < oldValue) { 859 newValue = scrollbar.getMaximum(); 860 } 861 else if (delta < 0 && newValue > oldValue) { 862 newValue = scrollbar.getMinimum(); 863 } 864 865 scrollbar.setValue(newValue); 866 } 867 868 protected void scrollByBlock(int direction) 869 { 870 scrollByBlock(scrollbar, direction); 871 trackHighlight = direction > 0 ? INCREASE_HIGHLIGHT : DECREASE_HIGHLIGHT; 872 Rectangle dirtyRect = getTrackBounds(); 873 scrollbar.repaint(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height); 874 } 875 876 880 static void scrollByUnits(JScrollBar scrollbar, int direction, 881 int units) { 882 int delta; 885 886 for (int i=0; i<units; i++) { 887 if (direction > 0) { 888 delta = scrollbar.getUnitIncrement(direction); 889 } 890 else { 891 delta = -scrollbar.getUnitIncrement(direction); 892 } 893 894 int oldValue = scrollbar.getValue(); 895 int newValue = oldValue + delta; 896 897 if (delta > 0 && newValue < oldValue) { 899 newValue = scrollbar.getMaximum(); 900 } 901 else if (delta < 0 && newValue > oldValue) { 902 newValue = scrollbar.getMinimum(); 903 } 904 if (oldValue == newValue) { 905 break; 906 } 907 scrollbar.setValue(newValue); 908 } 909 } 910 911 protected void scrollByUnit(int direction) { 912 scrollByUnits(scrollbar, direction, 1); 913 } 914 915 922 public boolean getSupportsAbsolutePositioning() { 923 return supportsAbsolutePositioning; 924 } 925 926 930 protected class ModelListener implements ChangeListener { 931 public void stateChanged(ChangeEvent e) { 932 if (!useCachedValue) { 933 scrollBarValue = scrollbar.getValue(); 934 } 935 layoutContainer(scrollbar); 936 useCachedValue = false; 937 } 938 } 939 940 941 944 protected class TrackListener 945 extends MouseAdapter implements MouseMotionListener 946 { 947 protected transient int offset; 948 protected transient int currentMouseX, currentMouseY; 949 private transient int direction = +1; 950 951 public void mouseReleased(MouseEvent e) 952 { 953 if (isDragging) { 954 updateThumbState(e.getX(), e.getY()); 955 } 956 if (SwingUtilities.isRightMouseButton(e) || 957 (!getSupportsAbsolutePositioning() && 958 SwingUtilities.isMiddleMouseButton(e))) 959 return; 960 if(!scrollbar.isEnabled()) 961 return; 962 963 Rectangle r = getTrackBounds(); 964 scrollbar.repaint(r.x, r.y, r.width, r.height); 965 966 trackHighlight = NO_HIGHLIGHT; 967 isDragging = false; 968 offset = 0; 969 scrollTimer.stop(); 970 useCachedValue = true; 971 scrollbar.setValueIsAdjusting(false); 972 } 973 974 975 982 public void mousePressed(MouseEvent e) 983 { 984 if (SwingUtilities.isRightMouseButton(e) || 985 (!getSupportsAbsolutePositioning() && 986 SwingUtilities.isMiddleMouseButton(e))) 987 return; 988 if(!scrollbar.isEnabled()) 989 return; 990 991 if (!scrollbar.hasFocus() && scrollbar.isRequestFocusEnabled()) { 992 scrollbar.requestFocus(); 993 } 994 995 useCachedValue = true; 996 scrollbar.setValueIsAdjusting(true); 997 998 currentMouseX = e.getX(); 999 currentMouseY = e.getY(); 1000 1001 if(getThumbBounds().contains(currentMouseX, currentMouseY)) { 1003 switch (scrollbar.getOrientation()) { 1004 case JScrollBar.VERTICAL: 1005 offset = currentMouseY - getThumbBounds().y; 1006 break; 1007 case JScrollBar.HORIZONTAL: 1008 offset = currentMouseX - getThumbBounds().x; 1009 break; 1010 } 1011 isDragging = true; 1012 return; 1013 } 1014 else if (getSupportsAbsolutePositioning() && 1015 SwingUtilities.isMiddleMouseButton(e)) { 1016 switch (scrollbar.getOrientation()) { 1017 case JScrollBar.VERTICAL: 1018 offset = getThumbBounds().height / 2; 1019 break; 1020 case JScrollBar.HORIZONTAL: 1021 offset = getThumbBounds().width / 2; 1022 break; 1023 } 1024 isDragging = true; 1025 setValueFrom(e); 1026 return; 1027 } 1028 isDragging = false; 1029 1030 Dimension sbSize = scrollbar.getSize(); 1031 direction = +1; 1032 1033 switch (scrollbar.getOrientation()) { 1034 case JScrollBar.VERTICAL: 1035 if (getThumbBounds().isEmpty()) { 1036 int scrollbarCenter = sbSize.height / 2; 1037 direction = (currentMouseY < scrollbarCenter) ? -1 : +1; 1038 } else { 1039 int thumbY = getThumbBounds().y; 1040 direction = (currentMouseY < thumbY) ? -1 : +1; 1041 } 1042 break; 1043 case JScrollBar.HORIZONTAL: 1044 if (getThumbBounds().isEmpty()) { 1045 int scrollbarCenter = sbSize.width / 2; 1046 direction = (currentMouseX < scrollbarCenter) ? -1 : +1; 1047 } else { 1048 int thumbX = getThumbBounds().x; 1049 direction = (currentMouseX < thumbX) ? -1 : +1; 1050 } 1051 if (!scrollbar.getComponentOrientation().isLeftToRight()) { 1052 direction = -direction; 1053 } 1054 break; 1055 } 1056 scrollByBlock(direction); 1057 1058 scrollTimer.stop(); 1059 scrollListener.setDirection(direction); 1060 scrollListener.setScrollByBlock(true); 1061 startScrollTimerIfNecessary(); 1062 } 1063 1064 1065 1071 public void mouseDragged(MouseEvent e) { 1072 if (SwingUtilities.isRightMouseButton(e) || 1073 (!getSupportsAbsolutePositioning() && 1074 SwingUtilities.isMiddleMouseButton(e))) 1075 return; 1076 if(!scrollbar.isEnabled() || getThumbBounds().isEmpty()) { 1077 return; 1078 } 1079 if (isDragging) { 1080 setValueFrom(e); 1081 } else { 1082 currentMouseX = e.getX(); 1083 currentMouseY = e.getY(); 1084 updateThumbState(currentMouseX, currentMouseY); 1085 startScrollTimerIfNecessary(); 1086 } 1087 } 1088 1089 private void setValueFrom(MouseEvent e) { 1090 boolean active = isThumbRollover(); 1091 BoundedRangeModel model = scrollbar.getModel(); 1092 Rectangle thumbR = getThumbBounds(); 1093 float trackLength; 1094 int thumbMin, thumbMax, thumbPos; 1095 1096 if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { 1097 thumbMin = decrButton.getY() + decrButton.getHeight(); 1098 thumbMax = incrButton.getY() - thumbR.height; 1099 thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e.getY() - offset))); 1100 setThumbBounds(thumbR.x, thumbPos, thumbR.width, thumbR.height); 1101 trackLength = getTrackBounds().height; 1102 } 1103 else { 1104 if (scrollbar.getComponentOrientation().isLeftToRight()) { 1105 thumbMin = decrButton.getX() + decrButton.getWidth(); 1106 thumbMax = incrButton.getX() - thumbR.width; 1107 } else { 1108 thumbMin = incrButton.getX() + incrButton.getWidth(); 1109 thumbMax = decrButton.getX() - thumbR.width; 1110 } 1111 thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e.getX() - offset))); 1112 setThumbBounds(thumbPos, thumbR.y, thumbR.width, thumbR.height); 1113 trackLength = getTrackBounds().width; 1114 } 1115 1116 1120 if (thumbPos == thumbMax) { 1121 if (scrollbar.getOrientation() == JScrollBar.VERTICAL || 1122 scrollbar.getComponentOrientation().isLeftToRight()) { 1123 scrollbar.setValue(model.getMaximum() - model.getExtent()); 1124 } else { 1125 scrollbar.setValue(model.getMinimum()); 1126 } 1127 } 1128 else { 1129 float valueMax = model.getMaximum() - model.getExtent(); 1130 float valueRange = valueMax - model.getMinimum(); 1131 float thumbValue = thumbPos - thumbMin; 1132 float thumbRange = thumbMax - thumbMin; 1133 int value; 1134 if (scrollbar.getOrientation() == JScrollBar.VERTICAL || 1135 scrollbar.getComponentOrientation().isLeftToRight()) { 1136 value = (int)(0.5 + ((thumbValue / thumbRange) * valueRange)); 1137 } else { 1138 value = (int)(0.5 + (((thumbMax - thumbPos) / thumbRange) * valueRange)); 1139 } 1140 1141 useCachedValue = true; 1142 scrollBarValue = value + model.getMinimum(); 1143 scrollbar.setValue(adjustValueIfNecessary(scrollBarValue)); 1144 } 1145 setThumbRollover(active); 1146 } 1147 1148 private int adjustValueIfNecessary(int value) { 1149 if (scrollbar.getParent() instanceof JScrollPane) { 1150 JScrollPane scrollpane = (JScrollPane)scrollbar.getParent(); 1151 JViewport viewport = scrollpane.getViewport(); 1152 Component view = viewport.getView(); 1153 if (view instanceof JList) { 1154 JList list = (JList)view; 1155 if (DefaultLookup.getBoolean(list, list.getUI(), 1156 "List.lockToPositionOnScroll", false)) { 1157 int adjustedValue = value; 1158 int mode = list.getLayoutOrientation(); 1159 int orientation = scrollbar.getOrientation(); 1160 if (orientation == JScrollBar.VERTICAL && mode == JList.VERTICAL) { 1161 int index = list.locationToIndex(new Point(0, value)); 1162 Rectangle rect = list.getCellBounds(index, index); 1163 if (rect != null) { 1164 adjustedValue = rect.y; 1165 } 1166 } 1167 if (orientation == JScrollBar.HORIZONTAL && 1168 (mode == JList.VERTICAL_WRAP || mode == JList.HORIZONTAL_WRAP)) { 1169 if (scrollpane.getComponentOrientation().isLeftToRight()) { 1170 int index = list.locationToIndex(new Point(value, 0)); 1171 Rectangle rect = list.getCellBounds(index, index); 1172 if (rect != null) { 1173 adjustedValue = rect.x; 1174 } 1175 } 1176 else { 1177 Point loc = new Point(value, 0); 1178 int extent = viewport.getExtentSize().width; 1179 loc.x += extent - 1; 1180 int index = list.locationToIndex(loc); 1181 Rectangle rect = list.getCellBounds(index, index); 1182 if (rect != null) { 1183 adjustedValue = rect.x + rect.width - extent; 1184 } 1185 } 1186 } 1187 value = adjustedValue; 1188 1189 } 1190 } 1191 } 1192 return value; 1193 } 1194 1195 private void startScrollTimerIfNecessary() { 1196 if (scrollTimer.isRunning()) { 1197 return; 1198 } 1199 switch (scrollbar.getOrientation()) { 1200 case JScrollBar.VERTICAL: 1201 if (direction >0) { 1202 if (getThumbBounds().y + getThumbBounds().height < 1203 trackListener.currentMouseY) { 1204 scrollTimer.start(); 1205 } 1206 } else if (getThumbBounds().y > 1207 trackListener.currentMouseY) { 1208 scrollTimer.start(); 1209 } 1210 break; 1211 case JScrollBar.HORIZONTAL: 1212 if (direction >0) { 1213 if (getThumbBounds().x + getThumbBounds().width < 1214 trackListener.currentMouseX) { 1215 scrollTimer.start(); 1216 } 1217 } else if (getThumbBounds().x > 1218 trackListener.currentMouseX) { 1219 scrollTimer.start(); 1220 } 1221 break; 1222 } 1223 } 1224 1225 public void mouseMoved(MouseEvent e) { 1226 if (!isDragging) { 1227 updateThumbState(e.getX(), e.getY()); 1228 } 1229 } 1230 1231 1237 public void mouseExited(MouseEvent e) { 1238 if (!isDragging) { 1239 setThumbRollover(false); 1240 } 1241 } 1242 } 1243 1244 1245 1248 protected class ArrowButtonListener extends MouseAdapter 1249 { 1250 boolean handledEvent; 1254 1255 public void mousePressed(MouseEvent e) { 1256 if(!scrollbar.isEnabled()) { return; } 1257 if( ! SwingUtilities.isLeftMouseButton(e)) { return; } 1260 1261 int direction = (e.getSource() == incrButton) ? 1 : -1; 1262 1263 scrollByUnit(direction); 1264 scrollTimer.stop(); 1265 scrollListener.setDirection(direction); 1266 scrollListener.setScrollByBlock(false); 1267 scrollTimer.start(); 1268 1269 handledEvent = true; 1270 if (!scrollbar.hasFocus() && scrollbar.isRequestFocusEnabled()) { 1271 scrollbar.requestFocus(); 1272 } 1273 } 1274 1275 public void mouseReleased(MouseEvent e) { 1276 scrollTimer.stop(); 1277 handledEvent = false; 1278 scrollbar.setValueIsAdjusting(false); 1279 } 1280 } 1281 1282 1283 1287 protected class ScrollListener implements ActionListener 1288 { 1289 int direction = +1; 1290 boolean useBlockIncrement; 1291 1292 public ScrollListener() { 1293 direction = +1; 1294 useBlockIncrement = false; 1295 } 1296 1297 public ScrollListener(int dir, boolean block) { 1298 direction = dir; 1299 useBlockIncrement = block; 1300 } 1301 1302 public void setDirection(int direction) { this.direction = direction; } 1303 public void setScrollByBlock(boolean block) { this.useBlockIncrement = block; } 1304 1305 public void actionPerformed(ActionEvent e) { 1306 if(useBlockIncrement) { 1307 scrollByBlock(direction); 1308 if(scrollbar.getOrientation() == JScrollBar.VERTICAL) { 1310 if(direction > 0) { 1311 if(getThumbBounds().y + getThumbBounds().height 1312 >= trackListener.currentMouseY) 1313 ((Timer)e.getSource()).stop(); 1314 } else if(getThumbBounds().y <= trackListener.currentMouseY) { 1315 ((Timer)e.getSource()).stop(); 1316 } 1317 } else { 1318 if(direction > 0) { 1319 if(getThumbBounds().x + getThumbBounds().width 1320 >= trackListener.currentMouseX) 1321 ((Timer)e.getSource()).stop(); 1322 } else if(getThumbBounds().x <= trackListener.currentMouseX) { 1323 ((Timer)e.getSource()).stop(); 1324 } 1325 } 1326 } else { 1327 scrollByUnit(direction); 1328 } 1329 1330 if(direction > 0 1331 && scrollbar.getValue()+scrollbar.getVisibleAmount() 1332 >= scrollbar.getMaximum()) 1333 ((Timer)e.getSource()).stop(); 1334 else if(direction < 0 1335 && scrollbar.getValue() <= scrollbar.getMinimum()) 1336 ((Timer)e.getSource()).stop(); 1337 } 1338 } 1339 1340 1341 private void updateButtonDirections() { 1342 int orient = scrollbar.getOrientation(); 1343 if (scrollbar.getComponentOrientation().isLeftToRight()) { 1344 if (incrButton instanceof BasicArrowButton ) { 1345 ((BasicArrowButton )incrButton).setDirection( 1346 orient == HORIZONTAL? EAST : SOUTH); 1347 } 1348 if (decrButton instanceof BasicArrowButton ) { 1349 ((BasicArrowButton )decrButton).setDirection( 1350 orient == HORIZONTAL? WEST : NORTH); 1351 } 1352 } 1353 else { 1354 if (incrButton instanceof BasicArrowButton ) { 1355 ((BasicArrowButton )incrButton).setDirection( 1356 orient == HORIZONTAL? WEST : SOUTH); 1357 } 1358 if (decrButton instanceof BasicArrowButton ) { 1359 ((BasicArrowButton )decrButton).setDirection( 1360 orient == HORIZONTAL ? EAST : NORTH); 1361 } 1362 } 1363 } 1364 1365 public class PropertyChangeHandler implements PropertyChangeListener 1366 { 1367 1372 public void propertyChange(PropertyChangeEvent e) { 1373 getHandler().propertyChange(e); 1374 } 1375 } 1376 1377 1378 1381 private static class Actions extends UIAction { 1382 private static final String POSITIVE_UNIT_INCREMENT = 1383 "positiveUnitIncrement"; 1384 private static final String POSITIVE_BLOCK_INCREMENT = 1385 "positiveBlockIncrement"; 1386 private static final String NEGATIVE_UNIT_INCREMENT = 1387 "negativeUnitIncrement"; 1388 private static final String NEGATIVE_BLOCK_INCREMENT = 1389 "negativeBlockIncrement"; 1390 private static final String MIN_SCROLL = "minScroll"; 1391 private static final String MAX_SCROLL = "maxScroll"; 1392 1393 Actions(String name) { 1394 super(name); 1395 } 1396 1397 public void actionPerformed(ActionEvent e) { 1398 JScrollBar scrollBar = (JScrollBar)e.getSource(); 1399 String key = getName(); 1400 if (key == POSITIVE_UNIT_INCREMENT) { 1401 scroll(scrollBar, POSITIVE_SCROLL, false); 1402 } 1403 else if (key == POSITIVE_BLOCK_INCREMENT) { 1404 scroll(scrollBar, POSITIVE_SCROLL, true); 1405 } 1406 else if (key == NEGATIVE_UNIT_INCREMENT) { 1407 scroll(scrollBar, NEGATIVE_SCROLL, false); 1408 } 1409 else if (key == NEGATIVE_BLOCK_INCREMENT) { 1410 scroll(scrollBar, NEGATIVE_SCROLL, true); 1411 } 1412 else if (key == MIN_SCROLL) { 1413 scroll(scrollBar, BasicScrollBarUI.MIN_SCROLL, true); 1414 } 1415 else if (key == MAX_SCROLL) { 1416 scroll(scrollBar, BasicScrollBarUI.MAX_SCROLL, true); 1417 } 1418 } 1419 private void scroll(JScrollBar scrollBar, int dir, boolean block) { 1420 1421 if (dir == NEGATIVE_SCROLL || dir == POSITIVE_SCROLL) { 1422 int amount; 1423 if (block) { 1427 if (dir == NEGATIVE_SCROLL) { 1428 amount = -1 * scrollBar.getBlockIncrement(-1); 1429 } 1430 else { 1431 amount = scrollBar.getBlockIncrement(1); 1432 } 1433 } 1434 else { 1435 if (dir == NEGATIVE_SCROLL) { 1436 amount = -1 * scrollBar.getUnitIncrement(-1); 1437 } 1438 else { 1439 amount = scrollBar.getUnitIncrement(1); 1440 } 1441 } 1442 scrollBar.setValue(scrollBar.getValue() + amount); 1443 } 1444 else if (dir == BasicScrollBarUI.MIN_SCROLL) { 1445 scrollBar.setValue(scrollBar.getMinimum()); 1446 } 1447 else if (dir == BasicScrollBarUI.MAX_SCROLL) { 1448 scrollBar.setValue(scrollBar.getMaximum()); 1449 } 1450 } 1451 } 1452 1453 1454 private class Handler implements FocusListener, PropertyChangeListener { 1458 public void focusGained(FocusEvent e) { 1462 scrollbar.repaint(); 1463 } 1464 1465 public void focusLost(FocusEvent e) { 1466 scrollbar.repaint(); 1467 } 1468 1469 1470 public void propertyChange(PropertyChangeEvent e) { 1474 String propertyName = e.getPropertyName(); 1475 1476 if ("model" == propertyName) { 1477 BoundedRangeModel oldModel = (BoundedRangeModel)e.getOldValue(); 1478 BoundedRangeModel newModel = (BoundedRangeModel)e.getNewValue(); 1479 oldModel.removeChangeListener(modelListener); 1480 newModel.addChangeListener(modelListener); 1481 scrollBarValue = scrollbar.getValue(); 1482 scrollbar.repaint(); 1483 scrollbar.revalidate(); 1484 } else if ("orientation" == propertyName) { 1485 updateButtonDirections(); 1486 } else if ("componentOrientation" == propertyName) { 1487 updateButtonDirections(); 1488 InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); 1489 SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED, inputMap); 1490 } 1491 } 1492 } 1493} 1494 1495 1496 | Popular Tags |