-
Bug
-
Resolution: Unresolved
-
P4
-
6u3
-
x86
-
windows_xp
J2SE Version (please include all output from java -version flag):
java version "1.6.0_03"
Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
Java HotSpot(TM) Client VM (build 1.6.0_03-b05, mixed mode, sharing)
Does this problem occur on J2SE 5.0.x or 6.0? Yes / No (pick one)
Yes
Operating System Configuration Information (be specific):
Microsoft Windows XP [Version 5.1.2600]
Bug Description:
AbstractLayoutCache.isExpanded(TreePath) is both implemented incorrectly and called when it should not be
The JavaDoc states that AbstractLayoutCache.isExpanded(TreePath) Returns true if the value identified by row is currently expanded.
There is another method AbstractLayoutCache.getExpandedState(TreePath) which Returns true if the path is expanded, and visible.
1) Both Implementations (FixedHeightLayoutCache and VariableHeightLayoutCache) incorrectly implement
AbstractLayoutCache.isExpanded(TreePath) to do the same as AbstractLayoutCache.getExpandedState(TreePath).
The problem appears to be that they are calling getNodeForPath(path, true, false) instead of
getNodeForPath(path, false, false), and so are ending up returning false even if the value identified
by row is currently expanded.
2) BasicTreeUI.Handler.treeNodesChanged(TreeModelEvent) is calling treeState.isExpanded(parentPath) instead of
treeState.getExpandedState(parentPath). It then incorrectly assumes that 'Changed nodes are visible'
(copied from the developers comments).
As a result of these everything calling these is also getting incorrect results and there can also be NullPointerExceptions:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.plaf.basic.BasicTreeUI$Handler.treeNodesChanged(BasicTreeUI.java:3771)
at javax.swing.tree.DefaultTreeModel.fireTreeNodesChanged(DefaultTreeModel.java:468)
at javax.swing.tree.DefaultTreeModel.nodesChanged(DefaultTreeModel.java:330)
at javax.swing.tree.DefaultTreeModel.nodeChanged(DefaultTreeModel.java:261)
at Test$1.run(Test.java:32)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
Here is some sample code where I have made VariableHeightLayoutCache isExpanded(TreePath) use
getNodeForPath(path, false, false) instead of getNodeForPath(path, true, false). Now
VariableHeightLayoutCache.isExpanded(TreePath) will correctly return true when
the TreePath is expanded and BasicTreeUI.Handler.treeNodesChanged(TreeModelEvent) will
throw the NullPointerException as shown above.
import static javax.swing.JFrame.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.metal.*;
import javax.swing.event.*;
import javax.swing.tree.*;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
JTree tree = new JTree() {
public void updateUI() {
setUI(new MetalTreeUI() {
protected AbstractLayoutCache createLayoutCache() {
return new AdaptedVariableHeightLayoutCache();
}
});
}
};
frame.add(new JScrollPane(tree));
frame.setSize(500, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
TreePath path0 = tree.getPathForRow(0);
TreePath path1 = tree.getPathForRow(1);
tree.expandPath(path1);
TreePath path2 = tree.getPathForRow(2);
tree.collapsePath(path0);
((DefaultTreeModel)tree.getModel()).nodeChanged((TreeNode)path2.getLastPathComponent());
}
});
}
}
java version "1.6.0_03"
Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
Java HotSpot(TM) Client VM (build 1.6.0_03-b05, mixed mode, sharing)
Does this problem occur on J2SE 5.0.x or 6.0? Yes / No (pick one)
Yes
Operating System Configuration Information (be specific):
Microsoft Windows XP [Version 5.1.2600]
Bug Description:
AbstractLayoutCache.isExpanded(TreePath) is both implemented incorrectly and called when it should not be
The JavaDoc states that AbstractLayoutCache.isExpanded(TreePath) Returns true if the value identified by row is currently expanded.
There is another method AbstractLayoutCache.getExpandedState(TreePath) which Returns true if the path is expanded, and visible.
1) Both Implementations (FixedHeightLayoutCache and VariableHeightLayoutCache) incorrectly implement
AbstractLayoutCache.isExpanded(TreePath) to do the same as AbstractLayoutCache.getExpandedState(TreePath).
The problem appears to be that they are calling getNodeForPath(path, true, false) instead of
getNodeForPath(path, false, false), and so are ending up returning false even if the value identified
by row is currently expanded.
2) BasicTreeUI.Handler.treeNodesChanged(TreeModelEvent) is calling treeState.isExpanded(parentPath) instead of
treeState.getExpandedState(parentPath). It then incorrectly assumes that 'Changed nodes are visible'
(copied from the developers comments).
As a result of these everything calling these is also getting incorrect results and there can also be NullPointerExceptions:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.plaf.basic.BasicTreeUI$Handler.treeNodesChanged(BasicTreeUI.java:3771)
at javax.swing.tree.DefaultTreeModel.fireTreeNodesChanged(DefaultTreeModel.java:468)
at javax.swing.tree.DefaultTreeModel.nodesChanged(DefaultTreeModel.java:330)
at javax.swing.tree.DefaultTreeModel.nodeChanged(DefaultTreeModel.java:261)
at Test$1.run(Test.java:32)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
Here is some sample code where I have made VariableHeightLayoutCache isExpanded(TreePath) use
getNodeForPath(path, false, false) instead of getNodeForPath(path, true, false). Now
VariableHeightLayoutCache.isExpanded(TreePath) will correctly return true when
the TreePath is expanded and BasicTreeUI.Handler.treeNodesChanged(TreeModelEvent) will
throw the NullPointerException as shown above.
import static javax.swing.JFrame.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.metal.*;
import javax.swing.event.*;
import javax.swing.tree.*;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
JTree tree = new JTree() {
public void updateUI() {
setUI(new MetalTreeUI() {
protected AbstractLayoutCache createLayoutCache() {
return new AdaptedVariableHeightLayoutCache();
}
});
}
};
frame.add(new JScrollPane(tree));
frame.setSize(500, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
TreePath path0 = tree.getPathForRow(0);
TreePath path1 = tree.getPathForRow(1);
tree.expandPath(path1);
TreePath path2 = tree.getPathForRow(2);
tree.collapsePath(path0);
((DefaultTreeModel)tree.getModel()).nodeChanged((TreeNode)path2.getLastPathComponent());
}
});
}
}