blob: 926c31e56e22f9160de6d91bb59f2deb34c56a0f [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.swing.plaf.synth;
27
28import java.awt.*;
29import java.awt.event.*;
30import java.lang.reflect.*;
31import javax.swing.*;
32import javax.accessibility.*;
33import javax.swing.FocusManager;
34import javax.swing.plaf.*;
35import javax.swing.border.*;
36import javax.swing.text.*;
37import javax.swing.event.*;
38import javax.swing.plaf.basic.*;
39import java.beans.PropertyChangeListener;
40import java.beans.PropertyChangeEvent;
41import sun.awt.AppContext;
42import sun.swing.plaf.synth.SynthUI;
43
44/**
45 * Synth's ComboBoxUI.
46 *
47 * @author Scott Violet
48 */
49class SynthComboBoxUI extends BasicComboBoxUI implements
50 PropertyChangeListener, SynthUI {
51 private SynthStyle style;
52 private boolean useListColors;
53
54 public static ComponentUI createUI(JComponent c) {
55 return new SynthComboBoxUI();
56 }
57
58 protected void installDefaults() {
59 updateStyle(comboBox);
60 }
61
62 private void updateStyle(JComboBox comboBox) {
63 SynthStyle oldStyle = style;
64 SynthContext context = getContext(comboBox, ENABLED);
65
66 style = SynthLookAndFeel.updateStyle(context, this);
67 if (style != oldStyle) {
68 useListColors = style.getBoolean(context,
69 "ComboBox.rendererUseListColors", true);
70 if (oldStyle != null) {
71 uninstallKeyboardActions();
72 installKeyboardActions();
73 }
74 }
75 context.dispose();
76
77 if(listBox != null) {
78 SynthLookAndFeel.updateStyles(listBox);
79 }
80 }
81
82 protected void installListeners() {
83 comboBox.addPropertyChangeListener(this);
84 super.installListeners();
85 }
86
87 protected void uninstallDefaults() {
88 SynthContext context = getContext(comboBox, ENABLED);
89
90 style.uninstallDefaults(context);
91 context.dispose();
92 style = null;
93 }
94
95 protected void uninstallListeners() {
96 comboBox.removePropertyChangeListener(this);
97 super.uninstallListeners();
98 }
99
100 public SynthContext getContext(JComponent c) {
101 return getContext(c, getComponentState(c));
102 }
103
104 private SynthContext getContext(JComponent c, int state) {
105 return SynthContext.getContext(SynthContext.class, c,
106 SynthLookAndFeel.getRegion(c), style, state);
107 }
108
109 private Region getRegion(JComponent c) {
110 return SynthLookAndFeel.getRegion(c);
111 }
112
113 private int getComponentState(JComponent c) {
114 return SynthLookAndFeel.getComponentState(c);
115 }
116
117 protected ComboPopup createPopup() {
118 SynthComboPopup popup = new SynthComboPopup( comboBox );
119 return popup;
120 }
121
122 protected ListCellRenderer createRenderer() {
123 return new SynthComboBoxRenderer();
124 }
125
126 protected ComboBoxEditor createEditor() {
127 return new SynthComboBoxEditor();
128 }
129
130 //
131 // end UI Initialization
132 //======================
133
134
135 public void propertyChange(PropertyChangeEvent e) {
136 if (SynthLookAndFeel.shouldUpdateStyle(e)) {
137 updateStyle(comboBox);
138 }
139 }
140
141 protected JButton createArrowButton() {
142 SynthArrowButton button = new SynthArrowButton(SwingConstants.SOUTH);
143 button.setName("ComboBox.arrowButton");
144 return button;
145 }
146
147 //=================================
148 // begin ComponentUI Implementation
149
150 public void update(Graphics g, JComponent c) {
151 SynthContext context = getContext(c);
152
153 SynthLookAndFeel.update(context, g);
154 context.getPainter().paintComboBoxBackground(context, g, 0, 0,
155 c.getWidth(), c.getHeight());
156 paint(context, g);
157 context.dispose();
158 }
159
160 public void paint(Graphics g, JComponent c) {
161 SynthContext context = getContext(c);
162
163 paint(context, g);
164 context.dispose();
165 }
166
167 protected void paint(SynthContext context, Graphics g) {
168 hasFocus = comboBox.hasFocus();
169 if ( !comboBox.isEditable() ) {
170 Rectangle r = rectangleForCurrentValue();
171 paintCurrentValue(g,r,hasFocus);
172 }
173 }
174
175 public void paintBorder(SynthContext context, Graphics g, int x,
176 int y, int w, int h) {
177 context.getPainter().paintComboBoxBorder(context, g, x, y, w, h);
178 }
179
180
181 /**
182 * Paints the currently selected item.
183 */
184 public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) {
185 ListCellRenderer renderer = comboBox.getRenderer();
186 Component c;
187
188 if ( hasFocus && !isPopupVisible(comboBox) ) {
189 c = renderer.getListCellRendererComponent( listBox,
190 comboBox.getSelectedItem(),
191 -1,
192 false,
193 false );
194 }
195 else {
196 c = renderer.getListCellRendererComponent( listBox,
197 comboBox.getSelectedItem(),
198 -1,
199 false,
200 false );
201 }
202 // Fix for 4238829: should lay out the JPanel.
203 boolean shouldValidate = false;
204 if (c instanceof JPanel) {
205 shouldValidate = true;
206 }
207
208 if (c instanceof UIResource) {
209 c.setName("ComboBox.renderer");
210 currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y,
211 bounds.width,bounds.height, shouldValidate);
212 }
213 else {
214 currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y,
215 bounds.width,bounds.height, shouldValidate);
216 }
217 }
218
219 /**
220 * From BasicComboBoxRenderer v 1.18.
221 */
222 private class SynthComboBoxRenderer extends JLabel implements ListCellRenderer, UIResource {
223 public SynthComboBoxRenderer() {
224 super();
225 setText(" ");
226 }
227
228 public String getName() {
229 // As SynthComboBoxRenderer's are asked for a size BEFORE they
230 // are parented getName is overriden to force the name to be
231 // ComboBox.renderer if it isn't set. If we didn't do this the
232 // wrong style could be used for size calculations.
233 String name = super.getName();
234 if (name == null) {
235 return "ComboBox.renderer";
236 }
237 return name;
238 }
239
240 public Component getListCellRendererComponent(JList list, Object value,
241 int index, boolean isSelected, boolean cellHasFocus) {
242 setName("ComboBox.listRenderer");
243 SynthLookAndFeel.resetSelectedUI();
244 if (isSelected) {
245 setBackground(list.getSelectionBackground());
246 setForeground(list.getSelectionForeground());
247 if (!useListColors) {
248 SynthLookAndFeel.setSelectedUI(
249 (SynthLabelUI)SynthLookAndFeel.getUIOfType(getUI(),
250 SynthLabelUI.class), isSelected, cellHasFocus,
251 list.isEnabled(), false);
252 }
253 }
254 else {
255 setBackground(list.getBackground());
256 setForeground(list.getForeground());
257 }
258
259 setFont(list.getFont());
260
261 if (value instanceof Icon) {
262 setIcon((Icon)value);
263 setText("");
264 }
265 else {
266 String text = (value == null) ? " " : value.toString();
267
268 if ("".equals(text)) {
269 text = " ";
270 }
271 setText(text);
272 }
273
274 // The renderer component should inherit the enabled and
275 // orientation state of its parent combobox. This is
276 // especially needed for GTK comboboxes, where the
277 // ListCellRenderer's state determines the visual state
278 // of the combobox.
279 setEnabled(comboBox.isEnabled());
280 setComponentOrientation(comboBox.getComponentOrientation());
281
282 return this;
283 }
284
285 public void paint(Graphics g) {
286 super.paint(g);
287 SynthLookAndFeel.resetSelectedUI();
288 }
289 }
290
291
292 /**
293 * From BasicCombBoxEditor v 1.24.
294 */
295 private static class SynthComboBoxEditor implements
296 ComboBoxEditor, UIResource {
297 protected JTextField editor;
298 private Object oldValue;
299
300 public SynthComboBoxEditor() {
301 editor = new JTextField("",9);
302 editor.setName("ComboBox.textField");
303 }
304
305 public Component getEditorComponent() {
306 return editor;
307 }
308
309 /**
310 * Sets the item that should be edited.
311 *
312 * @param anObject the displayed value of the editor
313 */
314 public void setItem(Object anObject) {
315 String text;
316
317 if ( anObject != null ) {
318 text = anObject.toString();
319 oldValue = anObject;
320 } else {
321 text = "";
322 }
323 // workaround for 4530952
324 if (!text.equals(editor.getText())) {
325 editor.setText(text);
326 }
327 }
328
329 public Object getItem() {
330 Object newValue = editor.getText();
331
332 if (oldValue != null && !(oldValue instanceof String)) {
333 // The original value is not a string. Should return the value in it's
334 // original type.
335 if (newValue.equals(oldValue.toString())) {
336 return oldValue;
337 } else {
338 // Must take the value from the editor and get the value and cast it to the new type.
339 Class cls = oldValue.getClass();
340 try {
341 Method method = cls.getMethod("valueOf", new Class[]{String.class});
342 newValue = method.invoke(oldValue, new Object[] { editor.getText()});
343 } catch (Exception ex) {
344 // Fail silently and return the newValue (a String object)
345 }
346 }
347 }
348 return newValue;
349 }
350
351 public void selectAll() {
352 editor.selectAll();
353 editor.requestFocus();
354 }
355
356 public void addActionListener(ActionListener l) {
357 editor.addActionListener(l);
358 }
359
360 public void removeActionListener(ActionListener l) {
361 editor.removeActionListener(l);
362 }
363 }
364}