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 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 if (WindowsMenuItemUI.isVistaPainting()) { 627 XPStyle xp = XPStyle.getXP(); 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 if (WindowsMenuItemUI.isVistaPainting()) { 661 Skin skin = XPStyle.getXP().getSkin(null, Part.MP_POPUPSUBMENU); 662 return skin.getWidth(); 663 } else { 664 return 4; 665 } 666 } 667 public int getIconHeight() { 668 if (WindowsMenuItemUI.isVistaPainting()) { 669 Skin skin = XPStyle.getXP().getSkin(null, Part.MP_POPUPSUBMENU); 670 return skin.getHeight(); 671 } else { 672 return 8; 673 } 674 } 675 } // End class MenuArrowIcon 676 677 static class VistaMenuItemCheckIconFactory 678 implements MenuItemCheckIconFactory { 679 private static final int OFFSET = 3; 680 681 public Icon getIcon(JMenuItem component) { 682 return new VistaMenuItemCheckIcon(component); 683 } 684 685 public boolean isCompatible(Object icon, String prefix) { 686 return icon instanceof VistaMenuItemCheckIcon 687 && ((VistaMenuItemCheckIcon) icon).type == getType(prefix); 688 } 689 690 public Icon getIcon(String type) { 691 return new VistaMenuItemCheckIcon(type); 692 } 693 694 static int getIconWidth() { 695 XPStyle xp = XPStyle.getXP(); 696 return ((xp != null) ? xp.getSkin(null, Part.MP_POPUPCHECK).getWidth() : 16) 697 + 2 * OFFSET; 698 } 699 700 private static Class<? extends JMenuItem> getType(Component c) { 701 Class<? extends JMenuItem> rv = null; 702 if (c instanceof JCheckBoxMenuItem) { 703 rv = JCheckBoxMenuItem.class; 704 } else if (c instanceof JRadioButtonMenuItem) { 705 rv = JRadioButtonMenuItem.class; 706 } else if (c instanceof JMenu) { 707 rv = JMenu.class; 708 } else if (c instanceof JMenuItem) { 709 rv = JMenuItem.class; 710 } 711 return rv; 712 } 713 714 private static Class<? extends JMenuItem> getType(String type) { 715 Class<? extends JMenuItem> rv = null; 716 if (type == "CheckBoxMenuItem") { 717 rv = JCheckBoxMenuItem.class; 718 } else if (type == "RadioButtonMenuItem") { 719 rv = JRadioButtonMenuItem.class; 720 } else if (type == "Menu") { 721 rv = JMenu.class; 722 } else if (type == "MenuItem") { 723 rv = JMenuItem.class; 724 } else { 725 // this should never happen 726 rv = JMenuItem.class; 727 } 728 return rv; 729 } 730 731 /** 732 * CheckIcon for JMenuItem, JMenu, JCheckBoxMenuItem and 733 * JRadioButtonMenuItem. 734 * Note: to be used on Vista only. 735 */ 736 @SuppressWarnings("serial") // Same-version serialization only 737 private static class VistaMenuItemCheckIcon 738 implements Icon, UIResource, Serializable { 739 740 private final JMenuItem menuItem; 741 private final Class<? extends JMenuItem> type; 742 743 VistaMenuItemCheckIcon(JMenuItem menuItem) { 744 this.type = getType(menuItem); 745 this.menuItem = menuItem; 746 } 747 VistaMenuItemCheckIcon(String type) { 748 this.type = getType(type); 749 this.menuItem = null; 750 } 751 752 public int getIconHeight() { 753 Icon lafIcon = getLaFIcon(); 754 if (lafIcon != null) { 755 return lafIcon.getIconHeight(); 756 } 757 Icon icon = getIcon(); 758 int height = 0; 759 if (icon != null) { 760 height = icon.getIconHeight() + 2 * OFFSET; 761 } else { 762 XPStyle xp = XPStyle.getXP(); 763 if (xp != null) { 764 Skin skin = xp.getSkin(null, Part.MP_POPUPCHECK); 765 height = skin.getHeight() + 2 * OFFSET; 766 } else { 767 height = 16 + 2 * OFFSET; 768 } 769 } 770 return height; 771 } 772 773 public int getIconWidth() { 774 Icon lafIcon = getLaFIcon(); 775 if (lafIcon != null) { 776 return lafIcon.getIconWidth(); 777 } 778 Icon icon = getIcon(); 779 int width = 0; 780 if (icon != null) { 781 width = icon.getIconWidth() + 2 * OFFSET; 782 } else { 783 width = VistaMenuItemCheckIconFactory.getIconWidth(); 784 } 785 return width; 786 } 787 788 public void paintIcon(Component c, Graphics g, int x, int y) { 789 Icon lafIcon = getLaFIcon(); 790 if (lafIcon != null) { 791 lafIcon.paintIcon(c, g, x, y); 792 return; 793 } 794 assert menuItem == null || c == menuItem; 795 Icon icon = getIcon(); 796 if (type == JCheckBoxMenuItem.class 797 || type == JRadioButtonMenuItem.class) { 798 AbstractButton b = (AbstractButton) c; 799 if (b.isSelected()) { 800 Part backgroundPart = Part.MP_POPUPCHECKBACKGROUND; 801 Part part = Part.MP_POPUPCHECK; 802 State backgroundState; 803 State state; 804 if (isEnabled(c, null)) { 805 backgroundState = 806 (icon != null) ? State.BITMAP : State.NORMAL; 807 state = (type == JRadioButtonMenuItem.class) 808 ? State.BULLETNORMAL 809 : State.CHECKMARKNORMAL; 810 } else { 811 backgroundState = State.DISABLEDPUSHED; 812 state = 813 (type == JRadioButtonMenuItem.class) 814 ? State.BULLETDISABLED 815 : State.CHECKMARKDISABLED; 816 } 817 Skin skin; 818 XPStyle xp = XPStyle.getXP(); 819 skin = xp.getSkin(c, backgroundPart); 820 skin.paintSkin(g, x, y, 821 getIconWidth(), getIconHeight(), backgroundState); 822 if (icon == null) { 823 skin = xp.getSkin(c, part); 824 skin.paintSkin(g, x + OFFSET, y + OFFSET, state); 825 } 826 } 827 } 828 if (icon != null) { 829 icon.paintIcon(c, g, x + OFFSET, y + OFFSET); 830 } 831 } 832 private static WindowsMenuItemUIAccessor getAccessor( 833 JMenuItem menuItem) { 834 WindowsMenuItemUIAccessor rv = null; 835 ButtonUI uiObject = (menuItem != null) ? menuItem.getUI() 836 : null; 837 if (uiObject instanceof WindowsMenuItemUI) { 838 rv = ((WindowsMenuItemUI) uiObject).accessor; 839 } else if (uiObject instanceof WindowsMenuUI) { 840 rv = ((WindowsMenuUI) uiObject).accessor; 841 } else if (uiObject instanceof WindowsCheckBoxMenuItemUI) { 842 rv = ((WindowsCheckBoxMenuItemUI) uiObject).accessor; 843 } else if (uiObject instanceof WindowsRadioButtonMenuItemUI) { 844 rv = ((WindowsRadioButtonMenuItemUI) uiObject).accessor; 845 } 846 return rv; 847 } 848 849 private static boolean isEnabled(Component c, State state) { 850 if (state == null && c instanceof JMenuItem) { 851 WindowsMenuItemUIAccessor accessor = 852 getAccessor((JMenuItem) c); 853 if (accessor != null) { 854 state = accessor.getState((JMenuItem) c); 855 } 856 } 857 if (state == null) { 858 if (c != null) { 859 return c.isEnabled(); 860 } else { 861 return true; 862 } 863 } else { 864 return (state != State.DISABLED) 865 && (state != State.DISABLEDHOT) 866 && (state != State.DISABLEDPUSHED); 867 } 868 } 869 private Icon getIcon() { 870 Icon rv = null; 871 if (menuItem == null) { 872 return rv; 873 } 874 WindowsMenuItemUIAccessor accessor = 875 getAccessor(menuItem); 876 State state = (accessor != null) ? accessor.getState(menuItem) 877 : null; 878 if (isEnabled(menuItem, null)) { 879 if (state == State.PUSHED) { 880 rv = menuItem.getPressedIcon(); 881 } else { 882 rv = menuItem.getIcon(); 883 } 884 } else { 885 rv = menuItem.getDisabledIcon(); 886 } 887 return rv; 888 } 889 /** 890 * Check if developer changed icon in the UI table. 891 * 892 * @return the icon to use or {@code null} if the current one is to 893 * be used 894 */ 895 private Icon getLaFIcon() { 896 // use icon from the UI table if it does not match this one. 897 Icon rv = (Icon) UIManager.getDefaults().get(typeToString(type)); 898 if (rv instanceof VistaMenuItemCheckIcon 899 && ((VistaMenuItemCheckIcon) rv).type == type) { 900 rv = null; 901 } 902 return rv; 903 } 904 905 private static String typeToString( 906 Class<? extends JMenuItem> type) { 907 assert type == JMenuItem.class 908 || type == JMenu.class 909 || type == JCheckBoxMenuItem.class 910 || type == JRadioButtonMenuItem.class; 911 StringBuilder sb = new StringBuilder(type.getName()); 912 // remove package name, dot and the first character 913 sb.delete(0, sb.lastIndexOf("J") + 1); 914 sb.append(".checkIcon"); 915 return sb.toString(); 916 } 917 } 918 } // End class VistaMenuItemCheckIconFactory 919 }