# HG changeset patch # User alexsch # Date 1326201070 -14400 # Node ID f486e3ec76e63cde48b848e696c3576dcc5c200f # Parent d2da29f30ae4f0beaab7c28b8863a1743513c57f 6505523: NullPointerException in BasicTreeUI when a node is removed by expansion listener Reviewed-by: rupashka diff -r d2da29f30ae4 -r f486e3ec76e6 jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java Tue Jan 10 15:46:30 2012 +0400 +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java Tue Jan 10 17:11:10 2012 +0400 @@ -1932,20 +1932,22 @@ else { Rectangle beginRect = getPathBounds(tree, getPathForRow (tree, beginRow)); - Rectangle visRect = tree.getVisibleRect(); - Rectangle testRect = beginRect; - int beginY = beginRect.y; - int maxY = beginY + visRect.height; - - for(int counter = beginRow + 1; counter <= endRow; counter++) { - testRect = getPathBounds(tree, - getPathForRow(tree, counter)); - if((testRect.y + testRect.height) > maxY) - counter = endRow; + if (beginRect != null) { + Rectangle visRect = tree.getVisibleRect(); + Rectangle testRect = beginRect; + int beginY = beginRect.y; + int maxY = beginY + visRect.height; + + for(int counter = beginRow + 1; counter <= endRow; counter++) { + testRect = getPathBounds(tree, + getPathForRow(tree, counter)); + if((testRect.y + testRect.height) > maxY) + counter = endRow; + } + tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1, + testRect.y + testRect.height- + beginY)); } - tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1, - testRect.y + testRect.height- - beginY)); } } } @@ -3485,7 +3487,7 @@ } Rectangle bounds = getPathBounds(tree, path); - if (y > (bounds.y + bounds.height)) { + if (bounds == null || y > (bounds.y + bounds.height)) { return false; } diff -r d2da29f30ae4 -r f486e3ec76e6 jdk/test/javax/swing/JTree/6505523/bug6505523.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTree/6505523/bug6505523.java Tue Jan 10 17:11:10 2012 +0400 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012, 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 6505523 + * @summary NullPointerException in BasicTreeUI when a node is removed by expansion listener + * @author Alexandr Scherbatiy + * @run main bug6505523 + */ +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import sun.awt.SunToolkit; + +public class bug6505523 { + + private static JTree tree; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + Point point = getRowPointToClick(2); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + toolkit.realSync(); + + } + + private static Point getRowPointToClick(final int row) throws Exception { + + final Point[] result = new Point[1]; + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + Rectangle rect = tree.getRowBounds(row); + Point point = new Point(rect.x - 5, rect.y + rect.height / 2); + SwingUtilities.convertPointToScreen(point, tree); + result[0] = point; + } + }); + + return result[0]; + } + + private static void createAndShowGUI() { + final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Problem with NPE under JDK 1.6"); + final DefaultMutableTreeNode problematic = new DefaultMutableTreeNode("Expand me and behold a NPE in stderr"); + problematic.add(new DefaultMutableTreeNode("some content")); + root.add(new DefaultMutableTreeNode("irrelevant...")); + root.add(problematic); + + final DefaultTreeModel model = new DefaultTreeModel(root); + tree = new JTree(model); + tree.setRootVisible(true); + tree.setShowsRootHandles(true); + tree.expandRow(0); + tree.collapseRow(2); + + // this is critical - without dragEnabled everything works + tree.setDragEnabled(true); + + tree.addTreeExpansionListener(new TreeExpansionListener() { + + @Override + public void treeExpanded(TreeExpansionEvent event) { + TreeNode parent = problematic.getParent(); + if (parent instanceof DefaultMutableTreeNode) { + model.removeNodeFromParent(problematic); + } + } + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + } + }); + + JFrame frame = new JFrame("JTree Problem"); + frame.add(new JScrollPane(tree)); + frame.setSize(500, 300); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} \ No newline at end of file