001/* MetalComboBoxButton.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.Graphics;
044import java.awt.Insets;
045
046import javax.swing.CellRendererPane;
047import javax.swing.Icon;
048import javax.swing.JButton;
049import javax.swing.JComboBox;
050import javax.swing.JList;
051import javax.swing.ListCellRenderer;
052import javax.swing.UIManager;
053
054/**
055 * A button used by the {@link MetalComboBoxUI} class.
056 */
057public class MetalComboBoxButton
058  extends JButton
059{
060
061  /** A reference to the JComboBox that the button belongs to. */
062  protected JComboBox comboBox;
063
064  /** A reference to the JList. */
065  protected JList listBox;
066  
067  /**
068   * Used for rendering the selected item.
069   */
070  protected CellRendererPane rendererPane;
071  
072  /** The button icon. */
073  protected Icon comboIcon;
074  
075  /** Display just the icon, or the icon plus the label. */
076  protected boolean iconOnly;
077  
078  /**
079   * Creates a new button.
080   * 
081   * @param cb  the combo that the button is used for (<code>null</code> not 
082   *            permitted).
083   * @param i  the icon displayed on the button.
084   * @param pane  the rendering pane.
085   * @param list  the list.
086   */
087  public MetalComboBoxButton(JComboBox cb, Icon i, CellRendererPane pane,
088      JList list)
089  {
090    this(cb, i, cb.isEditable(), pane, list);  
091  }
092  
093  /**
094   * Creates a new button.
095   * 
096   * @param cb  the combo that the button is used for (<code>null</code> not 
097   *            permitted).
098   * @param i  the icon displayed on the button.
099   * @param onlyIcon  a flag that specifies whether the button displays only an
100   *                  icon, or text as well.
101   * @param pane  the rendering pane.
102   * @param list  the list.
103   */
104  public MetalComboBoxButton(JComboBox cb, Icon i, boolean onlyIcon,
105      CellRendererPane pane, JList list)
106  {
107    super();
108    if (cb == null)
109      throw new NullPointerException("Null 'cb' argument");
110    comboBox = cb;
111    comboIcon = i;
112    iconOnly = onlyIcon;
113    listBox = list;
114    rendererPane = pane;
115    setRolloverEnabled(false);
116    setEnabled(comboBox.isEnabled());
117    setFocusable(comboBox.isEnabled());
118  }
119  
120  /**
121   * Returns the combo box that the button is used with.
122   * 
123   * @return The combo box.
124   */
125  public final JComboBox getComboBox()
126  {
127    return comboBox;
128  }
129  
130  /**
131   * Sets the combo box that the button is used with.
132   * 
133   * @param cb  the combo box.
134   */
135  public final void setComboBox(JComboBox cb)
136  {
137    comboBox = cb;
138  }
139  
140  /**
141   * Returns the icon displayed by the button.  By default, this will be an
142   * instance of {@link MetalComboBoxIcon}.
143   * 
144   * @return The icon displayed by the button.
145   */
146  public final Icon getComboIcon()
147  {
148    return comboIcon;
149  }
150  
151  /**
152   * Sets the icon displayed by the button.
153   * 
154   * @param i  the icon.
155   */
156  public final void setComboIcon(Icon i)
157  {
158    comboIcon = i;
159  }
160  
161  /**
162   * Returns a flag that controls whether the button displays an icon only,
163   * or text as well.
164   * 
165   * @return A boolean.
166   */
167  public final boolean isIconOnly()
168  {
169    return iconOnly;
170  }
171  
172  /**
173   * Sets the flag that controls whether the button displays an icon only,
174   * or text as well.
175   * 
176   * @param isIconOnly  the flag.
177   */
178  public final void setIconOnly(boolean isIconOnly)
179  {
180    iconOnly = isIconOnly;
181  }
182  
183  /**
184   * Returns <code>false</code>, to indicate that this component is not part
185   * of the focus traversal group.
186   * 
187   * @return <code>false</code>
188   */
189  public boolean isFocusTraversable()
190  {
191    return false;
192  }
193  
194  /**
195   * Enables or disables the button.
196   * 
197   * @param enabled  the new status.
198   */
199  public void setEnabled(boolean enabled)
200  {
201    super.setEnabled(enabled);
202    if (enabled)
203      {
204        setBackground(comboBox.getBackground());
205        setForeground(comboBox.getForeground());
206      }
207    else
208      {
209        setBackground(UIManager.getColor("ComboBox.disabledBackground"));
210        setForeground(UIManager.getColor("ComboBox.disabledForeground"));
211      }
212  }
213  
214  /**
215   * Paints the component.
216   * 
217   * @param g  the graphics device.
218   */
219  public void paintComponent(Graphics g)
220  {
221    super.paintComponent(g);
222    Insets insets = this.getInsets();
223    int w = getWidth() - (insets.left + insets.right);
224    int h = getHeight() - (insets.top + insets.bottom);
225    if (h > 0 && w > 0)
226      {
227        int x1 = insets.left;
228        int y1 = insets.top;
229        int x2 = x1 + (w - 1);
230        int y2 = y1 + (h - 1);
231        int iconWidth = 0;
232        int iconX = x2;
233        if (comboIcon != null)
234          {
235            iconWidth = comboIcon.getIconWidth();
236            int iconHeight = comboIcon.getIconHeight();
237            int iconY;
238            if (iconOnly)
239              {
240                iconX = getWidth() / 2 - iconWidth / 2;
241                iconY = getHeight() / 2 - iconHeight / 2;
242              }
243            else
244              {
245                iconX = x1 + (w - 1) - iconWidth;
246                iconY = y1 + (y2 - y1) / 2 - iconHeight / 2;
247              }
248            comboIcon.paintIcon(this, g, iconX, iconY);
249            if (this.hasFocus())
250              {
251                g.setColor(MetalLookAndFeel.getFocusColor());
252                g.drawRect(x1 - 1, y1 - 1, w + 3, h + 1);
253              }
254          }
255        if (! iconOnly && comboBox != null)
256          {
257            ListCellRenderer renderer = comboBox.getRenderer();
258            boolean pressed = this.getModel().isPressed();
259            Component comp = renderer.getListCellRendererComponent(listBox,
260                comboBox.getSelectedItem(), -1, false, false);
261            comp.setFont(rendererPane.getFont());
262            
263            if ((model.isArmed() && model.isPressed())
264                || (comboBox.isFocusOwner() && !comboBox.isPopupVisible()))
265              {
266                if (isOpaque())
267                  {
268                    comp.setBackground(UIManager.getColor("Button.select"));
269                    comp.setForeground(comboBox.getForeground());
270                  }
271              }
272            else if (! comboBox.isEnabled())
273              {
274                if (this.isOpaque())
275                  {
276                    Color dbg =
277                      UIManager.getColor("ComboBox.disabledBackground");
278                    comp.setBackground(dbg);
279                    Color dfg =
280                      UIManager.getColor("ComboBox.disabledForeground");
281                    comp.setForeground(dfg);
282                  }
283              }
284            else
285              {
286                comp.setForeground(comboBox.getForeground());
287                comp.setBackground(comboBox.getBackground());
288              }
289            int wr = w - (insets.right + iconWidth);
290            rendererPane.paintComponent(g, comp, this, x1, y1, wr, h);
291          }
292      }
293  }
294}