1 /* 2 * Copyright (c) 2000, 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 sun.swing.SwingUtilities2; 29 30 import java.awt.*; 31 32 import javax.swing.*; 33 import javax.swing.plaf.UIResource; 34 35 import static com.sun.java.swing.plaf.windows.TMSchema.*; 36 37 /** 38 * A collection of static utility methods used for rendering the Windows look 39 * and feel. 40 * 41 * @author Mark Davidson 42 * @since 1.4 43 */ 44 public class WindowsGraphicsUtils { 45 46 /** 47 * Renders a text String in Windows without the mnemonic. 48 * This is here because the WindowsUI hiearchy doesn't match the Component heirarchy. All 49 * the overriden paintText methods of the ButtonUI delegates will call this static method. 50 * <p> 51 * @param g Graphics context 52 * @param b Current button to render 53 * @param textRect Bounding rectangle to render the text. 54 * @param text String to render 55 */ 56 public static void paintText(Graphics g, AbstractButton b, 57 Rectangle textRect, String text, 58 int textShiftOffset) { 59 FontMetrics fm = SwingUtilities2.getFontMetrics(b, g); 60 61 int mnemIndex = b.getDisplayedMnemonicIndex(); 62 // W2K Feature: Check to see if the Underscore should be rendered. 63 if (WindowsLookAndFeel.isMnemonicHidden() == true) { 64 mnemIndex = -1; 65 } 66 67 XPStyle xp = XPStyle.getXP(); 68 if (xp != null && !(b instanceof JMenuItem)) { 69 paintXPText(b, g, textRect.x + textShiftOffset, 70 textRect.y + fm.getAscent() + textShiftOffset, 71 text, mnemIndex); 72 } else { 73 paintClassicText(b, g, textRect.x + textShiftOffset, 74 textRect.y + fm.getAscent() + textShiftOffset, 75 text, mnemIndex); 76 } 77 } 78 79 static void paintClassicText(AbstractButton b, Graphics g, int x, int y, 80 String text, int mnemIndex) { 81 ButtonModel model = b.getModel(); 82 83 /* Draw the Text */ 84 Color color = b.getForeground(); 85 if(model.isEnabled()) { 86 /*** paint the text normally */ 87 if(!(b instanceof JMenuItem && model.isArmed()) 88 && !(b instanceof JMenu && (model.isSelected() || model.isRollover()))) { 89 /* We shall not set foreground color for selected menu or 90 * armed menuitem. Foreground must be set in appropriate 91 * Windows* class because these colors passes from 92 * BasicMenuItemUI as protected fields and we can't 93 * reach them from this class */ 94 g.setColor(b.getForeground()); 95 } 96 SwingUtilities2.drawStringUnderlineCharAt(b, g,text, mnemIndex, x, y); 97 } else { /*** paint the text disabled ***/ 98 color = UIManager.getColor("Button.shadow"); 99 Color shadow = UIManager.getColor("Button.disabledShadow"); 100 if(model.isArmed()) { 101 color = UIManager.getColor("Button.disabledForeground"); 102 } else { 103 if (shadow == null) { 104 shadow = b.getBackground().darker(); 105 } 106 g.setColor(shadow); 107 SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, 108 x + 1, y + 1); 109 } 110 if (color == null) { 111 color = b.getBackground().brighter(); 112 } 113 g.setColor(color); 114 SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); 115 } 116 } 117 118 static void paintXPText(AbstractButton b, Graphics g, int x, int y, 119 String text, int mnemIndex) { 120 Part part = WindowsButtonUI.getXPButtonType(b); 121 State state = WindowsButtonUI.getXPButtonState(b); 122 paintXPText(b, part, state, g, x, y, text, mnemIndex); 123 } 124 125 static void paintXPText(AbstractButton b, Part part, State state, 126 Graphics g, int x, int y, String text, int mnemIndex) { 127 XPStyle xp = XPStyle.getXP(); 128 if (xp == null) { 129 return; 130 } 131 Color textColor = b.getForeground(); 132 133 if (textColor instanceof UIResource) { 134 textColor = xp.getColor(b, part, state, Prop.TEXTCOLOR, b.getForeground()); 135 // to work around an apparent bug in Windows, use the pushbutton 136 // color for disabled toolbar buttons if the disabled color is the 137 // same as the enabled color 138 if (part == Part.TP_BUTTON && state == State.DISABLED) { 139 Color enabledColor = xp.getColor(b, part, State.NORMAL, 140 Prop.TEXTCOLOR, b.getForeground()); 141 if(textColor.equals(enabledColor)) { 142 textColor = xp.getColor(b, Part.BP_PUSHBUTTON, state, 143 Prop.TEXTCOLOR, textColor); 144 } 145 } 146 // only draw shadow if developer hasn't changed the foreground color 147 // and if the current style has text shadows. 148 TypeEnum shadowType = xp.getTypeEnum(b, part, 149 state, Prop.TEXTSHADOWTYPE); 150 if (shadowType == TypeEnum.TST_SINGLE || 151 shadowType == TypeEnum.TST_CONTINUOUS) { 152 Color shadowColor = xp.getColor(b, part, state, 153 Prop.TEXTSHADOWCOLOR, Color.black); 154 Point offset = xp.getPoint(b, part, state, Prop.TEXTSHADOWOFFSET); 155 if (offset != null) { 156 g.setColor(shadowColor); 157 SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, 158 x + offset.x, 159 y + offset.y); 160 } 161 } 162 } 163 164 g.setColor(textColor); 165 SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); 166 } 167 168 static boolean isLeftToRight(Component c) { 169 return c.getComponentOrientation().isLeftToRight(); 170 } 171 172 /* 173 * Repaints all the components with the mnemonics in the given window and 174 * all its owned windows. 175 */ 176 static void repaintMnemonicsInWindow(Window w) { 177 if(w == null || !w.isShowing()) { 178 return; 179 } 180 181 Window[] ownedWindows = w.getOwnedWindows(); 182 for(int i=0;i<ownedWindows.length;i++) { 183 repaintMnemonicsInWindow(ownedWindows[i]); 184 } 185 186 repaintMnemonicsInContainer(w); 187 } 188 189 /* 190 * Repaints all the components with the mnemonics in container. 191 * Recursively searches for all the subcomponents. 192 */ 193 static void repaintMnemonicsInContainer(Container cont) { 194 Component c; 195 for(int i=0; i<cont.getComponentCount(); i++) { 196 c = cont.getComponent(i); 197 if(c == null || !c.isVisible()) { 198 continue; 199 } 200 if(c instanceof AbstractButton 201 && ((AbstractButton)c).getMnemonic() != '\0') { 202 c.repaint(); 203 continue; 204 } else if(c instanceof JLabel 205 && ((JLabel)c).getDisplayedMnemonic() != '\0') { 206 c.repaint(); 207 continue; 208 } 209 if(c instanceof Container) { 210 repaintMnemonicsInContainer((Container)c); 211 } 212 } 213 } 214 }