1 /* 2 * Copyright (c) 2000, 2015, 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 hierarchy doesn't match the Component hierarchy. All 49 * the overriden paintText methods of the ButtonUI delegates will call this static method. 50 * 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 = getDisabledTextColor(b); 99 if (color == null) { 100 color = UIManager.getColor("Button.shadow"); 101 } 102 Color shadow = UIManager.getColor("Button.disabledShadow"); 103 if(model.isArmed()) { 104 color = UIManager.getColor("Button.disabledForeground"); 105 } else { 106 if (shadow == null) { 107 shadow = b.getBackground().darker(); 108 } 109 g.setColor(shadow); 110 SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, 111 x + 1, y + 1); 112 } 113 if (color == null) { 114 color = b.getBackground().brighter(); 115 } 116 g.setColor(color); 117 SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); 118 } 119 } 120 121 private static Color getDisabledTextColor(AbstractButton b) { 122 if (b instanceof JCheckBox) { 123 return UIManager.getColor("CheckBox.disabledText"); 124 } else if (b instanceof JRadioButton) { 125 return UIManager.getColor("RadioButton.disabledText"); 126 } else if (b instanceof JToggleButton) { 127 return UIManager.getColor("ToggleButton.disabledText"); 128 } else if (b instanceof JButton) { 129 return UIManager.getColor("Button.disabledText"); 130 } 131 return null; 132 } 133 134 static void paintXPText(AbstractButton b, Graphics g, int x, int y, 135 String text, int mnemIndex) { 136 Part part = WindowsButtonUI.getXPButtonType(b); 137 State state = WindowsButtonUI.getXPButtonState(b); 138 paintXPText(b, part, state, g, x, y, text, mnemIndex); 139 } 140 141 static void paintXPText(AbstractButton b, Part part, State state, 142 Graphics g, int x, int y, String text, int mnemIndex) { 143 XPStyle xp = XPStyle.getXP(); 144 if (xp == null) { 145 return; 146 } 147 Color textColor; 148 if (b.isEnabled()) { 149 textColor = b.getForeground(); 150 } 151 else { 152 textColor = getDisabledTextColor(b); 153 } 154 155 if (textColor == null || textColor instanceof UIResource) { 156 textColor = xp.getColor(b, part, state, Prop.TEXTCOLOR, b.getForeground()); 157 // to work around an apparent bug in Windows, use the pushbutton 158 // color for disabled toolbar buttons if the disabled color is the 159 // same as the enabled color 160 if (part == Part.TP_BUTTON && state == State.DISABLED) { 161 Color enabledColor = xp.getColor(b, part, State.NORMAL, 162 Prop.TEXTCOLOR, b.getForeground()); 163 if(textColor.equals(enabledColor)) { 164 textColor = xp.getColor(b, Part.BP_PUSHBUTTON, state, 165 Prop.TEXTCOLOR, textColor); 166 } 167 } 168 // only draw shadow if developer hasn't changed the foreground color 169 // and if the current style has text shadows. 170 TypeEnum shadowType = xp.getTypeEnum(b, part, 171 state, Prop.TEXTSHADOWTYPE); 172 if (shadowType == TypeEnum.TST_SINGLE || 173 shadowType == TypeEnum.TST_CONTINUOUS) { 174 Color shadowColor = xp.getColor(b, part, state, 175 Prop.TEXTSHADOWCOLOR, Color.black); 176 Point offset = xp.getPoint(b, part, state, Prop.TEXTSHADOWOFFSET); 177 if (offset != null) { 178 g.setColor(shadowColor); 179 SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, 180 x + offset.x, 181 y + offset.y); 182 } 183 } 184 } 185 186 g.setColor(textColor); 187 SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); 188 } 189 190 static boolean isLeftToRight(Component c) { 191 return c.getComponentOrientation().isLeftToRight(); 192 } 193 194 /* 195 * Repaints all the components with the mnemonics in the given window and 196 * all its owned windows. 197 */ 198 static void repaintMnemonicsInWindow(Window w) { 199 if(w == null || !w.isShowing()) { 200 return; 201 } 202 203 Window[] ownedWindows = w.getOwnedWindows(); 204 for(int i=0;i<ownedWindows.length;i++) { 205 repaintMnemonicsInWindow(ownedWindows[i]); 206 } 207 208 repaintMnemonicsInContainer(w); 209 } 210 211 /* 212 * Repaints all the components with the mnemonics in container. 213 * Recursively searches for all the subcomponents. 214 */ 215 static void repaintMnemonicsInContainer(Container cont) { 216 Component c; 217 for(int i=0; i<cont.getComponentCount(); i++) { 218 c = cont.getComponent(i); 219 if(c == null || !c.isVisible()) { 220 continue; 221 } 222 if(c instanceof AbstractButton 223 && ((AbstractButton)c).getMnemonic() != '\0') { 224 c.repaint(); 225 continue; 226 } else if(c instanceof JLabel 227 && ((JLabel)c).getDisplayedMnemonic() != '\0') { 228 c.repaint(); 229 continue; 230 } 231 if(c instanceof Container) { 232 repaintMnemonicsInContainer((Container)c); 233 } 234 } 235 } 236 }