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