Path: blob/master/test/jdk/javax/swing/GraphicsConfigNotifier/StalePreferredSize.java
41149 views
/*1* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.awt.Dimension;24import java.awt.EventQueue;25import java.awt.FlowLayout;26import java.awt.Font;27import java.util.List;28import java.util.Objects;29import java.util.concurrent.Callable;3031import javax.swing.JButton;32import javax.swing.JCheckBox;33import javax.swing.JComboBox;34import javax.swing.JComponent;35import javax.swing.JEditorPane;36import javax.swing.JFormattedTextField;37import javax.swing.JFrame;38import javax.swing.JLabel;39import javax.swing.JList;40import javax.swing.JMenu;41import javax.swing.JMenuItem;42import javax.swing.JRadioButton;43import javax.swing.JScrollPane;44import javax.swing.JSpinner;45import javax.swing.JTable;46import javax.swing.JTextArea;47import javax.swing.JTextField;48import javax.swing.JToolTip;49import javax.swing.JTree;50import javax.swing.Popup;51import javax.swing.PopupFactory;52import javax.swing.SpinnerListModel;53import javax.swing.SwingUtilities;54import javax.swing.UIManager;55import javax.swing.UnsupportedLookAndFeelException;56import javax.swing.tree.DefaultMutableTreeNode;5758import sun.swing.MenuItemLayoutHelper;5960import static javax.swing.UIManager.getInstalledLookAndFeels;6162/**63* @test64* @key headful65* @bug 8201552 8213843 821353566* @summary Initial layout of the component should use correct graphics config.67* It is checked by SwingUtilities.updateComponentTreeUI(), if layout68* was correct the call to updateComponentTreeUI() will be no-op.69* @modules java.desktop/sun.swing70* @compile -encoding utf-8 StalePreferredSize.java71* @run main/othervm/timeout=400 StalePreferredSize72* @run main/othervm/timeout=400 -Dsun.java2d.uiScale=1 StalePreferredSize73* @run main/othervm/timeout=400 -Dsun.java2d.uiScale=2.25 StalePreferredSize74*/75public final class StalePreferredSize {7677// Some text to be tested78static final String TEXT[] = new String[]{79"<span>A few words to get started before the "80+ "bug</span><span>overlapping text</span>",81"A quick brown fox jumps over the lazy dog",82"El veloz murciélago hindú comía feliz cardillo y kiwi. La cigüeña "83+ "tocaba el saxofón detrás del palenque de paja",84"Voix ambiguë d’un cœur qui au zéphyr préfère les jattes de kiwis",85"다람쥐 헌 쳇바퀴에 타고파",86"Съешь ещё этих мягких французских булок да выпей же чаю"};8788static JFrame frame;89static Popup popup;90static JComponent component;91static int typeFont = 0; // 0 - default, 1 - bold, 2 - italic92static boolean addViaPopup;9394public static void main(final String[] args) throws Exception {95for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) {96EventQueue.invokeAndWait(() -> setLookAndFeel(laf));97for (typeFont = 0; typeFont < 3; typeFont++) {98System.err.println("typeFont = " + typeFont);99for (boolean usePopup : new boolean[]{true, false}) {100addViaPopup = usePopup;101System.err.println("Use popup: " + usePopup);102for (final boolean html : new boolean[]{true, false}) {103for (String text : TEXT) {104if (html) {105text = "<html>" + text + "</html>";106}107test(text);108}109}110}111}112}113}114115private static void test(String text) throws Exception {116System.err.println("text = " + text);117// Each Callable create a component to be tested118final List<Callable<JComponent>> comps = List.of(119() -> new JLabel(text),120() -> new JButton(text),121() -> new JMenuItem(text),122() -> new JMenu(text),123() -> new JList<>(new String[]{text}),124() -> new JComboBox<>(new String[]{text}),125() -> new JTextField(text),126() -> new JTextArea(text),127() -> new JCheckBox(text),128() -> new JFormattedTextField(text),129() -> new JRadioButton(text),130() -> new JTree(new DefaultMutableTreeNode(text)),131() -> new JSpinner(new SpinnerListModel(new String[]{text})),132() -> {133JToolTip tip = new JToolTip();134tip.setTipText(text);135return tip;136},137() -> {138JEditorPane pane = new JEditorPane();139pane.setText(text);140return pane;141},142() -> {143JTable table = new JTable(1, 1);144table.getModel().setValueAt(text, 0, 0);145return table;146}147);148149for (final Callable<JComponent> creator : comps) {150checkComponent(creator);151}152}153154static void checkComponent(Callable<JComponent> creator) throws Exception {155EventQueue.invokeAndWait(() -> {156157try {158component = creator.call();159} catch (Exception e) {160throw new RuntimeException(e);161}162163component.setEnabled(false); // minimize paint/focus events amount164Font font = component.getFont();165if (typeFont == 1) {166component.setFont(new Font(font.deriveFont(Font.BOLD).getAttributes()));167}168if (typeFont == 2) {169component.setFont(new Font(font.deriveFont(Font.ITALIC).getAttributes()));170}171172frame = new JFrame();173// incorrect initial insets may ruin our size calculation174frame.setUndecorated(true); // TODO JDK-8244388175frame.setLayout(new FlowLayout());176frame.setSize(700, 400);177frame.setLocationRelativeTo(null);178if (addViaPopup) {179// doing our best to show lightweight or mediumweight popup180int x = frame.getX() + 50;181int y = frame.getY() + 200;182PopupFactory factory = PopupFactory.getSharedInstance();183popup = factory.getPopup(frame, component, x, y);184if (component instanceof JMenuItem) {185// TODO JDK-8244400186MenuItemLayoutHelper.clearUsedParentClientProperties((JMenuItem)component);187}188} else {189frame.add(new JScrollPane(component));190}191frame.setVisible(true);192if (popup != null) {193popup.show();194}195});196197EventQueue.invokeAndWait(() -> {198if (!component.isValid()) {199dispose();200throw new RuntimeException("Component must be valid");201}202203// After the frame was shown we change nothing, so current layout204// should be optimal and updateComponentTreeUI() should be no-op205Dimension before = component.getPreferredSize();206SwingUtilities.updateComponentTreeUI(frame);207Dimension after = component.getPreferredSize();208209// We change the font size to some big value, as a result the210// layout and preferredSize of the component should be changed211component.setFont(component.getFont().deriveFont(35f));212Dimension last = component.getPreferredSize();213214dispose();215216if (!Objects.equals(before, after)) {217System.err.println("Component: " + component);218System.err.println("Before: " + before);219System.err.println("After: " + after);220throw new RuntimeException("Wrong PreferredSize");221}222// TODO JDK-8206024223// if (Objects.equals(after, last)) {224// System.err.println("Component: " + component);225// System.err.println("After: " + after);226// System.err.println("Last: " + last);227// throw new RuntimeException("Wrong PreferredSize");228// }229});230}231232private static void dispose() {233if (popup != null) {234popup.hide();235popup = null;236}237frame.dispose();238}239240private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) {241try {242UIManager.setLookAndFeel(laf.getClassName());243System.err.println("LookAndFeel: " + laf.getClassName());244} catch (final UnsupportedLookAndFeelException ignored) {245System.err.println(246"Unsupported LookAndFeel: " + laf.getClassName());247} catch (ClassNotFoundException | InstantiationException |248IllegalAccessException e) {249throw new RuntimeException(e);250}251}252}253254255