United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4626920 : Editable JComboBox width not correct

Details
Type:
Bug
Submit Date:
2002-01-23
Status:
Resolved
Updated Date:
2003-04-12
Project Name:
JDK
Resolved Date:
2002-08-12
Component:
client-libs
OS:
windows_2000
Sub-Component:
javax.swing
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:
1.4.2 (mantis)

Related Reports

Sub Tasks

Description
 Build 020122_1, Win 2000, JDK 1.3.1
javax.jms.Queue displayed without letter 'j' in the Type drop list of the 'Add Resource Environment Reference' dialog.

****

Real problem here is that an editable JComboBox is not
sized correctly. The longest string is not entirely
displayed.

Here is a test app that exhibits the problem:

/* ComboTest.java */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ComboTest extends JPanel {

    static public final String[] RES_TYPES = {
                "a really really long entry",
                "javax.jms.Queue",      // NOI18N
                "javax.jms.Topic"       // NOI18N
    };


    public ComboTest () {

        setLayout (new BoxLayout (this, BoxLayout.Y_AXIS));

        JPanel cbpanel = new JPanel ();
        cbpanel.setLayout (new FlowLayout (FlowLayout.CENTER));

        /* The editable JComboBox width will not be OK (not wide enough) */
        JComboBox cb = new JComboBox (RES_TYPES);
        cb.setEditable (true);
        cbpanel.add (cb);

        add (cbpanel);

        /* The non-editable JComboBox width will be OK */
        cb = new JComboBox (RES_TYPES);
        cbpanel = new JPanel ();
        cbpanel.add (cb);

        add (cbpanel);

    }

    public static void main (String [] args) {
        JFrame jf = new JFrame ("Editable JComboBox Test");
        jf.addWindowListener (new WindowAdapter () {
            public void windowClosing (WindowEvent evt) {
                System.exit (0);
            }
        });
        ComboTest combotest = new ComboTest ();
        jf.getContentPane ().add (combotest);
        jf.pack ();
        jf.setLocation (300, 300);
        jf.setSize (200, 200);
        jf.setVisible (true);
    }

}


                                    

Comments
WORK AROUND

A workaround is to use the new setPrototypeDisplayValue() method on JComboBox. This has a performance benefit as well since it doesn't have to iterate over the combo box items to find the longest item.

In the example, you would use:

	cb.setPrototypeDislayValue(RES_TYPES[0] + " ");

###@###.### 2002-05-06
                                     
2002-05-06
SUGGESTED FIX

Partial fix for the bug uncovered by setting a prototype display value on an editable combo box:


------- BasicComboBoxUI.java -------
1274c1274
<             Dimension d;
---
> 	    Dimension d;
1296,1301d1295
< 	    if ( comboBox.isEditable() ) {
< 		d = editor.getPreferredSize();
< 		result.width = Math.max(result.width,d.width);
< 		result.height = Math.max(result.height,d.height);
< 	    }
< 
1302a1297,1302
> 	if ( comboBox.isEditable() ) {
> 	    Dimension d = editor.getPreferredSize();
> 	    result.width = Math.max(result.width,d.width);
> 	    result.height = Math.max(result.height,d.height);
> 	}
> 

###@###.### 2002-05-06
                                     
2002-05-06
EVALUATION

This seems to be a swing bug. I wrote a small test
case with a JComboBox with the same 2 entries and
it exhibited the same problem. It appears that
the combo box is not sized properly (width-wise)
when it is editable. If it is not editable, then
the longest string appears just fine. I've
included a sample app that exhibits the problem
in the "Description".

###@###.### 2002-04-10

The front of the string in an editable combo box appears to be cropped. One workaround is to use the prototype display value for the combo box and set it for a larger value. See the workaround section for details.

Unfortunately, that exposes a small bug in BasicComboBoxUI.getDisplaySize() such that the preferred size of the editable combo box doesn't take into account of the size of the editor. The block starting with comboBox.isEditable() should be moved out of the else clause in which the prototype value does not exist.

