1. /*
  2. * @(#)MetalScrollBarUI.java 1.22 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.plaf.metal;
  8. import java.awt.Component;
  9. import java.awt.Container;
  10. import java.awt.LayoutManager;
  11. import java.awt.Adjustable;
  12. import java.awt.event.AdjustmentListener;
  13. import java.awt.event.AdjustmentEvent;
  14. import java.awt.event.ActionListener;
  15. import java.awt.event.ActionEvent;
  16. import java.awt.event.MouseListener;
  17. import java.awt.event.MouseMotionListener;
  18. import java.awt.event.MouseAdapter;
  19. import java.awt.event.MouseEvent;
  20. import java.awt.Graphics;
  21. import java.awt.Dimension;
  22. import java.awt.Rectangle;
  23. import java.awt.Point;
  24. import java.awt.Insets;
  25. import java.awt.Color;
  26. import java.awt.IllegalComponentStateException;
  27. import java.beans.*;
  28. import javax.swing.*;
  29. import javax.swing.event.*;
  30. import javax.swing.plaf.*;
  31. import javax.swing.plaf.basic.BasicScrollBarUI;
  32. /**
  33. * Implementation of ScrollBarUI for the Metal Look and Feel
  34. * <p>
  35. *
  36. * @version 1.22 11/29/01
  37. * @author Tom Santos
  38. * @author Steve Wilson
  39. */
  40. public class MetalScrollBarUI extends BasicScrollBarUI
  41. {
  42. private static Color shadowColor;
  43. private static Color highlightColor;
  44. private static Color darkShadowColor;
  45. private static Color thumbColor;
  46. private static Color thumbShadow;
  47. private static Color thumbHighlightColor;
  48. protected MetalBumps bumps;
  49. protected MetalScrollButton increaseButton;
  50. protected MetalScrollButton decreaseButton;
  51. protected int scrollBarWidth;
  52. public static final String FREE_STANDING_PROP = "JScrollBar.isFreeStanding";
  53. protected boolean isFreeStanding = true;
  54. public static ComponentUI createUI( JComponent c )
  55. {
  56. return new MetalScrollBarUI();
  57. }
  58. protected void installDefaults() {
  59. scrollBarWidth = ((Integer)(UIManager.get( "ScrollBar.width" ))).intValue();
  60. if (scrollbar.getBackground() == null || scrollbar.getBackground() instanceof UIResource)
  61. scrollbar.setBackground(UIManager.getColor("ScrollBar.background"));
  62. super.installDefaults();
  63. bumps = new MetalBumps( 10, 10, thumbHighlightColor, thumbShadow, thumbColor );
  64. }
  65. protected void installListeners(){
  66. super.installListeners();
  67. ((ScrollBarListener)propertyChangeListener).handlePropertyChange( scrollbar.getClientProperty( FREE_STANDING_PROP ) );
  68. }
  69. protected PropertyChangeListener createPropertyChangeListener(){
  70. return new ScrollBarListener();
  71. }
  72. protected void configureScrollBarColors()
  73. {
  74. shadowColor = UIManager.getColor("ScrollBar.shadow");
  75. highlightColor = UIManager.getColor("ScrollBar.highlight");
  76. darkShadowColor = UIManager.getColor("ScrollBar.darkShadow");
  77. thumbColor = UIManager.getColor("ScrollBar.thumb");
  78. thumbShadow = UIManager.getColor("ScrollBar.thumbShadow");
  79. thumbHighlightColor = UIManager.getColor("ScrollBar.thumbHighlight");
  80. }
  81. public Dimension getPreferredSize( JComponent c )
  82. {
  83. if ( scrollbar.getOrientation() == JScrollBar.VERTICAL )
  84. {
  85. return new Dimension( scrollBarWidth, scrollBarWidth * 3 + 10 );
  86. }
  87. else // Horizontal
  88. {
  89. return new Dimension( scrollBarWidth * 3 + 10, scrollBarWidth );
  90. }
  91. }
  92. /** Returns the view that represents the decrease view.
  93. */
  94. protected JButton createDecreaseButton( int orientation )
  95. {
  96. decreaseButton = new MetalScrollButton( orientation, scrollBarWidth, isFreeStanding );
  97. return decreaseButton;
  98. }
  99. /** Returns the view that represents the increase view. */
  100. protected JButton createIncreaseButton( int orientation )
  101. {
  102. increaseButton = new MetalScrollButton( orientation, scrollBarWidth, isFreeStanding );
  103. return increaseButton;
  104. }
  105. protected void paintTrack( Graphics g, JComponent c, Rectangle trackBounds )
  106. {
  107. g.translate( trackBounds.x, trackBounds.y );
  108. if ( scrollbar.getOrientation() == JScrollBar.VERTICAL )
  109. {
  110. if ( !isFreeStanding ) {
  111. trackBounds.width += 2;
  112. }
  113. if ( c.isEnabled() ) {
  114. g.setColor( darkShadowColor );
  115. g.drawLine( 0, 0, 0, trackBounds.height - 1 );
  116. g.drawLine( trackBounds.width - 2, 0, trackBounds.width - 2, trackBounds.height - 1 );
  117. g.drawLine( 2, trackBounds.height - 1, trackBounds.width - 1, trackBounds.height - 1);
  118. g.drawLine( 2, 0, trackBounds.width - 2, 0 );
  119. g.setColor( shadowColor );
  120. // g.setColor( Color.red);
  121. g.drawLine( 1, 1, 1, trackBounds.height - 2 );
  122. g.drawLine( 1, 1, trackBounds.width - 3, 1 );
  123. if (scrollbar.getValue() != scrollbar.getMaximum()) { // thumb shadow
  124. int y = thumbRect.y + thumbRect.height - trackBounds.y;
  125. g.drawLine( 1, y, trackBounds.width-1, y);
  126. }
  127. g.setColor(highlightColor);
  128. g.drawLine( trackBounds.width - 1, 0, trackBounds.width - 1, trackBounds.height - 1 );
  129. } else {
  130. MetalUtils.drawDisabledBorder(g, 0, 0, trackBounds.width, trackBounds.height );
  131. }
  132. if ( !isFreeStanding ) {
  133. trackBounds.width -= 2;
  134. }
  135. }
  136. else // HORIZONTAL
  137. {
  138. if ( !isFreeStanding ) {
  139. trackBounds.height += 2;
  140. }
  141. if ( c.isEnabled() ) {
  142. g.setColor( darkShadowColor );
  143. g.drawLine( 0, 0, trackBounds.width - 1, 0 ); // top
  144. g.drawLine( 0, 2, 0, trackBounds.height - 2 ); // left
  145. g.drawLine( 0, trackBounds.height - 2, trackBounds.width - 1, trackBounds.height - 2 ); // bottom
  146. g.drawLine( trackBounds.width - 1, 2, trackBounds.width - 1, trackBounds.height - 1 ); // right
  147. g.setColor( shadowColor );
  148. // g.setColor( Color.red);
  149. g.drawLine( 1, 1, trackBounds.width - 2, 1 ); // top
  150. g.drawLine( 1, 1, 1, trackBounds.height - 3 ); // left
  151. g.drawLine( 0, trackBounds.height - 1, trackBounds.width - 1, trackBounds.height - 1 ); // bottom
  152. if (scrollbar.getValue() != scrollbar.getMaximum()) { // thumb shadow
  153. int x = thumbRect.x + thumbRect.width - trackBounds.x;
  154. g.drawLine( x, 1, x, trackBounds.height-1);
  155. }
  156. } else {
  157. MetalUtils.drawDisabledBorder(g, 0, 0, trackBounds.width, trackBounds.height );
  158. }
  159. if ( !isFreeStanding ) {
  160. trackBounds.height -= 2;
  161. }
  162. }
  163. g.translate( -trackBounds.x, -trackBounds.y );
  164. }
  165. protected void paintThumb( Graphics g, JComponent c, Rectangle thumbBounds )
  166. {
  167. if (!c.isEnabled()) {
  168. return;
  169. }
  170. g.translate( thumbBounds.x, thumbBounds.y );
  171. if ( scrollbar.getOrientation() == JScrollBar.VERTICAL )
  172. {
  173. if ( !isFreeStanding ) {
  174. thumbBounds.width += 2;
  175. }
  176. g.setColor( thumbColor );
  177. g.fillRect( 0, 0, thumbBounds.width - 2, thumbBounds.height - 1 );
  178. g.setColor( thumbShadow );
  179. g.drawRect( 0, 0, thumbBounds.width - 2, thumbBounds.height - 1 );
  180. g.setColor( thumbHighlightColor );
  181. g.drawLine( 1, 1, thumbBounds.width - 3, 1 );
  182. g.drawLine( 1, 1, 1, thumbBounds.height - 2 );
  183. bumps.setBumpArea( thumbBounds.width - 6, thumbBounds.height - 7 );
  184. bumps.paintIcon( c, g, 3, 4 );
  185. if ( !isFreeStanding ) {
  186. thumbBounds.width -= 2;
  187. }
  188. }
  189. else // HORIZONTAL
  190. {
  191. if ( !isFreeStanding ) {
  192. thumbBounds.height += 2;
  193. }
  194. g.setColor( thumbColor );
  195. g.fillRect( 0, 0, thumbBounds.width - 1, thumbBounds.height - 2 );
  196. g.setColor( thumbShadow );
  197. g.drawRect( 0, 0, thumbBounds.width - 1, thumbBounds.height - 2 );
  198. g.setColor( thumbHighlightColor );
  199. g.drawLine( 1, 1, thumbBounds.width - 3, 1 );
  200. g.drawLine( 1, 1, 1, thumbBounds.height - 3 );
  201. bumps.setBumpArea( thumbBounds.width - 7, thumbBounds.height - 6 );
  202. bumps.paintIcon( c, g, 4, 3 );
  203. if ( !isFreeStanding ) {
  204. thumbBounds.height -= 2;
  205. }
  206. }
  207. g.translate( -thumbBounds.x, -thumbBounds.y );
  208. }
  209. protected Dimension getMinimumThumbSize()
  210. {
  211. return new Dimension( scrollBarWidth, scrollBarWidth );
  212. }
  213. /**
  214. * This is overridden only to increase the invalid area. This
  215. * ensures that the "Shadow" below the thumb is invalidated
  216. */
  217. protected void setThumbBounds(int x, int y, int width, int height)
  218. {
  219. /* If the thumbs bounds haven't changed, we're done.
  220. */
  221. if ((thumbRect.x == x) &&
  222. (thumbRect.y == y) &&
  223. (thumbRect.width == width) &&
  224. (thumbRect.height == height)) {
  225. return;
  226. }
  227. /* Update thumbRect, and repaint the union of x,y,w,h and
  228. * the old thumbRect.
  229. */
  230. int minX = Math.min(x, thumbRect.x);
  231. int minY = Math.min(y, thumbRect.y);
  232. int maxX = Math.max(x + width, thumbRect.x + thumbRect.width);
  233. int maxY = Math.max(y + height, thumbRect.y + thumbRect.height);
  234. thumbRect.setBounds(x, y, width, height);
  235. scrollbar.repaint(minX, minY, (maxX - minX)+1, (maxY - minY)+1);
  236. }
  237. class ScrollBarListener extends BasicScrollBarUI.PropertyChangeHandler
  238. {
  239. public void propertyChange(PropertyChangeEvent e)
  240. {
  241. String name = e.getPropertyName();
  242. if ( name.equals( FREE_STANDING_PROP ) )
  243. {
  244. handlePropertyChange( e.getNewValue() );
  245. }
  246. else {
  247. super.propertyChange( e );
  248. }
  249. }
  250. public void handlePropertyChange( Object newValue )
  251. {
  252. if ( newValue != null )
  253. {
  254. boolean temp = ((Boolean)newValue).booleanValue();
  255. boolean becameFlush = temp == false && isFreeStanding == true;
  256. boolean becameNormal = temp == true && isFreeStanding == false;
  257. isFreeStanding = temp;
  258. if ( becameFlush ) {
  259. toFlush();
  260. }
  261. else if ( becameNormal ) {
  262. toFreeStanding();
  263. }
  264. }
  265. else
  266. {
  267. if ( !isFreeStanding ) {
  268. isFreeStanding = true;
  269. toFreeStanding();
  270. }
  271. // This commented-out block is used for testing flush scrollbars.
  272. /*
  273. if ( isFreeStanding ) {
  274. isFreeStanding = false;
  275. toFlush();
  276. }
  277. */
  278. }
  279. if ( increaseButton != null )
  280. {
  281. increaseButton.setFreeStanding( isFreeStanding );
  282. }
  283. if ( decreaseButton != null )
  284. {
  285. decreaseButton.setFreeStanding( isFreeStanding );
  286. }
  287. }
  288. protected void toFlush() {
  289. scrollBarWidth -= 2;
  290. }
  291. protected void toFreeStanding() {
  292. scrollBarWidth += 2;
  293. }
  294. } // end class ScrollBarListener
  295. }