1. /*
  2. * @(#)MetalBumps.java 1.25 03/12/19
  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.metal;
  8. import java.awt.*;
  9. import java.awt.image.*;
  10. import javax.swing.*;
  11. import java.io.*;
  12. import java.util.*;
  13. /**
  14. * Implements the bumps used throughout the Metal Look and Feel.
  15. *
  16. * @version 1.25 12/19/03
  17. * @author Tom Santos
  18. * @author Steve Wilson
  19. */
  20. class MetalBumps implements Icon {
  21. static final Color ALPHA = new Color(0, 0, 0, 0);
  22. protected int xBumps;
  23. protected int yBumps;
  24. protected Color topColor;
  25. protected Color shadowColor;
  26. protected Color backColor;
  27. protected static Vector buffers = new Vector();
  28. protected BumpBuffer buffer;
  29. public MetalBumps( Dimension bumpArea ) {
  30. this( bumpArea.width, bumpArea.height );
  31. }
  32. public MetalBumps( int width, int height ) {
  33. this(width, height, MetalLookAndFeel.getPrimaryControlHighlight(),
  34. MetalLookAndFeel.getPrimaryControlDarkShadow(),
  35. MetalLookAndFeel.getPrimaryControlShadow());
  36. }
  37. /**
  38. * Creates MetalBumps of the specified size with the specified colors.
  39. * If <code>newBackColor</code> is null, the background will be
  40. * transparent.
  41. */
  42. public MetalBumps( int width, int height,
  43. Color newTopColor, Color newShadowColor, Color newBackColor ) {
  44. setBumpArea( width, height );
  45. setBumpColors( newTopColor, newShadowColor, newBackColor );
  46. }
  47. private BumpBuffer getBuffer(GraphicsConfiguration gc, Color aTopColor,
  48. Color aShadowColor, Color aBackColor) {
  49. if (buffer != null && buffer.hasSameConfiguration(
  50. gc, aTopColor, aShadowColor, aBackColor)) {
  51. return buffer;
  52. }
  53. BumpBuffer result = null;
  54. Enumeration elements = buffers.elements();
  55. while ( elements.hasMoreElements() ) {
  56. BumpBuffer aBuffer = (BumpBuffer)elements.nextElement();
  57. if ( aBuffer.hasSameConfiguration(gc, aTopColor, aShadowColor,
  58. aBackColor)) {
  59. result = aBuffer;
  60. break;
  61. }
  62. }
  63. if (result == null) {
  64. result = new BumpBuffer(gc, topColor, shadowColor, backColor);
  65. buffers.addElement(result);
  66. }
  67. return result;
  68. }
  69. public void setBumpArea( Dimension bumpArea ) {
  70. setBumpArea( bumpArea.width, bumpArea.height );
  71. }
  72. public void setBumpArea( int width, int height ) {
  73. xBumps = width / 2;
  74. yBumps = height / 2;
  75. }
  76. public void setBumpColors( Color newTopColor, Color newShadowColor, Color newBackColor ) {
  77. topColor = newTopColor;
  78. shadowColor = newShadowColor;
  79. if (newBackColor == null) {
  80. backColor = ALPHA;
  81. }
  82. else {
  83. backColor = newBackColor;
  84. }
  85. }
  86. public void paintIcon( Component c, Graphics g, int x, int y ) {
  87. GraphicsConfiguration gc = (g instanceof Graphics2D) ?
  88. (GraphicsConfiguration)((Graphics2D)g).
  89. getDeviceConfiguration() : null;
  90. buffer = getBuffer(gc, topColor, shadowColor, backColor);
  91. int bufferWidth = buffer.getImageSize().width;
  92. int bufferHeight = buffer.getImageSize().height;
  93. int iconWidth = getIconWidth();
  94. int iconHeight = getIconHeight();
  95. int x2 = x + iconWidth;
  96. int y2 = y + iconHeight;
  97. int savex = x;
  98. while (y < y2) {
  99. int h = Math.min(y2 - y, bufferHeight);
  100. for (x = savex; x < x2; x += bufferWidth) {
  101. int w = Math.min(x2 - x, bufferWidth);
  102. g.drawImage(buffer.getImage(),
  103. x, y, x+w, y+h,
  104. 0, 0, w, h,
  105. null);
  106. }
  107. y += bufferHeight;
  108. }
  109. }
  110. public int getIconWidth() {
  111. return xBumps * 2;
  112. }
  113. public int getIconHeight() {
  114. return yBumps * 2;
  115. }
  116. }
  117. class BumpBuffer {
  118. static final int IMAGE_SIZE = 64;
  119. static Dimension imageSize = new Dimension( IMAGE_SIZE, IMAGE_SIZE );
  120. transient Image image;
  121. Color topColor;
  122. Color shadowColor;
  123. Color backColor;
  124. private GraphicsConfiguration gc;
  125. public BumpBuffer(GraphicsConfiguration gc, Color aTopColor,
  126. Color aShadowColor, Color aBackColor) {
  127. this.gc = gc;
  128. topColor = aTopColor;
  129. shadowColor = aShadowColor;
  130. backColor = aBackColor;
  131. createImage();
  132. fillBumpBuffer();
  133. }
  134. public boolean hasSameConfiguration(GraphicsConfiguration gc,
  135. Color aTopColor, Color aShadowColor,
  136. Color aBackColor) {
  137. if (this.gc != null) {
  138. if (!this.gc.equals(gc)) {
  139. return false;
  140. }
  141. }
  142. else if (gc != null) {
  143. return false;
  144. }
  145. return topColor.equals( aTopColor ) &&
  146. shadowColor.equals( aShadowColor ) &&
  147. backColor.equals( aBackColor );
  148. }
  149. /**
  150. * Returns the Image containing the bumps appropriate for the passed in
  151. * <code>GraphicsConfiguration</code>.
  152. */
  153. public Image getImage() {
  154. return image;
  155. }
  156. public Dimension getImageSize() {
  157. return imageSize;
  158. }
  159. /**
  160. * Paints the bumps into the current image.
  161. */
  162. private void fillBumpBuffer() {
  163. Graphics g = image.getGraphics();
  164. g.setColor( backColor );
  165. g.fillRect( 0, 0, IMAGE_SIZE, IMAGE_SIZE );
  166. g.setColor(topColor);
  167. for (int x = 0; x < IMAGE_SIZE; x+=4) {
  168. for (int y = 0; y < IMAGE_SIZE; y+=4) {
  169. g.drawLine( x, y, x, y );
  170. g.drawLine( x+2, y+2, x+2, y+2);
  171. }
  172. }
  173. g.setColor(shadowColor);
  174. for (int x = 0; x < IMAGE_SIZE; x+=4) {
  175. for (int y = 0; y < IMAGE_SIZE; y+=4) {
  176. g.drawLine( x+1, y+1, x+1, y+1 );
  177. g.drawLine( x+3, y+3, x+3, y+3);
  178. }
  179. }
  180. g.dispose();
  181. }
  182. /**
  183. * Creates the image appropriate for the passed in
  184. * <code>GraphicsConfiguration</code>, which may be null.
  185. */
  186. private void createImage() {
  187. if (gc != null) {
  188. image = gc.createCompatibleImage(IMAGE_SIZE, IMAGE_SIZE,
  189. (backColor != MetalBumps.ALPHA) ? Transparency.OPAQUE :
  190. Transparency.BITMASK);
  191. }
  192. else {
  193. int cmap[] = { backColor.getRGB(), topColor.getRGB(),
  194. shadowColor.getRGB() };
  195. IndexColorModel icm = new IndexColorModel(8, 3, cmap, 0, false,
  196. (backColor == MetalBumps.ALPHA) ? 0 : -1,
  197. DataBuffer.TYPE_BYTE);
  198. image = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE,
  199. BufferedImage.TYPE_BYTE_INDEXED, icm);
  200. }
  201. }
  202. }