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