1. /*
  2. * @(#)SynthScrollBarUI.java 1.24 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.gtk;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.beans.*;
  11. import javax.swing.*;
  12. import javax.swing.event.*;
  13. import javax.swing.plaf.*;
  14. /**
  15. * Implementation of ScrollBarUI for the Basic Look and Feel
  16. *
  17. * @version 1.24, 01/23/03 (based on BasicScrollBarUI v 1.74)
  18. * @author Rich Schiavi
  19. * @author David Kloba
  20. * @author Hans Muller
  21. */
  22. // ScrollBar consists of the following parts:
  23. // Button to increase the current value
  24. // Button to decrese the current value
  25. // Track
  26. // Thumb
  27. class SynthScrollBarUI extends ScrollBarUI implements SynthUI, LayoutManager, SwingConstants, FocusListener {
  28. private static final int POSITIVE_SCROLL = 1;
  29. private static final int NEGATIVE_SCROLL = -1;
  30. private static final int MIN_SCROLL = 2;
  31. private static final int MAX_SCROLL = 3;
  32. private static final Insets tmpInsets = new Insets(0, 0, 0, 0);
  33. private SynthStyle style;
  34. private SynthStyle thumbStyle;
  35. private SynthStyle trackStyle;
  36. protected Dimension minimumThumbSize;
  37. protected Dimension maximumThumbSize;
  38. protected JScrollBar scrollbar;
  39. protected JButton incrButton;
  40. protected JButton decrButton;
  41. protected boolean isDragging;
  42. protected TrackListener trackListener;
  43. protected ArrowButtonListener buttonListener;
  44. protected ModelListener modelListener;
  45. protected Rectangle thumbRect;
  46. protected Rectangle trackRect;
  47. protected int trackHighlight;
  48. protected static final int NO_HIGHLIGHT = 0;
  49. protected static final int DECREASE_HIGHLIGHT = 1;
  50. protected static final int INCREASE_HIGHLIGHT = 2;
  51. protected ScrollListener scrollListener;
  52. protected PropertyChangeListener propertyChangeListener;
  53. protected Timer scrollTimer;
  54. /**
  55. * True if the mouse is over the thumb.
  56. */
  57. private boolean thumbActive;
  58. private final static int scrollSpeedThrottle = 60; // delay in milli seconds
  59. /** True indicates a middle click will absolutely position the
  60. * scrollbar. */
  61. private boolean supportsAbsolutePositioning;
  62. /** Hint as to what width (when vertical) or height (when horizontal)
  63. * should be.
  64. */
  65. private int scrollBarWidth;
  66. public static ComponentUI createUI(JComponent c) {
  67. return new SynthScrollBarUI();
  68. }
  69. public static void loadActionMap(ActionMap map) {
  70. // NOTE: this needs to remain static. If you have a need to
  71. // have Actions that reference the UI in the ActionMap,
  72. // then you'll also need to change the registeration of the
  73. // ActionMap.
  74. map.put("positiveUnitIncrement", new SharedActionScroller
  75. (POSITIVE_SCROLL, false));
  76. map.put("positiveBlockIncrement", new SharedActionScroller
  77. (POSITIVE_SCROLL, true));
  78. map.put("negativeUnitIncrement", new SharedActionScroller
  79. (NEGATIVE_SCROLL, false));
  80. map.put("negativeBlockIncrement", new SharedActionScroller
  81. (NEGATIVE_SCROLL, true));
  82. map.put("minScroll", new SharedActionScroller(MIN_SCROLL, true));
  83. map.put("maxScroll", new SharedActionScroller(MAX_SCROLL, true));
  84. }
  85. public void installUI(JComponent c) {
  86. scrollbar = (JScrollBar)c;
  87. thumbRect = new Rectangle(0, 0, 0, 0);
  88. trackRect = new Rectangle(0, 0, 0, 0);
  89. installDefaults();
  90. installComponents();
  91. installKeyboardActions();
  92. installListeners();
  93. }
  94. public void uninstallUI(JComponent c) {
  95. scrollbar = (JScrollBar)c;
  96. uninstallListeners();
  97. uninstallKeyboardActions();
  98. uninstallComponents();
  99. uninstallDefaults();
  100. c.setLayout(null);
  101. thumbRect = null;
  102. scrollbar = null;
  103. incrButton = null;
  104. decrButton = null;
  105. }
  106. protected void installDefaults() {
  107. fetchStyle(scrollbar);
  108. trackHighlight = NO_HIGHLIGHT;
  109. scrollbar.setLayout(this);
  110. }
  111. private void fetchStyle(JScrollBar c) {
  112. SynthContext context = getContext(c, ENABLED);
  113. SynthStyle oldStyle = style;
  114. style = SynthLookAndFeel.updateStyle(context, this);
  115. // Add properties other than JComponent colors, Borders and
  116. // opacity settings here:
  117. if (style != oldStyle) {
  118. Insets insets = c.getInsets();
  119. scrollBarWidth =
  120. style.getInt(context, "ScrollBar.thumbHeight", 14);
  121. minimumThumbSize = new Dimension();
  122. if (c.getOrientation() == JScrollBar.VERTICAL) {
  123. minimumThumbSize.width = scrollBarWidth;
  124. minimumThumbSize.height = 7;
  125. scrollBarWidth += insets.left + insets.right;
  126. } else {
  127. minimumThumbSize.width = 7;
  128. minimumThumbSize.height = scrollBarWidth;
  129. scrollBarWidth += insets.top + insets.bottom;
  130. }
  131. maximumThumbSize = (Dimension)style.get(context,
  132. "ScrollBar.maximumThumbSize");
  133. supportsAbsolutePositioning = style.getBoolean(context,
  134. "ScrollBar.allowsAbsolutePositioning", false);
  135. }
  136. context.dispose();
  137. context = getContext(c, Region.SCROLL_BAR_TRACK, ENABLED);
  138. trackStyle = SynthLookAndFeel.updateStyle(context, this);
  139. context.dispose();
  140. context = getContext(c, Region.SCROLL_BAR_THUMB, ENABLED);
  141. thumbStyle = SynthLookAndFeel.updateStyle(context, this);
  142. context.dispose();
  143. }
  144. protected void installComponents(){
  145. switch (scrollbar.getOrientation()) {
  146. case JScrollBar.VERTICAL:
  147. incrButton = createIncreaseButton(SOUTH);
  148. decrButton = createDecreaseButton(NORTH);
  149. break;
  150. case JScrollBar.HORIZONTAL:
  151. if (scrollbar.getComponentOrientation().isLeftToRight()) {
  152. incrButton = createIncreaseButton(EAST);
  153. decrButton = createDecreaseButton(WEST);
  154. } else {
  155. incrButton = createIncreaseButton(WEST);
  156. decrButton = createDecreaseButton(EAST);
  157. }
  158. break;
  159. }
  160. scrollbar.add(incrButton);
  161. scrollbar.add(decrButton);
  162. }
  163. protected void uninstallComponents() {
  164. scrollbar.remove(incrButton);
  165. scrollbar.remove(decrButton);
  166. }
  167. protected void installListeners() {
  168. trackListener = createTrackListener();
  169. buttonListener = createArrowButtonListener();
  170. modelListener = createModelListener();
  171. propertyChangeListener = createPropertyChangeListener();
  172. scrollbar.addMouseListener(trackListener);
  173. scrollbar.addMouseMotionListener(trackListener);
  174. scrollbar.getModel().addChangeListener(modelListener);
  175. scrollbar.addPropertyChangeListener(propertyChangeListener);
  176. if (incrButton != null) {
  177. incrButton.addMouseListener(buttonListener);
  178. }
  179. if (decrButton != null) {
  180. decrButton.addMouseListener(buttonListener);
  181. }
  182. scrollListener = createScrollListener();
  183. scrollTimer = new Timer(scrollSpeedThrottle, scrollListener);
  184. scrollTimer.setInitialDelay(300); // default InitialDelay?
  185. // PENDING: there should be a property for this to avoid installing
  186. // the listener unless necessary.
  187. scrollbar.addFocusListener(this);
  188. }
  189. protected void installKeyboardActions() {
  190. LazyActionMap.installLazyActionMap(scrollbar, SynthScrollBarUI.class,
  191. "ScrollBar.actionMap");
  192. InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED);
  193. SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED,
  194. inputMap);
  195. }
  196. protected void uninstallKeyboardActions(){
  197. SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED,
  198. null);
  199. SwingUtilities.replaceUIActionMap(scrollbar, null);
  200. }
  201. private InputMap getInputMap(int condition) {
  202. if (condition == JComponent.WHEN_FOCUSED) {
  203. SynthContext context = getContext(scrollbar, ENABLED);
  204. SynthStyle style = context.getStyle();
  205. InputMap keyMap = (InputMap)style.get(context,
  206. "ScrollBar.focusInputMap");
  207. InputMap rtlKeyMap;
  208. if (scrollbar.getComponentOrientation().isLeftToRight() &&
  209. ((rtlKeyMap = (InputMap)style.get(context,
  210. "ScrollBar.focusInputMap.RightToLeft")) != null)) {
  211. rtlKeyMap.setParent(keyMap);
  212. keyMap = rtlKeyMap;
  213. }
  214. context.dispose();
  215. return keyMap;
  216. }
  217. return null;
  218. }
  219. protected void uninstallListeners() {
  220. scrollTimer.stop();
  221. scrollTimer = null;
  222. if (decrButton != null){
  223. decrButton.removeMouseListener(buttonListener);
  224. }
  225. if (incrButton != null){
  226. incrButton.removeMouseListener(buttonListener);
  227. }
  228. scrollbar.getModel().removeChangeListener(modelListener);
  229. scrollbar.removeMouseListener(trackListener);
  230. scrollbar.removeMouseMotionListener(trackListener);
  231. scrollbar.removePropertyChangeListener(propertyChangeListener);
  232. scrollbar.removeFocusListener(this);
  233. }
  234. protected void uninstallDefaults(){
  235. SynthContext context = getContext(scrollbar, ENABLED);
  236. style.uninstallDefaults(context);
  237. context.dispose();
  238. style = null;
  239. context = getContext(scrollbar, Region.SCROLL_BAR_TRACK, ENABLED);
  240. trackStyle.uninstallDefaults(context);
  241. context.dispose();
  242. trackStyle = null;
  243. context = getContext(scrollbar, Region.SCROLL_BAR_THUMB, ENABLED);
  244. thumbStyle.uninstallDefaults(context);
  245. context.dispose();
  246. thumbStyle = null;
  247. }
  248. public SynthContext getContext(JComponent c) {
  249. return getContext(c, getComponentState(c));
  250. }
  251. private SynthContext getContext(JComponent c, int state) {
  252. return SynthContext.getContext(SynthContext.class, c,
  253. SynthLookAndFeel.getRegion(c), style, state);
  254. }
  255. private Region getRegion(JComponent c) {
  256. return SynthLookAndFeel.getRegion(c);
  257. }
  258. private int getComponentState(JComponent c) {
  259. return SynthLookAndFeel.getComponentState(c);
  260. }
  261. private SynthContext getContext(JComponent c, Region region) {
  262. return getContext(c, region, getComponentState(c, region));
  263. }
  264. private SynthContext getContext(JComponent c, Region region, int state) {
  265. SynthStyle style = trackStyle;
  266. if (region == Region.SCROLL_BAR_THUMB) {
  267. style = thumbStyle;
  268. }
  269. return SynthContext.getContext(SynthContext.class, c, region, style,
  270. state);
  271. }
  272. private int getComponentState(JComponent c, Region region) {
  273. if (region == Region.SCROLL_BAR_THUMB && thumbActive &&c.isEnabled()) {
  274. return MOUSE_OVER;
  275. }
  276. return SynthLookAndFeel.getComponentState(c);
  277. }
  278. protected TrackListener createTrackListener(){
  279. return new TrackListener();
  280. }
  281. protected ArrowButtonListener createArrowButtonListener(){
  282. return new ArrowButtonListener();
  283. }
  284. protected ModelListener createModelListener(){
  285. return new ModelListener();
  286. }
  287. protected ScrollListener createScrollListener(){
  288. return new ScrollListener();
  289. }
  290. protected PropertyChangeListener createPropertyChangeListener() {
  291. return new PropertyChangeHandler();
  292. }
  293. public void update(Graphics g, JComponent c) {
  294. SynthContext context = getContext(c);
  295. SynthLookAndFeel.update(context, g);
  296. paint(context, g);
  297. context.dispose();
  298. }
  299. public void paint(Graphics g, JComponent c) {
  300. SynthContext context = getContext(c);
  301. paint(context, g);
  302. context.dispose();
  303. }
  304. protected void paint(SynthContext context, Graphics g) {
  305. SynthContext subcontext = getContext(scrollbar,
  306. Region.SCROLL_BAR_TRACK);
  307. paintTrack(subcontext, g, getTrackBounds());
  308. subcontext.dispose();
  309. subcontext = getContext(scrollbar, Region.SCROLL_BAR_THUMB);
  310. paintThumb(subcontext, g, getThumbBounds());
  311. subcontext.dispose();
  312. }
  313. protected void paintTrack(SynthContext ss, Graphics g,
  314. Rectangle trackBounds) {
  315. SynthLookAndFeel.updateSubregion(ss, g, trackBounds);
  316. }
  317. protected void paintThumb(SynthContext ss, Graphics g,
  318. Rectangle thumbBounds) {
  319. SynthLookAndFeel.updateSubregion(ss, g, thumbBounds);
  320. }
  321. int getTrackHighlight() {
  322. return trackHighlight;
  323. }
  324. Rectangle getDecreaseHighlightRegion(Rectangle rect) {
  325. Insets insets = scrollbar.getInsets(tmpInsets);
  326. Rectangle thumbR = getThumbBounds();
  327. if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
  328. rect.x = insets.left;
  329. rect.y = decrButton.getY() + decrButton.getHeight();
  330. rect.width = scrollbar.getWidth() - (insets.left + insets.right);
  331. rect.height = thumbR.y - rect.y;
  332. }
  333. else {
  334. rect.x = decrButton.getX() + decrButton.getHeight();
  335. rect.y = insets.top;
  336. rect.width = thumbR.x - rect.x;
  337. rect.height = scrollbar.getHeight() - (insets.top + insets.bottom);
  338. }
  339. return rect;
  340. }
  341. Rectangle getIncreaseHighlightRegion(Rectangle rect) {
  342. Insets insets = scrollbar.getInsets(tmpInsets);
  343. Rectangle thumbR = getThumbBounds();
  344. if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
  345. rect.x = insets.left;
  346. rect.y = thumbR.y + thumbR.height;
  347. rect.width = scrollbar.getWidth() - (insets.left + insets.right);
  348. rect.height = incrButton.getY() - rect.y;
  349. }
  350. else {
  351. rect.x = thumbR.x + thumbR.width;
  352. rect.y = insets.top;
  353. rect.width = incrButton.getX() - rect.x;
  354. rect.height = scrollbar.getHeight() - (insets.top + insets.bottom);
  355. }
  356. return rect;
  357. }
  358. /**
  359. * A vertical scrollbar's preferred width is the maximum of
  360. * preferred widths of the (non <code>null</code>)
  361. * increment/decrement buttons,
  362. * and the minimum width of the thumb. The preferred height is the
  363. * sum of the preferred heights of the same parts. The basis for
  364. * the preferred size of a horizontal scrollbar is similar.
  365. * <p>
  366. * The <code>preferredSize</code> is only computed once, subsequent
  367. * calls to this method just return a cached size.
  368. *
  369. * @param c the <code>JScrollBar</code> that's delegating this method to us
  370. * @return the preferred size of a Basic JScrollBar
  371. * @see #getMaximumSize
  372. * @see #getMinimumSize
  373. */
  374. public Dimension getPreferredSize(JComponent c) {
  375. return (scrollbar.getOrientation() == JScrollBar.VERTICAL)
  376. ? new Dimension(scrollBarWidth, 48)
  377. : new Dimension(48, scrollBarWidth);
  378. }
  379. /**
  380. * A vertical scrollbar's minimum width is the largest
  381. * minimum width of the (non <code>null</code>) increment/decrement buttons,
  382. * and the minimum width of the thumb. The minimum height is the
  383. * sum of the minimum heights of the same parts. The basis for
  384. * the preferred size of a horizontal scrollbar is similar.
  385. * <p>
  386. * The <code>minimumSize</code> is only computed once, subsequent
  387. * calls to this method just return a cached size.
  388. *
  389. * @param c the <code>JScrollBar</code> that's delegating this method to us
  390. * @return the minimum size of a basic <code>JScrollBar</code>
  391. * @see #getMaximumSize
  392. * @see #getPreferredSize
  393. */
  394. public Dimension getMinimumSize(JComponent c) {
  395. return getPreferredSize(c);
  396. }
  397. /**
  398. * @param c The JScrollBar that's delegating this method to us.
  399. * @return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
  400. * @see #getMinimumSize
  401. * @see #getPreferredSize
  402. */
  403. public Dimension getMaximumSize(JComponent c) {
  404. return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
  405. }
  406. protected JButton createDecreaseButton(int orientation) {
  407. SynthArrowButton synthArrowButton = new SynthArrowButton(orientation);
  408. synthArrowButton.setName("ScrollBar.button");
  409. return synthArrowButton;
  410. }
  411. protected JButton createIncreaseButton(int orientation) {
  412. SynthArrowButton synthArrowButton = new SynthArrowButton(orientation);
  413. synthArrowButton.setName("ScrollBar.button");
  414. return synthArrowButton;
  415. }
  416. /**
  417. * Return the smallest acceptable size for the thumb. If the scrollbar
  418. * becomes so small that this size isn't available, the thumb will be
  419. * hidden.
  420. * <p>
  421. * <b>Warning </b>: the value returned by this method should not be
  422. * be modified, it's a shared static constant.
  423. *
  424. * @return The smallest acceptable size for the thumb.
  425. * @see #getMaximumThumbSize
  426. */
  427. protected Dimension getMinimumThumbSize() {
  428. return minimumThumbSize;
  429. }
  430. /**
  431. * Return the largest acceptable size for the thumb. To create a fixed
  432. * size thumb one make this method and <code>getMinimumThumbSize</code>
  433. * return the same value.
  434. * <p>
  435. * <b>Warning </b>: the value returned by this method should not be
  436. * be modified, it's a shared static constant.
  437. *
  438. * @return The largest acceptable size for the thumb.
  439. * @see #getMinimumThumbSize
  440. */
  441. protected Dimension getMaximumThumbSize() {
  442. return maximumThumbSize;
  443. }
  444. /*
  445. * LayoutManager Implementation
  446. */
  447. public void addLayoutComponent(String name, Component child) {}
  448. public void removeLayoutComponent(Component child) {}
  449. public Dimension preferredLayoutSize(Container scrollbarContainer) {
  450. return getPreferredSize((JComponent)scrollbarContainer);
  451. }
  452. public Dimension minimumLayoutSize(Container scrollbarContainer) {
  453. return getMinimumSize((JComponent)scrollbarContainer);
  454. }
  455. protected void layoutVScrollbar(JScrollBar sb)
  456. {
  457. Dimension sbSize = sb.getSize();
  458. Insets sbInsets = sb.getInsets();
  459. /*
  460. * Width and left edge of the buttons and thumb.
  461. */
  462. // Same size as the thumb.
  463. int itemW = sbSize.width - (sbInsets.left + sbInsets.right);
  464. int itemX = sbInsets.left;
  465. /* Nominal locations of the buttons, assuming their preferred
  466. * size will fit.
  467. */
  468. int decrButtonH = itemW;
  469. int decrButtonY = sbInsets.top;
  470. int incrButtonH = itemW;
  471. int incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH);
  472. /* The thumb must fit within the height left over after we
  473. * subtract the preferredSize of the buttons and the insets.
  474. */
  475. int sbInsetsH = sbInsets.top + sbInsets.bottom;
  476. int sbButtonsH = decrButtonH + incrButtonH;
  477. float trackH = sbSize.height - (sbInsetsH + sbButtonsH);
  478. /* Compute the height and origin of the thumb. The case
  479. * where the thumb is at the bottom edge is handled specially
  480. * to avoid numerical problems in computing thumbY. Enforce
  481. * the thumbs min/max dimensions. If the thumb doesn't
  482. * fit in the track (trackH) we'll hide it later.
  483. */
  484. float min = sb.getMinimum();
  485. float extent = sb.getVisibleAmount();
  486. float range = sb.getMaximum() - min;
  487. float value = sb.getValue();
  488. int thumbH = (range <= 0)
  489. ? getMaximumThumbSize().height : (int)(trackH * (extent / range));
  490. thumbH = Math.max(thumbH, getMinimumThumbSize().height);
  491. thumbH = Math.min(thumbH, getMaximumThumbSize().height);
  492. int thumbY = incrButtonY - thumbH;
  493. if (sb.getValue() < (sb.getMaximum() - sb.getVisibleAmount())) {
  494. float thumbRange = trackH - thumbH;
  495. thumbY = (int)(0.5f + (thumbRange * ((value - min) / (range - extent))));
  496. thumbY += decrButtonY + decrButtonH;
  497. }
  498. /* If the buttons don't fit, allocate half of the available
  499. * space to each and move the lower one (incrButton) down.
  500. */
  501. int sbAvailButtonH = (sbSize.height - sbInsetsH);
  502. if (sbAvailButtonH < sbButtonsH) {
  503. incrButtonH = decrButtonH = sbAvailButtonH / 2;
  504. incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH);
  505. }
  506. decrButton.setBounds(itemX, decrButtonY, itemW, decrButtonH);
  507. incrButton.setBounds(itemX, incrButtonY, itemW, incrButtonH);
  508. /* Update the trackRect field.
  509. */
  510. int itrackY = decrButtonY + decrButtonH;
  511. int itrackH = incrButtonY - itrackY;
  512. trackRect.setBounds(itemX, itrackY, itemW, itrackH);
  513. /* If the thumb isn't going to fit, zero it's bounds. Otherwise
  514. * make sure it fits between the buttons. Note that setting the
  515. * thumbs bounds will cause a repaint.
  516. */
  517. if(thumbH >= (int)trackH) {
  518. setThumbBounds(0, 0, 0, 0);
  519. }
  520. else {
  521. if ((thumbY + thumbH) > incrButtonY) {
  522. thumbY = incrButtonY - thumbH;
  523. }
  524. if (thumbY < (decrButtonY + decrButtonH)) {
  525. thumbY = decrButtonY + decrButtonH + 1;
  526. }
  527. setThumbBounds(itemX, thumbY, itemW, thumbH);
  528. }
  529. }
  530. protected void layoutHScrollbar(JScrollBar sb)
  531. {
  532. Dimension sbSize = sb.getSize();
  533. Insets sbInsets = sb.getInsets();
  534. /* Height and top edge of the buttons and thumb.
  535. */
  536. int itemH = sbSize.height - (sbInsets.top + sbInsets.bottom);
  537. int itemY = sbInsets.top;
  538. boolean ltr = sb.getComponentOrientation().isLeftToRight();
  539. /* Nominal locations of the buttons, assuming their preferred
  540. * size will fit.
  541. */
  542. int leftButtonW = itemH;
  543. int leftButtonX = sbInsets.left;
  544. int rightButtonW = itemH;
  545. int rightButtonX = sbSize.width - (sbInsets.right + rightButtonW);
  546. /* The thumb must fit within the width left over after we
  547. * subtract the preferredSize of the buttons and the insets.
  548. */
  549. int sbInsetsW = sbInsets.left + sbInsets.right;
  550. int sbButtonsW = leftButtonW + rightButtonW;
  551. float trackW = sbSize.width - (sbInsetsW + sbButtonsW);
  552. /* Compute the width and origin of the thumb. Enforce
  553. * the thumbs min/max dimensions. The case where the thumb
  554. * is at the right edge is handled specially to avoid numerical
  555. * problems in computing thumbX. If the thumb doesn't
  556. * fit in the track (trackH) we'll hide it later.
  557. */
  558. float min = sb.getMinimum();
  559. float max = sb.getMaximum();
  560. float extent = sb.getVisibleAmount();
  561. float range = max - min;
  562. float value = sb.getValue();
  563. int thumbW = (range <= 0)
  564. ? getMaximumThumbSize().width : (int)(trackW * (extent / range));
  565. thumbW = Math.max(thumbW, getMinimumThumbSize().width);
  566. thumbW = Math.min(thumbW, getMaximumThumbSize().width);
  567. int thumbX = ltr ? rightButtonX - thumbW : leftButtonX + leftButtonW;
  568. if (sb.getValue() < (max - sb.getVisibleAmount())) {
  569. float thumbRange = trackW - thumbW;
  570. if( ltr ) {
  571. thumbX = (int)(0.5f + (thumbRange * ((value - min) / (range - extent))));
  572. } else {
  573. thumbX = (int)(0.5f + (thumbRange * ((max - extent - value) / (range - extent))));
  574. }
  575. thumbX += leftButtonX + leftButtonW;
  576. }
  577. /* If the buttons don't fit, allocate half of the available
  578. * space to each and move the right one over.
  579. */
  580. int sbAvailButtonW = (sbSize.width - sbInsetsW);
  581. if (sbAvailButtonW < sbButtonsW) {
  582. rightButtonW = leftButtonW = sbAvailButtonW / 2;
  583. rightButtonX = sbSize.width - (sbInsets.right + rightButtonW);
  584. }
  585. (ltr ? decrButton : incrButton).setBounds(leftButtonX, itemY, leftButtonW, itemH);
  586. (ltr ? incrButton : decrButton).setBounds(rightButtonX, itemY, rightButtonW, itemH);
  587. /* Update the trackRect field.
  588. */
  589. int itrackX = leftButtonX + leftButtonW;
  590. int itrackW = rightButtonX - itrackX;
  591. trackRect.setBounds(itrackX, itemY, itrackW, itemH);
  592. /* Make sure the thumb fits between the buttons. Note
  593. * that setting the thumbs bounds causes a repaint.
  594. */
  595. if (thumbW >= (int)trackW) {
  596. setThumbBounds(0, 0, 0, 0);
  597. }
  598. else {
  599. if (thumbX + thumbW > rightButtonX) {
  600. thumbX = rightButtonX - thumbW;
  601. }
  602. if (thumbX < leftButtonX + leftButtonW) {
  603. thumbX = leftButtonX + leftButtonW + 1;
  604. }
  605. setThumbBounds(thumbX, itemY, thumbW, itemH);
  606. }
  607. }
  608. public void layoutContainer(Container scrollbarContainer)
  609. {
  610. /* If the user is dragging the value, we'll assume that the
  611. * scrollbars layout is OK modulo the thumb which is being
  612. * handled by the dragging code.
  613. */
  614. if (isDragging) {
  615. return;
  616. }
  617. JScrollBar scrollbar = (JScrollBar)scrollbarContainer;
  618. switch (scrollbar.getOrientation()) {
  619. case JScrollBar.VERTICAL:
  620. layoutVScrollbar(scrollbar);
  621. break;
  622. case JScrollBar.HORIZONTAL:
  623. layoutHScrollbar(scrollbar);
  624. break;
  625. }
  626. }
  627. /**
  628. * Set the bounds of the thumb and force a repaint that includes
  629. * the old thumbBounds and the new one.
  630. *
  631. * @see #getThumbBounds
  632. */
  633. protected void setThumbBounds(int x, int y, int width, int height)
  634. {
  635. /* If the thumbs bounds haven't changed, we're done.
  636. */
  637. if ((thumbRect.x == x) &&
  638. (thumbRect.y == y) &&
  639. (thumbRect.width == width) &&
  640. (thumbRect.height == height)) {
  641. return;
  642. }
  643. /* Update thumbRect, and repaint the union of x,y,w,h and
  644. * the old thumbRect.
  645. */
  646. int minX = Math.min(x, thumbRect.x);
  647. int minY = Math.min(y, thumbRect.y);
  648. int maxX = Math.max(x + width, thumbRect.x + thumbRect.width);
  649. int maxY = Math.max(y + height, thumbRect.y + thumbRect.height);
  650. thumbRect.setBounds(x, y, width, height);
  651. scrollbar.repaint(minX, minY, maxX - minX, maxY - minY);
  652. // PENDING: Is there a way to get the current mouse location?
  653. setThumbActive(false);
  654. }
  655. /**
  656. * Return the current size/location of the thumb.
  657. * <p>
  658. * <b>Warning </b>: the value returned by this method should not be
  659. * be modified, it's a reference to the actual rectangle, not a copy.
  660. *
  661. * @return The current size/location of the thumb.
  662. * @see #setThumbBounds
  663. */
  664. protected Rectangle getThumbBounds() {
  665. return thumbRect;
  666. }
  667. /**
  668. * Returns the current bounds of the track, i.e. the space in between
  669. * the increment and decrement buttons, less the insets. The value
  670. * returned by this method is updated each time the scrollbar is
  671. * laid out (validated).
  672. * <p>
  673. * <b>Warning </b>: the value returned by this method should not be
  674. * be modified, it's a reference to the actual rectangle, not a copy.
  675. *
  676. * @return the current bounds of the scrollbar track
  677. * @see #layoutContainer
  678. */
  679. protected Rectangle getTrackBounds() {
  680. return trackRect;
  681. }
  682. /*
  683. * Method for scrolling by a block increment.
  684. * Added for mouse wheel scrolling support, RFE 4202656.
  685. */
  686. static void scrollByBlock(JScrollBar scrollbar, int direction) {
  687. // This method is called from BasicScrollPaneUI to implement wheel
  688. // scrolling, and also from scrollByBlock().
  689. int oldValue = scrollbar.getValue();
  690. int blockIncrement = scrollbar.getBlockIncrement(direction);
  691. int delta = blockIncrement * ((direction > 0) ? +1 : -1);
  692. scrollbar.setValue(oldValue + delta);
  693. }
  694. protected void scrollByBlock(int direction)
  695. {
  696. scrollByBlock(scrollbar, direction);
  697. trackHighlight = direction > 0 ? INCREASE_HIGHLIGHT : DECREASE_HIGHLIGHT;
  698. Rectangle dirtyRect = getTrackBounds();
  699. scrollbar.repaint(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
  700. }
  701. /*
  702. * Method for scrolling by a unit increment.
  703. * Added for mouse wheel scrolling support, RFE 4202656.
  704. */
  705. static void scrollByUnits(JScrollBar scrollbar, int direction,
  706. int units) {
  707. // This method is called from BasicScrollPaneUI to implement wheel
  708. // scrolling, as well as from scrollByUnit().
  709. int delta = units;
  710. if (direction > 0) {
  711. delta *= scrollbar.getUnitIncrement(direction);
  712. }
  713. else {
  714. delta *= -scrollbar.getUnitIncrement(direction);
  715. }
  716. int oldValue = scrollbar.getValue();
  717. int newValue = oldValue + delta;
  718. // Check for overflow.
  719. if (delta > 0 && newValue < oldValue) {
  720. newValue = scrollbar.getMaximum();
  721. }
  722. else if (delta < 0 && newValue > oldValue) {
  723. newValue = scrollbar.getMinimum();
  724. }
  725. scrollbar.setValue(newValue);
  726. }
  727. protected void scrollByUnit(int direction) {
  728. scrollByUnits(scrollbar, direction, 1);
  729. }
  730. /**
  731. * Indicates whether the user can absolutely position the offset with
  732. * a mouse click (usually the middle mouse button).
  733. * <p>The return value is determined from the UIManager property
  734. * ScrollBar.allowsAbsolutePositioning.
  735. */
  736. private boolean getSupportsAbsolutePositioning() {
  737. return supportsAbsolutePositioning;
  738. }
  739. private void updateThumbState(int x, int y) {
  740. Rectangle rect = getThumbBounds();
  741. setThumbActive(rect.contains(x, y));
  742. }
  743. private void setThumbActive(boolean active) {
  744. if (thumbActive != active) {
  745. thumbActive = active;
  746. scrollbar.repaint(getThumbBounds());
  747. }
  748. }
  749. public boolean isThumbActive() {
  750. return thumbActive;
  751. }
  752. /**
  753. * A listener to listen for model changes.
  754. *
  755. */
  756. protected class ModelListener implements ChangeListener {
  757. public void stateChanged(ChangeEvent e) {
  758. layoutContainer(scrollbar);
  759. }
  760. }
  761. //
  762. // FocusListener
  763. //
  764. public void focusGained(FocusEvent e) {
  765. scrollbar.repaint();
  766. }
  767. public void focusLost(FocusEvent e) {
  768. scrollbar.repaint();
  769. }
  770. /**
  771. * Track mouse drags.
  772. */
  773. protected class TrackListener
  774. extends MouseAdapter implements MouseMotionListener
  775. {
  776. protected transient int offset;
  777. protected transient int currentMouseX, currentMouseY;
  778. private transient int direction = +1;
  779. public void mouseReleased(MouseEvent e)
  780. {
  781. if (isDragging) {
  782. updateThumbState(e.getX(), e.getY());
  783. }
  784. // PENDING: this should come from the look and feel
  785. if (SwingUtilities.isRightMouseButton(e) ||
  786. (!getSupportsAbsolutePositioning() &&
  787. SwingUtilities.isMiddleMouseButton(e)))
  788. return;
  789. if(!scrollbar.isEnabled())
  790. return;
  791. Rectangle r = getTrackBounds();
  792. scrollbar.repaint(r.x, r.y, r.width, r.height);
  793. trackHighlight = NO_HIGHLIGHT;
  794. isDragging = false;
  795. offset = 0;
  796. scrollTimer.stop();
  797. scrollbar.setValueIsAdjusting(false);
  798. }
  799. /**
  800. * If the mouse is pressed above the "thumb" component
  801. * then reduce the scrollbars value by one page ("page up"),
  802. * otherwise increase it by one page. If there is no
  803. * thumb then page up if the mouse is in the upper half
  804. * of the track.
  805. */
  806. public void mousePressed(MouseEvent e)
  807. {
  808. if (SwingUtilities.isRightMouseButton(e) ||
  809. (!getSupportsAbsolutePositioning() &&
  810. SwingUtilities.isMiddleMouseButton(e)))
  811. return;
  812. if(!scrollbar.isEnabled())
  813. return;
  814. if (!scrollbar.hasFocus() && scrollbar.isRequestFocusEnabled()) {
  815. scrollbar.requestFocus();
  816. }
  817. scrollbar.setValueIsAdjusting(true);
  818. currentMouseX = e.getX();
  819. currentMouseY = e.getY();
  820. // Clicked in the Thumb area?
  821. if(getThumbBounds().contains(currentMouseX, currentMouseY)) {
  822. switch (scrollbar.getOrientation()) {
  823. case JScrollBar.VERTICAL:
  824. offset = currentMouseY - getThumbBounds().y;
  825. break;
  826. case JScrollBar.HORIZONTAL:
  827. offset = currentMouseX - getThumbBounds().x;
  828. break;
  829. }
  830. isDragging = true;
  831. return;
  832. }
  833. else if (getSupportsAbsolutePositioning() &&
  834. SwingUtilities.isMiddleMouseButton(e)) {
  835. switch (scrollbar.getOrientation()) {
  836. case JScrollBar.VERTICAL:
  837. offset = getThumbBounds().height / 2;
  838. break;
  839. case JScrollBar.HORIZONTAL:
  840. offset = getThumbBounds().width / 2;
  841. break;
  842. }
  843. isDragging = true;
  844. setValueFrom(e);
  845. return;
  846. }
  847. isDragging = false;
  848. Dimension sbSize = scrollbar.getSize();
  849. direction = +1;
  850. switch (scrollbar.getOrientation()) {
  851. case JScrollBar.VERTICAL:
  852. if (getThumbBounds().isEmpty()) {
  853. int scrollbarCenter = sbSize.height / 2;
  854. direction = (currentMouseY < scrollbarCenter) ? -1 : +1;
  855. } else {
  856. int thumbY = getThumbBounds().y;
  857. direction = (currentMouseY < thumbY) ? -1 : +1;
  858. }
  859. break;
  860. case JScrollBar.HORIZONTAL:
  861. if (getThumbBounds().isEmpty()) {
  862. int scrollbarCenter = sbSize.width / 2;
  863. direction = (currentMouseX < scrollbarCenter) ? -1 : +1;
  864. } else {
  865. int thumbX = getThumbBounds().x;
  866. direction = (currentMouseX < thumbX) ? -1 : +1;
  867. }
  868. if (!scrollbar.getComponentOrientation().isLeftToRight()) {
  869. direction = -direction;
  870. }
  871. break;
  872. }
  873. scrollByBlock(direction);
  874. scrollTimer.stop();
  875. scrollListener.setDirection(direction);
  876. scrollListener.setScrollByBlock(true);
  877. startScrollTimerIfNecessary();
  878. }
  879. /**
  880. * Set the models value to the position of the thumb's top of Vertical
  881. * scrollbar, or the left/right of Horizontal scrollbar in
  882. * left-to-right/right-to-left scrollbar relative to the origin of the
  883. * track.
  884. */
  885. public void mouseDragged(MouseEvent e) {
  886. setValueFrom(e);
  887. if (SwingUtilities.isRightMouseButton(e) ||
  888. (!getSupportsAbsolutePositioning() &&
  889. SwingUtilities.isMiddleMouseButton(e)))
  890. return;
  891. if(!scrollbar.isEnabled() || getThumbBounds().isEmpty()) {
  892. return;
  893. }
  894. if (isDragging) {
  895. setValueFrom(e);
  896. } else {
  897. currentMouseX = e.getX();
  898. currentMouseY = e.getY();
  899. startScrollTimerIfNecessary();
  900. }
  901. }
  902. private void setValueFrom(MouseEvent e) {
  903. boolean active = isThumbActive();
  904. BoundedRangeModel model = scrollbar.getModel();
  905. Rectangle thumbR = getThumbBounds();
  906. float trackLength;
  907. int thumbMin, thumbMax, thumbPos;
  908. if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
  909. thumbMin = decrButton.getY() + decrButton.getHeight();
  910. thumbMax = incrButton.getY() - thumbR.height;
  911. thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e.getY() - offset)));
  912. setThumbBounds(thumbR.x, thumbPos, thumbR.width, thumbR.height);
  913. trackLength = getTrackBounds().height;
  914. }
  915. else {
  916. if (scrollbar.getComponentOrientation().isLeftToRight()) {
  917. thumbMin = decrButton.getX() + decrButton.getWidth();
  918. thumbMax = incrButton.getX() - thumbR.width;
  919. } else {
  920. thumbMin = incrButton.getX() + incrButton.getWidth();
  921. thumbMax = decrButton.getX() - thumbR.width;
  922. }
  923. thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e.getX() - offset)));
  924. setThumbBounds(thumbPos, thumbR.y, thumbR.width, thumbR.height);
  925. trackLength = getTrackBounds().width;
  926. }
  927. /* Set the scrollbars value. If the thumb has reached the end of
  928. * the scrollbar, then just set the value to its maximum. Otherwise
  929. * compute the value as accurately as possible.
  930. */
  931. if (thumbPos == thumbMax) {
  932. if (scrollbar.getOrientation() == JScrollBar.VERTICAL ||
  933. scrollbar.getComponentOrientation().isLeftToRight()) {
  934. scrollbar.setValue(model.getMaximum() - model.getExtent());
  935. } else {
  936. scrollbar.setValue(model.getMinimum());
  937. }
  938. }
  939. else {
  940. float valueMax = model.getMaximum() - model.getExtent();
  941. float valueRange = valueMax - model.getMinimum();
  942. float thumbValue = thumbPos - thumbMin;
  943. float thumbRange = thumbMax - thumbMin;
  944. int value;
  945. if (scrollbar.getOrientation() == JScrollBar.VERTICAL ||
  946. scrollbar.getComponentOrientation().isLeftToRight()) {
  947. value = (int)(0.5 + ((thumbValue / thumbRange) * valueRange));
  948. } else {
  949. value = (int)(0.5 + (((thumbMax - thumbPos) / thumbRange) * valueRange));
  950. }
  951. scrollbar.setValue(value + model.getMinimum());
  952. }
  953. setThumbActive(active);
  954. }
  955. private void startScrollTimerIfNecessary() {
  956. if (scrollTimer.isRunning()) {
  957. return;
  958. }
  959. switch (scrollbar.getOrientation()) {
  960. case JScrollBar.VERTICAL:
  961. if (direction >0) {
  962. if (getThumbBounds().y + getThumbBounds().height <
  963. trackListener.currentMouseY) {
  964. scrollTimer.start();
  965. }
  966. } else if (getThumbBounds().y >
  967. trackListener.currentMouseY) {
  968. scrollTimer.start();
  969. }
  970. break;
  971. case JScrollBar.HORIZONTAL:
  972. if (direction >0) {
  973. if (getThumbBounds().x + getThumbBounds().width <
  974. trackListener.currentMouseX) {
  975. scrollTimer.start();
  976. }
  977. } else if (getThumbBounds().x >
  978. trackListener.currentMouseX) {
  979. scrollTimer.start();
  980. }
  981. break;
  982. }
  983. }
  984. public void mouseMoved(MouseEvent e) {
  985. if (!isDragging) {
  986. updateThumbState(e.getX(), e.getY());
  987. }
  988. }
  989. public void mouseEntered(MouseEvent e) {
  990. }
  991. public void mouseExited(MouseEvent e) {
  992. if (!isDragging) {
  993. setThumbActive(false);
  994. }
  995. }
  996. }
  997. /**
  998. * Listener for cursor keys.
  999. */
  1000. protected class ArrowButtonListener extends MouseAdapter
  1001. {
  1002. // Because we are handling both mousePressed and Actions
  1003. // we need to make sure we don't fire under both conditions.
  1004. // (keyfocus on scrollbars causes action without mousePress
  1005. boolean handledEvent;
  1006. public void mousePressed(MouseEvent e) {
  1007. if(!scrollbar.isEnabled()) { return; }
  1008. // not an unmodified left mouse button
  1009. //if(e.getModifiers() != InputEvent.BUTTON1_MASK) {return; }
  1010. if( ! SwingUtilities.isLeftMouseButton(e)) { return; }
  1011. int direction = (e.getSource() == incrButton) ? 1 : -1;
  1012. scrollByUnit(direction);
  1013. scrollTimer.stop();
  1014. scrollListener.setDirection(direction);
  1015. scrollListener.setScrollByBlock(false);
  1016. scrollTimer.start();
  1017. handledEvent = true;
  1018. if (!scrollbar.hasFocus() && scrollbar.isRequestFocusEnabled()) {
  1019. scrollbar.requestFocus();
  1020. }
  1021. }
  1022. public void mouseReleased(MouseEvent e) {
  1023. scrollTimer.stop();
  1024. handledEvent = false;
  1025. scrollbar.setValueIsAdjusting(false);
  1026. }
  1027. }
  1028. /**
  1029. * Listener for scrolling events initiated in the
  1030. * <code>ScrollPane</code>.
  1031. */
  1032. protected class ScrollListener implements ActionListener
  1033. {
  1034. int direction = +1;
  1035. boolean useBlockIncrement;
  1036. public ScrollListener() {
  1037. direction = +1;
  1038. useBlockIncrement = false;
  1039. }
  1040. public ScrollListener(int dir, boolean block) {
  1041. direction = dir;
  1042. useBlockIncrement = block;
  1043. }
  1044. public void setDirection(int direction) { this.direction = direction; }
  1045. public void setScrollByBlock(boolean block) { this.useBlockIncrement = block; }
  1046. public void actionPerformed(ActionEvent e) {
  1047. if(useBlockIncrement) {
  1048. scrollByBlock(direction);
  1049. // Stop scrolling if the thumb catches up with the mouse
  1050. if(scrollbar.getOrientation() == JScrollBar.VERTICAL) {
  1051. if(direction > 0) {
  1052. if(getThumbBounds().y + getThumbBounds().height
  1053. >= trackListener.currentMouseY)
  1054. ((Timer)e.getSource()).stop();
  1055. } else if(getThumbBounds().y <= trackListener.currentMouseY) {
  1056. ((Timer)e.getSource()).stop();
  1057. }
  1058. } else {
  1059. if(direction > 0) {
  1060. if(getThumbBounds().x + getThumbBounds().width
  1061. >= trackListener.currentMouseX)
  1062. ((Timer)e.getSource()).stop();
  1063. } else if(getThumbBounds().x <= trackListener.currentMouseX) {
  1064. ((Timer)e.getSource()).stop();
  1065. }
  1066. }
  1067. } else {
  1068. scrollByUnit(direction);
  1069. }
  1070. if(direction > 0
  1071. && scrollbar.getValue()+scrollbar.getVisibleAmount()
  1072. >= scrollbar.getMaximum())
  1073. ((Timer)e.getSource()).stop();
  1074. else if(direction < 0
  1075. && scrollbar.getValue() <= scrollbar.getMinimum())
  1076. ((Timer)e.getSource()).stop();
  1077. }
  1078. }
  1079. class PropertyChangeHandler implements PropertyChangeListener
  1080. {
  1081. public void propertyChange(PropertyChangeEvent e) {
  1082. String propertyName = e.getPropertyName();
  1083. if (SynthLookAndFeel.shouldUpdateStyle(e)) {
  1084. fetchStyle((JScrollBar)e.getSource());
  1085. }
  1086. if ("model".equals(propertyName)) {
  1087. BoundedRangeModel oldModel = (BoundedRangeModel)e.getOldValue();
  1088. BoundedRangeModel newModel = (BoundedRangeModel)e.getNewValue();
  1089. oldModel.removeChangeListener(modelListener);
  1090. newModel.addChangeListener(modelListener);
  1091. scrollbar.repaint();
  1092. scrollbar.revalidate();
  1093. } else if ("orientation".equals(propertyName)) {
  1094. Integer orient = (Integer)e.getNewValue();
  1095. if (scrollbar.getComponentOrientation().isLeftToRight()) {
  1096. if (incrButton instanceof SynthArrowButton) {
  1097. ((SynthArrowButton)incrButton).setDirection(orient.intValue() == HORIZONTAL?
  1098. EAST : SOUTH);
  1099. }
  1100. if (decrButton instanceof SynthArrowButton) {
  1101. ((SynthArrowButton)decrButton).setDirection(orient.intValue() == HORIZONTAL?
  1102. WEST : NORTH);
  1103. }
  1104. } else {
  1105. if (incrButton instanceof SynthArrowButton) {
  1106. ((SynthArrowButton)incrButton).setDirection(orient.intValue() == HORIZONTAL?
  1107. WEST : SOUTH);
  1108. }
  1109. if (decrButton instanceof SynthArrowButton) {
  1110. ((SynthArrowButton)decrButton).setDirection(orient.intValue() == HORIZONTAL?
  1111. EAST : NORTH);
  1112. }
  1113. }
  1114. } else if ("componentOrientation".equals(propertyName)) {
  1115. ComponentOrientation co = scrollbar.getComponentOrientation();
  1116. incrButton.setComponentOrientation(co);
  1117. decrButton.setComponentOrientation(co);
  1118. if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL) {
  1119. if (co.isLeftToRight()) {
  1120. if (incrButton instanceof SynthArrowButton) {
  1121. ((SynthArrowButton)incrButton).setDirection(EAST);
  1122. }
  1123. if (decrButton instanceof SynthArrowButton) {
  1124. ((SynthArrowButton)decrButton).setDirection(WEST);
  1125. }
  1126. } else {
  1127. if (incrButton instanceof SynthArrowButton) {
  1128. ((SynthArrowButton)incrButton).setDirection(WEST);
  1129. }
  1130. if (decrButton instanceof SynthArrowButton) {
  1131. ((SynthArrowButton)decrButton).setDirection(EAST);
  1132. }
  1133. }
  1134. }
  1135. InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED);
  1136. SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED, inputMap);
  1137. }
  1138. }
  1139. }
  1140. /**
  1141. * Used for scrolling the scrollbar.
  1142. */
  1143. private static class SharedActionScroller extends AbstractAction {
  1144. private int dir;
  1145. private boolean block;
  1146. SharedActionScroller(int dir, boolean block) {
  1147. this.dir = dir;
  1148. this.block = block;
  1149. }
  1150. public void actionPerformed(ActionEvent e) {
  1151. JScrollBar scrollBar = (JScrollBar)e.getSource();
  1152. if (dir == NEGATIVE_SCROLL || dir == POSITIVE_SCROLL) {
  1153. int amount;
  1154. // Don't use the BasicScrollBarUI.scrollByXXX methods as we
  1155. // don't want to use an invokeLater to reset the trackHighlight
  1156. // via an invokeLater
  1157. if (block) {
  1158. if (dir == NEGATIVE_SCROLL) {
  1159. amount = -1 * scrollBar.getBlockIncrement(-1);
  1160. }
  1161. else {
  1162. amount = scrollBar.getBlockIncrement(1);
  1163. }
  1164. }
  1165. else {
  1166. if (dir == NEGATIVE_SCROLL) {
  1167. amount = -1 * scrollBar.getUnitIncrement(-1);
  1168. }
  1169. else {
  1170. amount = scrollBar.getUnitIncrement(1);
  1171. }
  1172. }
  1173. scrollBar.setValue(scrollBar.getValue() + amount);
  1174. }
  1175. else if (dir == MIN_SCROLL) {
  1176. scrollBar.setValue(scrollBar.getMinimum());
  1177. }
  1178. else if (dir == MAX_SCROLL) {
  1179. scrollBar.setValue(scrollBar.getMaximum());
  1180. }
  1181. }
  1182. }
  1183. }