1 /* 2 * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing.plaf.basic; 26 27 import javax.swing.*; 28 import java.awt.Component; 29 import java.awt.Color; 30 import java.awt.Dimension; 31 import java.awt.Font; 32 import java.awt.FontMetrics; 33 import java.awt.Graphics; 34 import java.awt.Insets; 35 import java.awt.Rectangle; 36 import java.awt.event.KeyEvent; 37 import sun.swing.SwingUtilities2; 38 39 40 /* 41 * @author Hans Muller 42 */ 43 44 public class BasicGraphicsUtils 45 { 46 47 private static final Insets GROOVE_INSETS = new Insets(2, 2, 2, 2); 48 private static final Insets ETCHED_INSETS = new Insets(2, 2, 2, 2); 49 50 public static void drawEtchedRect(Graphics g, int x, int y, int w, int h, 51 Color shadow, Color darkShadow, 52 Color highlight, Color lightHighlight) 53 { 54 Color oldColor = g.getColor(); // Make no net change to g 55 g.translate(x, y); 56 57 g.setColor(shadow); 58 g.drawLine(0, 0, w-1, 0); // outer border, top 59 g.drawLine(0, 1, 0, h-2); // outer border, left 60 61 g.setColor(darkShadow); 62 g.drawLine(1, 1, w-3, 1); // inner border, top 63 g.drawLine(1, 2, 1, h-3); // inner border, left 64 65 g.setColor(lightHighlight); 66 g.drawLine(w-1, 0, w-1, h-1); // outer border, bottom 67 g.drawLine(0, h-1, w-1, h-1); // outer border, right 68 69 g.setColor(highlight); 70 g.drawLine(w-2, 1, w-2, h-3); // inner border, right 71 g.drawLine(1, h-2, w-2, h-2); // inner border, bottom 72 73 g.translate(-x, -y); 74 g.setColor(oldColor); 75 } 76 77 78 /** 79 * Returns the amount of space taken up by a border drawn by 80 * <code>drawEtchedRect()</code> 81 * 82 * @return the inset of an etched rect 83 */ 84 public static Insets getEtchedInsets() { 85 return ETCHED_INSETS; 86 } 87 88 89 public static void drawGroove(Graphics g, int x, int y, int w, int h, 90 Color shadow, Color highlight) 91 { 92 Color oldColor = g.getColor(); // Make no net change to g 93 g.translate(x, y); 94 95 g.setColor(shadow); 96 g.drawRect(0, 0, w-2, h-2); 97 98 g.setColor(highlight); 99 g.drawLine(1, h-3, 1, 1); 100 g.drawLine(1, 1, w-3, 1); 101 102 g.drawLine(0, h-1, w-1, h-1); 103 g.drawLine(w-1, h-1, w-1, 0); 104 105 g.translate(-x, -y); 106 g.setColor(oldColor); 107 } 108 109 /** 110 * Returns the amount of space taken up by a border drawn by 111 * <code>drawGroove()</code> 112 * 113 * @return the inset of a groove border 114 */ 115 public static Insets getGrooveInsets() { 116 return GROOVE_INSETS; 117 } 118 119 120 public static void drawBezel(Graphics g, int x, int y, int w, int h, 121 boolean isPressed, boolean isDefault, 122 Color shadow, Color darkShadow, 123 Color highlight, Color lightHighlight) 124 { 125 Color oldColor = g.getColor(); // Make no net change to g 126 g.translate(x, y); 127 128 if (isPressed && isDefault) { 129 g.setColor(darkShadow); 130 g.drawRect(0, 0, w - 1, h - 1); 131 g.setColor(shadow); 132 g.drawRect(1, 1, w - 3, h - 3); 133 } else if (isPressed) { 134 drawLoweredBezel(g, x, y, w, h, 135 shadow, darkShadow, highlight, lightHighlight); 136 } else if (isDefault) { 137 g.setColor(darkShadow); 138 g.drawRect(0, 0, w-1, h-1); 139 140 g.setColor(lightHighlight); 141 g.drawLine(1, 1, 1, h-3); 142 g.drawLine(2, 1, w-3, 1); 143 144 g.setColor(highlight); 145 g.drawLine(2, 2, 2, h-4); 146 g.drawLine(3, 2, w-4, 2); 147 148 g.setColor(shadow); 149 g.drawLine(2, h-3, w-3, h-3); 150 g.drawLine(w-3, 2, w-3, h-4); 151 152 g.setColor(darkShadow); 153 g.drawLine(1, h-2, w-2, h-2); 154 g.drawLine(w-2, h-2, w-2, 1); 155 } else { 156 g.setColor(lightHighlight); 157 g.drawLine(0, 0, 0, h-1); 158 g.drawLine(1, 0, w-2, 0); 159 160 g.setColor(highlight); 161 g.drawLine(1, 1, 1, h-3); 162 g.drawLine(2, 1, w-3, 1); 163 164 g.setColor(shadow); 165 g.drawLine(1, h-2, w-2, h-2); 166 g.drawLine(w-2, 1, w-2, h-3); 167 168 g.setColor(darkShadow); 169 g.drawLine(0, h-1, w-1, h-1); 170 g.drawLine(w-1, h-1, w-1, 0); 171 } 172 g.translate(-x, -y); 173 g.setColor(oldColor); 174 } 175 176 public static void drawLoweredBezel(Graphics g, int x, int y, int w, int h, 177 Color shadow, Color darkShadow, 178 Color highlight, Color lightHighlight) { 179 g.setColor(darkShadow); 180 g.drawLine(0, 0, 0, h-1); 181 g.drawLine(1, 0, w-2, 0); 182 183 g.setColor(shadow); 184 g.drawLine(1, 1, 1, h-2); 185 g.drawLine(1, 1, w-3, 1); 186 187 g.setColor(lightHighlight); 188 g.drawLine(0, h-1, w-1, h-1); 189 g.drawLine(w-1, h-1, w-1, 0); 190 191 g.setColor(highlight); 192 g.drawLine(1, h-2, w-2, h-2); 193 g.drawLine(w-2, h-2, w-2, 1); 194 } 195 196 197 /** Draw a string with the graphics <code>g</code> at location (x,y) 198 * just like <code>g.drawString</code> would. 199 * The first occurrence of <code>underlineChar</code> 200 * in text will be underlined. The matching algorithm is 201 * not case sensitive. 202 */ 203 public static void drawString(Graphics g,String text,int underlinedChar,int x,int y) { 204 int index=-1; 205 206 if (underlinedChar != '\0') { 207 char uc = Character.toUpperCase((char)underlinedChar); 208 char lc = Character.toLowerCase((char)underlinedChar); 209 int uci = text.indexOf(uc); 210 int lci = text.indexOf(lc); 211 212 if(uci == -1) { 213 index = lci; 214 } 215 else if(lci == -1) { 216 index = uci; 217 } 218 else { 219 index = (lci < uci) ? lci : uci; 220 } 221 } 222 drawStringUnderlineCharAt(g, text, index, x, y); 223 } 224 225 /** 226 * Draw a string with the graphics <code>g</code> at location 227 * (<code>x</code>, <code>y</code>) 228 * just like <code>g.drawString</code> would. 229 * The character at index <code>underlinedIndex</code> 230 * in text will be underlined. If <code>index</code> is beyond the 231 * bounds of <code>text</code> (including < 0), nothing will be 232 * underlined. 233 * 234 * @param g Graphics to draw with 235 * @param text String to draw 236 * @param underlinedIndex Index of character in text to underline 237 * @param x x coordinate to draw at 238 * @param y y coordinate to draw at 239 * @since 1.4 240 */ 241 public static void drawStringUnderlineCharAt(Graphics g, String text, 242 int underlinedIndex, int x,int y) { 243 SwingUtilities2.drawStringUnderlineCharAt(null, g, text, 244 underlinedIndex, x, y); 245 } 246 247 public static void drawDashedRect(Graphics g,int x,int y,int width,int height) { 248 int vx,vy; 249 250 // draw upper and lower horizontal dashes 251 for (vx = x; vx < (x + width); vx+=2) { 252 g.fillRect(vx, y, 1, 1); 253 g.fillRect(vx, y + height-1, 1, 1); 254 } 255 256 // draw left and right vertical dashes 257 for (vy = y; vy < (y + height); vy+=2) { 258 g.fillRect(x, vy, 1, 1); 259 g.fillRect(x+width-1, vy, 1, 1); 260 } 261 } 262 263 public static Dimension getPreferredButtonSize(AbstractButton b, int textIconGap) 264 { 265 if(b.getComponentCount() > 0) { 266 return null; 267 } 268 269 Icon icon = (Icon) b.getIcon(); 270 String text = b.getText(); 271 272 Font font = b.getFont(); 273 FontMetrics fm = b.getFontMetrics(font); 274 275 Rectangle iconR = new Rectangle(); 276 Rectangle textR = new Rectangle(); 277 Rectangle viewR = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE); 278 279 SwingUtilities.layoutCompoundLabel( 280 (JComponent) b, fm, text, icon, 281 b.getVerticalAlignment(), b.getHorizontalAlignment(), 282 b.getVerticalTextPosition(), b.getHorizontalTextPosition(), 283 viewR, iconR, textR, (text == null ? 0 : textIconGap) 284 ); 285 286 /* The preferred size of the button is the size of 287 * the text and icon rectangles plus the buttons insets. 288 */ 289 290 Rectangle r = iconR.union(textR); 291 292 Insets insets = b.getInsets(); 293 r.width += insets.left + insets.right; 294 r.height += insets.top + insets.bottom; 295 296 return r.getSize(); 297 } 298 299 /* 300 * Convenience function for determining ComponentOrientation. Helps us 301 * avoid having Munge directives throughout the code. 302 */ 303 static boolean isLeftToRight( Component c ) { 304 return c.getComponentOrientation().isLeftToRight(); 305 } 306 }