This fixes BasicTreeUI.getPathBounds() to also consider the tree's insets, plus it adds a bunch of null checks for safety (all of this stuff is public API and can thus be overridden to return null, so...).
2007-04-03 Roman Kennke <[EMAIL PROTECTED]> * javax/swing/plaf/basic/BasicTreeUI.java (getPathBounds): Consider the tree's insets. Added a bunch of null checks. /Roman -- http://kennke.org/blog/
Index: javax/swing/plaf/basic/BasicTreeUI.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTreeUI.java,v retrieving revision 1.156 diff -u -1 -5 -r1.156 BasicTreeUI.java --- javax/swing/plaf/basic/BasicTreeUI.java 10 Dec 2006 20:25:48 -0000 1.156 +++ javax/swing/plaf/basic/BasicTreeUI.java 3 Apr 2007 20:40:32 -0000 @@ -104,31 +104,31 @@ import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import javax.swing.tree.VariableHeightLayoutCache; /** * A delegate providing the user interface for <code>JTree</code> according to * the Basic look and feel. * * @see javax.swing.JTree * @author Lillian Angel ([EMAIL PROTECTED]) * @author Sascha Brawer ([EMAIL PROTECTED]) * @author Audrius Meskauskas ([EMAIL PROTECTED]) */ public class BasicTreeUI - extends TreeUI + extends TreeUI { /** * The tree cell editing may be started by the single mouse click on the * selected cell. To separate it from the double mouse click, the editing * session starts after this time (in ms) after that single click, and only no * other clicks were performed during that time. */ static int WAIT_TILL_EDITING = 900; /** Collapse Icon for the tree. */ protected transient Icon collapsedIcon; /** Expanded Icon for the tree. */ protected transient Icon expandedIcon; @@ -644,31 +644,42 @@ return treeSelectionModel; } /** * Returns the Rectangle enclosing the label portion that the last item in * path will be drawn to. Will return null if any component in path is * currently valid. * * @param tree is the current tree the path will be drawn to. * @param path is the current path the tree to draw to. * @return the Rectangle enclosing the label portion that the last item in the * path will be drawn to. */ public Rectangle getPathBounds(JTree tree, TreePath path) { - return treeState.getBounds(path, new Rectangle()); + Rectangle bounds = null; + if (tree != null && treeState != null) + { + bounds = treeState.getBounds(path, null); + Insets i = tree.getInsets(); + if (bounds != null && i != null) + { + bounds.x += i.left; + bounds.y += i.top; + } + } + return bounds; } /** * Returns the max height of all the nodes in the tree. * * @param tree - the current tree * @return the max height. */ int getMaxHeight(JTree tree) { if (maxHeight != 0) return maxHeight; Icon e = UIManager.getIcon("Tree.openIcon"); Icon c = UIManager.getIcon("Tree.closedIcon"); @@ -1549,31 +1560,30 @@ int rows = treeState.getRowCount(); if (rows == 0) // There is nothing to do if the tree is empty. return; Rectangle clip = g.getClipBounds(); Insets insets = tree.getInsets(); if (clip != null && treeModel != null) { int startIndex = tree.getClosestRowForLocation(clip.x, clip.y); int endIndex = tree.getClosestRowForLocation(clip.x + clip.width, clip.y + clip.height); - // Also paint dashes to the invisible nodes below. // These should be painted first, otherwise they may cover // the control icons. if (endIndex < rows) for (int i = endIndex + 1; i < rows; i++) { TreePath path = treeState.getPathForRow(i); if (isLastChild(path)) paintVerticalPartOfLeg(g, clip, insets, path); } // The two loops are required to ensure that the lines are not // painted over the other tree components. int n = endIndex - startIndex + 1;