8003400: JTree scrolling problem when using large model in WindowsLookAndFeel
Reviewed-by: alexsch
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java Thu Jan 24 17:57:02 2013 +0400
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java Thu Jan 24 18:06:24 2013 +0400
@@ -1879,6 +1879,20 @@
visRect.x -= i.left;
visRect.y -= i.top;
}
+ // we should consider a non-visible area above
+ Component component = SwingUtilities.getUnwrappedParent(tree);
+ if (component instanceof JViewport) {
+ component = component.getParent();
+ if (component instanceof JScrollPane) {
+ JScrollPane pane = (JScrollPane) component;
+ JScrollBar bar = pane.getHorizontalScrollBar();
+ if ((bar != null) && bar.isVisible()) {
+ int height = bar.getHeight();
+ visRect.y -= height;
+ visRect.height += height;
+ }
+ }
+ }
preferredSize.width = treeState.getPreferredWidth(visRect);
}
else {
@@ -4504,7 +4518,7 @@
}
}
- private void home(JTree tree, BasicTreeUI ui, int direction,
+ private void home(JTree tree, final BasicTreeUI ui, int direction,
boolean addToSelection, boolean changeSelection) {
// disable moving of lead unless in discontiguous mode
@@ -4514,7 +4528,7 @@
changeSelection = true;
}
- int rowCount = ui.getRowCount(tree);
+ final int rowCount = ui.getRowCount(tree);
if (rowCount > 0) {
if(direction == -1) {
@@ -4566,6 +4580,13 @@
ui.setLeadSelectionPath(ui.getPathForRow(tree,
rowCount - 1), true);
}
+ if (ui.isLargeModel()){
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ ui.ensureRowsAreVisible(rowCount - 1, rowCount - 1);
+ }
+ });
+ }
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTree/8003400/Test8003400.java Thu Jan 24 18:06:24 2013 +0400
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013, 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 8003400
+ * @summary Tests that JTree shows the last row
+ * @author Sergey Malenkov
+ * @run main/othervm Test8003400
+ * @run main/othervm Test8003400 reverse
+ * @run main/othervm Test8003400 system
+ * @run main/othervm Test8003400 system reverse
+ */
+
+import sun.awt.SunToolkit;
+
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.event.KeyEvent;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class Test8003400 {
+
+ private static final String TITLE = "Test JTree with a large model";
+ private static List<String> OBJECTS = Arrays.asList(TITLE, "x", "y", "z");
+ private static JScrollPane pane;
+
+ public static void main(String[] args) throws Exception {
+ for (String arg : args) {
+ if (arg.equals("reverse")) {
+ Collections.reverse(OBJECTS);
+ }
+ if (arg.equals("system")) {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ }
+ }
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ DefaultMutableTreeNode root = new DefaultMutableTreeNode();
+
+ JTree tree = new JTree(root);
+ tree.setLargeModel(true);
+ tree.setRowHeight(16);
+
+ JFrame frame = new JFrame(TITLE);
+ frame.add(pane = new JScrollPane(tree));
+ frame.setSize(200, 100);
+ frame.setLocationRelativeTo(null);
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ frame.setVisible(true);
+
+ for (String object : OBJECTS) {
+ root.add(new DefaultMutableTreeNode(object));
+ }
+ tree.expandRow(0);
+ }
+ });
+
+ SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+ toolkit.realSync(500);
+ new Robot().keyPress(KeyEvent.VK_END);
+ toolkit.realSync(500);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ JTree tree = (JTree) pane.getViewport().getView();
+ Rectangle inner = tree.getRowBounds(tree.getRowCount() - 1);
+ Rectangle outer = SwingUtilities.convertRectangle(tree, inner, pane);
+ outer.y += tree.getRowHeight() - 1 - pane.getVerticalScrollBar().getHeight();
+ // error reporting only for automatic testing
+ if (null != System.getProperty("test.src", null)) {
+ SwingUtilities.getWindowAncestor(pane).dispose();
+ if (outer.y != 0) {
+ throw new Error("TEST FAILED: " + outer.y);
+ }
+ }
+ }
+ });
+ }
+}