From cc9148ddef95c6ca27ff9fee4c17fb0d4ba7f88e Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Tue, 22 Apr 2025 20:27:17 +0000 Subject: [PATCH] 8354695: Open source several swing tests batch7 Reviewed-by: kizune, achung --- .../jdk/javax/swing/JRootPane/bug4403624.java | 106 +++ .../HorizScrollers.java | 234 ++++++ .../RTLScrollers.java | 684 ++++++++++++++++++ .../javax/swing/JScrollPane/bug4166037.java | 167 +++++ .../javax/swing/JScrollPane/bug4237517.java | 69 ++ .../javax/swing/JScrollPane/bug4237560.java | 77 ++ .../javax/swing/JScrollPane/bug4244899.java | 99 +++ 7 files changed, 1436 insertions(+) create mode 100644 test/jdk/javax/swing/JRootPane/bug4403624.java create mode 100644 test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java create mode 100644 test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java create mode 100644 test/jdk/javax/swing/JScrollPane/bug4166037.java create mode 100644 test/jdk/javax/swing/JScrollPane/bug4237517.java create mode 100644 test/jdk/javax/swing/JScrollPane/bug4237560.java create mode 100644 test/jdk/javax/swing/JScrollPane/bug4244899.java diff --git a/test/jdk/javax/swing/JRootPane/bug4403624.java b/test/jdk/javax/swing/JRootPane/bug4403624.java new file mode 100644 index 00000000000..1c3ba3ddd2a --- /dev/null +++ b/test/jdk/javax/swing/JRootPane/bug4403624.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001, 2025, 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 4403624 + * @summary Tests JRootPane layout with invisible menubar + * @key headful + * @run main bug4403624 + */ + +import java.awt.Color; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.SwingUtilities; + +public class bug4403624 { + private static JFrame f; + private static Container c; + private static JButton b; + private static volatile Point p; + private static volatile int bWidth; + private static volatile int bHeight; + private static final int OFFSET = 2; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4403624 Test"); + JMenuBar mbar; + mbar = new JMenuBar(); + mbar.add(new JMenu("Menu")); + f.setJMenuBar(mbar); + b = new JButton("Hide Menu"); + b.addActionListener(e -> mbar.setVisible(false)); + c = f.getContentPane(); + c.setLayout(new FlowLayout()); + c.setBackground(Color.GREEN); + c.add(b); + f.pack(); + f.setLocationRelativeTo(null); + f.setAlwaysOnTop(true); + f.setVisible(true); + }); + + Robot r = new Robot(); + r.setAutoDelay(200); + r.waitForIdle(); + r.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + p = b.getLocationOnScreen(); + bWidth = b.getWidth(); + bHeight = b.getHeight(); + }); + + r.mouseMove(p.x + (bWidth / 2), p.y + (bHeight / 2)); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + SwingUtilities.invokeAndWait(() -> p = c.getLocationOnScreen()); + + Color c = r.getPixelColor(p.x + OFFSET, p.y + OFFSET); + + if (c.getGreen() < 240 && c.getBlue() > 10 && c.getRed() > 10) { + System.out.println("EXPECTED: " + Color.GREEN); + System.out.println("ACTUAL: " + c); + throw new RuntimeException("Failure to hide menu bar."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java new file mode 100644 index 00000000000..b584fd66da3 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2004, 2025, 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 5078454 + * @summary Test horizontal wheel scroll behavior of (including RTL) + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual HorizScrollers + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; + +public class HorizScrollers { + private static final String INSTRUCTIONS = """ + This is a semi-automatic test with three phases. + For each phase, you will need to change the mouse setting, as + directed by a dialog. Once the correct setting is confirmed, + the next test phase will run automatically. + DO NOT TOUCH ANYTHING DURING TESTING! + + The test will automatically FAIL during testing if something + fails. Otherwise, the test will automatically PASS after the + third testing phase. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("HorizScrollers Instructions") + .instructions(INSTRUCTIONS) + .columns(45) + .testTimeOut(10) + .splitUIRight(ConfigPanel::new) + .logArea(6) + .build() + .awaitAndCheck(); + } + + private static final int[] SCROLLAMTS = {1, 30, 3}; + private static final String[] CONFIG_MSGS = { + "Set the scrolling speed to the slowest value (1 line).", + "Set the scrolling speed to the fastest value (30 lines).", + "Set the scrolling speed to two ticks above the slowest value (3 lines)." + }; + + private static int current = 0; + private static final String MW_TEXT = "Rotate the mouse wheel here"; + private static final String CONFIG_INSTRUCTION_TEMPLATE = """ + Configure Mouse Wheel for Phase %d + + Open the Mouse Control Panel and go to the 'Wheel' tab. + If 'Wheel' tab is not available just press Pass. + + %s + + Test the setting on the area below. + Once the mouse is setup correctly, the area will turn green. + When you're ready for the next part of the test to run, press GO! + """; + + static class ConfigPanel extends JPanel + implements ActionListener, MouseWheelListener { + JTextArea msg; + JButton goBtn; + JLabel mwArea; + int scrollAmount; + + private final Color defaultBg; + + ConfigPanel() { + this.scrollAmount = SCROLLAMTS[current]; + Container content = this; + content.setLayout(new BorderLayout()); + msg = new JTextArea(); + msg.setMargin(new Insets(5, 5, 5, 5)); + msg.setEditable(false); + msg.setLineWrap(true); + msg.setWrapStyleWord(true); + content.add(msg, BorderLayout.NORTH); + + mwArea = new JLabel(MW_TEXT, SwingConstants.CENTER); + mwArea.setPreferredSize(new Dimension(200, 250)); + mwArea.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + mwArea.setOpaque(true); + mwArea.addMouseWheelListener(this); + content.add(mwArea, BorderLayout.CENTER); + + defaultBg = mwArea.getBackground(); + setPhase(current); + + goBtn = new JButton("GO!"); + goBtn.setEnabled(false); + goBtn.addActionListener(this); + JPanel flowPanel = new JPanel(); + flowPanel.setLayout(new FlowLayout()); + flowPanel.add(goBtn); + content.add(flowPanel, BorderLayout.SOUTH); + + setPreferredSize(new Dimension(600, 400)); + } + + public void setPhase(int phase) { + if (phase < 3) { + setVisible(true); + PassFailJFrame.log("Phase %d scroll speed %d" + .formatted(phase + 1, SCROLLAMTS[phase])); + PassFailJFrame.log(CONFIG_MSGS[phase]); + + scrollAmount = SCROLLAMTS[phase]; + msg.setText(CONFIG_INSTRUCTION_TEMPLATE + .formatted(phase + 1, CONFIG_MSGS[phase])); + mwArea.setBackground(defaultBg); + mwArea.setText(MW_TEXT); + } else { + // all cases passed + showFinalReminderIfNeeded(false); + } + } + + private void showFinalReminderIfNeeded(boolean isFailure) { + if (scrollAmount != 3) { + JOptionPane.showMessageDialog( + ConfigPanel.this.getTopLevelAncestor(), + ("Test %s. please make sure you have restored " + + "the original speed value blah blah") + .formatted(isFailure + ? "failed" + : "passed"), + isFailure + ? "Failure" + : "Success", + isFailure + ? JOptionPane.WARNING_MESSAGE + : JOptionPane.INFORMATION_MESSAGE + ); + } + + if (isFailure) { + PassFailJFrame.forceFail(); + } else { + PassFailJFrame.forcePass(); + } + } + + public void actionPerformed(ActionEvent e) { + if (e.getSource() == goBtn) { + goBtn.setEnabled(false); + + new Thread(() -> { // new thread to avoid running robot on EDT + boolean passed; + try { + passed = RTLScrollers.runTest(SCROLLAMTS[current]); + } catch (Exception ex) { + PassFailJFrame.log("Failure: " + ex); + SwingUtilities.invokeLater(() -> + showFinalReminderIfNeeded(true)); + return; + } + + PassFailJFrame.log("Phase %d passed: %b\n" + .formatted(current + 1, passed)); + if (passed) { + SwingUtilities.invokeLater(() -> { + goBtn.setEnabled(true); + setPhase(++current); + }); + } else { + SwingUtilities.invokeLater(() -> + showFinalReminderIfNeeded(true)); + } + }).start(); + } + } + + public void mouseWheelMoved(MouseWheelEvent e) { + int eventScrollAmt = e.getScrollAmount(); + if (eventScrollAmt == scrollAmount) { + mwArea.setBackground(Color.GREEN); + mwArea.setText("Mouse wheel configured - press Go"); + goBtn.setEnabled(true); + goBtn.requestFocusInWindow(); + PassFailJFrame.log("Proceed to the test with go button"); + return; + } + if (eventScrollAmt < scrollAmount) { + mwArea.setText("Increase the scroll speed. (Want:" + + scrollAmount + " Got:" + eventScrollAmt + ")"); + } else { + mwArea.setText("Decrease the scroll speed. (Want:" + + scrollAmount + " Got:" + eventScrollAmt + ")"); + } + } + } +} \ No newline at end of file diff --git a/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java new file mode 100644 index 00000000000..24e8df6fad8 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java @@ -0,0 +1,684 @@ +/* + * Copyright (c) 2004, 2025, 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. + */ + +// A few Swing components which use the mouse wheel to scroll + +import java.awt.AWTException; +import java.awt.Color; +import java.awt.ComponentOrientation; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.DefaultListModel; +import javax.swing.ImageIcon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.ListModel; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +public class RTLScrollers extends JDialog + implements MouseWheelListener, ActionListener { + private static final int ROWS = 5; + private static final int COLUMNS = 150; + private static final int WINWIDTH = 1000; + + static RTLScrollers rtl; + static volatile RTLScrollers f; + static volatile boolean retVal; + static volatile JScrollPane jsp; + static volatile JScrollBar hsb; + static volatile JScrollBar sb; + static volatile Point loc; + static volatile Dimension size; + TestList list; + JScrollPane listScroller; + JTextArea text; + JScrollPane textScroller; + TestTable table; + JScrollPane tableScroller; + JCheckBoxMenuItem rightToLeft; + ImageIcon photoIcon; + int scrollAmount; + + private static Robot robot; + private static BufferedImage logo = genIcon(166, 39, Color.PINK); + private static BufferedImage photo = genIcon(59, 80, Color.MAGENTA); + private static BufferedImage photo2 = genIcon(80, 53, Color.ORANGE); + + private static BufferedImage genIcon(int width, int height, Color color) { + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics g = image.getGraphics(); + g.setColor(color); + g.fillRect(0, 0, width, height); + + return image; + } + + public RTLScrollers() { + this(0); + } + + public RTLScrollers(int scrollAmount) { + super(new JFrame(), "RTLScrollers", false); + + this.scrollAmount = scrollAmount; + Container content = getContentPane(); + content.setLayout(new GridBagLayout()); + + DefaultListModel listModel = new DefaultListModel<>(); + + photoIcon = new ImageIcon(photo); + for (int i = 0; i < COLUMNS / 4 ; i++) { + for (int j = 0; j < ROWS; j++) { + listModel.addElement(new ImageIcon(logo)); + } + for (int j = 0; j < ROWS; j++) { + listModel.addElement(photoIcon); + } + for (int j = 0; j < ROWS; j++) { + listModel.addElement(new ImageIcon(photo2)); + } + for (int j = 0; j < ROWS; j++) { + listModel.addElement("Text Item " + ((1 + i) * 3)); + } + } + + list = new TestList(listModel); + list.setVisibleRowCount(ROWS); + list.setLayoutOrientation(JList.VERTICAL_WRAP); + listScroller = new JScrollPane(list); + listScroller.addMouseWheelListener(this); + + text = new JTextArea(); + for (int j = 0; j < ROWS ; j++) { + for (int i = 0; i < COLUMNS ; i++) { + text.append(i + " some text, some more text, a really long line of text "); + } + text.append("\n"); + } + + textScroller = new JScrollPane(text); + textScroller.addMouseWheelListener(this); + + DefaultTableModel model = new DefaultTableModel(ROWS, COLUMNS); + table = new TestTable(model); + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + for (int i = 0; i < COLUMNS; i++) { + for (int j = 0; j < ROWS; j++) { + table.setValueAt(j + ", " + i, j, i); + } + + TableColumn column = table.getColumnModel().getColumn(i); + + if (i % 4 == 0) { + column.setMinWidth(0); + column.setPreferredWidth(0); + column.setMaxWidth(0); + } + else if ((i + 1) % 4 == 0) { + column.setMinWidth(95); + column.setPreferredWidth(95); + column.setMaxWidth(95); + } + else if ((i + 2) % 4 == 0) { + column.setMinWidth(26); + column.setPreferredWidth(26); + column.setMaxWidth(26); + } + else { + column.setMinWidth(50); + column.setPreferredWidth(50); + column.setMaxWidth(50); + } + } + tableScroller = new JScrollPane(table); + tableScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + tableScroller.addMouseWheelListener(this); + + GridBagConstraints tableGBC = new GridBagConstraints(0, + 0, + 1, + 1, + 1.0, + 0.3, + GridBagConstraints.CENTER, + GridBagConstraints.BOTH, + new Insets(0,0,0,0), + 0, + 0); + content.add(tableScroller, tableGBC); + GridBagConstraints textGBC = new GridBagConstraints(0, + 1, + 1, + 1, + 1.0, + 0.3, + GridBagConstraints.CENTER, + GridBagConstraints.BOTH, + new Insets(0,0,0,0), + 0, + 0); + content.add(textScroller, textGBC); + + GridBagConstraints listGBC = new GridBagConstraints(0, + 2, + 1, + 5, + 1.0, + 1.2, + GridBagConstraints.CENTER, + GridBagConstraints.BOTH, + new Insets(0,0,0,0), + 0, + 0); + + content.add(listScroller, listGBC); + + rightToLeft = new JCheckBoxMenuItem("Right-To-Left", false); + rightToLeft.addActionListener(this); + JMenu menu = new JMenu("Component Orientation"); + menu.add(rightToLeft); + + JMenuItem close = new JMenuItem("Close"); + close.addActionListener(e -> RTLScrollers.this.setVisible(false)); + menu.add(close); + + JMenuBar mb = new JMenuBar(); + mb.add(menu); + setJMenuBar(mb); + setBounds(0, 0, WINWIDTH, 760); + setLocationRelativeTo(null); + } + + public void actionPerformed(ActionEvent e) { + if (rightToLeft.getState()) { + applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + } + else { + applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + } + } + public void mouseWheelMoved(MouseWheelEvent e) { + System.out.println("Rotation: " + e.getWheelRotation()); + } + + public static boolean runTest(int scrollAmount) + throws InterruptedException, InvocationTargetException { + System.out.println("RTLS.runTest()"); + if (robot == null) { + try { + robot = new Robot(); + robot.setAutoDelay(150); + robot.setAutoWaitForIdle(true); + } + catch (AWTException e) { + e.printStackTrace(); + return false; + } + } + + SwingUtilities.invokeAndWait(() -> { + rtl = new RTLScrollers(scrollAmount); + rtl.setVisible(true); + }); + robot.delay(100); + + SwingUtilities.invokeAndWait(() -> { + try { + retVal = rtl.runTests(scrollAmount); + } catch (Exception e) { + e.printStackTrace(); + } finally { + rtl.setVisible(false); + rtl.dispose(); + } + }); + + robot.delay(100); + System.out.println("RTLS.runTest(): " + retVal); + return retVal; + } + + private boolean runTests(int scrollAmount) + throws InterruptedException, InvocationTargetException { + if (robot == null) { + try { + robot = new Robot(); + robot.setAutoDelay(150); + robot.setAutoWaitForIdle(true); + } + catch (AWTException e) { + e.printStackTrace(); + return false; + } + } + + // + // run robot tests + // + robot.delay(500); + + System.out.println("Testing Table"); + testComp(table, scrollAmount); + + System.out.println("Testing List"); + testComp(list, scrollAmount); + + SwingUtilities.invokeAndWait(() -> { + applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + }); + robot.delay(100); + + System.out.println("Testing RTL Table"); + testComp(table, scrollAmount); + + System.out.println("Testing RTL List"); + testComp(list, scrollAmount); + + return true; + } + + public boolean testComp(TestTools comp, int scrollAmount) + throws InterruptedException, InvocationTargetException { + // Make sure we start from the beginning + SwingUtilities.invokeAndWait(() -> { + jsp = (JScrollPane)((JComponent)comp).getParent().getParent(); + hsb = jsp.getHorizontalScrollBar(); + hsb.setValue(hsb.getMinimum()); + + loc = jsp.getLocationOnScreen(); + size = jsp.getSize(); + }); + int midx = loc.x + size.width / 2; + int midy = loc.y + size.height / 2; + int maxIdx = 0; + robot.mouseMove(midx, midy); + + // Don't bother for max scroll w/ RTL JList, because the block increment is broken + if (scrollAmount != 30 || !(comp instanceof TestList) + || getComponentOrientation().isLeftToRight()) { + scrollToMiddle(jsp, robot); + + // check that we're lined up + comp.checkTopCellIsLinedUp(); + + int startVal = hsb.getValue(); + int leadingCell = comp.getLeadingCell().y; + System.out.println("leadingCell is " + leadingCell); + + // become unaligned + int width = comp.getLeadingCellWidth(); + int midVal = startVal + width / 2; + System.out.println("becoming unaligned: startVal is " + + startVal + ", midVal is " + midVal); + SwingUtilities.invokeAndWait(() -> hsb.setValue(midVal)); + + // + // Check partial inc up + // + robot.mouseWheel(-1); + + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, -scrollAmount + 1); + } + comp.checkTopCellIsLinedUp(); + + // + // Check partial inc down + // + SwingUtilities.invokeAndWait(() -> hsb.setValue(midVal)); + robot.delay(100); + robot.mouseWheel(1); + + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, scrollAmount); + } + comp.checkTopCellIsLinedUp(); + + // + // Check full inc down (3 times) + // + SwingUtilities.invokeAndWait(() -> hsb.setValue(startVal)); + leadingCell = comp.getLeadingCell().y; + + // Once... + robot.mouseWheel(1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, scrollAmount); + } + comp.checkTopCellIsLinedUp(); + + // Twice... + robot.mouseWheel(1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, (2 * scrollAmount)); + } + + comp.checkTopCellIsLinedUp(); + + // Thrice... + robot.mouseWheel(1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, (3 * scrollAmount)); + + } + comp.checkTopCellIsLinedUp(); + + // + // Check full inc up (3 times) + // + leadingCell = comp.getLeadingCell().y; + + // Once... + robot.mouseWheel(-1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, -scrollAmount); + } + comp.checkTopCellIsLinedUp(); + + // Twice... + robot.mouseWheel(-1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, -(2 * scrollAmount)); + } + comp.checkTopCellIsLinedUp(); + + // Thrice... + robot.mouseWheel(-1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, -(3 * scrollAmount)); + } + comp.checkTopCellIsLinedUp(); + } + + // + // Test acceleration for max scrolling + // (this part should still work for RTL JList) + if (scrollAmount == 30) { + SwingUtilities.invokeAndWait(() -> { + hsb.setValue(hsb.getMinimum()); + }); + robot.delay(100); + robot.mouseWheel(2); + robot.mouseWheel(2); + robot.mouseWheel(2); + if (hsb.getValue() < hsb.getMaximum() - hsb.getVisibleAmount()) { + throw new RuntimeException("Wheel acceleration for max " + + "scrolling doesn't work: hsb value (" + hsb.getValue() + + " < hsb max (" + hsb.getMaximum() + + ") - hsb vis (" + hsb.getVisibleAmount() + ")"); + } + robot.delay(100); + robot.mouseWheel(-2); + robot.mouseWheel(-2); + robot.mouseWheel(-2); + if (hsb.getValue() > hsb.getMinimum()) { + throw new RuntimeException("Wheel acceleration for max " + + "scrolling doesn't work: hsb value (" + + hsb.getValue() + " > hsb min (" + hsb.getMinimum() + ")"); + } + } + + return true; + } + + class TestTable extends JTable implements TestTools { + final int[] MAXVALS = {23, 67, 67, 89, 111, 89, 66, 45}; //Lookup table + public TestTable(TableModel model) { + super(model); + } + + public void checkTopCellIsLinedUp() { + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + Point leading = getLeadingCell(); + Rectangle visRect = getVisibleRect(); + Rectangle cellRect = getCellRect(leading.x, leading.y, true); + + if (isLeftToRight) { + if (cellRect.x != visRect.x) { + throw new RuntimeException("leading cell is not aligned!"); + } + } + else { + if (cellRect.x + cellRect.width != visRect.x + visRect.width) { + throw new RuntimeException("leading cell is not aligned!"); + } + } + } + + public void checkTopCellIs(int col) { + Point cell = getLeadingCell(); + if (cell.y != col) { + throw new RuntimeException("leading cell (" + cell.y + + ") is not " + col); + } + } + + /* + * Account for 0-width cells + * + * shift is a non-0 number of visible cells to shift. The shift is + * augmented for zero-width cells, and the new sum is passed into + * checkTopCellIs(). + */ + public void checkTopCellIs(int col, int shift) { + if (shift == 0) { + checkTopCellIs(col); + return; + } + + int row = getLeadingCell().x; + int newShift = 0; + int foundCells = 0; + int direction = shift > 0 ? 1 : -1; + int index = col; + Rectangle cellRect; + + while (foundCells < Math.abs(shift)) { + index += direction; + cellRect = getCellRect(row, index, true); + if (cellRect.width > 0) { + foundCells++; + } + newShift++; + } + + checkTopCellIs(col + (direction*newShift)); + } + + public void checkTopCellIsMax(int idx) { + checkTopCellIs(MAXVALS[idx]); + } + + public int getLeadingCellWidth() { + Point leading = getLeadingCell(); + Rectangle cellRect = getCellRect(leading.x, leading.y, true); + return cellRect.width; + } + + public Point getLeadingCell() { + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + Rectangle visRect = getVisibleRect(); + int row = rowAtPoint(visRect.getLocation()); + int column; + if (isLeftToRight) { + column = columnAtPoint(visRect.getLocation()); + } + else { + column = columnAtPoint(new Point(visRect.x + visRect.width - 1, visRect.y)); + } + return new Point(row, column); + } + } + + class TestList extends JList implements TestTools { + final int[] MAXVALS = {5, 16, 15, 20, 25, 20, 15, 10 }; + public TestList(ListModel model) { + super(model); + } + + // Note - implemented in terms of columns + public Point getLeadingCell() { + System.out.println("TL.gLC(): first vis index is " + + getFirstVisibleIndex()); + return new Point(getFirstVisibleIndex() / ROWS, + getFirstVisibleIndex() / ROWS); + } + public void checkTopCellIsLinedUp() { + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + int visIdx = getFirstVisibleIndex(); + Rectangle cellRect = getCellBounds(visIdx, visIdx); + Rectangle visRect = getVisibleRect(); + if (isLeftToRight) { + if (cellRect.x != visRect.x) { + throw new RuntimeException("leading cell is not aligned!"); + } + } + else { + if (cellRect.x + cellRect.width != visRect.x + visRect.width) { + throw new RuntimeException("leading cell is not aligned!"); + } + } + } + public void checkTopCellIs(int col) { + int firstVis = getLeadingCell().y; + if (firstVis != col) { + throw new RuntimeException("leading cell (" + + firstVis + ") is not " + col); + } + } + public void checkTopCellIs(int idx, int shift) { + checkTopCellIs(idx + shift); + + } + public void checkTopCellIsMax(int idx) { + checkTopCellIs(MAXVALS[idx]); + } + public int getLeadingCellWidth() { + int visIdx = getFirstVisibleIndex(); + Rectangle cellRect = getCellBounds(visIdx, visIdx); + System.out.println("TL.gLCW(): leading cell width is " + cellRect.width); + return cellRect.width; + } + } + + private interface TestTools { + /** + * Throws a runtime exception if the top cell isn't lined up + */ + void checkTopCellIsLinedUp(); + void checkTopCellIs(int col); + void checkTopCellIs(int col, int shift); + int getLeadingCellWidth(); + Point getLeadingCell(); + + void checkTopCellIsMax(int idx); + } + + public void scrollToMiddle(JScrollPane jsp, Robot robot) + throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(() -> { + sb = jsp.getHorizontalScrollBar(); + loc = sb.getLocationOnScreen(); + size = sb.getSize(); + }); + robot.setAutoDelay(250); + + robot.mouseMove(loc.x + size.width / 2, + loc.y + size.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + SwingUtilities.invokeAndWait(() -> { + if (jsp == listScroller) { + int idx = list.getFirstVisibleIndex(); + list.ensureIndexIsVisible(idx); + } + }); + } + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> f = new RTLScrollers()); + } finally { + SwingUtilities.invokeAndWait(() -> { + f.setVisible(true); + f.dispose(); + }); + } + } +} diff --git a/test/jdk/javax/swing/JScrollPane/bug4166037.java b/test/jdk/javax/swing/JScrollPane/bug4166037.java new file mode 100644 index 00000000000..e2ce75867a7 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/bug4166037.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2000, 2025, 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 4166037 + * @summary Tests if changes to JScrollPane propagate to ScrollPaneLayout + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4166037 + */ + +import java.awt.Color; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneLayout; + +public class bug4166037 { + static final String INSTRUCTIONS = """ + Press button "Never". Scroll bars should disappear. + Press button "Always". Scroll bars should appear. + Press button "Colhead". Label ColumnHeader should + get replaced with yellow rectangles. + Press button "Corner". You should see 4 green + rectangles in the corners of the scroll pane. + Press button "Rowhead". Label RowHeader should get + replaced with yellow rectangles. + Press button "Viewport". Viewport (the rest of the + area except scrollbars) should get replaced with yellow + rectangles. + If the behavior is as described, the test PASSES. + Otherwise, this test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4166037 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4166037::createUI) + .logArea() + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("JScrollPane in JScrollLayout Test"); + JScrollPane scroll = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + JPanel p = new JPanel(); + scroll.setSize(200, 200); + f.add(scroll); + f.setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS)); + JButton bn = new JButton("Never"); + bn.addActionListener(e -> { + PassFailJFrame.log("pane before: " + + scroll.getVerticalScrollBarPolicy() + + scroll.getHorizontalScrollBarPolicy()); + PassFailJFrame.log("layout before: " + + ((ScrollPaneLayout) scroll.getLayout()).getVerticalScrollBarPolicy() + + ((ScrollPaneLayout) scroll.getLayout()).getHorizontalScrollBarPolicy()); + scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); + scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + PassFailJFrame.log("pane after: " + + scroll.getVerticalScrollBarPolicy() + + scroll.getHorizontalScrollBarPolicy()); + PassFailJFrame.log("layout after: " + + ((ScrollPaneLayout) scroll.getLayout()).getVerticalScrollBarPolicy() + + ((ScrollPaneLayout) scroll.getLayout()).getHorizontalScrollBarPolicy()); + }); + JButton ba = new JButton("Always"); + ba.addActionListener(e -> { + PassFailJFrame.log("pane before: " + + scroll.getVerticalScrollBarPolicy() + + scroll.getHorizontalScrollBarPolicy()); + PassFailJFrame.log("layout before: " + + ((ScrollPaneLayout) scroll.getLayout()).getVerticalScrollBarPolicy() + + ((ScrollPaneLayout) scroll.getLayout()).getHorizontalScrollBarPolicy()); + scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + PassFailJFrame.log("pane after: " + + scroll.getVerticalScrollBarPolicy() + + scroll.getHorizontalScrollBarPolicy()); + PassFailJFrame.log("layout after: " + + ((ScrollPaneLayout) scroll.getLayout()).getVerticalScrollBarPolicy() + + ((ScrollPaneLayout) scroll.getLayout()).getHorizontalScrollBarPolicy()); + }); + JLabel ch = new JLabel("ColumnHeader"); + scroll.setColumnHeaderView(ch); + JButton b1 = new JButton("Colhead"); + b1.addActionListener(e -> { + JPanel filler = new JPanel(); + filler.setSize(150, 150); + filler.setBackground(Color.yellow); + scroll.getColumnHeader().add(filler); + }); + JButton b2 = new JButton("Corners"); + b2.addActionListener(e -> { + JPanel filler1 = new JPanel(); + filler1.setSize(150, 150); + filler1.setBackground(Color.green); + scroll.setCorner(JScrollPane.LOWER_RIGHT_CORNER, filler1); + JPanel filler2 = new JPanel(); + filler2.setSize(150, 150); + filler2.setBackground(Color.green); + scroll.setCorner(JScrollPane.LOWER_LEFT_CORNER, filler2); + JPanel filler3 = new JPanel(); + filler3.setSize(150, 150); + filler3.setBackground(Color.green); + scroll.setCorner(JScrollPane.UPPER_RIGHT_CORNER, filler3); + JPanel filler4 = new JPanel(); + filler4.setSize(150, 150); + filler4.setBackground(Color.green); + scroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, filler4); + }); + JLabel rh = new JLabel("RowHeader"); + scroll.setRowHeaderView(rh); + JButton b3 = new JButton("Rowhead"); + b3.addActionListener(e -> { + JPanel filler = new JPanel(); + filler.setSize(150, 150); + filler.setBackground(Color.yellow); + scroll.getRowHeader().add(filler); + }); + JButton b4 = new JButton("Viewport"); + b4.addActionListener(e -> { + JPanel filler = new JPanel(); + filler.setSize(150, 150); + filler.setBackground(Color.yellow); + scroll.getViewport().add(filler); + }); + + p.add(bn); + p.add(ba); + p.add(b1); + p.add(b2); + p.add(b3); + p.add(b4); + f.add(p); + f.setSize(300, 300); + return f; + } +} diff --git a/test/jdk/javax/swing/JScrollPane/bug4237517.java b/test/jdk/javax/swing/JScrollPane/bug4237517.java new file mode 100644 index 00000000000..4e1d1356199 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/bug4237517.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1999, 2025, 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 4237517 + * @summary Tests that scrolling with blit draws the right thing + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4237517 + */ + +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; + +public class bug4237517 { + static final String INSTRUCTIONS = """ + Select the first item in the list and hit PageDown + key two times. If the list is redrawn correctly, + i.e. if the digits go in order, then the test PASSES. + Otherwise, the test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4237517 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4237517::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Scrolling Window Blit Test"); + String[] data = new String[100]; + + for (int counter = 0; counter < data.length; counter++) { + data[counter] = Integer.toString(counter); + } + JList list = new JList(data); + JScrollPane sp = new JScrollPane(list); + sp.getViewport().putClientProperty("EnableWindowBlit", Boolean.TRUE); + f.add(sp); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/javax/swing/JScrollPane/bug4237560.java b/test/jdk/javax/swing/JScrollPane/bug4237560.java new file mode 100644 index 00000000000..4f8f27683e5 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/bug4237560.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2025, 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 4237560 + * @summary Tests that JScrollPane do not distort TAB order in an HTML page + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4237560 + */ + +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JScrollPane; + +public class bug4237560 { + static final String INSTRUCTIONS = """ + A JEditorPane contains 10 input fields and is inserted into + JScrollPane. Click text field #8 so that it is selected. Press + TAB three times (even if text field #9 and #10 are not visible in + the ScrollPane). If this gives focus to the first text field (#1) + the test PASSES, else it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4237560 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4237560::createUI) + .build() + .awaitAndCheck(); + } + + private static final String TEXT = "
\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
"; + + private static JFrame createUI() { + JFrame frame = new JFrame("JScrollPane HTML TAB Test"); + JEditorPane viewer = new JEditorPane("text/html", TEXT); + viewer.setEditable(false); + frame.add(new JScrollPane(viewer)); + frame.setSize(300, 300); + return frame; + } +} diff --git a/test/jdk/javax/swing/JScrollPane/bug4244899.java b/test/jdk/javax/swing/JScrollPane/bug4244899.java new file mode 100644 index 00000000000..4cb5367f4f5 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/bug4244899.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999, 2025, 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 4244899 + * @summary Tests whether scrolling with blit has artifacts + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4244899 + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +public class bug4244899 { + static final String INSTRUCTIONS = """ + Widen the first column of the table, so that + you get a horizontal scrollbar. Click in the + scrollbar (not on the thumb, but in the track). + If you notice some artifacts/flashing at + the bottom of the frame, the test FAILS. + Otherwise, the test PASSES. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4244899 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4244899::createUI) + .build() + .awaitAndCheck(); + } + + static class TestModel extends AbstractTableModel { + private final int rows = 20; + private final int cols = 5; + + private Integer[][] data; + + public TestModel() { + data = new Integer[rows][]; + int realCount = 0; + for (int counter = 0; counter < rows; counter++) { + data[counter] = new Integer[cols]; + for (int y = 0; y < cols; y++) { + data[counter][y] = Integer.valueOf(realCount); + realCount = (realCount + 1) % 23; + } + } + } + + public int getRowCount() { + return data.length; + } + + public int getColumnCount() { + return data[0].length; + } + + public Object getValueAt(int row, int column) { + return data[row][column]; + } + } + + static JFrame createUI() { + JFrame f = new JFrame("Scrolling Blit Artifact Test"); + JTable table = new JTable(new TestModel()); + JScrollPane sp = new JScrollPane(table); + sp.getViewport().putClientProperty("EnableWindowBlit", Boolean.TRUE); + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + f.add(sp); + f.setSize(400, 400); + return f; + } +}