From b0db194b79eae70d3033da968fad8a73170b1256 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 7 Dec 2022 15:31:26 +0530 Subject: [PATCH 1/2] Combobox componnet rendering fix --- .../java/swing/plaf/gtk/GTKLookAndFeel.java | 1 + .../swing/plaf/synth/SynthComboBoxUI.java | 28 ++++ .../native/libawt_xawt/awt/gtk3_interface.c | 2 +- .../TestComboBoxComponentRendering.java | 151 ++++++++++++++++++ .../swing/JComboBox/TestComboBoxHeight.java | 2 +- 5 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 test/jdk/javax/swing/JComboBox/TestComboBoxComponentRendering.java diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index 0016e78414b7c..138a116bcf9c4 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -577,6 +577,7 @@ public Object createValue(UIDefaults table) { }), "ComboBox.font", new FontLazyValue(Region.COMBO_BOX), "ComboBox.isEnterSelectablePopup", Boolean.TRUE, + "ComboBox.squareButton", Boolean.FALSE, "EditorPane.caretForeground", caretColor, diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java index 452707fd126c0..60ff60087e2e0 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java @@ -352,6 +352,34 @@ public void update(Graphics g, JComponent c) { paint(context, g); } + /** + * The minimum size is the size of the display area plus insets plus the button. + */ + @Override + public Dimension getMinimumSize( JComponent c ) { + if ( !isMinimumSizeDirty ) { + return new Dimension(cachedMinimumSize); + } + Dimension size = getDisplaySize(); + Insets insets = getInsets(); + Insets arrowInsets = arrowButton.getInsets(); + //calculate the width and height of the button + int buttonHeight = size.height; + int buttonWidth = squareButton ? + buttonHeight : + arrowButton.getPreferredSize().width; + //adjust the size based on the button width + size.height += insets.top + insets.bottom + arrowInsets.top + + arrowInsets.bottom; + size.width += insets.left + insets.right +arrowInsets.left + + arrowInsets.right + buttonWidth; + + cachedMinimumSize.setSize( size.width, size.height ); + isMinimumSizeDirty = false; + + return new Dimension(size); + } + /** * Paints the specified component according to the Look and Feel. *

This method is not used by Synth Look and Feel. diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c index c0c28b77c2d67..fa448f8e752fc 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -1473,7 +1473,7 @@ static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type, break; case COMBO_BOX_ARROW_BUTTON: - s = (int)(0.3 * height + 0.5) + 1; + s = (int)(0.3 * MIN(height, width) + 0.5) + 1; a = G_PI; break; diff --git a/test/jdk/javax/swing/JComboBox/TestComboBoxComponentRendering.java b/test/jdk/javax/swing/JComboBox/TestComboBoxComponentRendering.java new file mode 100644 index 0000000000000..0e176a911a39c --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/TestComboBoxComponentRendering.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8218474 + * @key headful + * @requires (os.family == "linux") + * @summary Verifies if combobox components are rendered correctly. + * @run main TestComboBoxComponentRendering + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.image.BufferedImage; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.io.File; +import javax.imageio.ImageIO; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class TestComboBoxComponentRendering { + private static JFrame frame; + private static JComboBox cb; + private static Robot robot; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.setAutoDelay(100); + + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + if (!laf.getClassName().contains("MotifLookAndFeel") && + !laf.getClassName().contains("MetalLookAndFeel")) { + System.out.println("Testing LAF: " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + doTesting(laf); + } + } + } + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Unsupported LAF: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static void doTesting(UIManager.LookAndFeelInfo laf) + throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + createAndShowUI(); + }); + boolean passed = false; + robot.waitForIdle(); + robot.delay(1000); + + Point pt = cb.getLocationOnScreen(); + BufferedImage img = robot.createScreenCapture( + new Rectangle(pt.x, pt.y, cb.getWidth(), cb.getHeight())); + for (int x = 20; x < img.getWidth()-20; ++x) { + for (int y = 20; y < img.getHeight()-20; ++y) { + if (img.getRGB(x,y) == Color.RED.getRGB()) { + passed = true; + break; + } + } + if (passed) + break; + } + + if (passed) { + System.out.println("Passed"); + } else { + ImageIO.write(img, "png", + new File("ComboBox.png")); + throw new RuntimeException("ComboBox components not rendered" + + " correctly for: " + laf.getClassName()); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" }; + frame = new JFrame(); + cb = new JComboBox(petStrings); + cb.setRenderer(new ComboBoxCustomRenderer()); + frame.pack(); + frame.add(cb); + frame.setSize(200,250); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } +} + +class ComboBoxCustomRenderer extends JLabel + implements ListCellRenderer { + + public ComboBoxCustomRenderer() { + setOpaque(true); + setHorizontalAlignment(CENTER); + setVerticalAlignment(CENTER); + } + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + setText(value.toString()); + setForeground(Color.RED); + return this; + } +} diff --git a/test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java b/test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java index 5cd5edcbbcc65..b06dcdce3e9c0 100644 --- a/test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java +++ b/test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java @@ -24,7 +24,7 @@ /* * @test * @key headful - * @bug 4517214 + * @bug 4517214 8218474 * @summary Tests that comboBox is not doubleheight if editable and has TitledBorder */ From ea53f8aee03d676fd114aa717ef702cee8e47cae Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 22 Dec 2022 15:58:46 +0530 Subject: [PATCH 2/2] Review comment update --- .../share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java index 60ff60087e2e0..9389806d49985 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java @@ -371,7 +371,7 @@ public Dimension getMinimumSize( JComponent c ) { //adjust the size based on the button width size.height += insets.top + insets.bottom + arrowInsets.top + arrowInsets.bottom; - size.width += insets.left + insets.right +arrowInsets.left + size.width += insets.left + insets.right + arrowInsets.left + arrowInsets.right + buttonWidth; cachedMinimumSize.setSize( size.width, size.height );