001: /*
002: * SmoothGradientComboBoxUI.java
003: *
004: * Copyright (C) 2002, 2003, 2004, 2005, 2006 Takis Diakoumis
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: */
021:
022: package org.underworldlabs.swing.plaf.smoothgradient;
023:
024: import java.awt.Color;
025: import java.awt.Container;
026: import java.awt.Dimension;
027: import java.awt.Insets;
028: import java.awt.LayoutManager;
029: import java.beans.PropertyChangeEvent;
030: import java.beans.PropertyChangeListener;
031:
032: import javax.swing.ComboBoxEditor;
033: import javax.swing.JButton;
034: import javax.swing.JComboBox;
035: import javax.swing.JComponent;
036: import javax.swing.UIManager;
037: import javax.swing.plaf.ComponentUI;
038: import javax.swing.plaf.basic.BasicComboBoxUI;
039: import javax.swing.plaf.basic.ComboPopup;
040: import javax.swing.plaf.metal.MetalComboBoxUI;
041: import javax.swing.plaf.metal.MetalScrollBarUI;
042:
043: /* ----------------------------------------------------------
044: * CVS NOTE: Changes to the CVS repository prior to the
045: * release of version 3.0.0beta1 has meant a
046: * resetting of CVS revision numbers.
047: * ----------------------------------------------------------
048: */
049:
050: /**
051: *
052: * @author Takis Diakoumis
053: * @version $Revision: 1.4 $
054: * @date $Date: 2006/05/14 06:56:07 $
055: */
056: public final class SmoothGradientComboBoxUI extends MetalComboBoxUI {
057:
058: public static ComponentUI createUI(JComponent b) {
059: return new SmoothGradientComboBoxUI();
060: }
061:
062: /**
063: * Creates the editor that is to be used in editable combo boxes.
064: * This method only gets called if a custom editor has not already
065: * been installed in the JComboBox.
066: */
067: protected ComboBoxEditor createEditor() {
068: return new SmoothGradientComboBoxEditor.UIResource();
069: }
070:
071: protected ComboPopup createPopup() {
072: return new PolishedComboPopup(comboBox);
073: }
074:
075: /**
076: * Overriden to correct the combobox height.
077: */
078: public Dimension getMinimumSize(JComponent c) {
079: if (!isMinimumSizeDirty) {
080: return new Dimension(cachedMinimumSize);
081: }
082:
083: Dimension size = null;
084:
085: if (!comboBox.isEditable() && arrowButton != null
086: && arrowButton instanceof SmoothGradientComboBoxButton) {
087:
088: SmoothGradientComboBoxButton button = (SmoothGradientComboBoxButton) arrowButton;
089: Insets buttonInsets = button.getInsets();
090: Insets insets = comboBox.getInsets();
091:
092: size = getDisplaySize();
093:
094: /*
095: * The next line will lead to good results if used with standard renderers;
096: * In case, a custom renderer is used, it may use a different height,
097: * and we can't help much.
098: */
099: size.height += 2;
100:
101: size.width += insets.left + insets.right;
102: size.width += buttonInsets.left + buttonInsets.right;
103: size.width += buttonInsets.right
104: + button.getComboIcon().getIconWidth();
105: size.height += insets.top + insets.bottom;
106: size.height += buttonInsets.top + buttonInsets.bottom;
107:
108: } else if (comboBox.isEditable() && arrowButton != null
109: && editor != null) {
110:
111: // Includes the text editor border and inner margin
112: size = getDisplaySize();
113:
114: // Since the button is positioned besides the editor,
115: // do not add the buttons margin to the height.
116:
117: Insets insets = comboBox.getInsets();
118: size.height += insets.top + insets.bottom;
119: } else {
120: size = super .getMinimumSize(c);
121: }
122:
123: cachedMinimumSize.setSize(size.width, size.height);
124: isMinimumSizeDirty = false;
125:
126: return new Dimension(cachedMinimumSize);
127: }
128:
129: /**
130: * Creates and answers the arrow button that is to be used in the combo box.<p>
131: *
132: * Overridden to use a button that can have a pseudo 3D effect.
133: */
134: protected JButton createArrowButton() {
135: return new SmoothGradientComboBoxButton(comboBox,
136: SmoothGradientIconFactory.getComboBoxButtonIcon(),
137: comboBox.isEditable(), currentValuePane, listBox);
138: }
139:
140: /**
141: * Creates a layout manager for managing the components which
142: * make up the combo box.<p>
143: *
144: * Overriden to use a layout that has a fixed width arrow button.
145: *
146: * @return an instance of a layout manager
147: */
148: protected LayoutManager createLayoutManager() {
149: return new PolishedComboBoxLayoutManager();
150: }
151:
152: /**
153: * This layout manager handles the 'standard' layout of combo boxes.
154: * It puts the arrow button to the right and the editor to the left.
155: * If there is no editor it still keeps the arrow button to the right.
156: *
157: * Overriden to use a fixed arrow button width.
158: */
159: private class PolishedComboBoxLayoutManager extends
160: MetalComboBoxUI.MetalComboBoxLayoutManager {
161:
162: public void layoutContainer(Container parent) {
163: JComboBox cb = (JComboBox) parent;
164:
165: // Use superclass behavior if the combobox is not editable.
166: if (!cb.isEditable()) {
167: super .layoutContainer(parent);
168: return;
169: }
170:
171: int width = cb.getWidth();
172: int height = cb.getHeight();
173:
174: Insets insets = getInsets();
175: int buttonWidth = UIManager.getInt("ScrollBar.width");
176: int buttonHeight = height - (insets.top + insets.bottom);
177:
178: if (arrowButton != null) {
179: if (cb.getComponentOrientation().isLeftToRight()) {
180: arrowButton.setBounds(width
181: - (insets.right + buttonWidth), insets.top,
182: buttonWidth, buttonHeight);
183: } else {
184: arrowButton.setBounds(insets.left, insets.top,
185: buttonWidth, buttonHeight);
186: }
187: }
188: if (editor != null) {
189: editor.setBounds(rectangleForCurrentValue());
190: }
191: }
192: }
193:
194: // Required if we have a combobox button that does not extend MetalComboBoxButton
195: public PropertyChangeListener createPropertyChangeListener() {
196: return new PolishedPropertyChangeListener();
197: }
198:
199: // Overriden to use PlasticComboBoxButton instead of a MetalComboBoxButton.
200: // Required if we have a combobox button that does not extend MetalComboBoxButton
201: private class PolishedPropertyChangeListener extends
202: BasicComboBoxUI.PropertyChangeHandler {
203:
204: public void propertyChange(PropertyChangeEvent e) {
205: super .propertyChange(e);
206: String propertyName = e.getPropertyName();
207:
208: if (propertyName.equals("editable")) {
209: SmoothGradientComboBoxButton button = (SmoothGradientComboBoxButton) arrowButton;
210: button.setIconOnly(comboBox.isEditable());
211: comboBox.repaint();
212: } else if (propertyName.equals("background")) {
213: Color color = (Color) e.getNewValue();
214: arrowButton.setBackground(color);
215: listBox.setBackground(color);
216:
217: } else if (propertyName.equals("foreground")) {
218: Color color = (Color) e.getNewValue();
219: arrowButton.setForeground(color);
220: listBox.setForeground(color);
221: }
222: }
223: }
224:
225: // Differs from the MetalComboPopup in that it uses the standard popmenu border.
226: private class PolishedComboPopup extends MetalComboPopup {
227:
228: private PolishedComboPopup(JComboBox combo) {
229: super (combo);
230: }
231:
232: /**
233: * Configures the list created by #createList().
234: */
235: protected void configureList() {
236: super .configureList();
237: list.setForeground(UIManager
238: .getColor("MenuItem.foreground"));
239: list.setBackground(UIManager
240: .getColor("MenuItem.background"));
241: }
242:
243: /**
244: * Configures the JScrollPane created by #createScroller().
245: */
246: protected void configureScroller() {
247: super.configureScroller();
248: scroller.getVerticalScrollBar().putClientProperty(
249: MetalScrollBarUI.FREE_STANDING_PROP, Boolean.FALSE);
250: }
251:
252: }
253:
254: }
|