/* * Copyright (c) 2018, 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. */ import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Font; import java.util.Objects; import java.util.concurrent.Callable; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JEditorPane; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JToolTip; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.tree.DefaultMutableTreeNode; import static javax.swing.UIManager.getInstalledLookAndFeels; /** * @test * @key headful * @bug 8201552 * @summary Initial layout of the component should use correct graphics config. * It is checked by SwingUtilities.updateComponentTreeUI(), if layout * was correct the call to updateComponentTreeUI() will be no-op. * @compile -encoding utf-8 StalePreferredSize.java * @run main StalePreferredSize * @run main/othervm -Dsun.java2d.uiScale=2.25 StalePreferredSize */ public final class StalePreferredSize { static final String HTML = "A few words to get started before the " + "bugoverlapping text"; // Some text to be tested static String TEXT1 = "A quick brown fox jumps over the lazy dog"; static String TEXT2 = "El veloz murciélago hindú comía feliz cardillo y " + "kiwi. La cigüeña tocaba el saxofón detrás del palenque de paja"; static String TEXT3 = "Voix ambiguë d’un cœur qui au zéphyr préfère les " + "jattes de kiwis"; static String TEXT4 = "다람쥐 헌 쳇바퀴에 타고파"; static String TEXT5 = "Съешь ещё этих мягких французских булок да выпей же чаю"; static JFrame frame; static Component component; static int typeFont = 0; // 0 - default, 1 - bold, 2 - italic public static void main(final String[] args) throws Exception { for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { EventQueue.invokeAndWait(() -> setLookAndFeel(laf)); for (; typeFont < 3; typeFont++) { System.err.println("typeFont = " + typeFont); test(HTML); test(TEXT1); test(TEXT2); test(TEXT3); test(TEXT4); test(TEXT5); } } } private static void test(String text) throws Exception { System.err.println("text = " + text); // Each Callable create a component to be tested Callable[] comps = { () -> new JLabel(text), () -> new JButton(text), () -> new JMenuItem(text), () -> new JMenu(text), () -> new JList<>(new String[]{text}), () -> new JComboBox<>(new String[]{text}), () -> new JTextField(text), () -> new JTextArea(text), () -> new JCheckBox(text), () -> new JFormattedTextField(text), () -> new JRadioButton(text), () -> new JTree(new DefaultMutableTreeNode(text)), //TODO () -> new JSpinner(new SpinnerListModel(new String[]{HTML})), () -> { JToolTip tip = new JToolTip(); tip.setTipText(text); return tip; }, () -> { JEditorPane pane = new JEditorPane(); pane.setText(text); return pane; }, () -> { JTable table = new JTable(1, 1); table.getModel().setValueAt(text, 0, 0); return table; } }; for (Callable creator : comps) { checkComponent(creator); } } static void checkComponent(Callable creator) throws Exception { EventQueue.invokeAndWait(() -> { try { component = creator.call(); } catch (Exception e) { throw new RuntimeException(e); } if (typeFont == 1) { component.setFont(component.getFont().deriveFont(Font.BOLD)); } if (typeFont == 2) { component.setFont(component.getFont().deriveFont(Font.ITALIC)); } frame = new JFrame(); frame.setLayout(new FlowLayout()); frame.add(new JScrollPane(component)); frame.setSize(300, 100); frame.setLocationRelativeTo(null); frame.setVisible(true); }); EventQueue.invokeAndWait(() -> { // After the frame was shown we change nothing, so current layout // should be optimal and updateComponentTreeUI() should be no-op Dimension before = component.getPreferredSize(); SwingUtilities.updateComponentTreeUI(frame); Dimension after = component.getPreferredSize(); frame.dispose(); if (!Objects.equals(before, after)) { System.err.println("Component: " + component); System.err.println("Before: " + before); System.err.println("After: " + after); throw new RuntimeException("Wrong PreferredSize"); } }); } private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) { try { UIManager.setLookAndFeel(laf.getClassName()); System.err.println("LookAndFeel: " + laf.getClassName()); } catch (final UnsupportedLookAndFeelException ignored) { System.err.println( "Unsupported LookAndFeel: " + laf.getClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); } } }