1. /*
  2. * @(#)MetalSliderUI.java 1.27 00/02/02
  3. *
  4. * Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package javax.swing.plaf.metal;
  11. import javax.swing.plaf.basic.BasicSliderUI;
  12. import java.awt.Component;
  13. import java.awt.Container;
  14. import java.awt.Graphics;
  15. import java.awt.Dimension;
  16. import java.awt.Rectangle;
  17. import java.awt.Point;
  18. import java.awt.Insets;
  19. import java.awt.Color;
  20. import java.io.Serializable;
  21. import java.awt.IllegalComponentStateException;
  22. import java.awt.Polygon;
  23. import java.beans.*;
  24. import javax.swing.border.AbstractBorder;
  25. import javax.swing.*;
  26. import javax.swing.event.*;
  27. import javax.swing.plaf.*;
  28. /**
  29. * A Java L&F implementation of SliderUI.
  30. * <p>
  31. * <strong>Warning:</strong>
  32. * Serialized objects of this class will not be compatible with
  33. * future Swing releases. The current serialization support is appropriate
  34. * for short term storage or RMI between applications running the same
  35. * version of Swing. A future release of Swing will provide support for
  36. * long term persistence.
  37. *
  38. * @version 1.27 02/02/00
  39. * @author Tom Santos
  40. */
  41. public class MetalSliderUI extends BasicSliderUI {
  42. protected final int TICK_BUFFER = 4;
  43. protected boolean filledSlider = false;
  44. protected static Color thumbColor;
  45. protected static Color highlightColor;
  46. protected static Color darkShadowColor;
  47. protected static int trackWidth;
  48. protected static int tickLength;
  49. protected static Icon horizThumbIcon;
  50. protected static Icon vertThumbIcon;
  51. protected final String SLIDER_FILL = "JSlider.isFilled";
  52. public static ComponentUI createUI(JComponent c) {
  53. return new MetalSliderUI();
  54. }
  55. public MetalSliderUI() {
  56. super( null );
  57. }
  58. public void installUI( JComponent c ) {
  59. trackWidth = ((Integer)UIManager.get( "Slider.trackWidth" )).intValue();
  60. tickLength = ((Integer)UIManager.get( "Slider.majorTickLength" )).intValue();
  61. horizThumbIcon = UIManager.getIcon( "Slider.horizontalThumbIcon" );
  62. vertThumbIcon = UIManager.getIcon( "Slider.verticalThumbIcon" );
  63. super.installUI( c );
  64. thumbColor = UIManager.getColor("Slider.thumb");
  65. highlightColor = UIManager.getColor("Slider.highlight");
  66. darkShadowColor = UIManager.getColor("Slider.darkShadow");
  67. scrollListener.setScrollByBlock( false );
  68. Object sliderFillProp = c.getClientProperty( SLIDER_FILL );
  69. if ( sliderFillProp != null ) {
  70. filledSlider = ((Boolean)sliderFillProp).booleanValue();
  71. }
  72. }
  73. protected PropertyChangeListener createPropertyChangeListener( JSlider slider ) {
  74. return new MetalPropertyListener();
  75. }
  76. protected class MetalPropertyListener extends BasicSliderUI.PropertyChangeHandler {
  77. public void propertyChange( PropertyChangeEvent e ) { // listen for slider fill
  78. super.propertyChange( e );
  79. String name = e.getPropertyName();
  80. if ( name.equals( SLIDER_FILL ) ) {
  81. if ( e.getNewValue() != null ) {
  82. filledSlider = ((Boolean)e.getNewValue()).booleanValue();
  83. }
  84. else {
  85. filledSlider = false;
  86. }
  87. }
  88. }
  89. }
  90. public void paintThumb(Graphics g) {
  91. Rectangle knobBounds = thumbRect;
  92. g.translate( knobBounds.x, knobBounds.y );
  93. if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  94. horizThumbIcon.paintIcon( slider, g, 0, 0 );
  95. }
  96. else {
  97. vertThumbIcon.paintIcon( slider, g, 0, 0 );
  98. }
  99. g.translate( -knobBounds.x, -knobBounds.y );
  100. }
  101. public void paintTrack(Graphics g) {
  102. Color trackColor = !slider.isEnabled() ? MetalLookAndFeel.getControlShadow() :
  103. slider.getForeground();
  104. boolean leftToRight = MetalUtils.isLeftToRight(slider);
  105. g.translate( trackRect.x, trackRect.y );
  106. int trackLeft = 0;
  107. int trackTop = 0;
  108. int trackRight = 0;
  109. int trackBottom = 0;
  110. // Draw the track
  111. if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  112. trackBottom = (trackRect.height - 1) - getThumbOverhang();
  113. trackTop = trackBottom - (getTrackWidth() - 1);
  114. trackRight = trackRect.width - 1;
  115. }
  116. else {
  117. if (leftToRight) {
  118. trackLeft = (trackRect.width - getThumbOverhang()) -
  119. getTrackWidth();
  120. trackRight = (trackRect.width - getThumbOverhang()) - 1;
  121. }
  122. else {
  123. trackLeft = getThumbOverhang();
  124. trackRight = getThumbOverhang() + getTrackWidth() - 1;
  125. }
  126. trackBottom = trackRect.height - 1;
  127. }
  128. if ( slider.isEnabled() ) {
  129. g.setColor( MetalLookAndFeel.getControlDarkShadow() );
  130. g.drawRect( trackLeft, trackTop,
  131. (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1 );
  132. g.setColor( MetalLookAndFeel.getControlHighlight() );
  133. g.drawLine( trackLeft + 1, trackBottom, trackRight, trackBottom );
  134. g.drawLine( trackRight, trackTop + 1, trackRight, trackBottom );
  135. g.setColor( MetalLookAndFeel.getControlShadow() );
  136. g.drawLine( trackLeft + 1, trackTop + 1, trackRight - 2, trackTop + 1 );
  137. g.drawLine( trackLeft + 1, trackTop + 1, trackLeft + 1, trackBottom - 2 );
  138. }
  139. else {
  140. g.setColor( MetalLookAndFeel.getControlShadow() );
  141. g.drawRect( trackLeft, trackTop,
  142. (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1 );
  143. }
  144. // Draw the fill
  145. if ( filledSlider ) {
  146. int middleOfThumb = 0;
  147. int fillTop = 0;
  148. int fillLeft = 0;
  149. int fillBottom = 0;
  150. int fillRight = 0;
  151. if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  152. middleOfThumb = thumbRect.x + (thumbRect.width / 2);
  153. middleOfThumb -= trackRect.x; // To compensate for the g.translate()
  154. fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
  155. fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;
  156. if ( !drawInverted() ) {
  157. fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
  158. fillRight = middleOfThumb;
  159. }
  160. else {
  161. fillLeft = middleOfThumb;
  162. fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;
  163. }
  164. }
  165. else {
  166. middleOfThumb = thumbRect.y + (thumbRect.height / 2);
  167. middleOfThumb -= trackRect.y; // To compensate for the g.translate()
  168. fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
  169. fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;
  170. if ( !drawInverted() ) {
  171. fillTop = middleOfThumb;
  172. fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;
  173. }
  174. else {
  175. fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
  176. fillBottom = middleOfThumb;
  177. }
  178. }
  179. if ( slider.isEnabled() ) {
  180. g.setColor( slider.getBackground() );
  181. g.drawLine( fillLeft, fillTop, fillRight, fillTop );
  182. g.drawLine( fillLeft, fillTop, fillLeft, fillBottom );
  183. g.setColor( MetalLookAndFeel.getControlShadow() );
  184. g.fillRect( fillLeft + 1, fillTop + 1,
  185. fillRight - fillLeft, fillBottom - fillTop );
  186. }
  187. else {
  188. g.setColor( MetalLookAndFeel.getControlShadow() );
  189. g.fillRect( fillLeft, fillTop,
  190. fillRight - fillLeft, trackBottom - trackTop );
  191. }
  192. }
  193. g.translate( -trackRect.x, -trackRect.y );
  194. }
  195. public void paintFocus(Graphics g) {
  196. }
  197. protected Dimension getThumbSize() {
  198. Dimension size = new Dimension();
  199. if ( slider.getOrientation() == JSlider.VERTICAL ) {
  200. size.width = 16;
  201. size.height = 15;
  202. }
  203. else {
  204. size.width = 15;
  205. size.height = 16;
  206. }
  207. return size;
  208. }
  209. /**
  210. * Gets the height of the tick area for horizontal sliders and the width of the
  211. * tick area for vertical sliders. BasicSliderUI uses the returned value to
  212. * determine the tick area rectangle.
  213. */
  214. public int getTickLength() {
  215. return slider.getOrientation() == JSlider.HORIZONTAL ? tickLength + TICK_BUFFER + 1 :
  216. tickLength + TICK_BUFFER + 3;
  217. }
  218. /**
  219. * Returns the shorter dimension of the track.
  220. */
  221. protected int getTrackWidth() {
  222. // This strange calculation is here to keep the
  223. // track in proportion to the thumb.
  224. final double kIdealTrackWidth = 7.0;
  225. final double kIdealThumbHeight = 16.0;
  226. final double kWidthScalar = kIdealTrackWidth / kIdealThumbHeight;
  227. if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  228. return (int)(kWidthScalar * thumbRect.height);
  229. }
  230. else {
  231. return (int)(kWidthScalar * thumbRect.width);
  232. }
  233. }
  234. /**
  235. * Returns the longer dimension of the slide bar. (The slide bar is only the
  236. * part that runs directly under the thumb)
  237. */
  238. protected int getTrackLength() {
  239. if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  240. return trackRect.width;
  241. }
  242. return trackRect.height;
  243. }
  244. /**
  245. * Returns the amount that the thumb goes past the slide bar.
  246. */
  247. protected int getThumbOverhang() {
  248. return 5;
  249. }
  250. protected void scrollDueToClickInTrack( int dir ) {
  251. scrollByUnit( dir );
  252. }
  253. protected void paintMinorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
  254. g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
  255. g.drawLine( x, TICK_BUFFER, x, TICK_BUFFER + (tickLength / 2) );
  256. }
  257. protected void paintMajorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
  258. g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
  259. g.drawLine( x, TICK_BUFFER , x, TICK_BUFFER + (tickLength - 1) );
  260. }
  261. protected void paintMinorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
  262. g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
  263. if (MetalUtils.isLeftToRight(slider)) {
  264. g.drawLine( TICK_BUFFER, y, TICK_BUFFER + (tickLength / 2), y );
  265. }
  266. else {
  267. g.drawLine( 0, y, tickLength2, y );
  268. }
  269. }
  270. protected void paintMajorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
  271. g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
  272. if (MetalUtils.isLeftToRight(slider)) {
  273. g.drawLine( TICK_BUFFER, y, TICK_BUFFER + tickLength, y );
  274. }
  275. else {
  276. g.drawLine( 0, y, tickLength, y );
  277. }
  278. }
  279. }