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