001/* MetalButtonUI.java 002 Copyright (C) 2005 Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package javax.swing.plaf.metal; 040 041import java.awt.Color; 042import java.awt.Component; 043import java.awt.Font; 044import java.awt.FontMetrics; 045import java.awt.Graphics; 046import java.awt.Rectangle; 047 048import javax.swing.AbstractButton; 049import javax.swing.ButtonModel; 050import javax.swing.JButton; 051import javax.swing.JComponent; 052import javax.swing.JToolBar; 053import javax.swing.SwingConstants; 054import javax.swing.UIManager; 055import javax.swing.plaf.ComponentUI; 056import javax.swing.plaf.UIResource; 057import javax.swing.plaf.basic.BasicButtonUI; 058 059/** 060 * A UI delegate for the {@link JButton} component. 061 * 062 * @author Roman Kennke (roman@kennke.org) 063 */ 064public class MetalButtonUI 065 extends BasicButtonUI 066{ 067 068 /** 069 * The shared button UI. 070 */ 071 private static MetalButtonUI sharedUI; 072 073 /** 074 * The color used to draw the focus rectangle around the text and/or icon. 075 */ 076 protected Color focusColor; 077 078 /** 079 * The background color for the button when it is pressed. 080 */ 081 protected Color selectColor; 082 083 /** 084 * The color for disabled button labels. 085 */ 086 protected Color disabledTextColor; 087 088 /** 089 * Returns a UI delegate for the specified component. 090 * 091 * @param c the component (should be a subclass of {@link AbstractButton}). 092 * 093 * @return A new instance of <code>MetalButtonUI</code>. 094 */ 095 public static ComponentUI createUI(JComponent c) 096 { 097 if (sharedUI == null) 098 sharedUI = new MetalButtonUI(); 099 return sharedUI; 100 } 101 102 /** 103 * Creates a new instance. 104 */ 105 public MetalButtonUI() 106 { 107 super(); 108 } 109 110 /** 111 * Returns the color for the focus border. 112 * 113 * @return the color for the focus border 114 */ 115 protected Color getFocusColor() 116 { 117 focusColor = UIManager.getColor(getPropertyPrefix() + "focus"); 118 return focusColor; 119 } 120 121 /** 122 * Returns the color that indicates a selected button. 123 * 124 * @return the color that indicates a selected button 125 */ 126 protected Color getSelectColor() 127 { 128 selectColor = UIManager.getColor(getPropertyPrefix() + "select"); 129 return selectColor; 130 } 131 132 /** 133 * Returns the color for the text label of disabled buttons. 134 * 135 * @return the color for the text label of disabled buttons 136 */ 137 protected Color getDisabledTextColor() 138 { 139 disabledTextColor = UIManager.getColor(getPropertyPrefix() 140 + "disabledText"); 141 return disabledTextColor; 142 } 143 144 /** 145 * Installs the default settings for the specified button. 146 * 147 * @param button the button. 148 * 149 * @see #uninstallDefaults(AbstractButton) 150 */ 151 public void installDefaults(AbstractButton button) 152 { 153 // This is overridden to be public, for whatever reason. 154 super.installDefaults(button); 155 } 156 157 /** 158 * Removes the defaults added by {@link #installDefaults(AbstractButton)}. 159 */ 160 public void uninstallDefaults(AbstractButton button) 161 { 162 // This is overridden to be public, for whatever reason. 163 super.uninstallDefaults(button); 164 } 165 166 /** 167 * Paints the background of the button to indicate that it is in the 168 * "pressed" state. 169 * 170 * @param g the graphics context. 171 * @param b the button. 172 */ 173 protected void paintButtonPressed(Graphics g, AbstractButton b) 174 { 175 if (b.isContentAreaFilled()) 176 { 177 g.setColor(getSelectColor()); 178 g.fillRect(0, 0, b.getWidth(), b.getHeight()); 179 } 180 } 181 182 /** 183 * Paints the focus rectangle around the button text and/or icon. 184 * 185 * @param g the graphics context. 186 * @param b the button. 187 * @param viewRect the button bounds. 188 * @param textRect the text bounds. 189 * @param iconRect the icon bounds. 190 */ 191 protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, 192 Rectangle textRect, Rectangle iconRect) 193 { 194 if (b.isEnabled() && b.hasFocus() && b.isFocusPainted()) 195 { 196 Color savedColor = g.getColor(); 197 g.setColor(getFocusColor()); 198 Rectangle focusRect = iconRect.union(textRect); 199 g.drawRect(focusRect.x - 1, focusRect.y, 200 focusRect.width + 1, focusRect.height); 201 g.setColor(savedColor); 202 } 203 } 204 205 /** 206 * Paints the button text. 207 * 208 * @param g the graphics context. 209 * @param c the button. 210 * @param textRect the text bounds. 211 * @param text the text to display. 212 */ 213 protected void paintText(Graphics g, JComponent c, Rectangle textRect, 214 String text) 215 { 216 AbstractButton b = (AbstractButton) c; 217 Font f = b.getFont(); 218 g.setFont(f); 219 FontMetrics fm = g.getFontMetrics(f); 220 221 if (b.isEnabled()) 222 { 223 g.setColor(b.getForeground()); 224 g.drawString(text, textRect.x, textRect.y + fm.getAscent()); 225 } 226 else 227 { 228 g.setColor(getDisabledTextColor()); 229 g.drawString(text, textRect.x, textRect.y + fm.getAscent()); 230 } 231 } 232 233 /** 234 * If the property <code>Button.gradient</code> is set, then a gradient is 235 * painted as background, otherwise the normal superclass behaviour is 236 * called. 237 */ 238 public void update(Graphics g, JComponent c) 239 { 240 AbstractButton b = (AbstractButton) c; 241 if ((b.getBackground() instanceof UIResource) 242 && b.isContentAreaFilled() && b.isEnabled()) 243 { 244 ButtonModel m = b.getModel(); 245 String uiKey = "Button.gradient"; 246 if (! isToolbarButton(b)) 247 { 248 if (! m.isArmed() && ! m.isPressed() && isDrawingGradient(uiKey)) 249 { 250 MetalUtils.paintGradient(g, 0, 0, b.getWidth(), b.getHeight(), 251 SwingConstants.VERTICAL, 252 uiKey); 253 paint(g, c); 254 return; 255 } 256 } 257 else if (m.isRollover() && isDrawingGradient(uiKey)) 258 { 259 MetalUtils.paintGradient(g, 0, 0, b.getWidth(), b.getHeight(), 260 SwingConstants.VERTICAL, 261 uiKey); 262 paint(g, c); 263 return; 264 } 265 } 266 // Fallback if we didn't have any of the two above cases. 267 super.update(g, c); 268 } 269 270 /** 271 * Returns <code>true</code> when the button is a toolbar button, 272 * <code>false</code> otherwise. 273 * 274 * @param b the button component to test 275 * 276 * @return <code>true</code> when the button is a toolbar button, 277 * <code>false</code> otherwise 278 */ 279 private boolean isToolbarButton(Component b) 280 { 281 Component parent = b.getParent(); 282 return parent instanceof JToolBar; 283 } 284 285 /** 286 * Returns <code>true</code> if we should draw the button gradient, 287 * <code>false</code> otherwise. 288 * 289 * @param uiKey the UIManager key for the gradient 290 * 291 * @return <code>true</code> if we should draw the button gradient, 292 * <code>false</code> otherwise 293 */ 294 private boolean isDrawingGradient(String uiKey) 295 { 296 return (UIManager.get(uiKey) != null); 297 } 298}