/*
* 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);
}
}
}