aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java')
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java778
1 files changed, 405 insertions, 373 deletions
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java
index 68e18a6ab01..464c8dd9f63 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java
@@ -42,6 +42,8 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
@@ -69,15 +71,17 @@ import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
-import javax.swing.UIDefaults;
+import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
/**
- * UI Delegate for JComboBox
+ * A UI delegate for the {@link JComboBox} component.
*
* @author Olga Rodimina
* @author Robert Schuster
@@ -85,52 +89,54 @@ import javax.swing.plaf.ComponentUI;
public class BasicComboBoxUI extends ComboBoxUI
{
/**
- * This arrow button that is displayed in the rigth side of JComboBox. This
- * button is used to hide and show combo box's list of items
+ * The arrow button that is displayed in the right side of JComboBox. This
+ * button is used to hide and show combo box's list of items.
*/
protected JButton arrowButton;
/**
- * The combo box for which this UI delegate is for
+ * The combo box represented by this UI delegate.
*/
protected JComboBox comboBox;
/**
- * Component that is responsible for displaying/editting selected item of
- * the combo box. By default JTextField is used as an editor for the
- * JComboBox
+ * The component that is responsible for displaying/editing the selected
+ * item of the combo box.
+ *
+ * @see BasicComboBoxEditor#getEditorComponent()
*/
protected Component editor;
/**
- * Listener listening to focus events occuring in the JComboBox
+ * A listener listening to focus events occurring in the {@link JComboBox}.
*/
protected FocusListener focusListener;
/**
- * tells whether JComboBox currently has focus
+ * A flag indicating whether JComboBox currently has the focus.
*/
protected boolean hasFocus;
/**
- * Listener listening to item events fired by the JComboBox
+ * A listener listening to item events fired by the {@link JComboBox}.
*/
protected ItemListener itemListener;
/**
- * KeyListener listening to key events that occur while JComboBox has focus
+ * A listener listening to key events that occur while {@link JComboBox} has
+ * the focus.
*/
protected KeyListener keyListener;
/**
- * MouseListener listening to mouse events occuring in the combo box
+ * A listener listening to mouse events occuring in the {@link JComboBox}.
*/
private MouseListener mouseListener;
/**
* List used when rendering selected item of the combo box. The selection
- * and foreground colors for combo box renderer are configured from this
- * list
+ * and foreground colors for combo box renderer are configured from this
+ * list.
*/
protected JList listBox;
@@ -140,11 +146,14 @@ public class BasicComboBoxUI extends ComboBoxUI
protected ListDataListener listDataListener;
/**
- * Popup list containing combo box's menu items
+ * Popup list containing the combo box's menu items.
*/
protected ComboPopup popup;
+
protected KeyListener popupKeyListener;
+
protected MouseListener popupMouseListener;
+
protected MouseMotionListener popupMouseMotionListener;
/**
@@ -152,30 +161,34 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
protected PropertyChangeListener propertyChangeListener;
+ /**
+ * The button background.
+ * @see #installDefaults()
+ */
+ private Color buttonBackground;
+
+ /**
+ * The button shadow.
+ * @see #installDefaults()
+ */
+ private Color buttonShadow;
+
/**
- * Colors that are used to render selected item in the combo box.
+ * The button dark shadow.
+ * @see #installDefaults()
*/
- private Color shadow;
- private Color darkShadow;
- private Color highlight;
- private Color lightHighlight;
+ private Color buttonDarkShadow;
+
+ /**
+ * The button highlight.
+ * @see #installDefaults()
+ */
+ private Color buttonHighlight;
/* Size of the largest item in the comboBox
* This is package-private to avoid an accessor method.
*/
- Dimension largestItemSize;
-
- // It seems that JComboBox doesn't have a border set explicitely. So we just
- // paint the border everytime combo box is displayed.
-
- /* border insets for this JComboBox
- * This is package-private to avoid an accessor method. */
- static final Insets borderInsets = new Insets(2, 2, 2, 2);
-
- // Width of the arrow button
- // This is package-private to avoid an accessor method.
- // FIXME: has wrong name for a constant.
- static final int arrowButtonWidth = 15;
+ Dimension displaySize;
// FIXME: This fields aren't used anywhere at this moment.
protected Dimension cachedMinimumSize;
@@ -183,19 +196,20 @@ public class BasicComboBoxUI extends ComboBoxUI
protected boolean isMinimumSizeDirty;
/**
- * Creates a new BasicComboBoxUI object.
+ * Creates a new <code>BasicComboBoxUI</code> object.
*/
public BasicComboBoxUI()
{
+ // Nothing to do here.
}
/**
- * Factory method to create a BasicComboBoxUI for the given {@link
- * JComponent}, which should be a {@link JComboBox}.
+ * A factory method to create a UI delegate for the given
+ * {@link JComponent}, which should be a {@link JComboBox}.
*
* @param c The {@link JComponent} a UI is being created for.
*
- * @return A BasicComboBoxUI for the {@link JComponent}.
+ * @return A UI delegate for the {@link JComponent}.
*/
public static ComponentUI createUI(JComponent c)
{
@@ -203,9 +217,11 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method installs the UI for the given JComponent.
+ * Installs the UI for the given {@link JComponent}.
*
- * @param c The JComponent to install a UI for.
+ * @param c the JComponent to install a UI for.
+ *
+ * @see #uninstallUI(JComponent)
*/
public void installUI(JComponent c)
{
@@ -213,20 +229,22 @@ public class BasicComboBoxUI extends ComboBoxUI
if (c instanceof JComboBox)
{
- comboBox = (JComboBox) c;
- comboBox.setOpaque(true);
- comboBox.setLayout(createLayoutManager());
- installDefaults();
- installComponents();
- installListeners();
- installKeyboardActions();
+ comboBox = (JComboBox) c;
+ comboBox.setOpaque(true);
+ comboBox.setLayout(createLayoutManager());
+ installDefaults();
+ installComponents();
+ installListeners();
+ installKeyboardActions();
}
}
/**
- * This method uninstalls the UI.
+ * Uninstalls the UI for the given {@link JComponent}.
*
* @param c The JComponent that is having this UI removed.
+ *
+ * @see #installUI(JComponent)
*/
public void uninstallUI(JComponent c)
{
@@ -238,27 +256,27 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method installs the defaults that are defined in the Basic look and
- * feel for this {@link JComboBox}.
+ * Installs the defaults that are defined in the {@link BasicLookAndFeel}
+ * for this {@link JComboBox}.
+ *
+ * @see #uninstallDefaults()
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- comboBox.setBackground(defaults.getColor("ComboBox.background"));
- comboBox.setFont(defaults.getFont("ComboBox.font"));
- comboBox.setForeground(defaults.getColor("ComboBox.foreground"));
-
- // Set default color that should be used to to render selected item
- // of the combo box.
- shadow = defaults.getColor("Button.shadow");
- darkShadow = defaults.getColor("Button.darkShadow");
- lightHighlight = defaults.getColor("Button.light");
- highlight = defaults.getColor("Button.highlight");
+ LookAndFeel.installColorsAndFont(comboBox, "ComboBox.background",
+ "ComboBox.foreground", "ComboBox.font");
+
+ // fetch the button color scheme
+ buttonBackground = UIManager.getColor("ComboBox.buttonBackground");
+ buttonShadow = UIManager.getColor("ComboBox.buttonShadow");
+ buttonDarkShadow = UIManager.getColor("ComboBox.buttonDarkShadow");
+ buttonHighlight = UIManager.getColor("ComboBox.buttonHighlight");
}
/**
- * This method creates and installs the listeners for this UI.
+ * Creates and installs the listeners for this UI.
+ *
+ * @see #uninstallListeners()
*/
protected void installListeners()
{
@@ -268,6 +286,7 @@ public class BasicComboBoxUI extends ComboBoxUI
focusListener = createFocusListener();
comboBox.addFocusListener(focusListener);
+ listBox.addFocusListener(focusListener);
itemListener = createItemListener();
comboBox.addItemListener(itemListener);
@@ -276,35 +295,40 @@ public class BasicComboBoxUI extends ComboBoxUI
comboBox.addKeyListener(keyListener);
mouseListener = createMouseListener();
- comboBox.addMouseListener(mouseListener);
+ arrowButton.addMouseListener(mouseListener);
// install listeners that listen to combo box model
listDataListener = createListDataListener();
comboBox.getModel().addListDataListener(listDataListener);
-
- configureArrowButton();
}
/**
- * This method uninstalls the defaults and sets any objects created during
- * install to null
+ * Uninstalls the defaults and sets any objects created during
+ * install to <code>null</code>.
+ *
+ * @see #installDefaults()
*/
protected void uninstallDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- comboBox.setBackground(null);
- comboBox.setFont(null);
- comboBox.setForeground(null);
-
- shadow = null;
- darkShadow = null;
- lightHighlight = null;
- highlight = null;
+ if (comboBox.getFont() instanceof UIResource)
+ comboBox.setFont(null);
+
+ if (comboBox.getForeground() instanceof UIResource)
+ comboBox.setForeground(null);
+
+ if (comboBox.getBackground() instanceof UIResource)
+ comboBox.setBackground(null);
+
+ buttonBackground = null;
+ buttonShadow = null;
+ buttonDarkShadow = null;
+ buttonHighlight = null;
}
/**
* Detaches all the listeners we attached in {@link #installListeners}.
+ *
+ * @see #installListeners()
*/
protected void uninstallListeners()
{
@@ -312,6 +336,7 @@ public class BasicComboBoxUI extends ComboBoxUI
propertyChangeListener = null;
comboBox.removeFocusListener(focusListener);
+ listBox.removeFocusListener(focusListener);
focusListener = null;
comboBox.removeItemListener(itemListener);
@@ -320,17 +345,15 @@ public class BasicComboBoxUI extends ComboBoxUI
comboBox.removeKeyListener(keyListener);
keyListener = null;
- comboBox.removeMouseListener(mouseListener);
+ arrowButton.removeMouseListener(mouseListener);
mouseListener = null;
comboBox.getModel().removeListDataListener(listDataListener);
listDataListener = null;
-
- unconfigureArrowButton();
}
/**
- * This method creates popup that will contain list of combo box's items
+ * Creates the popup that will contain list of combo box's items.
*
* @return popup containing list of combo box's items
*/
@@ -340,7 +363,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * Creates KeyListener to listen to key events.
+ * Creates a {@link KeyListener} to listen to key events.
*
* @return KeyListener that listens to key events.
*/
@@ -350,8 +373,8 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method create MouseListener that will listen to mouse event occuring
- * in combo box.
+ * Creates a {@link MouseListener} that will listen to mouse events occurring
+ * in the combo box.
*
* @return the MouseListener
*/
@@ -361,10 +384,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method create FocusListener that will listen to changes in this
+ * Creates the {@link FocusListener} that will listen to changes in this
* JComboBox's focus.
*
- * @return theFocusListener
+ * @return the FocusListener.
*/
protected FocusListener createFocusListener()
{
@@ -372,9 +395,9 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method create ListDataListener to listen to ComboBox's data model
+ * Creates a {@link ListDataListener} to listen to the combo box's data model.
*
- * @return ListDataListener
+ * @return The new listener.
*/
protected ListDataListener createListDataListener()
{
@@ -382,10 +405,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method creates ItemListener that will listen to to the changes in
+ * Creates an {@link ItemListener} that will listen to the changes in
* the JComboBox's selection.
*
- * @return the ItemListener
+ * @return The ItemListener
*/
protected ItemListener createItemListener()
{
@@ -393,10 +416,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method creates PropertyChangeListener to listen to the changes in
+ * Creates a {@link PropertyChangeListener} to listen to the changes in
* the JComboBox's bound properties.
*
- * @return the PropertyChangeListener
+ * @return The PropertyChangeListener
*/
protected PropertyChangeListener createPropertyChangeListener()
{
@@ -404,9 +427,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method returns layout manager for the combo box.
+ * Creates and returns a layout manager for the combo box. Subclasses can
+ * override this method to provide a different layout.
*
- * @return layout manager for the combo box
+ * @return a layout manager for the combo box.
*/
protected LayoutManager createLayoutManager()
{
@@ -414,10 +438,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method creates component that will be responsible for rendering the
+ * Creates a component that will be responsible for rendering the
* selected component in the combo box.
*
- * @return render for the combo box
+ * @return A renderer for the combo box.
*/
protected ListCellRenderer createRenderer()
{
@@ -425,58 +449,54 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * Creates component that will be responsible for displaying/editting
- * selected item in the combo box. This editor is used only when combo box
- * is editable.
+ * Creates the component that will be responsible for displaying/editing
+ * the selected item in the combo box. This editor is used only when combo
+ * box is editable.
*
- * @return component that will be responsible for displaying/editting
- * selected item in the combo box.
+ * @return A new component that will be responsible for displaying/editing
+ * the selected item in the combo box.
*/
protected ComboBoxEditor createEditor()
{
- return new BasicComboBoxEditor();
+ return new BasicComboBoxEditor.UIResource();
}
/**
- * This method installs components for this JComboBox. ArrowButton, main
- * part of combo box (upper part) and popup list of items are created and
+ * Installs the components for this JComboBox. ArrowButton, main
+ * part of combo box (upper part) and popup list of items are created and
* configured here.
*/
protected void installComponents()
{
- // create and install arrow button
- arrowButton = createArrowButton();
-
- comboBox.add(arrowButton);
-
- // Set list that will be used by BasicComboBoxRender
- // in order to determine the right colors when rendering
- listBox = new JList();
-
- Color background = arrowButton.getBackground();
- listBox.setBackground(background);
- listBox.setSelectionBackground(background.darker());
-
- Color foreground = arrowButton.getForeground();
- listBox.setForeground(foreground);
- listBox.setSelectionForeground(foreground);
+ // create drop down list of items
+ popup = createPopup();
+ listBox = popup.getList();
// set editor and renderer for the combo box. Editor is used
// only if combo box becomes editable, otherwise renderer is used
// to paint the selected item; combobox is not editable by default.
comboBox.setRenderer(createRenderer());
- comboBox.setEditor(createEditor());
- editor = comboBox.getEditor().getEditorComponent();
+ // create and install arrow button
+ arrowButton = createArrowButton();
+ configureArrowButton();
+ comboBox.add(arrowButton);
- // create drop down list of items
- popup = createPopup();
+ ComboBoxEditor currentEditor = comboBox.getEditor();
+ if (currentEditor == null || currentEditor instanceof UIResource)
+ {
+ currentEditor = createEditor();
+ comboBox.setEditor(currentEditor);
+ }
+ editor = currentEditor.getEditorComponent();
comboBox.revalidate();
}
/**
- * This method uninstalls components from this JComboBox
+ * Uninstalls components from this {@link JComboBox}.
+ *
+ * @see #installComponents()
*/
protected void uninstallComponents()
{
@@ -490,12 +510,18 @@ public class BasicComboBoxUI extends ComboBoxUI
comboBox.setRenderer(null);
- comboBox.setEditor(null);
- editor = null;
+ // if the editor is not an instanceof UIResource, it was not set by the
+ // UI delegate, so don't clear it...
+ ComboBoxEditor currentEditor = comboBox.getEditor();
+ if (currentEditor instanceof UIResource)
+ {
+ comboBox.setEditor(null);
+ editor = null;
+ }
}
/**
- * This method adds editor to the combo box
+ * Adds the current editor to the combo box.
*/
public void addEditor()
{
@@ -503,7 +529,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method removes editor from the combo box
+ * Removes the current editor from the combo box.
*/
public void removeEditor()
{
@@ -511,15 +537,17 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method configures editor for this combo box.
+ * Configures the editor for this combo box.
*/
protected void configureEditor()
{
+ editor.setFont(comboBox.getFont());
+ comboBox.getEditor().setItem(comboBox.getSelectedItem());
// FIXME: Need to implement. Set font and add listeners.
}
/**
- * This method removes all the listeners for the editor.
+ * Unconfigures the editor for this combo nox. This method is not implemented.
*/
protected void unconfigureEditor()
{
@@ -527,42 +555,50 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method adds listeners to the arrow button part of the combo box.
+ * Configures the arrow button.
+ *
+ * @see #configureArrowButton()
*/
public void configureArrowButton()
{
- arrowButton.addMouseListener(mouseListener);
+ arrowButton.setEnabled(comboBox.isEnabled());
+ arrowButton.setFont(comboBox.getFont());
}
/**
- * This method removes listeners from the arrow button part of the combo
- * box.
+ * Unconfigures the arrow button.
+ *
+ * @see #configureArrowButton()
+ *
+ * @specnote The specification says this method is implementation specific
+ * and should not be used or overridden.
*/
public void unconfigureArrowButton()
{
- arrowButton.removeMouseListener(mouseListener);
+ // Nothing to do here yet.
}
/**
- * This method create arrow button for this JComboBox. Arrow button is
- * responsible for displaying / hiding drop down list of items when it is
- * clicked.
+ * Creates an arrow button for this {@link JComboBox}. The arrow button is
+ * displayed at the right end of the combo box and is used to display/hide
+ * the drop down list of items.
*
- * @return JButton arrow button for this JComboBox.
+ * @return A new button.
*/
protected JButton createArrowButton()
{
- return new BasicArrowButton(BasicArrowButton.SOUTH);
+ return new BasicArrowButton(BasicArrowButton.SOUTH, buttonBackground,
+ buttonShadow, buttonDarkShadow, buttonHighlight);
}
/**
- * This method checks if popup part of the combo box is visible on the
- * screen
+ * Returns <code>true</code> if the popup is visible, and <code>false</code>
+ * otherwise.
*
* @param c The JComboBox to check
*
- * @return true if popup part of the JComboBox is visible and false
- * otherwise.
+ * @return <code>true</code> if popup part of the JComboBox is visible and
+ * <code>false</code> otherwise.
*/
public boolean isPopupVisible(JComboBox c)
{
@@ -570,7 +606,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * Displays/Hides JComboBox's list of items on the screen.
+ * Displays/hides the {@link JComboBox}'s list of items on the screen.
*
* @param c The combo box, for which list of items should be
* displayed/hidden
@@ -579,7 +615,10 @@ public class BasicComboBoxUI extends ComboBoxUI
public void setPopupVisible(JComboBox c, boolean v)
{
if (v)
- popup.show();
+ {
+ popup.show();
+ popup.getList().requestFocus();
+ }
else
popup.hide();
}
@@ -593,7 +632,7 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public boolean isFocusTraversable(JComboBox c)
{
- if (comboBox.isEditable())
+ if (!comboBox.isEditable())
return true;
return false;
@@ -607,56 +646,28 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public void paint(Graphics g, JComponent c)
{
- if (c instanceof JComboBox)
- {
- JComboBox cb = (JComboBox) c;
-
- paintBorder(g, comboBox.getBounds(), hasFocus);
-
- Rectangle rect = rectangleForCurrentValue();
- paintCurrentValueBackground(g, rect, hasFocus);
- paintCurrentValue(g, rect, hasFocus);
- }
- }
-
- private void paintBorder(Graphics g, Rectangle bounds, boolean hasFocus)
- {
- int x = 0;
- int y = 0;
- int width = bounds.width;
- int height = bounds.height;
-
- Color oldColor = g.getColor();
-
- if (! arrowButton.getModel().isPressed())
- BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height, Color.gray,
- Color.white, Color.gray, Color.white);
- else
- {
- g.setColor(darkShadow);
- g.drawRect(x, y, width, height);
- g.setColor(shadow);
- g.drawRect(x + 1, y + 1, width - 3, height - 3);
- }
- g.setColor(oldColor);
+ Rectangle rect = rectangleForCurrentValue();
+ paintCurrentValueBackground(g, rect, hasFocus);
+ paintCurrentValue(g, rect, hasFocus);
}
/**
- * Returns preferred size for the given menu item.
+ * Returns preferred size for the combo box.
*
* @param c comboBox for which to get preferred size
*
- * @return $Dimension$ preferred size for the given combo box
+ * @return The preferred size for the given combo box
*/
public Dimension getPreferredSize(JComponent c)
{
- // return null to indicate that combo box's layout will determin its
- // preferred size
- return null;
+ // note: overriding getMinimumSize() (for example in the MetalComboBoxUI
+ // class) affects the getPreferredSize() result, so it seems logical that
+ // this method is implemented by delegating to the getMinimumSize() method
+ return getMinimumSize(c);
}
/**
- * This method returns the minimum size for this {@link JComboBox} for this
+ * Returns the minimum size for this {@link JComboBox} for this
* look and feel.
*
* @param c The {@link JComponent} to find the minimum size for.
@@ -665,20 +676,26 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public Dimension getMinimumSize(JComponent c)
{
- return null;
+ Dimension d = getDisplaySize();
+ int arrowButtonWidth = d.height;
+ Dimension result = new Dimension(d.width + arrowButtonWidth, d.height);
+ return result;
}
+ /** The value returned by the getMaximumSize() method. */
+ private static final Dimension MAXIMUM_SIZE = new Dimension(32767, 32767);
+
/**
- * This method returns the maximum size for this {@link JComboBox} for this
+ * Returns the maximum size for this {@link JComboBox} for this
* look and feel.
*
* @param c The {@link JComponent} to find the maximum size for
*
- * @return The dimensions of the minimum size.
+ * @return The maximum size (<code>Dimension(32767, 32767)</code>).
*/
public Dimension getMaximumSize(JComponent c)
{
- return null;
+ return MAXIMUM_SIZE;
}
public int getAccessibleChildrenCount(JComponent c)
@@ -707,7 +724,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method selects next possible item relative to the current selection
+ * Selects next possible item relative to the current selection
* to be next selected item in the combo box.
*/
protected void selectNextPossibleValue()
@@ -718,7 +735,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method selects previous item relative to current selection to be
+ * Selects previous item relative to current selection to be
* next selected item.
*/
protected void selectPreviousPossibleValue()
@@ -729,8 +746,8 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method displays combo box popup if the popup is not currently shown
- * on the screen and hides it if it is currently shown
+ * Displays combo box popup if the popup is not currently shown
+ * on the screen and hides it if it is currently shown
*/
protected void toggleOpenClose()
{
@@ -738,34 +755,23 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method returns bounds in which comboBox's selected Item will be
- * displayed
+ * Returns the bounds in which comboBox's selected item will be
+ * displayed.
*
* @return rectangle bounds in which comboBox's selected Item will be
* displayed
*/
protected Rectangle rectangleForCurrentValue()
{
- Rectangle cbBounds = comboBox.getBounds();
-
- // Subtract width or the arrow button and border insets
- Rectangle rectForCurrentValue = new Rectangle(cbBounds.x
- + borderInsets.left,
- cbBounds.y
- + borderInsets.top,
- cbBounds.width
- - arrowButtonWidth
- - borderInsets.left
- - borderInsets.right,
- cbBounds.height
- - borderInsets.top
- - borderInsets.bottom);
-
+ Rectangle cbBounds = SwingUtilities.getLocalBounds(comboBox);
+ Rectangle abBounds = arrowButton.getBounds();
+ Rectangle rectForCurrentValue = new Rectangle(cbBounds.x, cbBounds.y,
+ cbBounds.width - abBounds.width, cbBounds.height);
return rectForCurrentValue;
}
/**
- * This method returns insets of the current border.
+ * Returns the insets of the current border.
*
* @return Insets representing space between combo box and its border
*/
@@ -775,7 +781,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method paints currently selected value in the main part of the combo
+ * Paints currently selected value in the main part of the combo
* box (part without popup).
*
* @param g graphics context
@@ -794,28 +800,29 @@ public class BasicComboBoxUI extends ComboBoxUI
* If there is currently no selected item we will take an empty
* String as replacement.
*/
- Component comp = comboBox.getRenderer()
- .getListCellRendererComponent(listBox,
- (currentValue != null ? currentValue : ""),
- -1,
- isPressed,
- hasFocus);
- if (! comboBox.isEnabled())
- comp.setEnabled(false);
-
- g.translate(borderInsets.left, borderInsets.top);
- comp.setBounds(0, 0, bounds.width, bounds.height);
- comp.paint(g);
- g.translate(-borderInsets.left, -borderInsets.top);
-
- comboBox.revalidate();
+ Component comp = comboBox.getRenderer().getListCellRendererComponent(
+ listBox, (currentValue != null ? currentValue : ""), -1,
+ isPressed, hasFocus);
+ if (! comboBox.isEnabled())
+ {
+ comp.setBackground(UIManager.getLookAndFeelDefaults().getColor(
+ "ComboBox.disabledBackground"));
+ comp.setForeground(UIManager.getLookAndFeelDefaults().getColor(
+ "ComboBox.disabledForeground"));
+ comp.setEnabled(false);
+ }
+ comp.setBounds(0, 0, bounds.width, bounds.height);
+ comp.setFont(comboBox.getFont());
+ comp.paint(g);
+
+ comboBox.revalidate();
}
else
comboBox.getEditor().setItem(comboBox.getSelectedItem());
}
/**
- * This method paints background of part of the combo box, where currently
+ * Paints the background of part of the combo box, where currently
* selected value is displayed. If the combo box has focus this method
* should also paint focus rectangle around the combo box.
*
@@ -832,58 +839,102 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * Returns default size for the combo box that doesn't contain any elements
- * in it
+ * Returns the default size for the display area of a combo box that does
+ * not contain any elements. This method returns the width and height of
+ * a single space in the current font, plus a margin of 1 pixel.
*
- * @return Default size of the combo box with no elements in it.
+ * @return The default display size.
+ *
+ * @see #getDisplaySize()
*/
protected Dimension getDefaultSize()
{
- return new Dimension(6, 17);
+ // There is nothing in the spec to say how this method should be
+ // implemented...so I've done some guessing, written some Mauve tests,
+ // and written something that gives dimensions that are close to the
+ // reference implementation.
+ FontMetrics fm = comboBox.getFontMetrics(comboBox.getFont());
+ int w = fm.charWidth(' ') + 2;
+ int h = fm.getHeight() + 2;
+ return new Dimension(w, h);
}
/**
- * Returns size of the largest item in the combo box. This size will be the
- * size of the combo box, not including the arrowButton.
+ * Returns the size of the display area for the combo box. This size will be
+ * the size of the combo box, not including the arrowButton.
*
- * @return dimensions of the largest item in the combo box.
+ * @return The size of the display area for the combo box.
*/
- protected Dimension getLargestItemSize()
+ protected Dimension getDisplaySize()
{
- ComboBoxModel model = comboBox.getModel();
- int numItems = model.getSize();
-
- // if combo box doesn't have any items then simply
- // return its default size
- if (numItems == 0)
+ if (!comboBox.isEditable())
{
- largestItemSize = getDefaultSize();
- return largestItemSize;
+ Object prototype = comboBox.getPrototypeDisplayValue();
+ if (prototype != null)
+ {
+ // calculate result based on prototype
+ ListCellRenderer renderer = comboBox.getRenderer();
+ Component comp = renderer.getListCellRendererComponent(listBox,
+ prototype, -1, false, false);
+ Dimension compSize = comp.getPreferredSize();
+ compSize.width += 2; // add 1 pixel margin around area
+ compSize.height += 2;
+ return compSize;
+ }
+ else
+ {
+ ComboBoxModel model = comboBox.getModel();
+ int numItems = model.getSize();
+
+ // if combo box doesn't have any items then simply
+ // return its default size
+ if (numItems == 0)
+ {
+ displaySize = getDefaultSize();
+ return displaySize;
+ }
+
+ Dimension size = new Dimension(0, 0);
+
+ // ComboBox's display size should be equal to the
+ // size of the largest item in the combo box.
+ ListCellRenderer renderer = comboBox.getRenderer();
+
+ for (int i = 0; i < numItems; i++)
+ {
+ Object item = model.getElementAt(i);
+ Component comp = renderer.getListCellRendererComponent(listBox,
+ item, -1, false, false);
+
+ Dimension compSize = comp.getPreferredSize();
+ if (compSize.width + 2 > size.width)
+ size.width = compSize.width + 2;
+ if (compSize.height + 2 > size.height)
+ size.height = compSize.height + 2;
+ }
+ displaySize = size;
+ return displaySize;
+ }
}
-
- Dimension size = new Dimension(0, 0);
-
- // ComboBox's display size should be equal to the
- // size of the largest item in the combo box.
- ListCellRenderer renderer = comboBox.getRenderer();
-
- for (int i = 0; i < numItems; i++)
+ else // an editable combo,
{
- Object item = model.getElementAt(i);
- String s = item.toString();
- Component comp = renderer.getListCellRendererComponent(listBox, item,
- -1, false, false);
-
- if (comp.getPreferredSize().getWidth() > size.getWidth())
- size = comp.getPreferredSize();
+ Component comp = comboBox.getEditor().getEditorComponent();
+ Dimension prefSize = comp.getPreferredSize();
+ int width = prefSize.width;
+ int height = prefSize.height + 2;
+ Object prototype = comboBox.getPrototypeDisplayValue();
+ if (prototype != null)
+ {
+ FontMetrics fm = comboBox.getFontMetrics(comboBox.getFont());
+ width = Math.max(width, fm.stringWidth(prototype.toString()) + 2);
+ }
+ displaySize = new Dimension(width, height);
+ return displaySize;
}
-
- largestItemSize = size;
- return largestItemSize;
}
/**
- * This method installs the keyboard actions for the JComboBox as specified
+ * Installs the keyboard actions for the {@link JComboBox} as specified
* by the look and feel.
*/
protected void installKeyboardActions()
@@ -892,7 +943,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method uninstalls the keyboard actions for the JComboBox there were
+ * Uninstalls the keyboard actions for the {@link JComboBox} there were
* installed by in {@link #installListeners}.
*/
protected void uninstallKeyboardActions()
@@ -901,22 +952,39 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This class is Layout Manager for this combo box.
+ * A {@link LayoutManager} used to position the sub-components of the
+ * {@link JComboBox}.
+ *
+ * @see BasicComboBoxUI#createLayoutManager()
*/
- public class ComboBoxLayoutManager extends Object implements LayoutManager
+ public class ComboBoxLayoutManager implements LayoutManager
{
/**
* Creates a new ComboBoxLayoutManager object.
*/
public ComboBoxLayoutManager()
{
+ // Nothing to do here.
}
+ /**
+ * Adds a component to the layout. This method does nothing, since the
+ * layout manager doesn't need to track the components.
+ *
+ * @param name the name to associate the component with (ignored).
+ * @param comp the component (ignored).
+ */
public void addLayoutComponent(String name, Component comp)
{
// Do nothing
}
+ /**
+ * Removes a component from the layout. This method does nothing, since
+ * the layout manager doesn't need to track the components.
+ *
+ * @param comp the component.
+ */
public void removeLayoutComponent(Component comp)
{
// Do nothing
@@ -925,43 +993,30 @@ public class BasicComboBoxUI extends ComboBoxUI
/**
* Returns preferred layout size of the JComboBox.
*
- * @param parent Container for which preferred size should be calculated
+ * @param parent the Container for which the preferred size should be
+ * calculated.
*
- * @return preferred size for the given container
+ * @return The preferred size for the given container
*/
public Dimension preferredLayoutSize(Container parent)
{
- Dimension d = new Dimension(0, 0);
-
- if (largestItemSize == null)
- largestItemSize = getLargestItemSize();
-
- // add size for the area that will display selected item
- d.width += largestItemSize.getWidth();
- d.height += largestItemSize.getHeight();
-
- // add size of the arrow button
- d.width += arrowButtonWidth;
-
- // add width and height of the border
- d.width += borderInsets.left + borderInsets.right;
- d.height += borderInsets.left + borderInsets.right;
-
- // Add combo box's insets
- Insets insets = parent.getInsets();
- d.width += insets.left + insets.right;
- d.width += insets.left + insets.right;
-
- return d;
+ return getPreferredSize((JComponent) parent);
}
+ /**
+ * Returns the minimum layout size.
+ *
+ * @param parent the container.
+ *
+ * @return The minimum size.
+ */
public Dimension minimumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
/**
- * This method layouts out the components in the container. It puts arrow
+ * Arranges the components in the container. It puts arrow
* button right end part of the comboBox. If the comboBox is editable
* then editor is placed to the left of arrow button, starting from the
* beginning.
@@ -972,21 +1027,19 @@ public class BasicComboBoxUI extends ComboBoxUI
{
// Position editor component to the left of arrow button if combo box is
// editable
- int editorWidth = comboBox.getBounds().width - arrowButtonWidth - 2;
+ int arrowSize = comboBox.getHeight();
+ int editorWidth = comboBox.getBounds().width - arrowSize;
if (comboBox.isEditable())
- editor.setBounds(borderInsets.left, borderInsets.top, editorWidth,
- comboBox.getBounds().height - borderInsets.left
- - borderInsets.top);
-
- arrowButton.setBounds(editorWidth, 2, arrowButtonWidth,
- comboBox.getBounds().height - 4);
+ editor.setBounds(0, 0, editorWidth, comboBox.getBounds().height);
+
+ arrowButton.setBounds(editorWidth, 0, arrowSize, arrowSize);
comboBox.revalidate();
}
}
/**
- * This class handles focus changes occuring in the combo box. This class is
+ * Handles focus changes occuring in the combo box. This class is
* responsible for repainting combo box whenever focus is gained or lost
* and also for hiding popup list of items whenever combo box loses its
* focus.
@@ -998,11 +1051,12 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public FocusHandler()
{
+ // Nothing to do here.
}
/**
- * This mehtod is invoked when combo box gains focus. It repaints main
- * part of combo box accordingally.
+ * Invoked when combo box gains focus. It repaints main
+ * part of combo box accordingly.
*
* @param e the FocusEvent
*/
@@ -1013,22 +1067,22 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method is invoked when combo box loses focus It repaint main part
- * of combo box accordingally and hides popup list of items.
+ * Invoked when the combo box loses focus. It repaints the main part
+ * of the combo box accordingly and hides the popup list of items.
*
* @param e the FocusEvent
*/
public void focusLost(FocusEvent e)
{
hasFocus = false;
+ setPopupVisible(comboBox, false);
comboBox.repaint();
- popup.hide();
}
}
/**
- * This class handles ItemEvent fired by the JComboBox when its selected
- * item changes.
+ * Handles {@link ItemEvent}s fired by the {@link JComboBox} when its
+ * selected item changes.
*/
public class ItemHandler extends Object implements ItemListener
{
@@ -1037,16 +1091,19 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public ItemHandler()
{
+ // Nothing to do here.
}
/**
- * This method is invoked when selected item becomes deselected or when
+ * Invoked when selected item becomes deselected or when
* new item becomes selected.
*
* @param e the ItemEvent representing item's state change.
*/
public void itemStateChanged(ItemEvent e)
{
+ if (e.getStateChange() == ItemEvent.SELECTED && comboBox.isEditable())
+ comboBox.getEditor().setItem(e.getItem());
comboBox.repaint();
}
}
@@ -1058,11 +1115,11 @@ public class BasicComboBoxUI extends ComboBoxUI
{
public KeyHandler()
{
+ // Nothing to do here.
}
- /*
- * This method is invoked whenever key is pressed while JComboBox is in
- * focus.
+ /**
+ * Invoked whenever key is pressed while JComboBox is in focus.
*/
public void keyPressed(KeyEvent e)
{
@@ -1072,7 +1129,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This class handles to the changes occuring in the JComboBox's data model
+ * Handles the changes occurring in the JComboBox's data model.
*/
public class ListDataHandler extends Object implements ListDataListener
{
@@ -1081,10 +1138,11 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public ListDataHandler()
{
+ // Nothing to do here.
}
/**
- * This method is invoked content's of JComboBox's data model are changed
+ * Invoked if the content's of JComboBox's data model are changed.
*
* @param e ListDataEvent describing the change.
*/
@@ -1094,36 +1152,27 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method is invoked when items were added to the JComboBox's data
- * model.
+ * Invoked when items are added to the JComboBox's data model.
*
* @param e ListDataEvent describing the change.
*/
public void intervalAdded(ListDataEvent e)
{
- // must determine if the size of the combo box should change
- int start = e.getIndex0();
- int end = e.getIndex1();
-
ComboBoxModel model = comboBox.getModel();
ListCellRenderer renderer = comboBox.getRenderer();
- if (largestItemSize == null)
- largestItemSize = new Dimension(0, 0);
+ if (displaySize == null)
+ displaySize = getDisplaySize();
+ if (displaySize.width < getDefaultSize().width)
+ displaySize.width = getDefaultSize().width;
+ if (displaySize.height < getDefaultSize().height)
+ displaySize.height = getDefaultSize().height;
- for (int i = start; i < end; i++)
- {
- Object item = model.getElementAt(i);
- Component comp = renderer.getListCellRendererComponent(new JList(),
- item, -1,
- false, false);
- if (comp.getPreferredSize().getWidth() > largestItemSize.getWidth())
- largestItemSize = comp.getPreferredSize();
- }
+ comboBox.repaint();
}
/**
- * This method is invoked when items were removed from the JComboBox's
+ * Invoked when items are removed from the JComboBox's
* data model.
*
* @param e ListDataEvent describing the change.
@@ -1131,23 +1180,29 @@ public class BasicComboBoxUI extends ComboBoxUI
public void intervalRemoved(ListDataEvent e)
{
// recalculate display size of the JComboBox.
- largestItemSize = getLargestItemSize();
+ displaySize = getDisplaySize();
comboBox.repaint();
}
}
/**
- * This class handles PropertyChangeEvents fired by JComboBox.
+ * Handles {@link PropertyChangeEvent}s fired by the {@link JComboBox}.
*/
public class PropertyChangeHandler extends Object
implements PropertyChangeListener
{
+ /**
+ * Creates a new instance.
+ */
public PropertyChangeHandler()
{
+ // Nothing to do here.
}
/**
- * This method is invoked whenever bound property of JComboBox changes.
+ * Invoked whenever bound property of JComboBox changes.
+ *
+ * @param e the event.
*/
public void propertyChange(PropertyChangeEvent e)
{
@@ -1185,59 +1240,36 @@ public class BasicComboBoxUI extends ComboBoxUI
if ((ComboBoxModel) e.getNewValue() != null)
comboBox.getModel().addListDataListener(listDataListener);
}
+ else if (e.getPropertyName().equals("font"))
+ {
+ Font font = (Font) e.getNewValue();
+ editor.setFont(font);
+ listBox.setFont(font);
+ arrowButton.setFont(font);
+ comboBox.revalidate();
+ comboBox.repaint();
+ }
// FIXME: Need to handle changes in other bound properties.
}
}
/**
- * MouseHandler listens to mouse events occuring in the combo box. This
- * class is responsible for repainting this JComboBox whenever the mouse is
- * being pressed or released over it.
+ * A handler for mouse events occurring in the combo box. An instance of
+ * this class is returned by the <code>createMouseListener()</code> method.
*/
private class MouseHandler extends MouseAdapter
{
/**
- * This method is invoked when mouse is pressed over the combo box. It
- * repaints the combo box accordinglly
+ * Invoked when mouse is pressed over the combo box. It toggles the
+ * visibility of the popup list.
*
- * @param e the MouseEvent
+ * @param e the event
*/
public void mousePressed(MouseEvent e)
{
if (comboBox.isEnabled())
- {
- if (e.getSource() instanceof JComboBox)
- {
- arrowButton.getModel().setPressed(true);
- arrowButton.getModel().setArmed(true);
- }
-
- comboBox.repaint();
-
- if (e.getSource() instanceof BasicArrowButton)
- toggleOpenClose();
- }
- }
-
- /**
- * This method is invoked when mouse is released over the combo box. It
- * repaints the combo box accordinglly
- *
- * @param e the MouseEvent
- */
- public void mouseReleased(MouseEvent e)
- {
- if (comboBox.isEnabled())
- {
- if (e.getSource() instanceof JComboBox)
- {
- arrowButton.getModel().setPressed(false);
- arrowButton.getModel().setArmed(false);
- }
-
- comboBox.repaint();
- }
+ toggleOpenClose();
}
}
}