blob: a829297d6298ee591e9f0242ed39a819ea35140b [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2006 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
26package com.sun.java.swing.plaf.windows;
27
28import javax.swing.*;
29import javax.swing.plaf.ButtonUI;
30import javax.swing.plaf.UIResource;
31
32import java.awt.*;
33import java.io.Serializable;
34
35import static com.sun.java.swing.plaf.windows.TMSchema.*;
36import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
37
38import sun.swing.MenuItemCheckIconFactory;
39
40/**
41 * Factory object that can vend Icons appropriate for the Windows L & F.
42 * <p>
43 * <strong>Warning:</strong>
44 * Serialized objects of this class will not be compatible with
45 * future Swing releases. The current serialization support is appropriate
46 * for short term storage or RMI between applications running the same
47 * version of Swing. A future release of Swing will provide support for
48 * long term persistence.
49 *
50 * @author David Kloba
51 * @author Georges Saab
52 * @author Rich Schiavi
53 */
54public class WindowsIconFactory implements Serializable
55{
56 private static Icon frame_closeIcon;
57 private static Icon frame_iconifyIcon;
58 private static Icon frame_maxIcon;
59 private static Icon frame_minIcon;
60 private static Icon frame_resizeIcon;
61 private static Icon checkBoxIcon;
62 private static Icon radioButtonIcon;
63 private static Icon checkBoxMenuItemIcon;
64 private static Icon radioButtonMenuItemIcon;
65 private static Icon menuItemCheckIcon;
66 private static Icon menuItemArrowIcon;
67 private static Icon menuArrowIcon;
68 private static VistaMenuItemCheckIconFactory menuItemCheckIconFactory;
69
70 public static Icon getMenuItemCheckIcon() {
71 if (menuItemCheckIcon == null) {
72 menuItemCheckIcon = new MenuItemCheckIcon();
73 }
74 return menuItemCheckIcon;
75 }
76
77 public static Icon getMenuItemArrowIcon() {
78 if (menuItemArrowIcon == null) {
79 menuItemArrowIcon = new MenuItemArrowIcon();
80 }
81 return menuItemArrowIcon;
82 }
83
84 public static Icon getMenuArrowIcon() {
85 if (menuArrowIcon == null) {
86 menuArrowIcon = new MenuArrowIcon();
87 }
88 return menuArrowIcon;
89 }
90
91 public static Icon getCheckBoxIcon() {
92 if (checkBoxIcon == null) {
93 checkBoxIcon = new CheckBoxIcon();
94 }
95 return checkBoxIcon;
96 }
97
98 public static Icon getRadioButtonIcon() {
99 if (radioButtonIcon == null) {
100 radioButtonIcon = new RadioButtonIcon();
101 }
102 return radioButtonIcon;
103 }
104
105 public static Icon getCheckBoxMenuItemIcon() {
106 if (checkBoxMenuItemIcon == null) {
107 checkBoxMenuItemIcon = new CheckBoxMenuItemIcon();
108 }
109 return checkBoxMenuItemIcon;
110 }
111
112 public static Icon getRadioButtonMenuItemIcon() {
113 if (radioButtonMenuItemIcon == null) {
114 radioButtonMenuItemIcon = new RadioButtonMenuItemIcon();
115 }
116 return radioButtonMenuItemIcon;
117 }
118
119 static
120 synchronized VistaMenuItemCheckIconFactory getMenuItemCheckIconFactory() {
121 if (menuItemCheckIconFactory == null) {
122 menuItemCheckIconFactory =
123 new VistaMenuItemCheckIconFactory();
124 }
125 return menuItemCheckIconFactory;
126 }
127
128 public static Icon createFrameCloseIcon() {
129 if (frame_closeIcon == null) {
130 frame_closeIcon = new FrameButtonIcon(Part.WP_CLOSEBUTTON);
131 }
132 return frame_closeIcon;
133 }
134
135 public static Icon createFrameIconifyIcon() {
136 if (frame_iconifyIcon == null) {
137 frame_iconifyIcon = new FrameButtonIcon(Part.WP_MINBUTTON);
138 }
139 return frame_iconifyIcon;
140 }
141
142 public static Icon createFrameMaximizeIcon() {
143 if (frame_maxIcon == null) {
144 frame_maxIcon = new FrameButtonIcon(Part.WP_MAXBUTTON);
145 }
146 return frame_maxIcon;
147 }
148
149 public static Icon createFrameMinimizeIcon() {
150 if (frame_minIcon == null) {
151 frame_minIcon = new FrameButtonIcon(Part.WP_RESTOREBUTTON);
152 }
153 return frame_minIcon;
154 }
155
156 public static Icon createFrameResizeIcon() {
157 if(frame_resizeIcon == null)
158 frame_resizeIcon = new ResizeIcon();
159 return frame_resizeIcon;
160 }
161
162
163 private static class FrameButtonIcon implements Icon, Serializable {
164 private Part part;
165
166 private FrameButtonIcon(Part part) {
167 this.part = part;
168 }
169
170 public void paintIcon(Component c, Graphics g, int x0, int y0) {
171 int width = getIconWidth();
172 int height = getIconHeight();
173
174 XPStyle xp = XPStyle.getXP();
175 if (xp != null) {
176 Skin skin = xp.getSkin(c, part);
177 JButton b = (JButton)c;
178 ButtonModel model = b.getModel();
179
180 // Find out if frame is inactive
181 JInternalFrame jif = (JInternalFrame)SwingUtilities.
182 getAncestorOfClass(JInternalFrame.class, b);
183 boolean jifSelected = (jif != null && jif.isSelected());
184
185 State state;
186 if (jifSelected) {
187 if (!model.isEnabled()) {
188 state = State.DISABLED;
189 } else if (model.isArmed() && model.isPressed()) {
190 state = State.PUSHED;
191 } else if (model.isRollover()) {
192 state = State.HOT;
193 } else {
194 state = State.NORMAL;
195 }
196 } else {
197 if (!model.isEnabled()) {
198 state = State.INACTIVEDISABLED;
199 } else if (model.isArmed() && model.isPressed()) {
200 state = State.INACTIVEPUSHED;
201 } else if (model.isRollover()) {
202 state = State.INACTIVEHOT;
203 } else {
204 state = State.INACTIVENORMAL;
205 }
206 }
207 skin.paintSkin(g, 0, 0, width, height, state);
208 } else {
209 g.setColor(Color.black);
210 int x = width / 12 + 2;
211 int y = height / 5;
212 int h = height - y * 2 - 1;
213 int w = width * 3/4 -3;
214 int thickness2 = Math.max(height / 8, 2);
215 int thickness = Math.max(width / 15, 1);
216 if (part == Part.WP_CLOSEBUTTON) {
217 int lineWidth;
218 if (width > 47) lineWidth = 6;
219 else if (width > 37) lineWidth = 5;
220 else if (width > 26) lineWidth = 4;
221 else if (width > 16) lineWidth = 3;
222 else if (width > 12) lineWidth = 2;
223 else lineWidth = 1;
224 y = height / 12 + 2;
225 if (lineWidth == 1) {
226 if (w % 2 == 1) { x++; w++; }
227 g.drawLine(x, y, x+w-2, y+w-2);
228 g.drawLine(x+w-2, y, x, y+w-2);
229 } else if (lineWidth == 2) {
230 if (w > 6) { x++; w--; }
231 g.drawLine(x, y, x+w-2, y+w-2);
232 g.drawLine(x+w-2, y, x, y+w-2);
233 g.drawLine(x+1, y, x+w-1, y+w-2);
234 g.drawLine(x+w-1, y, x+1, y+w-2);
235 } else {
236 x += 2; y++; w -= 2;
237 g.drawLine(x, y, x+w-1, y+w-1);
238 g.drawLine(x+w-1, y, x, y+w-1);
239 g.drawLine(x+1, y, x+w-1, y+w-2);
240 g.drawLine(x+w-2, y, x, y+w-2);
241 g.drawLine(x, y+1, x+w-2, y+w-1);
242 g.drawLine(x+w-1, y+1, x+1, y+w-1);
243 for (int i = 4; i <= lineWidth; i++) {
244 g.drawLine(x+i-2, y, x+w-1, y+w-i+1);
245 g.drawLine(x, y+i-2, x+w-i+1, y+w-1);
246 g.drawLine(x+w-i+1, y, x, y+w-i+1);
247 g.drawLine(x+w-1, y+i-2, x+i-2, y+w-1);
248 }
249 }
250 } else if (part == Part.WP_MINBUTTON) {
251 g.fillRect(x, y+h-thickness2, w-w/3, thickness2);
252 } else if (part == Part.WP_MAXBUTTON) {
253 g.fillRect(x, y, w, thickness2);
254 g.fillRect(x, y, thickness, h);
255 g.fillRect(x+w-thickness, y, thickness, h);
256 g.fillRect(x, y+h-thickness, w, thickness);
257 } else if (part == Part.WP_RESTOREBUTTON) {
258 g.fillRect(x+w/3, y, w-w/3, thickness2);
259 g.fillRect(x+w/3, y, thickness, h/3);
260 g.fillRect(x+w-thickness, y, thickness, h-h/3);
261 g.fillRect(x+w-w/3, y+h-h/3-thickness, w/3, thickness);
262
263 g.fillRect(x, y+h/3, w-w/3, thickness2);
264 g.fillRect(x, y+h/3, thickness, h-h/3);
265 g.fillRect(x+w-w/3-thickness, y+h/3, thickness, h-h/3);
266 g.fillRect(x, y+h-thickness, w-w/3, thickness);
267 }
268 }
269 }
270
271 public int getIconWidth() {
272 int width;
273 if (XPStyle.getXP() != null) {
274 // Fix for XP bug where sometimes these sizes aren't updated properly
275 // Assume for now that height is correct and derive width using the
276 // ratio from the uxtheme part
277 width = UIManager.getInt("InternalFrame.titleButtonHeight") -2;
278 Dimension d = XPStyle.getPartSize(Part.WP_CLOSEBUTTON, State.NORMAL);
279 if (d != null && d.width != 0 && d.height != 0) {
280 width = (int) ((float) width * d.width / d.height);
281 }
282 } else {
283 width = UIManager.getInt("InternalFrame.titleButtonWidth") -2;
284 }
285 if (XPStyle.getXP() != null) {
286 width -= 2;
287 }
288 return width;
289 }
290
291 public int getIconHeight() {
292 int height = UIManager.getInt("InternalFrame.titleButtonHeight")-4;
293 return height;
294 }
295 }
296
297
298
299 private static class ResizeIcon implements Icon, Serializable {
300 public void paintIcon(Component c, Graphics g, int x, int y) {
301 g.setColor(UIManager.getColor("InternalFrame.resizeIconHighlight"));
302 g.drawLine(0, 11, 11, 0);
303 g.drawLine(4, 11, 11, 4);
304 g.drawLine(8, 11, 11, 8);
305
306 g.setColor(UIManager.getColor("InternalFrame.resizeIconShadow"));
307 g.drawLine(1, 11, 11, 1);
308 g.drawLine(2, 11, 11, 2);
309 g.drawLine(5, 11, 11, 5);
310 g.drawLine(6, 11, 11, 6);
311 g.drawLine(9, 11, 11, 9);
312 g.drawLine(10, 11, 11, 10);
313 }
314 public int getIconWidth() { return 13; }
315 public int getIconHeight() { return 13; }
316 };
317
318 private static class CheckBoxIcon implements Icon, Serializable
319 {
320 final static int csize = 13;
321 public void paintIcon(Component c, Graphics g, int x, int y) {
322 JCheckBox cb = (JCheckBox) c;
323 ButtonModel model = cb.getModel();
324 XPStyle xp = XPStyle.getXP();
325
326 if (xp != null) {
327 State state;
328 if (model.isSelected()) {
329 state = State.CHECKEDNORMAL;
330 if (!model.isEnabled()) {
331 state = State.CHECKEDDISABLED;
332 } else if (model.isPressed() && model.isArmed()) {
333 state = State.CHECKEDPRESSED;
334 } else if (model.isRollover()) {
335 state = State.CHECKEDHOT;
336 }
337 } else {
338 state = State.UNCHECKEDNORMAL;
339 if (!model.isEnabled()) {
340 state = State.UNCHECKEDDISABLED;
341 } else if (model.isPressed() && model.isArmed()) {
342 state = State.UNCHECKEDPRESSED;
343 } else if (model.isRollover()) {
344 state = State.UNCHECKEDHOT;
345 }
346 }
347 Part part = Part.BP_CHECKBOX;
348 xp.getSkin(c, part).paintSkin(g, x, y, state);
349 } else {
350 // outer bevel
351 if(!cb.isBorderPaintedFlat()) {
352 // Outer top/left
353 g.setColor(UIManager.getColor("CheckBox.shadow"));
354 g.drawLine(x, y, x+11, y);
355 g.drawLine(x, y+1, x, y+11);
356
357 // Outer bottom/right
358 g.setColor(UIManager.getColor("CheckBox.highlight"));
359 g.drawLine(x+12, y, x+12, y+12);
360 g.drawLine(x, y+12, x+11, y+12);
361
362 // Inner top.left
363 g.setColor(UIManager.getColor("CheckBox.darkShadow"));
364 g.drawLine(x+1, y+1, x+10, y+1);
365 g.drawLine(x+1, y+2, x+1, y+10);
366
367 // Inner bottom/right
368 g.setColor(UIManager.getColor("CheckBox.light"));
369 g.drawLine(x+1, y+11, x+11, y+11);
370 g.drawLine(x+11, y+1, x+11, y+10);
371
372 // inside box
373 if((model.isPressed() && model.isArmed()) || !model.isEnabled()) {
374 g.setColor(UIManager.getColor("CheckBox.background"));
375 } else {
376 g.setColor(UIManager.getColor("CheckBox.interiorBackground"));
377 }
378 g.fillRect(x+2, y+2, csize-4, csize-4);
379 } else {
380 g.setColor(UIManager.getColor("CheckBox.shadow"));
381 g.drawRect(x+1, y+1, csize-3, csize-3);
382
383 if((model.isPressed() && model.isArmed()) || !model.isEnabled()) {
384 g.setColor(UIManager.getColor("CheckBox.background"));
385 } else {
386 g.setColor(UIManager.getColor("CheckBox.interiorBackground"));
387 }
388 g.fillRect(x+2, y+2, csize-4, csize-4);
389 }
390
391 if(model.isEnabled()) {
392 g.setColor(UIManager.getColor("CheckBox.foreground"));
393 } else {
394 g.setColor(UIManager.getColor("CheckBox.shadow"));
395 }
396
397 // paint check
398 if (model.isSelected()) {
399 g.drawLine(x+9, y+3, x+9, y+3);
400 g.drawLine(x+8, y+4, x+9, y+4);
401 g.drawLine(x+7, y+5, x+9, y+5);
402 g.drawLine(x+6, y+6, x+8, y+6);
403 g.drawLine(x+3, y+7, x+7, y+7);
404 g.drawLine(x+4, y+8, x+6, y+8);
405 g.drawLine(x+5, y+9, x+5, y+9);
406 g.drawLine(x+3, y+5, x+3, y+5);
407 g.drawLine(x+3, y+6, x+4, y+6);
408 }
409 }
410 }
411
412 public int getIconWidth() {
413 XPStyle xp = XPStyle.getXP();
414 if (xp != null) {
415 return xp.getSkin(null, Part.BP_CHECKBOX).getWidth();
416 } else {
417 return csize;
418 }
419 }
420
421 public int getIconHeight() {
422 XPStyle xp = XPStyle.getXP();
423 if (xp != null) {
424 return xp.getSkin(null, Part.BP_CHECKBOX).getHeight();
425 } else {
426 return csize;
427 }
428 }
429 }
430
431 private static class RadioButtonIcon implements Icon, UIResource, Serializable
432 {
433 public void paintIcon(Component c, Graphics g, int x, int y) {
434 AbstractButton b = (AbstractButton) c;
435 ButtonModel model = b.getModel();
436 XPStyle xp = XPStyle.getXP();
437
438 if (xp != null) {
439 Part part = Part.BP_RADIOBUTTON;
440 Skin skin = xp.getSkin(b, part);
441 State state;
442 int index = 0;
443 if (model.isSelected()) {
444 state = State.CHECKEDNORMAL;
445 if (!model.isEnabled()) {
446 state = State.CHECKEDDISABLED;
447 } else if (model.isPressed() && model.isArmed()) {
448 state = State.CHECKEDPRESSED;
449 } else if (model.isRollover()) {
450 state = State.CHECKEDHOT;
451 }
452 } else {
453 state = State.UNCHECKEDNORMAL;
454 if (!model.isEnabled()) {
455 state = State.UNCHECKEDDISABLED;
456 } else if (model.isPressed() && model.isArmed()) {
457 state = State.UNCHECKEDPRESSED;
458 } else if (model.isRollover()) {
459 state = State.UNCHECKEDHOT;
460 }
461 }
462 skin.paintSkin(g, x, y, state);
463 } else {
464 // fill interior
465 if((model.isPressed() && model.isArmed()) || !model.isEnabled()) {
466 g.setColor(UIManager.getColor("RadioButton.background"));
467 } else {
468 g.setColor(UIManager.getColor("RadioButton.interiorBackground"));
469 }
470 g.fillRect(x+2, y+2, 8, 8);
471
472
473 // outter left arc
474 g.setColor(UIManager.getColor("RadioButton.shadow"));
475 g.drawLine(x+4, y+0, x+7, y+0);
476 g.drawLine(x+2, y+1, x+3, y+1);
477 g.drawLine(x+8, y+1, x+9, y+1);
478 g.drawLine(x+1, y+2, x+1, y+3);
479 g.drawLine(x+0, y+4, x+0, y+7);
480 g.drawLine(x+1, y+8, x+1, y+9);
481
482 // outter right arc
483 g.setColor(UIManager.getColor("RadioButton.highlight"));
484 g.drawLine(x+2, y+10, x+3, y+10);
485 g.drawLine(x+4, y+11, x+7, y+11);
486 g.drawLine(x+8, y+10, x+9, y+10);
487 g.drawLine(x+10, y+9, x+10, y+8);
488 g.drawLine(x+11, y+7, x+11, y+4);
489 g.drawLine(x+10, y+3, x+10, y+2);
490
491
492 // inner left arc
493 g.setColor(UIManager.getColor("RadioButton.darkShadow"));
494 g.drawLine(x+4, y+1, x+7, y+1);
495 g.drawLine(x+2, y+2, x+3, y+2);
496 g.drawLine(x+8, y+2, x+9, y+2);
497 g.drawLine(x+2, y+3, x+2, y+3);
498 g.drawLine(x+1, y+4, x+1, y+7);
499 g.drawLine(x+2, y+8, x+2, y+8);
500
501
502 // inner right arc
503 g.setColor(UIManager.getColor("RadioButton.light"));
504 g.drawLine(x+2, y+9, x+3, y+9);
505 g.drawLine(x+4, y+10, x+7, y+10);
506 g.drawLine(x+8, y+9, x+9, y+9);
507 g.drawLine(x+9, y+8, x+9, y+8);
508 g.drawLine(x+10, y+7, x+10, y+4);
509 g.drawLine(x+9, y+3, x+9, y+3);
510
511
512 // indicate whether selected or not
513 if (model.isSelected()) {
514 if (model.isEnabled()) {
515 g.setColor(UIManager.getColor("RadioButton.foreground"));
516 } else {
517 g.setColor(UIManager.getColor("RadioButton.shadow"));
518 }
519 g.fillRect(x+4, y+5, 4, 2);
520 g.fillRect(x+5, y+4, 2, 4);
521 }
522 }
523 }
524
525 public int getIconWidth() {
526 XPStyle xp = XPStyle.getXP();
527 if (xp != null) {
528 return xp.getSkin(null, Part.BP_RADIOBUTTON).getWidth();
529 } else {
530 return 13;
531 }
532 }
533
534 public int getIconHeight() {
535 XPStyle xp = XPStyle.getXP();
536 if (xp != null) {
537 return xp.getSkin(null, Part.BP_RADIOBUTTON).getHeight();
538 } else {
539 return 13;
540 }
541 }
542 } // end class RadioButtonIcon
543
544
545 private static class CheckBoxMenuItemIcon implements Icon, UIResource, Serializable
546 {
547 public void paintIcon(Component c, Graphics g, int x, int y) {
548 AbstractButton b = (AbstractButton) c;
549 ButtonModel model = b.getModel();
550 boolean isSelected = model.isSelected();
551 if (isSelected) {
552 y = y - getIconHeight() / 2;
553 g.drawLine(x+9, y+3, x+9, y+3);
554 g.drawLine(x+8, y+4, x+9, y+4);
555 g.drawLine(x+7, y+5, x+9, y+5);
556 g.drawLine(x+6, y+6, x+8, y+6);
557 g.drawLine(x+3, y+7, x+7, y+7);
558 g.drawLine(x+4, y+8, x+6, y+8);
559 g.drawLine(x+5, y+9, x+5, y+9);
560 g.drawLine(x+3, y+5, x+3, y+5);
561 g.drawLine(x+3, y+6, x+4, y+6);
562 }
563 }
564 public int getIconWidth() { return 9; }
565 public int getIconHeight() { return 9; }
566
567 } // End class CheckBoxMenuItemIcon
568
569
570 private static class RadioButtonMenuItemIcon implements Icon, UIResource, Serializable
571 {
572 public void paintIcon(Component c, Graphics g, int x, int y) {
573 AbstractButton b = (AbstractButton) c;
574 ButtonModel model = b.getModel();
575 if (b.isSelected() == true) {
576 g.fillRoundRect(x+3,y+3, getIconWidth()-6, getIconHeight()-6,
577 4, 4);
578 }
579 }
580 public int getIconWidth() { return 12; }
581 public int getIconHeight() { return 12; }
582
583 } // End class RadioButtonMenuItemIcon
584
585
586 private static class MenuItemCheckIcon implements Icon, UIResource, Serializable{
587 public void paintIcon(Component c, Graphics g, int x, int y) {
588 /* For debugging:
589 Color oldColor = g.getColor();
590 g.setColor(Color.orange);
591 g.fill3DRect(x,y,getIconWidth(), getIconHeight(), true);
592 g.setColor(oldColor);
593 */
594 }
595 public int getIconWidth() { return 9; }
596 public int getIconHeight() { return 9; }
597
598 } // End class MenuItemCheckIcon
599
600 private static class MenuItemArrowIcon implements Icon, UIResource, Serializable {
601 public void paintIcon(Component c, Graphics g, int x, int y) {
602 /* For debugging:
603 Color oldColor = g.getColor();
604 g.setColor(Color.green);
605 g.fill3DRect(x,y,getIconWidth(), getIconHeight(), true);
606 g.setColor(oldColor);
607 */
608 }
609 public int getIconWidth() { return 4; }
610 public int getIconHeight() { return 8; }
611
612 } // End class MenuItemArrowIcon
613
614 private static class MenuArrowIcon implements Icon, UIResource, Serializable {
615 public void paintIcon(Component c, Graphics g, int x, int y) {
616 if (WindowsMenuItemUI.isVistaPainting()) {
617 XPStyle xp = XPStyle.getXP();
618 State state = State.NORMAL;
619 if (c instanceof JMenuItem) {
620 state = ((JMenuItem) c).getModel().isEnabled()
621 ? State.NORMAL : State.DISABLED;
622 }
623 Skin skin = xp.getSkin(c, Part.MP_POPUPSUBMENU);
624 if (WindowsGraphicsUtils.isLeftToRight(c)) {
625 skin.paintSkin(g, x, y, state);
626 } else {
627 Graphics2D g2d = (Graphics2D)g.create();
628 g2d.translate(x + skin.getWidth(), y);
629 g2d.scale(-1, 1);
630 skin.paintSkin(g2d, 0, 0, state);
631 g2d.dispose();
632 }
633 } else {
634 g.translate(x,y);
635 if( WindowsGraphicsUtils.isLeftToRight(c) ) {
636 g.drawLine( 0, 0, 0, 7 );
637 g.drawLine( 1, 1, 1, 6 );
638 g.drawLine( 2, 2, 2, 5 );
639 g.drawLine( 3, 3, 3, 4 );
640 } else {
641 g.drawLine( 4, 0, 4, 7 );
642 g.drawLine( 3, 1, 3, 6 );
643 g.drawLine( 2, 2, 2, 5 );
644 g.drawLine( 1, 3, 1, 4 );
645 }
646 g.translate(-x,-y);
647 }
648 }
649 public int getIconWidth() {
650 if (WindowsMenuItemUI.isVistaPainting()) {
651 Skin skin = XPStyle.getXP().getSkin(null, Part.MP_POPUPSUBMENU);
652 return skin.getWidth();
653 } else {
654 return 4;
655 }
656 }
657 public int getIconHeight() {
658 if (WindowsMenuItemUI.isVistaPainting()) {
659 Skin skin = XPStyle.getXP().getSkin(null, Part.MP_POPUPSUBMENU);
660 return skin.getHeight();
661 } else {
662 return 8;
663 }
664 }
665 } // End class MenuArrowIcon
666
667 static class VistaMenuItemCheckIconFactory
668 implements MenuItemCheckIconFactory {
669 private static final int OFFSET = 3;
670
671 public Icon getIcon(JMenuItem component) {
672 return new VistaMenuItemCheckIcon(component);
673 }
674
675 public boolean isCompatible(Object icon, String prefix) {
676 return icon instanceof VistaMenuItemCheckIcon
677 && ((VistaMenuItemCheckIcon) icon).type == getType(prefix);
678 }
679
680 public Icon getIcon(String type) {
681 return new VistaMenuItemCheckIcon(type);
682 }
683
684 static int getIconWidth() {
685 return XPStyle.getXP().getSkin(null, Part.MP_POPUPCHECK).getWidth()
686 + 2 * OFFSET;
687 }
688
689 private static Class<? extends JMenuItem> getType(Component c) {
690 Class<? extends JMenuItem> rv = null;
691 if (c instanceof JCheckBoxMenuItem) {
692 rv = JCheckBoxMenuItem.class;
693 } else if (c instanceof JRadioButtonMenuItem) {
694 rv = JRadioButtonMenuItem.class;
695 } else if (c instanceof JMenu) {
696 rv = JMenu.class;
697 } else if (c instanceof JMenuItem) {
698 rv = JMenuItem.class;
699 }
700 return rv;
701 }
702
703 private static Class<? extends JMenuItem> getType(String type) {
704 Class<? extends JMenuItem> rv = null;
705 if (type == "CheckBoxMenuItem") {
706 rv = JCheckBoxMenuItem.class;
707 } else if (type == "RadioButtonMenuItem") {
708 rv = JRadioButtonMenuItem.class;
709 } else if (type == "Menu") {
710 rv = JMenu.class;
711 } else if (type == "MenuItem") {
712 rv = JMenuItem.class;
713 } else {
714 // this should never happen
715 rv = JMenuItem.class;
716 }
717 return rv;
718 }
719
720 /**
721 * CheckIcon for JMenuItem, JMenu, JCheckBoxMenuItem and
722 * JRadioButtonMenuItem.
723 * Note: to be used on Vista only.
724 */
725 private static class VistaMenuItemCheckIcon
726 implements Icon, UIResource, Serializable {
727
728 private final JMenuItem menuItem;
729 private final Class<? extends JMenuItem> type;
730
731 VistaMenuItemCheckIcon(JMenuItem menuItem) {
732 this.type = getType(menuItem);
733 this.menuItem = menuItem;
734 }
735 VistaMenuItemCheckIcon(String type) {
736 this.type = getType(type);
737 this.menuItem = null;
738 }
739
740 public int getIconHeight() {
741 Icon lafIcon = getLaFIcon();
742 if (lafIcon != null) {
743 return lafIcon.getIconHeight();
744 }
745 Icon icon = getIcon();
746 int height = 0;
747 if (icon != null) {
748 height = icon.getIconHeight() + 2 * OFFSET;
749 } else {
750 Skin skin =
751 XPStyle.getXP().getSkin(null, Part.MP_POPUPCHECK);
752 height = skin.getHeight() + 2 * OFFSET;
753 }
754 return height;
755 }
756
757 public int getIconWidth() {
758 Icon lafIcon = getLaFIcon();
759 if (lafIcon != null) {
760 return lafIcon.getIconWidth();
761 }
762 Icon icon = getIcon();
763 int width = 0;
764 if (icon != null) {
765 width = icon.getIconWidth() + 2 * OFFSET;
766 } else {
767 width = VistaMenuItemCheckIconFactory.getIconWidth();
768 }
769 return width;
770 }
771
772 public void paintIcon(Component c, Graphics g, int x, int y) {
773 Icon lafIcon = getLaFIcon();
774 if (lafIcon != null) {
775 lafIcon.paintIcon(c, g, x, y);
776 return;
777 }
778 assert menuItem == null || c == menuItem;
779 Icon icon = getIcon();
780 if (type == JCheckBoxMenuItem.class
781 || type == JRadioButtonMenuItem.class) {
782 AbstractButton b = (AbstractButton) c;
783 if (b.isSelected()) {
784 Part backgroundPart = Part.MP_POPUPCHECKBACKGROUND;
785 Part part = Part.MP_POPUPCHECK;
786 State backgroundState;
787 State state;
788 if (isEnabled(c, null)) {
789 backgroundState =
790 (icon != null) ? State.BITMAP : State.NORMAL;
791 state = (type == JRadioButtonMenuItem.class)
792 ? State.BULLETNORMAL
793 : State.CHECKMARKNORMAL;
794 } else {
795 backgroundState = State.DISABLEDPUSHED;
796 state =
797 (type == JRadioButtonMenuItem.class)
798 ? State.BULLETDISABLED
799 : State.CHECKMARKDISABLED;
800 }
801 Skin skin;
802 XPStyle xp = XPStyle.getXP();
803 skin = xp.getSkin(c, backgroundPart);
804 skin.paintSkin(g, x, y,
805 getIconWidth(), getIconHeight(), backgroundState);
806 if (icon == null) {
807 skin = xp.getSkin(c, part);
808 skin.paintSkin(g, x + OFFSET, y + OFFSET, state);
809 }
810 }
811 }
812 if (icon != null) {
813 icon.paintIcon(c, g, x + OFFSET, y + OFFSET);
814 }
815 }
816 private static WindowsMenuItemUIAccessor getAccessor(
817 JMenuItem menuItem) {
818 WindowsMenuItemUIAccessor rv = null;
819 ButtonUI uiObject = (menuItem != null) ? menuItem.getUI()
820 : null;
821 if (uiObject instanceof WindowsMenuItemUI) {
822 rv = ((WindowsMenuItemUI) uiObject).accessor;
823 } else if (uiObject instanceof WindowsMenuUI) {
824 rv = ((WindowsMenuUI) uiObject).accessor;
825 } else if (uiObject instanceof WindowsCheckBoxMenuItemUI) {
826 rv = ((WindowsCheckBoxMenuItemUI) uiObject).accessor;
827 } else if (uiObject instanceof WindowsRadioButtonMenuItemUI) {
828 rv = ((WindowsRadioButtonMenuItemUI) uiObject).accessor;
829 }
830 return rv;
831 }
832
833 private static boolean isEnabled(Component c, State state) {
834 if (state == null && c instanceof JMenuItem) {
835 WindowsMenuItemUIAccessor accessor =
836 getAccessor((JMenuItem) c);
837 if (accessor != null) {
838 state = accessor.getState((JMenuItem) c);
839 }
840 }
841 if (state == null) {
842 if (c != null) {
843 return c.isEnabled();
844 } else {
845 return true;
846 }
847 } else {
848 return (state != State.DISABLED)
849 && (state != State.DISABLEDHOT)
850 && (state != State.DISABLEDPUSHED);
851 }
852 }
853 private Icon getIcon() {
854 Icon rv = null;
855 if (menuItem == null) {
856 return rv;
857 }
858 WindowsMenuItemUIAccessor accessor =
859 getAccessor(menuItem);
860 State state = (accessor != null) ? accessor.getState(menuItem)
861 : null;
862 if (isEnabled(menuItem, null)) {
863 if (state == State.PUSHED) {
864 rv = menuItem.getPressedIcon();
865 } else {
866 rv = menuItem.getIcon();
867 }
868 } else {
869 rv = menuItem.getDisabledIcon();
870 }
871 return rv;
872 }
873 /**
874 * Check if developer changed icon in the UI table.
875 *
876 * @return the icon to use or {@code null} if the current one is to
877 * be used
878 */
879 private Icon getLaFIcon() {
880 // use icon from the UI table if it does not match this one.
881 Icon rv = (Icon) UIManager.getDefaults().get(typeToString(type));
882 if (rv instanceof VistaMenuItemCheckIcon
883 && ((VistaMenuItemCheckIcon) rv).type == type) {
884 rv = null;
885 }
886 return rv;
887 }
888
889 private static String typeToString(
890 Class<? extends JMenuItem> type) {
891 assert type == JMenuItem.class
892 || type == JMenu.class
893 || type == JCheckBoxMenuItem.class
894 || type == JRadioButtonMenuItem.class;
895 StringBuilder sb = new StringBuilder(type.getName());
896 // remove package name, dot and the first character
897 sb.delete(0, sb.lastIndexOf("J") + 1);
898 sb.append(".checkIcon");
899 return sb.toString();
900 }
901 }
902 } // End class VistaMenuItemCheckIconFactory
903}