I'm not sure why the size of the element is shy by a few pixels. One solution is to introduce a magic number that will pad the width of the getMinimumSize(). However, this isn't the real solution. The getDisplaySize() iterates over the combo box values and uses the DefaultListCellRenderer with the current JComboBox font. Ultimately, the calculation is performed by BasicLabelUI.getPreferredSize(JComponent). The real bug may lie somewhere down that codepath.

###@###.### 2002-05-06

I think the calculation using the BasicComboBoxRenderer.getPreferedSize may be coming up a little short. This calculation is performed as part of the BasicComboBoxUI.getDisplaySize() calculation. This ultimately calls the BasicLabelUI.getPreferredSize() - which calculates the Insets of the JLabel renderer based on the BasicComboBoxRenderer border.

Doing a little hacking, tif the border of BasicComboBoxRenderer has the dimensions: 1,2,1,2, then the edit field seems to look ok. It seems that this problem has been with swing since the beginning. The empty noFocusBorder has been the same dimensions since the beginning.

The size calculation for the combo box seems far too complex. Perhaps it should be simplified by taking the properties of the ComboBox renderer from the combo box properties rather than the list. The addition of the renderer to the CellRendererPane is also questionable.

###@###.### 2002-06-26

This bug only exists for the MetalLookAndFeel (or Basic) and not the WindowsLookAndFeel.

Another problem is that the size of the editor in calculating the display size is not taken
into account if a prototype value is used. This was documented in my original evaluation.

BasicComboBoxUI: This algorithm of adding the renderer component to the currentValuePane,
getting the dimensions and then removing it is in the code in 3 places:

	currentValuePane.add(comp);
	comp.setFont(comboBox.getFont());
	Dimension d = comp.getPreferredSize();
	currentValuePane.remove(comp);

Not sure what is trying to be achieved here but should try to get rid of this and simplify for
the next major release.

My first suspiction was that the JTextField sizing is incorrect since the problem also
exists for JTextField. However, the bounds and the calculation of the editable portion
of the combo box doesn't use JTextField at all - instead it uses the sizing for
BasicLabelUI from the BasicComboBoxRenderer. The text field sizing bug may be a separate problem.

The solution will be to adjust the border dimensions in the BasicComboBoxRenderer.

###@###.### 2002-06-28

Code review from Scott:

I think this bug is caused by an interaction between MetalComboBoxUI
and BasicComboBoxUI, where MetalComboBoxUI specializes calculating the
preferred size but doesn't specialize layout.
MetalComboBoxUI.getMinimumSize has the following:

        else if ( comboBox.isEditable() &&
                  arrowButton != null &&
                  editor != null ) {
            size = super.getMinimumSize( c );
            Insets margin = arrowButton.getMargin();
            size.height += margin.top + margin.bottom;
        }

Which appears to amount to adding 1 to the height.

MetalComboBoxUI ends up calling into
BasicComboBoxUI.ComboBoxLayoutManager to do layout,
ComboBoxLayoutManager makes the button square, basing the size off
the height. Because the height has been adjusted by 1, the button ends
up being 1 pixel wider, and hence your off by 1 error in the width. YECK!
If you agree that this is in fact the source of your woes, a simple
solution would be to change MetalComboBoxUI.getMinimumSize to look like:

        else if ( comboBox.isEditable() &&
                  arrowButton != null &&
                  editor != null ) {
            size = super.getMinimumSize( c );
            Insets margin = arrowButton.getMargin();
            size.height += margin.top + margin.bottom;
            size.width += margin.left + margin.right;
        }

###@###.### 2002-07-17
                                     
2002-07-17
PUBLIC COMMENTS

.
                                     
2004-06-10
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
mantis
mantis-b02

FIXED IN:
mantis
mantis-b02

INTEGRATED IN:
mantis
mantis-b02


                                     
2004-06-14



Hardware and Software, Engineered to Work Together