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