8003400: JTree scrolling problem when using large model in WindowsLookAndFeel
authormalenkov
Thu, 24 Jan 2013 18:06:24 +0400
changeset 15333 56b81ef28fb4
parent 15332 aa02ac4b20b7
child 15334 19ab20cb461f
8003400: JTree scrolling problem when using large model in WindowsLookAndFeel Reviewed-by: alexsch
jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java
jdk/test/javax/swing/JTree/8003400/Test8003400.java
--- 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);
+                    }
+                }
+            }
+        });
+    }
+}