-
Bug
-
Resolution: Fixed
-
P4
-
1.4.0
-
beta
-
x86
-
windows_nt
Name: sv35042 Date: 10/09/2002
FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows NT
4.00.1381
ServicePack: 5
A DESCRIPTION OF THE PROBLEM :
MetalComboBoxUI computes wrong sizes if user-defined ArrowButton
is used, which is not subclasses from
MetalComboBoxButton.
If you use an user-defined ArrowButton in a MetalComboBox the
MetalComboBoxUI computes wrong sizes for the ComboBox.
In MetalComboBoxUI.getMinimumSize(JComponent c):
public Dimension getMinimumSize( JComponent c ) {
...
if ( !comboBox.isEditable() &&
arrowButton != null &&
arrowButton instanceof MetalComboBoxButton ) {
...
}
else if ( comboBox.isEditable() &&
arrowButton != null &&
editor != null ) {
size = super.getMinimumSize( c );
Insets margin = arrowButton.getMargin();
Insets insets = comboBox.getInsets();
if ( editor instanceof JComponent ) {
Insets editorInsets =
((JComponent)editor).getInsets();
size.height += editorInsets.top +
editorInsets.bottom;
}
size.height += margin.top + margin.bottom;
size.height += insets.top + insets.bottom;
}
else {
size = super.getMinimumSize( c );
}
...
The arrowButton is asked for its margins but neither they nor
the button's insets are used in computing the size of the
ComboBox.
This causes the ComboBox being too small.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Split the attached source into Files MyComboBox.java,
MyComboBoxButton.java, MyComboBoxUI.java, MyLAF.java
and T01.java
2. Compile the files into some directory.
3. Run T01
EXPECTED VERSUS ACTUAL BEHAVIOR :
The program displays a label, a MyComboBox widget and
a JComboBox widget.
The MyComboBox widget is several pixel smaller than
the JComboBox widgets.
I'd expect the MyComboBox widget to be the same
size, as it essentially uses the same ArrowButton, see
below.
Internally MyComboBox uses the MyComboBoxUI class which
is subclassed from MetalComboBoxUI and creates a
MyComboBoxButton for use as ArrowButton in the MyComboBox.
MyComboBoxButton is a copy of MetalComboBoxButton, with
just some names changed to fit the new class name
and to circumvent accessibility problems of
package-private classes etc.
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
----- MyComboBox.java
import javax.swing.JComboBox;
public class MyComboBox
extends JComboBox
{
public String getUIClassID() {
return "MyComboBoxUI";
}
public MyComboBox(Object[] items)
{
super(items);
}
}
----- MyComboBoxButton.java
/*
* @(#)MetalComboBoxButton.java 1.33 01/12/03
*
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
//package javax.swing.plaf.metal;
package myLAF;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.basic.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.border.*;
import java.io.Serializable;
/**
* JButton subclass to help out MetalComboBoxUI
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans<sup><font size="-2">TM</font></sup>
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @see MyComboBoxButton
* @version 1.33 12/03/01
* @author Tom Santos
*/
public class MyComboBoxButton extends JButton {
protected JComboBox comboBox;
protected JList listBox;
protected CellRendererPane rendererPane;
protected Icon comboIcon;
protected boolean iconOnly = false;
public final JComboBox getComboBox() { return comboBox;}
public final void setComboBox( JComboBox cb ) { comboBox = cb;}
public final Icon getComboIcon() { return comboIcon;}
public final void setComboIcon( Icon i ) { comboIcon = i;}
public final boolean isIconOnly() { return iconOnly;}
public final void setIconOnly( boolean isIconOnly ) { iconOnly = isIconOnly;}
MyComboBoxButton() {
super( "" );
DefaultButtonModel model = new DefaultButtonModel() {
public void setArmed( boolean armed ) {
super.setArmed( isPressed() ? true : armed );
}
};
setModel( model );
// Set the background and foreground to the combobox colors.
setBackground(UIManager.getColor("ComboBox.background"));
setForeground(UIManager.getColor("ComboBox.foreground"));
}
public MyComboBoxButton( JComboBox cb, Icon i,
CellRendererPane pane, JList list ) {
this();
comboBox = cb;
comboIcon = i;
rendererPane = pane;
listBox = list;
setEnabled( comboBox.isEnabled() );
}
public MyComboBoxButton( JComboBox cb, Icon i, boolean onlyIcon,
CellRendererPane pane, JList list ) {
this( cb, i, pane, list );
iconOnly = onlyIcon;
}
public boolean isFocusTraversable() {
return false;
}
public void paintComponent( Graphics g ) {
boolean leftToRight = true; //MetalUtils.isLeftToRight(comboBox);
// Paint the button as usual
super.paintComponent( g );
Insets insets = getInsets();
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);
if ( height <= 0 || width <= 0 ) {
return;
}
int left = insets.left;
int top = insets.top;
int right = left + (width - 1);
int bottom = top + (height - 1);
int iconWidth = 0;
int iconLeft = (leftToRight) ? right : left;
// Paint the icon
if ( comboIcon != null ) {
iconWidth = comboIcon.getIconWidth();
int iconHeight = comboIcon.getIconHeight();
int iconTop = 0;
if ( iconOnly ) {
iconLeft = (getWidth() / 2) - (iconWidth / 2);
iconTop = (getHeight() / 2) - (iconHeight / 2);
}
else {
if (leftToRight) {
iconLeft = (left + (width - 1)) - iconWidth;
}
else {
iconLeft = left;
}
iconTop = (top + ((bottom - top) / 2)) - (iconHeight / 2);
}
comboIcon.paintIcon( this, g, iconLeft, iconTop );
// Paint the focus
if ( comboBox.hasFocus() ) {
g.setColor(
javax.swing.plaf.metal.MetalLookAndFeel.getFocusColor() );
g.drawRect( left - 1, top - 1, width + 3, height + 1 );
}
}
// Let the renderer paint
if ( ! iconOnly && comboBox != null ) {
ListCellRenderer renderer = comboBox.getRenderer();
Component c;
boolean renderPressed = getModel().isPressed();
c = renderer.getListCellRendererComponent(listBox,
comboBox.getSelectedItem(),
-1,
renderPressed,
false);
c.setFont(rendererPane.getFont());
if ( model.isArmed() && model.isPressed() ) {
if ( isOpaque() ) {
c.setBackground(UIManager.getColor("Button.select"));
}
c.setForeground(comboBox.getForeground());
}
else if ( !comboBox.isEnabled() ) {
if ( isOpaque() ) {
c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
}
c.setForeground(UIManager.getColor("ComboBox.disabledForeground"));
}
else {
c.setForeground(comboBox.getForeground());
c.setBackground(comboBox.getBackground());
}
int cWidth = width - (insets.right + iconWidth);
// Fix for 4238829: should lay out the JPanel.
boolean shouldValidate = false;
if (c instanceof JPanel) {
shouldValidate = true;
}
if (leftToRight) {
rendererPane.paintComponent( g, c, this,
left, top, cWidth, height, shouldValidate );
}
else {
rendererPane.paintComponent( g, c, this,
left + iconWidth, top, cWidth, height, shouldValidate );
}
}
}
}
------ MyComboBoxUI.java
package myLAF;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.metal.*;
import myLAF.MyComboBoxButton;
public class MyComboBoxUI
extends MetalComboBoxUI
{
public static ComponentUI createUI(JComponent c) {
return new MyComboBoxUI();
}
protected JButton createArrowButton() {
JButton button = new MyComboBoxButton(comboBox,
new MetalComboBoxIcon(),
comboBox.isEditable(),
currentValuePane,
listBox);
button.setMargin(new Insets(0, 1, 1, 3));
return button;
}
}
------------- MyLAF.java
package myLAF;
import javax.swing.*;
import javax.swing.plaf.metal.*;
public class MyLAF
extends MetalLookAndFeel
{
public String getName() {
return "MyLAF";
}
public String getID() {
return "MyLAF";
}
public String getDescription() {
return "MY LOOK AND FEEL";
}
public boolean isSupportedLookAndFeel() {
return true;
}
protected void initClassDefaults(UIDefaults table) {
super.initClassDefaults(table);
table.putDefaults(new Object[] {
"MyComboBoxUI", "myLAF.MyComboBoxUI",
});
}
}
------- T01.java
import java.awt.*;
import javax.swing.*;
//import MyComboBox;
public class T01
extends JFrame
{
public static void main(String[] av)
{
try {
//
javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
javax.swing.UIManager.setLookAndFeel("myLAF.MyLAF");
} catch(Exception ex) {
System.err.println("Could not set L&F: "+ex);
System.exit(1);
}
T01 t = new T01();
t.init();
t.pack();
t.setVisible(true);
}
void init()
{
Container cont = getContentPane();
cont.setLayout(new FlowLayout());
cont.add(new JLabel("a MyComboBox:"));
cont.add(new MyComboBox(new Object[]{"red", "green", "blue"}));
cont.add(new JComboBox(new Object[]{"cyan", "yellow", "magenta"}));
}
}
---------- END SOURCE ----------
(Review ID: 145722)
======================================================================
- relates to
-
JDK-6279559 No appropriate CCC request for listed JDK 6.0 changes in javax.swing package
-
- Resolved
-