1 /*
2 * Copyright 1997-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 }