1 /* 2 * Copyright (c) 1998, 2019, 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 javax.swing.plaf.metal; 27 28 import sun.swing.SwingUtilities2; 29 import sun.awt.AppContext; 30 31 import java.awt.*; 32 import java.awt.event.*; 33 import java.lang.ref.*; 34 import java.util.*; 35 import javax.swing.plaf.basic.BasicToggleButtonUI; 36 37 import javax.swing.*; 38 import javax.swing.border.*; 39 import javax.swing.plaf.*; 40 import javax.swing.*; 41 42 import java.io.Serializable; 43 44 /** 45 * MetalToggleButton implementation 46 * <p> 47 * <strong>Warning:</strong> 48 * Serialized objects of this class will not be compatible with 49 * future Swing releases. The current serialization support is 50 * appropriate for short term storage or RMI between applications running 51 * the same version of Swing. As of 1.4, support for long term storage 52 * of all JavaBeans 53 * has been added to the <code>java.beans</code> package. 54 * Please see {@link java.beans.XMLEncoder}. 55 * 56 * @author Tom Santos 57 */ 58 @SuppressWarnings("serial") // Same-version serialization only 59 public class MetalToggleButtonUI extends BasicToggleButtonUI { 60 61 private static final Object METAL_TOGGLE_BUTTON_UI_KEY = new Object(); 62 63 /** 64 * The color of a focused toggle button. 65 */ 66 protected Color focusColor; 67 68 /** 69 * The color of a selected button. 70 */ 71 protected Color selectColor; 72 73 /** 74 * The color of a disabled text. 75 */ 76 protected Color disabledTextColor; 77 78 private boolean defaults_initialized = false; 79 80 // ******************************** 81 // Create PLAF 82 // ******************************** 83 84 /** 85 * Constructs the {@code MetalToogleButtonUI}. 86 * 87 * @param b a component 88 * @return the {@code MetalToogleButtonUI}. 89 */ 90 public static ComponentUI createUI(JComponent b) { 91 AppContext appContext = AppContext.getAppContext(); 92 MetalToggleButtonUI metalToggleButtonUI = 93 (MetalToggleButtonUI) appContext.get(METAL_TOGGLE_BUTTON_UI_KEY); 94 if (metalToggleButtonUI == null) { 95 metalToggleButtonUI = new MetalToggleButtonUI(); 96 appContext.put(METAL_TOGGLE_BUTTON_UI_KEY, metalToggleButtonUI); 97 } 98 return metalToggleButtonUI; 99 } 100 101 // ******************************** 102 // Install Defaults 103 // ******************************** 104 public void installDefaults(AbstractButton b) { 105 super.installDefaults(b); 106 if(!defaults_initialized) { 107 focusColor = UIManager.getColor(getPropertyPrefix() + "focus"); 108 selectColor = UIManager.getColor(getPropertyPrefix() + "select"); 109 disabledTextColor = UIManager.getColor(getPropertyPrefix() + "disabledText"); 110 defaults_initialized = true; 111 } 112 } 113 114 protected void uninstallDefaults(AbstractButton b) { 115 super.uninstallDefaults(b); 116 defaults_initialized = false; 117 } 118 119 // ******************************** 120 // Default Accessors 121 // ******************************** 122 /** 123 * Returns the color of a selected button. 124 * 125 * @return the color of a selected button 126 */ 127 protected Color getSelectColor() { 128 return selectColor; 129 } 130 131 /** 132 * Returns the color of a disabled text. 133 * 134 * @return the color of a disabled text 135 */ 136 protected Color getDisabledTextColor() { 137 return disabledTextColor; 138 } 139 140 /** 141 * Returns the color of a focused toggle button. 142 * 143 * @return the color of a focused toggle button 144 */ 145 protected Color getFocusColor() { 146 return focusColor; 147 } 148 149 150 // ******************************** 151 // Paint Methods 152 // ******************************** 153 /** 154 * If necessary paints the background of the component, then invokes 155 * <code>paint</code>. 156 * 157 * @param g Graphics to paint to 158 * @param c JComponent painting on 159 * @throws NullPointerException if <code>g</code> or <code>c</code> is 160 * null 161 * @see javax.swing.plaf.ComponentUI#update 162 * @see javax.swing.plaf.ComponentUI#paint 163 * @since 1.5 164 */ 165 public void update(Graphics g, JComponent c) { 166 AbstractButton button = (AbstractButton)c; 167 if ((c.getBackground() instanceof UIResource) && 168 button.isContentAreaFilled() && c.isEnabled()) { 169 ButtonModel model = button.getModel(); 170 if (!MetalUtils.isToolBarButton(c)) { 171 if (!model.isArmed() && !model.isPressed() && 172 MetalUtils.drawGradient( 173 c, g, "ToggleButton.gradient", 0, 0, c.getWidth(), 174 c.getHeight(), true)) { 175 paint(g, c); 176 return; 177 } 178 } 179 else if ((model.isRollover() || model.isSelected()) && 180 MetalUtils.drawGradient(c, g, "ToggleButton.gradient", 181 0, 0, c.getWidth(), c.getHeight(), true)) { 182 paint(g, c); 183 return; 184 } 185 } 186 super.update(g, c); 187 } 188 189 protected void paintButtonPressed(Graphics g, AbstractButton b) { 190 if ( b.isContentAreaFilled() ) { 191 g.setColor(getSelectColor()); 192 g.fillRect(0, 0, b.getWidth(), b.getHeight()); 193 } 194 } 195 196 protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text) { 197 AbstractButton b = (AbstractButton) c; 198 ButtonModel model = b.getModel(); 199 FontMetrics fm = SwingUtilities2.getFontMetrics(b, g); 200 int mnemIndex = b.getDisplayedMnemonicIndex(); 201 202 /* Draw the Text */ 203 if(model.isEnabled()) { 204 /*** paint the text normally */ 205 g.setColor(b.getForeground()); 206 } 207 else { 208 /*** paint the text disabled ***/ 209 if (model.isSelected()) { 210 g.setColor(c.getBackground()); 211 } else { 212 g.setColor(getDisabledTextColor()); 213 } 214 } 215 SwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemIndex, 216 textRect.x, textRect.y + fm.getAscent()); 217 } 218 219 protected void paintFocus(Graphics g, AbstractButton b, 220 Rectangle viewRect, Rectangle textRect, Rectangle iconRect){ 221 222 Rectangle focusRect = new Rectangle(); 223 String text = b.getText(); 224 boolean isIcon = b.getIcon() != null; 225 226 // If there is text 227 if ( text != null && !text.isEmpty()) { 228 if ( !isIcon ) { 229 focusRect.setBounds( textRect ); 230 } 231 else { 232 focusRect.setBounds( iconRect.union( textRect ) ); 233 } 234 } 235 // If there is an icon and no text 236 else if ( isIcon ) { 237 focusRect.setBounds( iconRect ); 238 } 239 240 g.setColor(getFocusColor()); 241 g.drawRect((focusRect.x-1), (focusRect.y-1), 242 focusRect.width+1, focusRect.height+1); 243 244 } 245 246 /** 247 * Paints the appropriate icon of the button <code>b</code> in the 248 * space <code>iconRect</code>. 249 * 250 * @param g Graphics to paint to 251 * @param b Button to render for 252 * @param iconRect space to render in 253 * @throws NullPointerException if any of the arguments are null. 254 * @since 1.5 255 */ 256 protected void paintIcon(Graphics g, AbstractButton b, Rectangle iconRect) { 257 super.paintIcon(g, b, iconRect); 258 } 259 }