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