001    /* MetalToggleButtonUI.java
002       Copyright (C) 2005 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing.plaf.metal;
040    
041    import java.awt.Color;
042    import java.awt.Font;
043    import java.awt.FontMetrics;
044    import java.awt.Graphics;
045    import java.awt.Rectangle;
046    
047    import javax.swing.AbstractButton;
048    import javax.swing.ButtonModel;
049    import javax.swing.JComponent;
050    import javax.swing.JToggleButton;
051    import javax.swing.SwingConstants;
052    import javax.swing.SwingUtilities;
053    import javax.swing.UIManager;
054    import javax.swing.plaf.ComponentUI;
055    import javax.swing.plaf.UIResource;
056    import javax.swing.plaf.basic.BasicButtonUI;
057    import javax.swing.plaf.basic.BasicToggleButtonUI;
058    
059    /**
060     * A UI delegate for the {@link JToggleButton} component.
061     */
062    public class MetalToggleButtonUI
063      extends BasicToggleButtonUI
064    {
065    
066      /** The color for the focus border. */
067      protected Color focusColor;
068    
069      /** The color that indicates a selected button. */
070      protected Color selectColor;
071    
072      /** The color for disabled button labels. */
073      protected Color disabledTextColor;
074    
075      /**
076       * Returns a new instance of <code>MetalToggleButtonUI</code>.
077       *
078       * @param component the component for which we return an UI instance
079       *
080       * @return A new instance of <code>MetalToggleButtonUI</code>.
081       */
082      public static ComponentUI createUI(JComponent component)
083      {
084        return new MetalToggleButtonUI();
085      }
086    
087      /**
088       * Constructs a new instance of <code>MetalToggleButtonUI</code>.
089       */
090      public MetalToggleButtonUI()
091      {
092        super();
093      }
094    
095      /**
096       * Returns the color for the focus border.
097       *
098       * @return the color for the focus border
099       */
100      protected Color getFocusColor()
101      {
102        return focusColor;
103      }
104    
105      /**
106       * Returns the color that indicates a selected button.
107       *
108       * @return the color that indicates a selected button
109       */
110      protected Color getSelectColor()
111      {
112        return selectColor;
113      }
114    
115      /**
116       * Returns the color for the text label of disabled buttons.  The value 
117       * is initialised in the {@link #installDefaults(AbstractButton)} method
118       * by reading the <code>ToggleButton.disabledText</code> item from the UI 
119       * defaults.
120       *
121       * @return The color for the text label of disabled buttons.
122       */
123      protected Color getDisabledTextColor()
124      {
125        return disabledTextColor;
126      }
127    
128      /**
129       * Updates the button with the defaults for this look and feel.
130       * 
131       * @param b  the button.
132       */
133      public void installDefaults(AbstractButton b)
134      {
135        super.installDefaults(b);
136        focusColor = UIManager.getColor(getPropertyPrefix() + "focus");
137        selectColor = UIManager.getColor(getPropertyPrefix() + "select");
138        disabledTextColor = UIManager.getColor(getPropertyPrefix() + "disabledText");
139      }
140      
141      /**
142       * Paints the button background when it is pressed/selected. 
143       * 
144       * @param g  the graphics device.
145       * @param b  the button.
146       */
147      protected void paintButtonPressed(Graphics g, AbstractButton b)
148      {
149        if (b.isContentAreaFilled() && b.isOpaque())
150          {
151            Color saved = g.getColor();
152            Rectangle bounds = SwingUtilities.getLocalBounds(b);
153            g.setColor(selectColor);
154            g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
155            g.setColor(saved);
156          }
157      }
158      
159      /**
160       * Paints the text for the button.
161       * 
162       * As of JDK 1.4 this method is obsolete.
163       * Use {@link BasicButtonUI#paintText(java.awt.Graphics, 
164       * javax.swing.AbstractButton, java.awt.Rectangle, java.lang.String)}.
165       *
166       * @param g  the graphics device.
167       * @param c  the component.
168       * @param textRect  the bounds for the text.
169       * @param text  the text.
170       * 
171       */
172      protected void paintText(Graphics g, JComponent c, Rectangle textRect,
173                               String text)
174      {
175        Font savedFont = g.getFont();
176        Color savedColor = g.getColor();
177        g.setFont(c.getFont());
178        if (c.isEnabled())
179          g.setColor(c.getForeground());
180        else
181          g.setColor(disabledTextColor);
182        FontMetrics fm = g.getFontMetrics(c.getFont());
183        int ascent = fm.getAscent();
184        g.drawString(text, textRect.x, textRect.y + ascent);
185        g.setFont(savedFont);
186        g.setColor(savedColor);
187      }
188      
189      /**
190       * Draws the focus highlight around the text and icon.
191       * 
192       * @param g  the graphics device.
193       * @param b  the button.
194       */
195      protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect,
196          Rectangle textRect, Rectangle iconRect)
197      {
198        if (!b.hasFocus())
199          return;
200        Color saved = g.getColor();
201        g.setColor(focusColor);
202        Rectangle fr = iconRect.union(textRect);
203        g.drawRect(fr.x - 1, fr.y - 1, fr.width + 1, fr.height + 1);
204        g.setColor(saved);    
205      }
206    
207      /**
208       * If the property <code>ToggleButton.gradient</code> is set, then a gradient
209       * is painted as background, otherwise the normal superclass behaviour is
210       * called.
211       */
212      public void update(Graphics g, JComponent c)
213      {
214        AbstractButton b = (AbstractButton) c;
215        ButtonModel m = b.getModel();
216        if (b.getBackground() instanceof UIResource
217            && b.isContentAreaFilled()
218            && b.isEnabled() && ! m.isArmed() && ! m.isPressed()
219            && UIManager.get(getPropertyPrefix() + "gradient") != null)
220          {
221            MetalUtils.paintGradient(g, 0, 0, c.getWidth(), c.getHeight(),
222                                     SwingConstants.VERTICAL,
223                                     getPropertyPrefix() + "gradient");
224            paint(g, c);
225          }
226        else
227          super.update(g, c);
228      }
229      
230    }