1 /* 2 * Copyright (c) 1998, 2013, 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 26 package com.sun.java.swing.plaf.windows; 27 28 import javax.swing.*; 29 import javax.swing.plaf.ButtonUI; 30 import javax.swing.plaf.UIResource; 31 32 import java.awt.*; 33 import java.io.Serializable; 34 35 import static com.sun.java.swing.plaf.windows.TMSchema.*; 36 import static com.sun.java.swing.plaf.windows.XPStyle.Skin; 37 38 import 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 */ 54 public 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 AbstractButton b = (AbstractButton)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 }