001 /*
002 * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.swing.plaf.synth;
027
028 import java.awt.*;
029 import java.awt.event.*;
030 import java.lang.reflect.*;
031 import javax.swing.*;
032 import javax.accessibility.*;
033 import javax.swing.FocusManager;
034 import javax.swing.plaf.*;
035 import javax.swing.border.*;
036 import javax.swing.text.*;
037 import javax.swing.event.*;
038 import javax.swing.plaf.basic.*;
039 import java.beans.PropertyChangeListener;
040 import java.beans.PropertyChangeEvent;
041 import sun.awt.AppContext;
042 import sun.swing.plaf.synth.SynthUI;
043
044 /**
045 * Synth's ComboBoxUI.
046 *
047 * @version 1.25, 05/05/07
048 * @author Scott Violet
049 */
050 class SynthComboBoxUI extends BasicComboBoxUI implements
051 PropertyChangeListener, SynthUI {
052 private SynthStyle style;
053 private boolean useListColors;
054
055 public static ComponentUI createUI(JComponent c) {
056 return new SynthComboBoxUI();
057 }
058
059 protected void installDefaults() {
060 updateStyle(comboBox);
061 }
062
063 private void updateStyle(JComboBox comboBox) {
064 SynthStyle oldStyle = style;
065 SynthContext context = getContext(comboBox, ENABLED);
066
067 style = SynthLookAndFeel.updateStyle(context, this );
068 if (style != oldStyle) {
069 useListColors = style.getBoolean(context,
070 "ComboBox.rendererUseListColors", true);
071 if (oldStyle != null) {
072 uninstallKeyboardActions();
073 installKeyboardActions();
074 }
075 }
076 context.dispose();
077
078 if (listBox != null) {
079 SynthLookAndFeel.updateStyles(listBox);
080 }
081 }
082
083 protected void installListeners() {
084 comboBox.addPropertyChangeListener(this );
085 super .installListeners();
086 }
087
088 protected void uninstallDefaults() {
089 SynthContext context = getContext(comboBox, ENABLED);
090
091 style.uninstallDefaults(context);
092 context.dispose();
093 style = null;
094 }
095
096 protected void uninstallListeners() {
097 comboBox.removePropertyChangeListener(this );
098 super .uninstallListeners();
099 }
100
101 public SynthContext getContext(JComponent c) {
102 return getContext(c, getComponentState(c));
103 }
104
105 private SynthContext getContext(JComponent c, int state) {
106 return SynthContext.getContext(SynthContext.class, c,
107 SynthLookAndFeel.getRegion(c), style, state);
108 }
109
110 private Region getRegion(JComponent c) {
111 return SynthLookAndFeel.getRegion(c);
112 }
113
114 private int getComponentState(JComponent c) {
115 return SynthLookAndFeel.getComponentState(c);
116 }
117
118 protected ComboPopup createPopup() {
119 SynthComboPopup popup = new SynthComboPopup(comboBox);
120 return popup;
121 }
122
123 protected ListCellRenderer createRenderer() {
124 return new SynthComboBoxRenderer();
125 }
126
127 protected ComboBoxEditor createEditor() {
128 return new SynthComboBoxEditor();
129 }
130
131 //
132 // end UI Initialization
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(
143 SwingConstants.SOUTH);
144 button.setName("ComboBox.arrowButton");
145 return button;
146 }
147
148 //=================================
149 // begin ComponentUI Implementation
150
151 public void update(Graphics g, JComponent c) {
152 SynthContext context = getContext(c);
153
154 SynthLookAndFeel.update(context, g);
155 context.getPainter().paintComboBoxBackground(context, g, 0, 0,
156 c.getWidth(), c.getHeight());
157 paint(context, g);
158 context.dispose();
159 }
160
161 public void paint(Graphics g, JComponent c) {
162 SynthContext context = getContext(c);
163
164 paint(context, g);
165 context.dispose();
166 }
167
168 protected void paint(SynthContext context, Graphics g) {
169 hasFocus = comboBox.hasFocus();
170 if (!comboBox.isEditable()) {
171 Rectangle r = rectangleForCurrentValue();
172 paintCurrentValue(g, r, hasFocus);
173 }
174 }
175
176 public void paintBorder(SynthContext context, Graphics g, int x,
177 int y, int w, int h) {
178 context.getPainter()
179 .paintComboBoxBorder(context, g, x, y, w, h);
180 }
181
182 /**
183 * Paints the currently selected item.
184 */
185 public void paintCurrentValue(Graphics g, Rectangle bounds,
186 boolean hasFocus) {
187 ListCellRenderer renderer = comboBox.getRenderer();
188 Component c;
189
190 if (hasFocus && !isPopupVisible(comboBox)) {
191 c = renderer.getListCellRendererComponent(listBox, comboBox
192 .getSelectedItem(), -1, false, false);
193 } else {
194 c = renderer.getListCellRendererComponent(listBox, comboBox
195 .getSelectedItem(), -1, false, false);
196 }
197 // Fix for 4238829: should lay out the JPanel.
198 boolean shouldValidate = false;
199 if (c instanceof JPanel) {
200 shouldValidate = true;
201 }
202
203 if (c instanceof UIResource) {
204 c.setName("ComboBox.renderer");
205 currentValuePane.paintComponent(g, c, comboBox, bounds.x,
206 bounds.y, bounds.width, bounds.height,
207 shouldValidate);
208 } else {
209 currentValuePane.paintComponent(g, c, comboBox, bounds.x,
210 bounds.y, bounds.width, bounds.height,
211 shouldValidate);
212 }
213 }
214
215 /**
216 * From BasicComboBoxRenderer v 1.18.
217 */
218 private class SynthComboBoxRenderer extends JLabel implements
219 ListCellRenderer, UIResource {
220 public SynthComboBoxRenderer() {
221 super ();
222 setText(" ");
223 }
224
225 public String getName() {
226 // As SynthComboBoxRenderer's are asked for a size BEFORE they
227 // are parented getName is overriden to force the name to be
228 // ComboBox.renderer if it isn't set. If we didn't do this the
229 // wrong style could be used for size calculations.
230 String name = super .getName();
231 if (name == null) {
232 return "ComboBox.renderer";
233 }
234 return name;
235 }
236
237 public Component getListCellRendererComponent(JList list,
238 Object value, int index, boolean isSelected,
239 boolean cellHasFocus) {
240 setName("ComboBox.listRenderer");
241 SynthLookAndFeel.resetSelectedUI();
242 if (isSelected) {
243 setBackground(list.getSelectionBackground());
244 setForeground(list.getSelectionForeground());
245 if (!useListColors) {
246 SynthLookAndFeel.setSelectedUI(
247 (SynthLabelUI) SynthLookAndFeel
248 .getUIOfType(getUI(),
249 SynthLabelUI.class),
250 isSelected, cellHasFocus, list.isEnabled(),
251 false);
252 }
253 } else {
254 setBackground(list.getBackground());
255 setForeground(list.getForeground());
256 }
257
258 setFont(list.getFont());
259
260 if (value instanceof Icon) {
261 setIcon((Icon) value);
262 setText("");
263 } else {
264 String text = (value == null) ? " " : value.toString();
265
266 if ("".equals(text)) {
267 text = " ";
268 }
269 setText(text);
270 }
271
272 // The renderer component should inherit the enabled and
273 // orientation state of its parent combobox. This is
274 // especially needed for GTK comboboxes, where the
275 // ListCellRenderer's state determines the visual state
276 // of the combobox.
277 setEnabled(comboBox.isEnabled());
278 setComponentOrientation(comboBox.getComponentOrientation());
279
280 return this ;
281 }
282
283 public void paint(Graphics g) {
284 super .paint(g);
285 SynthLookAndFeel.resetSelectedUI();
286 }
287 }
288
289 /**
290 * From BasicCombBoxEditor v 1.24.
291 */
292 private static class SynthComboBoxEditor implements ComboBoxEditor,
293 UIResource {
294 protected JTextField editor;
295 private Object oldValue;
296
297 public SynthComboBoxEditor() {
298 editor = new JTextField("", 9);
299 editor.setName("ComboBox.textField");
300 }
301
302 public Component getEditorComponent() {
303 return editor;
304 }
305
306 /**
307 * Sets the item that should be edited.
308 *
309 * @param anObject the displayed value of the editor
310 */
311 public void setItem(Object anObject) {
312 String text;
313
314 if (anObject != null) {
315 text = anObject.toString();
316 oldValue = anObject;
317 } else {
318 text = "";
319 }
320 // workaround for 4530952
321 if (!text.equals(editor.getText())) {
322 editor.setText(text);
323 }
324 }
325
326 public Object getItem() {
327 Object newValue = editor.getText();
328
329 if (oldValue != null && !(oldValue instanceof String)) {
330 // The original value is not a string. Should return the value in it's
331 // original type.
332 if (newValue.equals(oldValue.toString())) {
333 return oldValue;
334 } else {
335 // Must take the value from the editor and get the value and cast it to the new type.
336 Class cls = oldValue.getClass();
337 try {
338 Method method = cls.getMethod("valueOf",
339 new Class[] { String.class });
340 newValue = method.invoke(oldValue,
341 new Object[] { editor.getText() });
342 } catch (Exception ex) {
343 // Fail silently and return the newValue (a String object)
344 }
345 }
346 }
347 return newValue;
348 }
349
350 public void selectAll() {
351 editor.selectAll();
352 editor.requestFocus();
353 }
354
355 public void addActionListener(ActionListener l) {
356 editor.addActionListener(l);
357 }
358
359 public void removeActionListener(ActionListener l) {
360 editor.removeActionListener(l);
361 }
362 }
363 }
|