001    /* MetalComboBoxButton.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.Component;
043    import java.awt.Graphics;
044    import java.awt.Insets;
045    
046    import javax.swing.CellRendererPane;
047    import javax.swing.Icon;
048    import javax.swing.JButton;
049    import javax.swing.JComboBox;
050    import javax.swing.JList;
051    import javax.swing.ListCellRenderer;
052    import javax.swing.UIManager;
053    
054    /**
055     * A button used by the {@link MetalComboBoxUI} class.
056     */
057    public 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    }