1. /*
  2. * @(#)SynthSliderUI.java 1.94 01/12/03
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.plaf.synth;
  8. import java.awt.Component;
  9. import java.awt.Container;
  10. import java.awt.Adjustable;
  11. import java.awt.event.*;
  12. import java.awt.Graphics;
  13. import java.awt.Dimension;
  14. import java.awt.Font;
  15. import java.awt.FontMetrics;
  16. import java.awt.Rectangle;
  17. import java.awt.Point;
  18. import java.awt.Insets;
  19. import java.awt.Color;
  20. import java.awt.IllegalComponentStateException;
  21. import java.awt.Polygon;
  22. import java.beans.*;
  23. import java.util.Dictionary;
  24. import java.util.Enumeration;
  25. import javax.swing.border.AbstractBorder;
  26. import javax.swing.*;
  27. import javax.swing.event.*;
  28. import javax.swing.plaf.*;
  29. import javax.swing.plaf.basic.BasicSliderUI;
  30. import sun.swing.plaf.synth.SynthUI;
  31. import com.sun.java.swing.SwingUtilities2;
  32. /**
  33. * Synth's SliderUI.
  34. *
  35. * @version 1.21, 12/19/03
  36. * @author Joshua Outwater
  37. */
  38. class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener,
  39. SynthUI {
  40. protected Dimension contentDim = new Dimension();
  41. protected Rectangle valueRect = new Rectangle();
  42. protected boolean paintValue;
  43. private int trackHeight;
  44. private int trackBorder;
  45. private int thumbWidth;
  46. private int thumbHeight;
  47. private SynthStyle style;
  48. private SynthStyle sliderTrackStyle;
  49. private SynthStyle sliderThumbStyle;
  50. /** Used to determine the color to paint the thumb. */
  51. private transient boolean thumbActive;
  52. ///////////////////////////////////////////////////
  53. // ComponentUI Interface Implementation methods
  54. ///////////////////////////////////////////////////
  55. public static ComponentUI createUI(JComponent c) {
  56. return new SynthSliderUI((JSlider)c);
  57. }
  58. public SynthSliderUI(JSlider c) {
  59. super(c);
  60. }
  61. protected void installDefaults(JSlider slider) {
  62. updateStyle(slider);
  63. }
  64. protected void uninstallDefaults() {
  65. SynthContext context = getContext(slider, ENABLED);
  66. style.uninstallDefaults(context);
  67. context.dispose();
  68. style = null;
  69. context = getContext(slider, Region.SLIDER_TRACK, ENABLED);
  70. sliderTrackStyle.uninstallDefaults(context);
  71. context.dispose();
  72. sliderTrackStyle = null;
  73. context = getContext(slider, Region.SLIDER_THUMB, ENABLED);
  74. sliderThumbStyle.uninstallDefaults(context);
  75. context.dispose();
  76. sliderThumbStyle = null;
  77. }
  78. protected void installListeners(JSlider slider) {
  79. super.installListeners(slider);
  80. slider.addPropertyChangeListener(this);
  81. }
  82. protected void uninstallListeners() {
  83. slider.removePropertyChangeListener(this);
  84. super.uninstallListeners(slider);
  85. }
  86. private void updateStyle(JSlider c) {
  87. SynthContext context = getContext(c, ENABLED);
  88. SynthStyle oldStyle = style;
  89. style = SynthLookAndFeel.updateStyle(context, this);
  90. if (style != oldStyle) {
  91. thumbWidth =
  92. style.getInt(context, "Slider.thumbWidth", 30);
  93. thumbHeight =
  94. style.getInt(context, "Slider.thumbHeight", 14);
  95. trackBorder =
  96. style.getInt(context, "Slider.trackBorder", 1);
  97. trackHeight = thumbHeight + trackBorder * 2;
  98. paintValue = style.getBoolean(context,
  99. "Slider.paintValue", true);
  100. if (oldStyle != null) {
  101. uninstallKeyboardActions(c);
  102. installKeyboardActions(c);
  103. }
  104. }
  105. context.dispose();
  106. context = getContext(c, Region.SLIDER_TRACK, ENABLED);
  107. sliderTrackStyle =
  108. SynthLookAndFeel.updateStyle(context, this);
  109. context.dispose();
  110. context = getContext(c, Region.SLIDER_THUMB, ENABLED);
  111. sliderThumbStyle =
  112. SynthLookAndFeel.updateStyle(context, this);
  113. context.dispose();
  114. }
  115. protected TrackListener createTrackListener(JSlider s) {
  116. return new SynthTrackListener();
  117. }
  118. private void updateThumbState(int x, int y) {
  119. setThumbActive(thumbRect.contains(x, y));
  120. }
  121. private void setThumbActive(boolean active) {
  122. if (thumbActive != active) {
  123. thumbActive = active;
  124. slider.repaint(thumbRect);
  125. }
  126. }
  127. public Dimension getPreferredSize(JComponent c) {
  128. recalculateIfInsetsChanged();
  129. Dimension d = new Dimension(contentDim);
  130. if (slider.getOrientation() == JSlider.VERTICAL) {
  131. d.height = 200;
  132. } else {
  133. d.width = 200;
  134. }
  135. return d;
  136. }
  137. public Dimension getMinimumSize(JComponent c) {
  138. recalculateIfInsetsChanged();
  139. Dimension d = new Dimension(contentDim);
  140. if (slider.getOrientation() == JSlider.VERTICAL) {
  141. d.height = thumbRect.height + insetCache.top + insetCache.bottom;
  142. } else {
  143. d.width = thumbRect.width + insetCache.left + insetCache.right;
  144. }
  145. return d;
  146. }
  147. protected void calculateGeometry() {
  148. layout();
  149. calculateThumbLocation();
  150. }
  151. protected void layout() {
  152. SynthContext context = getContext(slider);
  153. SynthGraphicsUtils synthGraphics = style.getGraphicsUtils(context);
  154. // Set the thumb size.
  155. Dimension size = getThumbSize();
  156. thumbRect.setSize(size.width, size.height);
  157. // Get the insets for the track.
  158. Insets trackInsets = new Insets(0, 0, 0, 0);
  159. SynthContext trackContext = getContext(slider, Region.SLIDER_TRACK);
  160. style.getInsets(trackContext, trackInsets);
  161. trackContext.dispose();
  162. if (slider.getOrientation() == JSlider.HORIZONTAL) {
  163. // Calculate the height of all the subcomponents so we can center
  164. // them.
  165. valueRect.height = 0;
  166. if (paintValue) {
  167. valueRect.height =
  168. synthGraphics.getMaximumCharHeight(context);
  169. }
  170. trackRect.height = trackHeight;
  171. tickRect.height = 0;
  172. if (slider.getPaintTicks()) {
  173. tickRect.height = getTickLength();
  174. }
  175. labelRect.height = 0;
  176. if (slider.getPaintLabels()) {
  177. labelRect.height = getHeightOfTallestLabel();
  178. }
  179. contentDim.height = valueRect.height + trackRect.height
  180. + trackInsets.top + trackInsets.bottom
  181. + tickRect.height + labelRect.height + 4;
  182. contentDim.width = slider.getWidth() - insetCache.left
  183. - insetCache.right;
  184. int centerY = slider.getHeight() / 2 - contentDim.height / 2;
  185. // Layout the components.
  186. valueRect.x = trackRect.x = tickRect.x = labelRect.x =
  187. insetCache.left;
  188. valueRect.width = trackRect.width =
  189. tickRect.width = labelRect.width = contentDim.width;
  190. valueRect.y = centerY;
  191. centerY += valueRect.height + 2;
  192. trackRect.y = centerY + trackInsets.top;
  193. centerY += trackRect.height + trackInsets.top + trackInsets.bottom;
  194. tickRect.y = centerY;
  195. centerY += tickRect.height + 2;
  196. labelRect.y = centerY;
  197. centerY += labelRect.height;
  198. } else {
  199. // Calculate the width of all the subcomponents so we can center
  200. // them.
  201. trackRect.width = trackHeight;
  202. tickRect.width = 0;
  203. if (slider.getPaintTicks()) {
  204. tickRect.width = getTickLength();
  205. }
  206. labelRect.width = 0;
  207. if (slider.getPaintLabels()) {
  208. labelRect.width = getWidthOfWidestLabel();
  209. }
  210. valueRect.y = insetCache.top;
  211. valueRect.height = 0;
  212. if (paintValue) {
  213. valueRect.height =
  214. synthGraphics.getMaximumCharHeight(context);
  215. }
  216. contentDim.width = trackRect.width + trackInsets.left
  217. + trackInsets.right + tickRect.width
  218. + labelRect.width + 2 + insetCache.left + insetCache.right;
  219. contentDim.height = slider.getHeight()
  220. - insetCache.top - insetCache.bottom;
  221. int startX = slider.getWidth() / 2 - contentDim.width / 2;
  222. // Get the max width of the min or max value of the slider.
  223. FontMetrics fm = slider.getFontMetrics(slider.getFont());
  224. valueRect.width = Math.max(
  225. synthGraphics.computeStringWidth(context, slider.getFont(),
  226. fm, "" + slider.getMaximum()),
  227. synthGraphics.computeStringWidth(context, slider.getFont(),
  228. fm, "" + slider.getMinimum()));
  229. // Check to see if we need to make the width larger due to the size
  230. // of the value string. The value string is centered above the
  231. // track.
  232. if (valueRect.width > (trackRect.width + trackInsets.left
  233. + trackInsets.right)) {
  234. int diff = (valueRect.width - (trackRect.width
  235. + trackInsets.left + trackInsets.right)) / 2;
  236. contentDim.width += diff;
  237. startX += diff;
  238. }
  239. // Layout the components.
  240. trackRect.y = tickRect.y = labelRect.y =
  241. valueRect.y + valueRect.height;
  242. trackRect.height = tickRect.height = labelRect.height =
  243. contentDim.height - valueRect.height;
  244. if (SynthLookAndFeel.isLeftToRight(slider)) {
  245. trackRect.x = startX + trackInsets.left;
  246. startX += trackRect.width + trackInsets.right +
  247. trackInsets.left;
  248. tickRect.x = startX;
  249. startX += tickRect.width + 2;
  250. labelRect.x = startX;
  251. } else {
  252. labelRect.x = startX;
  253. startX += labelRect.width + 2;
  254. tickRect.x = startX;
  255. startX += tickRect.width + trackInsets.left;
  256. trackRect.x = startX;
  257. }
  258. }
  259. context.dispose();
  260. }
  261. protected void calculateThumbLocation() {
  262. if (slider.getSnapToTicks()) {
  263. int sliderValue = slider.getValue();
  264. int snappedValue = sliderValue;
  265. int majorTickSpacing = slider.getMajorTickSpacing();
  266. int minorTickSpacing = slider.getMinorTickSpacing();
  267. int tickSpacing = 0;
  268. if (minorTickSpacing > 0) {
  269. tickSpacing = minorTickSpacing;
  270. } else if (majorTickSpacing > 0) {
  271. tickSpacing = majorTickSpacing;
  272. }
  273. if (tickSpacing != 0) {
  274. // If it's not on a tick, change the value
  275. if ((sliderValue - slider.getMinimum()) % tickSpacing != 0) {
  276. float temp = (float)(sliderValue - slider.getMinimum())
  277. / (float)tickSpacing;
  278. int whichTick = Math.round( temp );
  279. snappedValue =
  280. slider.getMinimum() + (whichTick * tickSpacing);
  281. }
  282. if (snappedValue != sliderValue) {
  283. slider.setValue(snappedValue);
  284. }
  285. }
  286. }
  287. if (slider.getOrientation() == JSlider.HORIZONTAL) {
  288. int valuePosition = xPositionForValue(slider.getValue());
  289. thumbRect.x = valuePosition - (thumbRect.width / 2);
  290. thumbRect.y = trackRect.y + trackBorder;
  291. } else {
  292. int valuePosition = yPositionForValue(slider.getValue());
  293. thumbRect.x = trackRect.x + trackBorder;
  294. thumbRect.y = valuePosition - (thumbRect.height / 2);
  295. }
  296. }
  297. protected void calculateTickRect() {
  298. if (slider.getOrientation() == JSlider.HORIZONTAL) {
  299. tickRect.x = trackRect.x;
  300. tickRect.y = trackRect.y + trackRect.height + 2 + getTickLength();
  301. tickRect.width = trackRect.width;
  302. tickRect.height = getTickLength();
  303. if (!slider.getPaintTicks()) {
  304. --tickRect.y;
  305. tickRect.height = 0;
  306. }
  307. } else {
  308. if (SynthLookAndFeel.isLeftToRight(slider)) {
  309. tickRect.x = trackRect.x + trackRect.width;
  310. tickRect.width = getTickLength();
  311. } else {
  312. tickRect.width = getTickLength();
  313. tickRect.x = trackRect.x - tickRect.width;
  314. }
  315. tickRect.y = trackRect.y;
  316. tickRect.height = trackRect.height;
  317. if (!slider.getPaintTicks()) {
  318. --tickRect.x;
  319. tickRect.width = 0;
  320. }
  321. }
  322. }
  323. private static Rectangle unionRect = new Rectangle();
  324. public void setThumbLocation(int x, int y) {
  325. super.setThumbLocation(x, y);
  326. // Value rect is tied to the thumb location. We need to repaint when
  327. // the thumb repaints.
  328. slider.repaint(valueRect.x, valueRect.y,
  329. valueRect.width, valueRect.height);
  330. setThumbActive(false);
  331. }
  332. protected int xPositionForValue(int value) {
  333. int min = slider.getMinimum();
  334. int max = slider.getMaximum();
  335. int trackLeft = trackRect.x + thumbRect.width / 2 + trackBorder;
  336. int trackRight = trackRect.x + trackRect.width - thumbRect.width / 2
  337. - trackBorder;
  338. int trackLength = trackRight - trackLeft;
  339. double valueRange = (double)max - (double)min;
  340. double pixelsPerValue = (double)trackLength / valueRange;
  341. int xPosition;
  342. if (!drawInverted()) {
  343. xPosition = trackLeft;
  344. xPosition += Math.round( pixelsPerValue * ((double)value - min));
  345. } else {
  346. xPosition = trackRight;
  347. xPosition -= Math.round( pixelsPerValue * ((double)value - min));
  348. }
  349. xPosition = Math.max(trackLeft, xPosition);
  350. xPosition = Math.min(trackRight, xPosition);
  351. return xPosition;
  352. }
  353. protected int yPositionForValue(int value) {
  354. int min = slider.getMinimum();
  355. int max = slider.getMaximum();
  356. int trackTop = trackRect.y + thumbRect.height / 2 + trackBorder;
  357. int trackBottom = trackRect.y + trackRect.height
  358. - thumbRect.height / 2 - trackBorder;
  359. int trackLength = trackBottom - trackTop;
  360. double valueRange = (double)max - (double)min;
  361. double pixelsPerValue = (double)trackLength / (double)valueRange;
  362. int yPosition;
  363. if (!drawInverted()) {
  364. yPosition = trackTop;
  365. yPosition += Math.round(pixelsPerValue * ((double)max - value));
  366. } else {
  367. yPosition = trackTop;
  368. yPosition += Math.round(pixelsPerValue * ((double)value - min));
  369. }
  370. yPosition = Math.max(trackTop, yPosition);
  371. yPosition = Math.min(trackBottom, yPosition);
  372. return yPosition;
  373. }
  374. /**
  375. * Returns a value give a y position. If yPos is past the track at the
  376. * top or the bottom it will set the value to the min or max of the
  377. * slider, depending if the slider is inverted or not.
  378. */
  379. public int valueForYPosition(int yPos) {
  380. int value;
  381. int minValue = slider.getMinimum();
  382. int maxValue = slider.getMaximum();
  383. int trackTop = trackRect.y + thumbRect.height / 2 + trackBorder;
  384. int trackBottom = trackRect.y + trackRect.height
  385. - thumbRect.height / 2 - trackBorder;
  386. int trackLength = trackBottom - trackTop;
  387. if (yPos <= trackTop) {
  388. value = drawInverted() ? minValue : maxValue;
  389. } else if (yPos >= trackBottom) {
  390. value = drawInverted() ? maxValue : minValue;
  391. } else {
  392. int distanceFromTrackTop = yPos - trackTop;
  393. double valueRange = (double)maxValue - (double)minValue;
  394. double valuePerPixel = valueRange / (double)trackLength;
  395. int valueFromTrackTop =
  396. (int)Math.round(distanceFromTrackTop * valuePerPixel);
  397. value = drawInverted() ?
  398. minValue + valueFromTrackTop : maxValue - valueFromTrackTop;
  399. }
  400. return value;
  401. }
  402. /**
  403. * Returns a value give an x position. If xPos is past the track at the
  404. * left or the right it will set the value to the min or max of the
  405. * slider, depending if the slider is inverted or not.
  406. */
  407. public int valueForXPosition(int xPos) {
  408. int value;
  409. int minValue = slider.getMinimum();
  410. int maxValue = slider.getMaximum();
  411. int trackLeft = trackRect.x + thumbRect.width / 2 + trackBorder;
  412. int trackRight = trackRect.x + trackRect.width
  413. - thumbRect.width / 2 - trackBorder;
  414. int trackLength = trackRight - trackLeft;
  415. if (xPos <= trackLeft) {
  416. value = drawInverted() ? maxValue : minValue;
  417. } else if (xPos >= trackRight) {
  418. value = drawInverted() ? minValue : maxValue;
  419. } else {
  420. int distanceFromTrackLeft = xPos - trackLeft;
  421. double valueRange = (double)maxValue - (double)minValue;
  422. double valuePerPixel = valueRange / (double)trackLength;
  423. int valueFromTrackLeft =
  424. (int)Math.round(distanceFromTrackLeft * valuePerPixel);
  425. value = drawInverted() ?
  426. maxValue - valueFromTrackLeft : minValue + valueFromTrackLeft;
  427. }
  428. return value;
  429. }
  430. protected Dimension getThumbSize() {
  431. Dimension size = new Dimension();
  432. if (slider.getOrientation() == JSlider.VERTICAL) {
  433. size.width = thumbHeight;
  434. size.height = thumbWidth;
  435. } else {
  436. size.width = thumbWidth;
  437. size.height = thumbHeight;
  438. }
  439. return size;
  440. }
  441. protected void recalculateIfInsetsChanged() {
  442. SynthContext context = getContext(slider);
  443. Insets newInsets = style.getInsets(context, null);
  444. if (!newInsets.equals(insetCache)) {
  445. insetCache = newInsets;
  446. calculateGeometry();
  447. }
  448. context.dispose();
  449. }
  450. public Region getRegion(JComponent c) {
  451. return SynthLookAndFeel.getRegion(c);
  452. }
  453. public SynthContext getContext(JComponent c) {
  454. return getContext(c, getComponentState(c));
  455. }
  456. public SynthContext getContext(JComponent c, int state) {
  457. return SynthContext.getContext(SynthContext.class, c,
  458. SynthLookAndFeel.getRegion(c), style, state);
  459. }
  460. public SynthContext getContext(JComponent c, Region subregion) {
  461. return getContext(c, subregion, getComponentState(c, subregion));
  462. }
  463. private SynthContext getContext(JComponent c, Region subregion, int state) {
  464. SynthStyle style = null;
  465. Class klass = SynthContext.class;
  466. if (subregion == Region.SLIDER_TRACK) {
  467. style = sliderTrackStyle;
  468. } else if (subregion == Region.SLIDER_THUMB) {
  469. style = sliderThumbStyle;
  470. }
  471. return SynthContext.getContext(klass, c, subregion, style, state);
  472. }
  473. public int getComponentState(JComponent c) {
  474. return SynthLookAndFeel.getComponentState(c);
  475. }
  476. private int getComponentState(JComponent c, Region region) {
  477. if (region == Region.SLIDER_THUMB && thumbActive &&c.isEnabled()) {
  478. return MOUSE_OVER;
  479. }
  480. return SynthLookAndFeel.getComponentState(c);
  481. }
  482. public void update(Graphics g, JComponent c) {
  483. SynthContext context = getContext(c);
  484. SynthLookAndFeel.update(context, g);
  485. context.getPainter().paintSliderBackground(context,
  486. g, 0, 0, c.getWidth(), c.getHeight());
  487. paint(context, g);
  488. context.dispose();
  489. }
  490. public void paint(Graphics g, JComponent c) {
  491. SynthContext context = getContext(c);
  492. paint(context, g);
  493. context.dispose();
  494. }
  495. public void paint(SynthContext context, Graphics g) {
  496. recalculateIfInsetsChanged();
  497. recalculateIfOrientationChanged();
  498. Rectangle clip = g.getClipBounds();
  499. if (paintValue) {
  500. FontMetrics fm = SwingUtilities2.getFontMetrics(slider, g);
  501. valueRect.x = (thumbRect.x + (thumbRect.width / 2)) -
  502. context.getStyle().getGraphicsUtils(context).
  503. computeStringWidth(context, g.getFont(), fm,
  504. "" + slider.getValue()) / 2;
  505. g.setColor(context.getStyle().getColor(
  506. context, ColorType.TEXT_FOREGROUND));
  507. context.getStyle().getGraphicsUtils(context).paintText(
  508. context, g, "" + slider.getValue(), valueRect.x,
  509. valueRect.y, -1);
  510. }
  511. SynthContext subcontext = getContext(slider, Region.SLIDER_TRACK);
  512. paintTrack(subcontext, g, trackRect);
  513. subcontext.dispose();
  514. subcontext = getContext(slider, Region.SLIDER_THUMB);
  515. paintThumb(subcontext, g, thumbRect);
  516. subcontext.dispose();
  517. if (slider.getPaintTicks() && clip.intersects(tickRect)) {
  518. paintTicks(g);
  519. }
  520. if (slider.getPaintLabels() && clip.intersects(labelRect)) {
  521. paintLabels(g);
  522. }
  523. }
  524. public void paintBorder(SynthContext context, Graphics g, int x,
  525. int y, int w, int h) {
  526. context.getPainter().paintSliderBorder(context, g, x, y, w, h);
  527. }
  528. public void paintThumb(SynthContext context, Graphics g,
  529. Rectangle thumbBounds) {
  530. int orientation = slider.getOrientation();
  531. SynthLookAndFeel.updateSubregion(context, g, thumbBounds);
  532. context.getPainter().paintSliderThumbBackground(context, g,
  533. thumbBounds.x, thumbBounds.y, thumbBounds.width,
  534. thumbBounds.height, orientation);
  535. context.getPainter().paintSliderThumbBorder(context, g,
  536. thumbBounds.x, thumbBounds.y, thumbBounds.width,
  537. thumbBounds.height, orientation);
  538. }
  539. public void paintTrack(SynthContext context, Graphics g,
  540. Rectangle trackBounds) {
  541. SynthLookAndFeel.updateSubregion(context, g, trackBounds);
  542. context.getPainter().paintSliderTrackBackground(context, g,
  543. trackBounds.x, trackBounds.y, trackBounds.width,
  544. trackBounds.height);
  545. context.getPainter().paintSliderTrackBorder(context, g,
  546. trackBounds.x, trackBounds.y, trackBounds.width,
  547. trackBounds.height);
  548. }
  549. public void propertyChange(PropertyChangeEvent e) {
  550. if (SynthLookAndFeel.shouldUpdateStyle(e)) {
  551. updateStyle((JSlider)e.getSource());
  552. }
  553. }
  554. //////////////////////////////////////////////////
  555. /// Track Listener Class
  556. //////////////////////////////////////////////////
  557. /**
  558. * Track mouse movements.
  559. */
  560. protected class SynthTrackListener extends TrackListener {
  561. public void mouseExited(MouseEvent e) {
  562. setThumbActive(false);
  563. }
  564. public void mouseReleased(MouseEvent e) {
  565. super.mouseReleased(e);
  566. updateThumbState(e.getX(), e.getY());
  567. }
  568. public void mouseDragged(MouseEvent e) {
  569. SynthScrollBarUI ui;
  570. int thumbMiddle = 0;
  571. if (!slider.isEnabled()) {
  572. return;
  573. }
  574. currentMouseX = e.getX();
  575. currentMouseY = e.getY();
  576. if (!isDragging()) {
  577. return;
  578. }
  579. slider.setValueIsAdjusting(true);
  580. switch (slider.getOrientation()) {
  581. case JSlider.VERTICAL:
  582. int halfThumbHeight = thumbRect.height / 2;
  583. int thumbTop = e.getY() - offset;
  584. int trackTop = trackRect.y;
  585. int trackBottom = trackRect.y + trackRect.height
  586. - halfThumbHeight - trackBorder;
  587. int vMax = yPositionForValue(slider.getMaximum() -
  588. slider.getExtent());
  589. if (drawInverted()) {
  590. trackBottom = vMax;
  591. } else {
  592. trackTop = vMax;
  593. }
  594. thumbTop = Math.max(thumbTop, trackTop - halfThumbHeight);
  595. thumbTop = Math.min(thumbTop, trackBottom - halfThumbHeight);
  596. setThumbLocation(thumbRect.x, thumbTop);
  597. thumbMiddle = thumbTop + halfThumbHeight;
  598. slider.setValue(valueForYPosition(thumbMiddle));
  599. break;
  600. case JSlider.HORIZONTAL:
  601. int halfThumbWidth = thumbRect.width / 2;
  602. int thumbLeft = e.getX() - offset;
  603. int trackLeft = trackRect.x + halfThumbWidth + trackBorder;
  604. int trackRight = trackRect.x + trackRect.width
  605. - halfThumbWidth - trackBorder;
  606. int hMax = xPositionForValue(slider.getMaximum() -
  607. slider.getExtent());
  608. if (drawInverted()) {
  609. trackLeft = hMax;
  610. } else {
  611. trackRight = hMax;
  612. }
  613. thumbLeft = Math.max(thumbLeft, trackLeft - halfThumbWidth);
  614. thumbLeft = Math.min(thumbLeft, trackRight - halfThumbWidth);
  615. setThumbLocation(thumbLeft, thumbRect.y);
  616. thumbMiddle = thumbLeft + halfThumbWidth;
  617. slider.setValue(valueForXPosition(thumbMiddle));
  618. break;
  619. default:
  620. return;
  621. }
  622. if (slider.getValueIsAdjusting()) {
  623. setThumbActive(true);
  624. }
  625. }
  626. public void mouseMoved(MouseEvent e) {
  627. updateThumbState(e.getX(), e.getY());
  628. }
  629. }
  630. }