1. /*
  2. * @(#)BasicGraphicsUtils.java 1.46 01/11/29
  3. *
  4. * Copyright 2002 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.46 11/29/01
  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) {
  88. if (isDefault) {
  89. g.setColor(darkShadow); // outer border
  90. g.drawRect(0, 0, w-1, h-1);
  91. }
  92. g.setColor(shadow); // inner border
  93. g.drawRect(1, 1, w-3, h-3);
  94. }
  95. else {
  96. 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. }
  112. else {
  113. g.setColor(lightHighlight);
  114. g.drawLine(0, 0, 0, h-1);
  115. g.drawLine(1, 0, w-2, 0);
  116. g.setColor(highlight);
  117. g.drawLine(1, 1, 1, h-3);
  118. g.drawLine(2, 1, w-3, 1);
  119. g.setColor(shadow);
  120. g.drawLine(1, h-2, w-2, h-2);
  121. g.drawLine(w-2, 1, w-2, h-3);
  122. g.setColor(darkShadow);
  123. g.drawLine(0, h-1, w-1, h-1);
  124. g.drawLine(w-1, h-1, w-1, 0);
  125. }
  126. g.translate(-x, -y);
  127. g.setColor(oldColor);
  128. }
  129. }
  130. public static void drawLoweredBezel(Graphics g, int x, int y, int w, int h,
  131. Color shadow, Color darkShadow,
  132. Color highlight, Color lightHighlight) {
  133. g.setColor(darkShadow);
  134. g.drawLine(0, 0, 0, h-1);
  135. g.drawLine(1, 0, w-2, 0);
  136. g.setColor(shadow);
  137. g.drawLine(1, 1, 1, h-2);
  138. g.drawLine(1, 1, w-3, 1);
  139. g.setColor(lightHighlight);
  140. g.drawLine(0, h-1, w-1, h-1);
  141. g.drawLine(w-1, h-1, w-1, 0);
  142. g.setColor(highlight);
  143. g.drawLine(1, h-2, w-2, h-2);
  144. g.drawLine(w-2, h-2, w-2, 1);
  145. }
  146. /** Draw a string with the graphics g at location (x,y) just like g.drawString() would.
  147. * The first occurence of underlineChar in text will be underlined. The matching is
  148. * not case sensitive.
  149. */
  150. public static void drawString(Graphics g,String text,int underlinedChar,int x,int y) {
  151. // char b[] = new char[1];
  152. // String s;
  153. char lc,uc;
  154. int index=-1,lci,uci;
  155. if(underlinedChar != '\0') {
  156. // b[0] = (char)underlinedChar;
  157. // s = new String(b).toUpperCase();
  158. // uc = s.charAt(0);
  159. uc = Character.toUpperCase((char)underlinedChar);
  160. // s = new String(b).toLowerCase();
  161. lc = Character.toLowerCase((char)underlinedChar);
  162. uci = text.indexOf(uc);
  163. lci = text.indexOf(lc);
  164. if(uci == -1)
  165. index = lci;
  166. else if(lci == -1)
  167. index = uci;
  168. else
  169. index = (lci < uci) ? lci : uci;
  170. }
  171. g.drawString(text,x,y);
  172. if(index != -1) {
  173. FontMetrics fm = g.getFontMetrics();
  174. // Rectangle underlineRect = new Rectangle();
  175. int underlineRectX = x + fm.stringWidth(text.substring(0,index));
  176. int underlineRectY = y;
  177. int underlineRectWidth = fm.charWidth(text.charAt(index));
  178. int underlineRectHeight = 1;
  179. g.fillRect(underlineRectX, underlineRectY + fm.getDescent() - 1,
  180. underlineRectWidth, underlineRectHeight);
  181. }
  182. }
  183. public static void drawDashedRect(Graphics g,int x,int y,int width,int height) {
  184. int vx,vy;
  185. // draw upper and lower horizontal dashes
  186. for (vx = x; vx < (x + width); vx+=2) {
  187. g.drawLine(vx, y, vx, y);
  188. g.drawLine(vx, y + height-1, vx, y + height-1);
  189. }
  190. // draw left and right vertical dashes
  191. for (vy = y; vy < (y + height); vy+=2) {
  192. g.drawLine(x, vy, x, vy);
  193. g.drawLine(x+width-1, vy, x + width-1, vy);
  194. }
  195. }
  196. public static Dimension getPreferredButtonSize(AbstractButton b, int textIconGap)
  197. {
  198. if(b.getComponentCount() > 0) {
  199. return null;
  200. }
  201. Icon icon = (Icon) b.getIcon();
  202. String text = b.getText();
  203. Font font = b.getFont();
  204. FontMetrics fm = b.getToolkit().getFontMetrics(font);
  205. Rectangle iconR = new Rectangle();
  206. Rectangle textR = new Rectangle();
  207. Rectangle viewR = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE);
  208. SwingUtilities.layoutCompoundLabel(
  209. (JComponent) b, fm, text, icon,
  210. b.getVerticalAlignment(), b.getHorizontalAlignment(),
  211. b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
  212. viewR, iconR, textR, (text == null ? 0 : textIconGap)
  213. );
  214. /* The preferred size of the button is the size of
  215. * the text and icon rectangles plus the buttons insets.
  216. */
  217. Rectangle r = iconR.union(textR);
  218. Insets insets = b.getInsets();
  219. r.width += insets.left + insets.right;
  220. r.height += insets.top + insets.bottom;
  221. /* Ensure that the width and height of the button is odd,
  222. * to allow for the focus line.
  223. */
  224. if(r.width % 2 == 0) { r.width += 1; }
  225. if(r.height % 2 == 0) { r.height += 1; }
  226. return r.getSize();
  227. }
  228. /*
  229. * Convenience function for determining ComponentOrientation. Helps us
  230. * avoid having Munge directives throughout the code.
  231. */
  232. static boolean isLeftToRight( Component c ) {
  233. return c.getComponentOrientation().isLeftToRight();
  234. }
  235. }