1 /*
2 * Copyright (c) 1998, 2014, 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 java.awt.*;
29 import java.awt.event.*;
30 import javax.swing.plaf.basic.*;
31 import javax.swing.*;
32 import javax.swing.plaf.*;
33 import javax.swing.border.*;
34 import java.io.Serializable;
35
36 /**
37 * JButton subclass to help out MetalComboBoxUI
38 * <p>
39 * <strong>Warning:</strong>
40 * Serialized objects of this class will not be compatible with
41 * future Swing releases. The current serialization support is
42 * appropriate for short term storage or RMI between applications running
43 * the same version of Swing. As of 1.4, support for long term storage
44 * of all JavaBeans™
45 * has been added to the {@code java.beans} package.
46 * Please see {@link java.beans.XMLEncoder}.
47 *
48 * @see MetalComboBoxButton
49 * @author Tom Santos
50 */
51 @SuppressWarnings("serial") // Same-version serialization only
52 public class MetalComboBoxButton extends JButton {
53
54 /**
55 * The instance of {@code JComboBox}.
56 */
57 protected JComboBox<Object> comboBox;
58
59 /**
60 * The instance of {@code JList}.
61 */
62 protected JList<Object> listBox;
63
64 /**
65 * The instance of {@code CellRendererPane}.
66 */
67 protected CellRendererPane rendererPane;
68
69 /**
70 * The icon.
71 */
72 protected Icon comboIcon;
73
74 /**
75 * The {@code iconOnly} value.
76 */
77 protected boolean iconOnly = false;
78
79 /**
80 * Returns the {@code JComboBox}.
81 *
82 * @return the {@code JComboBox}
83 */
84 public final JComboBox<Object> getComboBox() { return comboBox;}
85
86 /**
87 * Sets the {@code JComboBox}.
88 *
89 * @param cb the {@code JComboBox}
90 */
91 public final void setComboBox( JComboBox<Object> cb ) { comboBox = cb;}
92
93 /**
94 * Returns the icon of the {@code JComboBox}.
95 *
96 * @return the icon of the {@code JComboBox}
97 */
98 public final Icon getComboIcon() { return comboIcon;}
99
100 /**
101 * Sets the icon of the {@code JComboBox}.
102 *
103 * @param i the icon of the {@code JComboBox}
104 */
105 public final void setComboIcon( Icon i ) { comboIcon = i;}
106
107 /**
108 * Returns the {@code isIconOnly} value.
109 *
110 * @return the {@code isIconOnly} value
111 */
112 public final boolean isIconOnly() { return iconOnly;}
113
114 /**
115 * If {@code isIconOnly} is {@code true} then only icon is painted.
116 *
117 * @param isIconOnly if {@code true} then only icon is painted
118 */
119 public final void setIconOnly( boolean isIconOnly ) { iconOnly = isIconOnly;}
120
121 MetalComboBoxButton() {
122 super( "" );
123 DefaultButtonModel model = new DefaultButtonModel() {
124 public void setArmed( boolean armed ) {
125 super.setArmed( isPressed() ? true : armed );
126 }
127 };
128 setModel( model );
129 }
130
131 /**
132 * Constructs a new instance of {@code MetalComboBoxButton}.
133 *
134 * @param cb an instance of {@code JComboBox}
135 * @param i an icon
136 * @param pane an instance of {@code CellRendererPane}
137 * @param list an instance of {@code JList}
138 */
139 public MetalComboBoxButton( JComboBox<Object> cb, Icon i,
140 CellRendererPane pane, JList<Object> list ) {
141 this();
142 comboBox = cb;
143 comboIcon = i;
144 rendererPane = pane;
145 listBox = list;
146 setEnabled( comboBox.isEnabled() );
147 }
148
149 /**
150 * Constructs a new instance of {@code MetalComboBoxButton}.
151 *
152 * @param cb an instance of {@code JComboBox}
153 * @param i an icon
154 * @param onlyIcon if {@code true} only icon is painted
155 * @param pane an instance of {@code CellRendererPane}
156 * @param list an instance of {@code JList}
157 */
158 public MetalComboBoxButton( JComboBox<Object> cb, Icon i, boolean onlyIcon,
159 CellRendererPane pane, JList<Object> list ) {
160 this( cb, i, pane, list );
161 iconOnly = onlyIcon;
162 }
163
164 @SuppressWarnings("deprecation")
165 public boolean isFocusTraversable() {
166 return false;
167 }
168
169 public void setEnabled(boolean enabled) {
170 super.setEnabled(enabled);
171
172 // Set the background and foreground to the combobox colors.
173 if (enabled) {
174 setBackground(comboBox.getBackground());
175 setForeground(comboBox.getForeground());
176 } else {
177 setBackground(UIManager.getColor("ComboBox.disabledBackground"));
178 setForeground(UIManager.getColor("ComboBox.disabledForeground"));
179 }
180 }
181
182 public void paintComponent( Graphics g ) {
183 boolean leftToRight = MetalUtils.isLeftToRight(comboBox);
184
185 // Paint the button as usual
186 super.paintComponent( g );
187
188 Insets insets = getInsets();
189
190 int width = getWidth() - (insets.left + insets.right);
191 int height = getHeight() - (insets.top + insets.bottom);
192
193 if ( height <= 0 || width <= 0 ) {
194 return;
195 }
196
197 int left = insets.left;
198 int top = insets.top;
199 int right = left + (width - 1);
200 int bottom = top + (height - 1);
201
202 int iconWidth = 0;
203 int iconLeft = (leftToRight) ? right : left;
204
205 // Paint the icon
206 if ( comboIcon != null ) {
207 iconWidth = comboIcon.getIconWidth();
208 int iconHeight = comboIcon.getIconHeight();
209 int iconTop = 0;
210
211 if ( iconOnly ) {
212 iconLeft = (getWidth() / 2) - (iconWidth / 2);
213 iconTop = (getHeight() / 2) - (iconHeight / 2);
214 }
215 else {
216 if (leftToRight) {
217 iconLeft = (left + (width - 1)) - iconWidth;
218 }
219 else {
220 iconLeft = left;
221 }
222 iconTop = (top + ((bottom - top) / 2)) - (iconHeight / 2);
223 }
224
225 comboIcon.paintIcon( this, g, iconLeft, iconTop );
226
227 // Paint the focus
228 if ( comboBox.hasFocus() && (!MetalLookAndFeel.usingOcean() ||
229 comboBox.isEditable())) {
230 g.setColor( MetalLookAndFeel.getFocusColor() );
231 g.drawRect( left - 1, top - 1, width + 3, height + 1 );
232 }
233 }
234
235 if (MetalLookAndFeel.usingOcean()) {
236 // With Ocean the button only paints the arrow, bail.
237 return;
238 }
239
240 // Let the renderer paint
241 if ( ! iconOnly && comboBox != null ) {
242 ListCellRenderer<Object> renderer = comboBox.getRenderer();
243 Component c;
244 boolean renderPressed = getModel().isPressed();
245 c = renderer.getListCellRendererComponent(listBox,
246 comboBox.getSelectedItem(),
247 -1,
248 renderPressed,
249 false);
250 c.setFont(rendererPane.getFont());
251
252 if ( model.isArmed() && model.isPressed() ) {
253 if ( isOpaque() ) {
254 c.setBackground(UIManager.getColor("Button.select"));
255 }
256 c.setForeground(comboBox.getForeground());
257 }
258 else if ( !comboBox.isEnabled() ) {
259 if ( isOpaque() ) {
260 c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
261 }
262 c.setForeground(UIManager.getColor("ComboBox.disabledForeground"));
263 }
264 else {
265 c.setForeground(comboBox.getForeground());
266 c.setBackground(comboBox.getBackground());
267 }
268
269
270 int cWidth = width - (insets.right + iconWidth);
271
272 // Fix for 4238829: should lay out the JPanel.
273 boolean shouldValidate = false;
274 if (c instanceof JPanel) {
275 shouldValidate = true;
276 }
277
278 if (leftToRight) {
279 rendererPane.paintComponent( g, c, this,
280 left, top, cWidth, height, shouldValidate );
281 }
282 else {
283 rendererPane.paintComponent( g, c, this,
284 left + iconWidth, top, cWidth, height, shouldValidate );
285 }
286 }
287 }
288
289 public Dimension getMinimumSize() {
290 Dimension ret = new Dimension();
291 Insets insets = getInsets();
292 ret.width = insets.left + getComboIcon().getIconWidth() + insets.right;
293 ret.height = insets.bottom + getComboIcon().getIconHeight() + insets.top;
294 return ret;
295 }
296 }
--- EOF ---