1. /*
  2. * @(#)BasicGraphicsUtils.java 1.61 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.basic;
  8. import javax.swing.*;
  9. import java.awt.Component;
  10. import java.awt.Color;
  11. import java.awt.Dimension;
  12. import java.awt.Font;
  13. import java.awt.FontMetrics;
  14. import java.awt.Graphics;
  15. import java.awt.Insets;
  16. import java.awt.Rectangle;
  17. import java.awt.event.KeyEvent;
  18. import com.sun.java.swing.SwingUtilities2;
  19. /*
  20. * @version 1.44 02/11/99
  21. * @author Hans Muller
  22. */
  23. public class BasicGraphicsUtils
  24. {
  25. private static final Insets GROOVE_INSETS = new Insets(2, 2, 2, 2);
  26. private static final Insets ETCHED_INSETS = new Insets(2, 2, 2, 2);
  27. public static void drawEtchedRect(Graphics g, int x, int y, int w, int h,
  28. Color shadow, Color darkShadow,
  29. Color highlight, Color lightHighlight)
  30. {
  31. Color oldColor = g.getColor(); // Make no net change to g
  32. g.translate(x, y);
  33. g.setColor(shadow);
  34. g.drawLine(0, 0, w-1, 0); // outer border, top
  35. g.drawLine(0, 1, 0, h-2); // outer border, left
  36. g.setColor(darkShadow);
  37. g.drawLine(1, 1, w-3, 1); // inner border, top
  38. g.drawLine(1, 2, 1, h-3); // inner border, left
  39. g.setColor(lightHighlight);
  40. g.drawLine(w-1, 0, w-1, h-1); // outer border, bottom
  41. g.drawLine(0, h-1, w-1, h-1); // outer border, right
  42. g.setColor(highlight);
  43. g.drawLine(w-2, 1, w-2, h-3); // inner border, right
  44. g.drawLine(1, h-2, w-2, h-2); // inner border, bottom
  45. g.translate(-x, -y);
  46. g.setColor(oldColor);
  47. }
  48. /**
  49. * Returns the amount of space taken up by a border drawn by
  50. * <code>drawEtchedRect()</code>
  51. *
  52. * @return the inset of an etched rect
  53. */
  54. public static Insets getEtchedInsets() {
  55. return ETCHED_INSETS;
  56. }
  57. public static void drawGroove(Graphics g, int x, int y, int w, int h,
  58. Color shadow, Color highlight)
  59. {
  60. Color oldColor = g.getColor(); // Make no net change to g
  61. g.translate(x, y);
  62. g.setColor(shadow);
  63. g.drawRect(0, 0, w-2, h-2);
  64. g.setColor(highlight);
  65. g.drawLine(1, h-3, 1, 1);
  66. g.drawLine(1, 1, w-3, 1);
  67. g.drawLine(0, h-1, w-1, h-1);
  68. g.drawLine(w-1, h-1, w-1, 0);
  69. g.translate(-x, -y);
  70. g.setColor(oldColor);
  71. }
  72. /**
  73. * Returns the amount of space taken up by a border drawn by
  74. * <code>drawGroove()</code>
  75. *
  76. * @return the inset of a groove border
  77. */
  78. public static Insets getGrooveInsets() {
  79. return GROOVE_INSETS;
  80. }
  81. public static void drawBezel(Graphics g, int x, int y, int w, int h,
  82. boolean isPressed, boolean isDefault,
  83. Color shadow, Color darkShadow,
  84. Color highlight, Color lightHighlight)
  85. {
  86. Color oldColor = g.getColor(); // Make no net change to g
  87. g.translate(x, y);
  88. if (isPressed && isDefault) {
  89. g.setColor(darkShadow);
  90. g.drawRect(0, 0, w - 1, h - 1);
  91. g.setColor(shadow);
  92. g.drawRect(1, 1, w - 3, h - 3);
  93. } else if (isPressed) {
  94. drawLoweredBezel(g, x, y, w, h,
  95. shadow, darkShadow, highlight, lightHighlight);
  96. } else if (isDefault) {
  97. g.setColor(darkShadow);
  98. g.drawRect(0, 0, w-1, h-1);
  99. g.setColor(lightHighlight);
  100. g.drawLine(1, 1, 1, h-3);
  101. g.drawLine(2, 1, w-3, 1);
  102. g.setColor(highlight);
  103. g.drawLine(2, 2, 2, h-4);
  104. g.drawLine(3, 2, w-4, 2);
  105. g.setColor(shadow);
  106. g.drawLine(2, h-3, w-3, h-3);
  107. g.drawLine(w-3, 2, w-3, h-4);
  108. g.setColor(darkShadow);
  109. g.drawLine(1, h-2, w-2, h-2);
  110. g.drawLine(w-2, h-2, w-2, 1);
  111. } else {
  112. g.setColor(lightHighlight);
  113. g.drawLine(0, 0, 0, h-1);
  114. g.drawLine(1, 0, w-2, 0);
  115. g.setColor(highlight);
  116. g.drawLine(1, 1, 1, h-3);
  117. g.drawLine(2, 1, w-3, 1);
  118. g.setColor(shadow);
  119. g.drawLine(1, h-2, w-2, h-2);
  120. g.drawLine(w-2, 1, w-2, h-3);
  121. g.setColor(darkShadow);
  122. g.drawLine(0, h-1, w-1, h-1);
  123. g.drawLine(w-1, h-1, w-1, 0);
  124. }
  125. g.translate(-x, -y);
  126. g.setColor(oldColor);
  127. }
  128. public static void drawLoweredBezel(Graphics g, int x, int y, int w, int h,
  129. Color shadow, Color darkShadow,
  130. Color highlight, Color lightHighlight) {
  131. g.setColor(darkShadow);
  132. g.drawLine(0, 0, 0, h-1);
  133. g.drawLine(1, 0, w-2, 0);
  134. g.setColor(shadow);
  135. g.drawLine(1, 1, 1, h-2);
  136. g.drawLine(1, 1, w-3, 1);
  137. g.setColor(lightHighlight);
  138. g.drawLine(0, h-1, w-1, h-1);
  139. g.drawLine(w-1, h-1, w-1, 0);
  140. g.setColor(highlight);
  141. g.drawLine(1, h-2, w-2, h-2);
  142. g.drawLine(w-2, h-2, w-2, 1);
  143. }
  144. /** Draw a string with the graphics <code>g</code> at location (x,y)
  145. * just like <code>g.drawString</code> would.
  146. * The first occurrence of <code>underlineChar</code>
  147. * in text will be underlined. The matching algorithm is
  148. * not case sensitive.
  149. */
  150. public static void drawString(Graphics g,String text,int underlinedChar,int x,int y) {
  151. int index=-1;
  152. if (underlinedChar != '\0') {
  153. char uc = Character.toUpperCase((char)underlinedChar);
  154. char lc = Character.toLowerCase((char)underlinedChar);
  155. int uci = text.indexOf(uc);
  156. int lci = text.indexOf(lc);
  157. if(uci == -1) {
  158. index = lci;
  159. }
  160. else if(lci == -1) {
  161. index = uci;
  162. }
  163. else {
  164. index = (lci < uci) ? lci : uci;
  165. }
  166. }
  167. drawStringUnderlineCharAt(g, text, index, x, y);
  168. }
  169. /**
  170. * Draw a string with the graphics <code>g</code> at location
  171. * (<code>x</code>, <code>y</code>)
  172. * just like <code>g.drawString</code> would.
  173. * The character at index <code>underlinedIndex</code>
  174. * in text will be underlined. If <code>index</code> is beyond the
  175. * bounds of <code>text</code> (including < 0), nothing will be
  176. * underlined.
  177. *
  178. * @param g Graphics to draw with
  179. * @param text String to draw
  180. * @param underlinedIndex Index of character in text to underline
  181. * @param x x coordinate to draw at
  182. * @param y y coordinate to draw at
  183. * @since 1.4
  184. */
  185. public static void drawStringUnderlineCharAt(Graphics g, String text,
  186. int underlinedIndex, int x,int y) {
  187. SwingUtilities2.drawStringUnderlineCharAt(null, g, text,
  188. underlinedIndex, x, y);
  189. }
  190. public static void drawDashedRect(Graphics g,int x,int y,int width,int height) {
  191. int vx,vy;
  192. // draw upper and lower horizontal dashes
  193. for (vx = x; vx < (x + width); vx+=2) {
  194. g.fillRect(vx, y, 1, 1);
  195. g.fillRect(vx, y + height-1, 1, 1);
  196. }
  197. // draw left and right vertical dashes
  198. for (vy = y; vy < (y + height); vy+=2) {
  199. g.fillRect(x, vy, 1, 1);
  200. g.fillRect(x+width-1, vy, 1, 1);
  201. }
  202. }
  203. public static Dimension getPreferredButtonSize(AbstractButton b, int textIconGap)
  204. {
  205. if(b.getComponentCount() > 0) {
  206. return null;
  207. }
  208. Icon icon = (Icon) b.getIcon();
  209. String text = b.getText();
  210. Font font = b.getFont();
  211. FontMetrics fm = b.getFontMetrics(font);
  212. Rectangle iconR = new Rectangle();
  213. Rectangle textR = new Rectangle();
  214. Rectangle viewR = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE);
  215. SwingUtilities.layoutCompoundLabel(
  216. (JComponent) b, fm, text, icon,
  217. b.getVerticalAlignment(), b.getHorizontalAlignment(),
  218. b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
  219. viewR, iconR, textR, (text == null ? 0 : textIconGap)
  220. );
  221. /* The preferred size of the button is the size of
  222. * the text and icon rectangles plus the buttons insets.
  223. */
  224. Rectangle r = iconR.union(textR);
  225. Insets insets = b.getInsets();
  226. r.width += insets.left + insets.right;
  227. r.height += insets.top + insets.bottom;
  228. return r.getSize();
  229. }
  230. /*
  231. * Convenience function for determining ComponentOrientation. Helps us
  232. * avoid having Munge directives throughout the code.
  233. */
  234. static boolean isLeftToRight( Component c ) {
  235. return c.getComponentOrientation().isLeftToRight();
  236. }
  237. }