KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jgoodies > looks > plastic > PlasticComboBoxUI


1 /*
2  * Copyright (c) 2001-2005 JGoodies Karsten Lentzsch. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * o Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  *
10  * o Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * o Neither the name of JGoodies Karsten Lentzsch nor the names of
15  * its contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31 package com.jgoodies.looks.plastic;
32
33 import java.awt.*;
34 import java.beans.PropertyChangeEvent JavaDoc;
35 import java.beans.PropertyChangeListener JavaDoc;
36
37 import javax.swing.*;
38 import javax.swing.plaf.ComponentUI JavaDoc;
39 import javax.swing.plaf.basic.BasicComboBoxUI JavaDoc;
40 import javax.swing.plaf.basic.ComboPopup JavaDoc;
41 import javax.swing.plaf.metal.MetalComboBoxUI JavaDoc;
42 import javax.swing.plaf.metal.MetalScrollBarUI JavaDoc;
43
44
45 /**
46  * The JGoodies Plastic Look and Feel implementation of <code>ComboBoxUI</code>.
47  * Has the same height as text fields - unless you change the renderer.
48  *
49 * @author Karsten Lentzsch
50 * @version $Revision: 1.5 $
51  */

52
53 public final class PlasticComboBoxUI extends MetalComboBoxUI JavaDoc {
54
55     public static ComponentUI JavaDoc createUI(JComponent b) {
56         return new PlasticComboBoxUI();
57     }
58
59     /**
60      * Creates the editor that is to be used in editable combo boxes.
61      * This method only gets called if a custom editor has not already
62      * been installed in the JComboBox.
63      */

64     protected ComboBoxEditor createEditor() {
65         return new PlasticComboBoxEditor.UIResource();
66     }
67     
68
69     protected ComboPopup JavaDoc createPopup() {
70         return new PlasticComboPopup(comboBox);
71     }
72     
73
74     /**
75      * Gets the insets from the JComboBox.
76      */

77     private Insets getEditorInsets() {
78         if (editor instanceof JComponent) {
79             return ((JComponent)editor).getInsets();
80         }
81         return new Insets(0, 0, 0, 0);
82     }
83     
84     /**
85      * Computes and returns the width of the arrow button in editable state.
86      * The perceived width shall be equal to the width of a scroll bar.
87      * Therefore we subtract a pixel that is perceived as part of the
88      * arrow button but that is painted by the editor's border.
89      *
90      * @return the width of the arrow button in editable state
91      */

92     private int getEditableButtonWidth() {
93         return UIManager.getInt("ScrollBar.width") - 1;
94     }
95     
96     /**
97      * Overriden to correct the combobox height.
98      */

99     public Dimension getMinimumSize(JComponent c) {
100         if (!isMinimumSizeDirty) {
101             return new Dimension(cachedMinimumSize);
102         }
103
104         Dimension size = null;
105         
106         if (!comboBox.isEditable()
107             && arrowButton != null
108             && arrowButton instanceof PlasticComboBoxButton) {
109
110             PlasticComboBoxButton button =
111                 (PlasticComboBoxButton) arrowButton;
112             Insets buttonInsets = button.getInsets();
113             Insets buttonMargin = button.getMargin();
114             Insets insets = comboBox.getInsets();
115             size = getDisplaySize();
116             
117             // System.out.println("button insets=" + buttonInsets);
118
// System.out.println("button margin=" + buttonMargin);
119

120             /*
121              * The next line will lead to good results if used with standard renderers;
122              * In case, a custom renderer is used, it may use a different height,
123              * and we can't help much.
124              */

125             size.height += 2;
126             size.width += insets.left + insets.right;
127             size.width += buttonInsets.left + buttonInsets.right;
128             size.width += buttonMargin.left + buttonMargin.right;
129             size.width += button.getComboIcon().getIconWidth();
130             size.height += insets.top + insets.bottom;
131             size.height += buttonInsets.top + buttonInsets.bottom;
132         } else if (
133             comboBox.isEditable() && arrowButton != null && editor != null) {
134
135             // The display size does often not include the editor's insets
136
size = getDisplaySize();
137             Insets insets = comboBox.getInsets();
138             Insets editorInsets = getEditorInsets();
139             int buttonWidth = getEditableButtonWidth();
140
141             size.width += insets.left + insets.right;
142             size.width += editorInsets.left + editorInsets.right -1;
143             size.width += buttonWidth;
144             size.height += insets.top + insets.bottom;
145         } else {
146             size = super.getMinimumSize(c);
147         }
148
149         cachedMinimumSize.setSize(size.width, size.height);
150         isMinimumSizeDirty = false;
151
152         return new Dimension(cachedMinimumSize);
153     }
154
155     /**
156      * Creates and answers the arrow button that is to be used in the combo box.<p>
157      *
158      * Overridden to use a button that can have a pseudo 3D effect.
159      */

160     protected JButton createArrowButton() {
161         return new PlasticComboBoxButton(
162             comboBox,
163             PlasticIconFactory.getComboBoxButtonIcon(),
164             comboBox.isEditable(),
165             currentValuePane,
166             listBox);
167     }
168
169     /**
170      * Creates a layout manager for managing the components which
171      * make up the combo box.<p>
172      *
173      * Overriden to use a layout that has a fixed width arrow button.
174      *
175      * @return an instance of a layout manager
176      */

177     protected LayoutManager createLayoutManager() {
178         return new PlasticComboBoxLayoutManager();
179     }
180
181     // Painting ***************************************************************
182

183     public void update(Graphics g, JComponent c) {
184         if (c.isOpaque()) {
185             g.setColor(c.getBackground());
186             g.fillRect(0, 0, c.getWidth(), c.getHeight());
187             if (isToolBarComboBox(c)) {
188                 c.setOpaque(false);
189             } }
190         paint(g, c);
191     }
192     
193     
194     /**
195      * Checks and answers if this combo is in a tool bar.
196      *
197      * @param c the component to check
198      * @return true if in tool bar, false otherwise
199      */

200     protected boolean isToolBarComboBox(JComponent c) {
201         Container parent = c.getParent();
202         return parent != null
203             && (parent instanceof JToolBar
204                 || parent.getParent() instanceof JToolBar);
205     }
206
207     
208     // Helper Classes *********************************************************
209

210     /**
211      * This layout manager handles the 'standard' layout of combo boxes.
212      * It puts the arrow button to the right and the editor to the left.
213      * If there is no editor it still keeps the arrow button to the right.
214      *
215      * Overriden to use a fixed arrow button width.
216      */

217     private class PlasticComboBoxLayoutManager
218         extends MetalComboBoxUI.MetalComboBoxLayoutManager JavaDoc {
219
220         public void layoutContainer(Container parent) {
221             JComboBox cb = (JComboBox) parent;
222
223             // Use superclass behavior if the combobox is not editable.
224
if (!cb.isEditable()) {
225                 super.layoutContainer(parent);
226                 return;
227             }
228
229             int width = cb.getWidth();
230             int height = cb.getHeight();
231
232             Insets insets = getInsets();
233             int buttonWidth = getEditableButtonWidth();
234             int buttonHeight = height - (insets.top + insets.bottom);
235
236             if (arrowButton != null) {
237                 if (cb.getComponentOrientation().isLeftToRight()) {
238                     arrowButton.setBounds(
239                         width - (insets.right + buttonWidth),
240                         insets.top,
241                         buttonWidth,
242                         buttonHeight);
243                 } else {
244                     arrowButton.setBounds(
245                         insets.left,
246                         insets.top,
247                         buttonWidth,
248                         buttonHeight);
249                 }
250             }
251             if (editor != null) {
252                 editor.setBounds(rectangleForCurrentValue());
253             }
254         }
255     }
256
257     // Required if we have a combobox button that does not extend MetalComboBoxButton
258
public PropertyChangeListener JavaDoc createPropertyChangeListener() {
259         return new PlasticPropertyChangeListener();
260     }
261
262     // Overriden to use PlasticComboBoxButton instead of a MetalComboBoxButton.
263
// Required if we have a combobox button that does not extend MetalComboBoxButton
264
private class PlasticPropertyChangeListener
265         extends BasicComboBoxUI.PropertyChangeHandler JavaDoc {
266
267         public void propertyChange(PropertyChangeEvent JavaDoc e) {
268             super.propertyChange(e);
269             String JavaDoc propertyName = e.getPropertyName();
270
271             if (propertyName.equals("editable")) {
272                 PlasticComboBoxButton button =
273                     (PlasticComboBoxButton) arrowButton;
274                 button.setIconOnly(comboBox.isEditable());
275                 comboBox.repaint();
276             } else if (propertyName.equals("background")) {
277                 Color color = (Color) e.getNewValue();
278                 arrowButton.setBackground(color);
279                 listBox.setBackground(color);
280
281             } else if (propertyName.equals("foreground")) {
282                 Color color = (Color) e.getNewValue();
283                 arrowButton.setForeground(color);
284                 listBox.setForeground(color);
285             }
286         }
287     }
288
289     // Differs from the MetalComboPopup in that it uses the standard popmenu border.
290
private class PlasticComboPopup extends MetalComboPopup {
291
292         private PlasticComboPopup(JComboBox combo) {
293             super(combo);
294         }
295
296         /**
297          * Configures the list created by #createList().
298          */

299         protected void configureList() {
300             super.configureList();
301             list.setForeground(UIManager.getColor("MenuItem.foreground"));
302             list.setBackground(UIManager.getColor("MenuItem.background"));
303         }
304
305         /**
306          * Configures the JScrollPane created by #createScroller().
307          */

308         protected void configureScroller() {
309             super.configureScroller();
310             scroller.getVerticalScrollBar().putClientProperty(
311                 MetalScrollBarUI.FREE_STANDING_PROP,
312                 Boolean.FALSE);
313         }
314
315     }
316
317 }
Popular Tags