1. /*
  2. * @(#)MatteBorder.java 1.22 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.border;
  8. import java.awt.Graphics;
  9. import java.awt.Insets;
  10. import java.awt.Rectangle;
  11. import java.awt.Component;
  12. import java.awt.Color;
  13. import javax.swing.Icon;
  14. /**
  15. * A class which provides a matte-like border of either a solid color
  16. * or a tiled icon.
  17. * <p>
  18. * <strong>Warning:</strong>
  19. * Serialized objects of this class will not be compatible with
  20. * future Swing releases. The current serialization support is
  21. * appropriate for short term storage or RMI between applications running
  22. * the same version of Swing. As of 1.4, support for long term storage
  23. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  24. * has been added to the <code>java.beans</code> package.
  25. * Please see {@link java.beans.XMLEncoder}.
  26. *
  27. * @version 1.22 12/19/03
  28. * @author Amy Fowler
  29. */
  30. public class MatteBorder extends EmptyBorder
  31. {
  32. protected Color color;
  33. protected Icon tileIcon;
  34. /**
  35. * Creates a matte border with the specified insets and color.
  36. * @param top the top inset of the border
  37. * @param left the left inset of the border
  38. * @param bottom the bottom inset of the border
  39. * @param right the right inset of the border
  40. * @param matteColor the color rendered for the border
  41. */
  42. public MatteBorder(int top, int left, int bottom, int right, Color matteColor) {
  43. super(top, left, bottom, right);
  44. this.color = matteColor;
  45. }
  46. /**
  47. * Creates a matte border with the specified insets and color.
  48. * @param borderInsets the insets of the border
  49. * @param matteColor the color rendered for the border
  50. */
  51. public MatteBorder(Insets borderInsets, Color matteColor) {
  52. super(borderInsets);
  53. this.color = matteColor;
  54. }
  55. /**
  56. * Creates a matte border with the specified insets and tile icon.
  57. * @param top the top inset of the border
  58. * @param left the left inset of the border
  59. * @param bottom the bottom inset of the border
  60. * @param right the right inset of the border
  61. * @param tileIcon the icon to be used for tiling the border
  62. */
  63. public MatteBorder(int top, int left, int bottom, int right, Icon tileIcon) {
  64. super(top, left, bottom, right);
  65. this.tileIcon = tileIcon;
  66. }
  67. /**
  68. * Creates a matte border with the specified insets and tile icon.
  69. * @param borderInsets the insets of the border
  70. * @param tileIcon the icon to be used for tiling the border
  71. */
  72. public MatteBorder(Insets borderInsets, Icon tileIcon) {
  73. super(borderInsets);
  74. this.tileIcon = tileIcon;
  75. }
  76. /**
  77. * Creates a matte border with the specified tile icon. The
  78. * insets will be calculated dynamically based on the size of
  79. * the tile icon, where the top and bottom will be equal to the
  80. * tile icon's height, and the left and right will be equal to
  81. * the tile icon's width.
  82. * @param tileIcon the icon to be used for tiling the border
  83. */
  84. public MatteBorder(Icon tileIcon) {
  85. this(-1,-1,-1,-1, tileIcon);
  86. }
  87. /**
  88. * Paints the matte border.
  89. */
  90. public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
  91. Insets insets = getBorderInsets(c);
  92. Color oldColor = g.getColor();
  93. g.translate(x, y);
  94. // If the tileIcon failed loading, paint as gray.
  95. if (tileIcon != null) {
  96. color = (tileIcon.getIconWidth() == -1) ? Color.gray : null;
  97. }
  98. if (color != null) {
  99. g.setColor(color);
  100. g.fillRect(0, 0, width - insets.right, insets.top);
  101. g.fillRect(0, insets.top, insets.left, height - insets.top);
  102. g.fillRect(insets.left, height - insets.bottom, width - insets.left, insets.bottom);
  103. g.fillRect(width - insets.right, 0, insets.right, height - insets.bottom);
  104. } else if (tileIcon != null) {
  105. int tileW = tileIcon.getIconWidth();
  106. int tileH = tileIcon.getIconHeight();
  107. int xpos, ypos, startx, starty;
  108. Graphics cg;
  109. // Paint top matte edge
  110. cg = g.create();
  111. cg.setClip(0, 0, width, insets.top);
  112. for (ypos = 0; insets.top - ypos > 0; ypos += tileH) {
  113. for (xpos = 0; width - xpos > 0; xpos += tileW) {
  114. tileIcon.paintIcon(c, cg, xpos, ypos);
  115. }
  116. }
  117. cg.dispose();
  118. // Paint left matte edge
  119. cg = g.create();
  120. cg.setClip(0, insets.top, insets.left, height - insets.top);
  121. starty = insets.top - (insets.top%tileH);
  122. startx = 0;
  123. for (ypos = starty; height - ypos > 0; ypos += tileH) {
  124. for (xpos = startx; insets.left - xpos > 0; xpos += tileW) {
  125. tileIcon.paintIcon(c, cg, xpos, ypos);
  126. }
  127. }
  128. cg.dispose();
  129. // Paint bottom matte edge
  130. cg = g.create();
  131. cg.setClip(insets.left, height - insets.bottom, width - insets.left, insets.bottom);
  132. starty = (height - insets.bottom) - ((height - insets.bottom)%tileH);
  133. startx = insets.left - (insets.left%tileW);
  134. for (ypos = starty; height - ypos > 0; ypos += tileH) {
  135. for (xpos = startx; width - xpos > 0; xpos += tileW) {
  136. tileIcon.paintIcon(c, cg, xpos, ypos);
  137. }
  138. }
  139. cg.dispose();
  140. // Paint right matte edge
  141. cg = g.create();
  142. cg.setClip(width - insets.right, insets.top, insets.right, height - insets.top - insets.bottom);
  143. starty = insets.top - (insets.top%tileH);
  144. startx = width - insets.right - ((width - insets.right)%tileW);
  145. for (ypos = starty; height - ypos > 0; ypos += tileH) {
  146. for (xpos = startx; width - xpos > 0; xpos += tileW) {
  147. tileIcon.paintIcon(c, cg, xpos, ypos);
  148. }
  149. }
  150. cg.dispose();
  151. }
  152. g.translate(-x, -y);
  153. g.setColor(oldColor);
  154. }
  155. /**
  156. * Returns the insets of the border.
  157. * @param c the component for which this border insets value applies
  158. */
  159. public Insets getBorderInsets(Component c) {
  160. return getBorderInsets();
  161. }
  162. /**
  163. * Reinitialize the insets parameter with this Border's current Insets.
  164. * @param c the component for which this border insets value applies
  165. * @param insets the object to be reinitialized
  166. */
  167. public Insets getBorderInsets(Component c, Insets insets) {
  168. return computeInsets(insets);
  169. }
  170. /**
  171. * Returns the insets of the border.
  172. */
  173. public Insets getBorderInsets() {
  174. return computeInsets(new Insets(0,0,0,0));
  175. }
  176. /* should be protected once api changes area allowed */
  177. private Insets computeInsets(Insets insets) {
  178. if (tileIcon != null && top == -1 && bottom == -1 &&
  179. left == -1 && right == -1) {
  180. int w = tileIcon.getIconWidth();
  181. int h = tileIcon.getIconHeight();
  182. insets.top = h;
  183. insets.right = w;
  184. insets.bottom = h;
  185. insets.left = w;
  186. } else {
  187. insets.left = left;
  188. insets.top = top;
  189. insets.right = right;
  190. insets.bottom = bottom;
  191. }
  192. return insets;
  193. }
  194. /**
  195. * Returns the color used for tiling the border or null
  196. * if a tile icon is being used.
  197. */
  198. public Color getMatteColor() {
  199. return color;
  200. }
  201. /**
  202. * Returns the icon used for tiling the border or null
  203. * if a solid color is being used.
  204. */
  205. public Icon getTileIcon() {
  206. return tileIcon;
  207. }
  208. /**
  209. * Returns whether or not the border is opaque.
  210. */
  211. public boolean isBorderOpaque() {
  212. // If a tileIcon is set, then it may contain transparent bits
  213. return color != null;
  214. }
  215. }