Skip to content

Commit 0935405

Browse files
committed
8218474: JComboBox display issue with GTKLookAndFeel
Backport-of: c4449224bbb70d1a0256ebf19297450ab0f98d4b
1 parent 4c12437 commit 0935405

File tree

5 files changed

+182
-2
lines changed

5 files changed

+182
-2
lines changed

src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ public Object createValue(UIDefaults table) {
577577
}),
578578
"ComboBox.font", new FontLazyValue(Region.COMBO_BOX),
579579
"ComboBox.isEnterSelectablePopup", Boolean.TRUE,
580+
"ComboBox.squareButton", Boolean.FALSE,
580581

581582

582583
"EditorPane.caretForeground", caretColor,

src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,34 @@ public void update(Graphics g, JComponent c) {
357357
paint(context, g);
358358
}
359359

360+
/**
361+
* The minimum size is the size of the display area plus insets plus the button.
362+
*/
363+
@Override
364+
public Dimension getMinimumSize( JComponent c ) {
365+
if ( !isMinimumSizeDirty ) {
366+
return new Dimension(cachedMinimumSize);
367+
}
368+
Dimension size = getDisplaySize();
369+
Insets insets = getInsets();
370+
Insets arrowInsets = arrowButton.getInsets();
371+
//calculate the width and height of the button
372+
int buttonHeight = size.height;
373+
int buttonWidth = squareButton ?
374+
buttonHeight :
375+
arrowButton.getPreferredSize().width;
376+
//adjust the size based on the button width
377+
size.height += insets.top + insets.bottom + arrowInsets.top
378+
+ arrowInsets.bottom;
379+
size.width += insets.left + insets.right + arrowInsets.left
380+
+ arrowInsets.right + buttonWidth;
381+
382+
cachedMinimumSize.setSize( size.width, size.height );
383+
isMinimumSizeDirty = false;
384+
385+
return new Dimension(size);
386+
}
387+
360388
/**
361389
* Paints the specified component according to the Look and Feel.
362390
* <p>This method is not used by Synth Look and Feel.

src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1525,7 +1525,7 @@ static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type,
15251525
break;
15261526

15271527
case COMBO_BOX_ARROW_BUTTON:
1528-
s = (int)(0.3 * height + 0.5) + 1;
1528+
s = (int)(0.3 * MIN(height, width) + 0.5) + 1;
15291529
a = G_PI;
15301530
break;
15311531

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8218474
27+
* @key headful
28+
* @requires (os.family == "linux")
29+
* @summary Verifies if combobox components are rendered correctly.
30+
* @run main TestComboBoxComponentRendering
31+
*/
32+
33+
import java.awt.Color;
34+
import java.awt.Component;
35+
import java.awt.image.BufferedImage;
36+
import java.awt.Point;
37+
import java.awt.Rectangle;
38+
import java.awt.Robot;
39+
import java.io.File;
40+
import javax.imageio.ImageIO;
41+
import javax.swing.JComboBox;
42+
import javax.swing.JFrame;
43+
import javax.swing.JLabel;
44+
import javax.swing.JList;
45+
import javax.swing.ListCellRenderer;
46+
import javax.swing.SwingUtilities;
47+
import javax.swing.UIManager;
48+
import javax.swing.UnsupportedLookAndFeelException;
49+
50+
public class TestComboBoxComponentRendering {
51+
private static JFrame frame;
52+
private static JComboBox cb;
53+
private static Robot robot;
54+
55+
public static void main(String[] args) throws Exception {
56+
robot = new Robot();
57+
robot.setAutoDelay(100);
58+
59+
for (UIManager.LookAndFeelInfo laf :
60+
UIManager.getInstalledLookAndFeels()) {
61+
if (!laf.getClassName().contains("MotifLookAndFeel") &&
62+
!laf.getClassName().contains("MetalLookAndFeel")) {
63+
System.out.println("Testing LAF: " + laf.getClassName());
64+
SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf));
65+
doTesting(laf);
66+
}
67+
}
68+
}
69+
70+
private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) {
71+
try {
72+
UIManager.setLookAndFeel(laf.getClassName());
73+
} catch (UnsupportedLookAndFeelException ignored) {
74+
System.out.println("Unsupported LAF: " + laf.getClassName());
75+
} catch (ClassNotFoundException | InstantiationException
76+
| IllegalAccessException e) {
77+
throw new RuntimeException(e);
78+
}
79+
}
80+
81+
private static void doTesting(UIManager.LookAndFeelInfo laf)
82+
throws Exception {
83+
try {
84+
SwingUtilities.invokeAndWait(() -> {
85+
createAndShowUI();
86+
});
87+
boolean passed = false;
88+
robot.waitForIdle();
89+
robot.delay(1000);
90+
91+
Point pt = cb.getLocationOnScreen();
92+
BufferedImage img = robot.createScreenCapture(
93+
new Rectangle(pt.x, pt.y, cb.getWidth(), cb.getHeight()));
94+
for (int x = 20; x < img.getWidth()-20; ++x) {
95+
for (int y = 20; y < img.getHeight()-20; ++y) {
96+
if (img.getRGB(x,y) == Color.RED.getRGB()) {
97+
passed = true;
98+
break;
99+
}
100+
}
101+
if (passed)
102+
break;
103+
}
104+
105+
if (passed) {
106+
System.out.println("Passed");
107+
} else {
108+
ImageIO.write(img, "png",
109+
new File("ComboBox.png"));
110+
throw new RuntimeException("ComboBox components not rendered" +
111+
" correctly for: " + laf.getClassName());
112+
}
113+
} finally {
114+
SwingUtilities.invokeAndWait(() -> {
115+
if (frame != null) {
116+
frame.dispose();
117+
}
118+
});
119+
}
120+
}
121+
122+
private static void createAndShowUI() {
123+
String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" };
124+
frame = new JFrame();
125+
cb = new JComboBox(petStrings);
126+
cb.setRenderer(new ComboBoxCustomRenderer());
127+
frame.pack();
128+
frame.add(cb);
129+
frame.setSize(200,250);
130+
frame.setLocationRelativeTo(null);
131+
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
132+
frame.setVisible(true);
133+
}
134+
}
135+
136+
class ComboBoxCustomRenderer extends JLabel
137+
implements ListCellRenderer {
138+
139+
public ComboBoxCustomRenderer() {
140+
setOpaque(true);
141+
setHorizontalAlignment(CENTER);
142+
setVerticalAlignment(CENTER);
143+
}
144+
145+
public Component getListCellRendererComponent(JList list, Object value,
146+
int index, boolean isSelected, boolean cellHasFocus) {
147+
setText(value.toString());
148+
setForeground(Color.RED);
149+
return this;
150+
}
151+
}

test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
/*
2525
* @test
2626
* @key headful
27-
* @bug 4517214
27+
* @bug 4517214 8218474
2828
* @summary Tests that comboBox is not doubleheight if editable and has TitledBorder
2929
*/
3030

0 commit comments

Comments
 (0)