This path fixes problems that were observed whey hiding/showing the tree
root node while the tree is displayed. It also extends the tree demo to
demonstrate the root node visibility changes.
2006-04-27 Audrius Meskauskas <[EMAIL PROTECTED]>
* examples/gnu/classpath/examples/swing/TreeDemo.java
(createContent): Added root visibility and selection listener demos.
* javax/swing/JTree.java (setRootVisible): If false, unselect
the root node, if it is selected.
* javax/swing/plaf/basic/BasicTreeUI.java
(TreeTraverseAction.actionPerformed): Do not select the root if it
is not visible.
* javax/swing/tree/DefaultTreeSelectionModel.java (removeSelectionPath,
removeSelectionPaths): Reset lead to null if the current lead path is
removed from selection.
* javax/swing/tree/TreePath.java (getParentPath): Cache the parent path.
* javax/swing/tree/FixedHeightLayoutCache.java (NodeRecord.getPath):
Return the same path regardless is root visible or not. (update):
Reduce the identation if the root is not visible.
* javax/swing/tree/VariableHeightLayoutCache.java (NodeRecord.getPath):
Return the same path regardless is root visible or not. (update):
Reduce the identation if the root is not visible.
Index: examples/gnu/classpath/examples/swing/TreeDemo.java
===================================================================
RCS file: /sources/classpath/classpath/examples/gnu/classpath/examples/swing/TreeDemo.java,v
retrieving revision 1.3
diff -u -r1.3 TreeDemo.java
--- examples/gnu/classpath/examples/swing/TreeDemo.java 26 Apr 2006 09:03:11 -0000 1.3
+++ examples/gnu/classpath/examples/swing/TreeDemo.java 27 Apr 2006 08:13:08 -0000
@@ -48,10 +48,13 @@
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
+import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.DefaultTreeSelectionModel;
@@ -169,6 +172,7 @@
}
});
+ // Demonstration of the various selection modes
final JCheckBox cbSingle = new JCheckBox("single selection");
cbSingle.addActionListener(new ActionListener()
{
@@ -182,18 +186,49 @@
DefaultTreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
}
});
-
+
+ // Demonstration of the root visibility changes
+ final JCheckBox cbRoot = new JCheckBox("root");
+ cbRoot.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ tree.setRootVisible(cbRoot.isSelected());
+ }
+ });
+ cbRoot.setSelected(true);
+
+ // Demonstration of the tree selection listener.
+ final JLabel choice = new JLabel("Make a choice");
+ tree.getSelectionModel().addTreeSelectionListener(
+ new TreeSelectionListener()
+ {
+ public void valueChanged(TreeSelectionEvent event)
+ {
+ TreePath was = event.getOldLeadSelectionPath();
+ TreePath now = event.getNewLeadSelectionPath();
+ String swas =
+ was == null ? "none":was.getLastPathComponent().toString();
+ String snow =
+ now == null ? "none":now.getLastPathComponent().toString();
+ choice.setText("From "+swas+" to "+snow);
+ }
+ }
+ );
+
setLayout(new BorderLayout());
JPanel p2 = new JPanel();
p2.add(add);
p2.add(cbSingle);
+ p2.add(cbRoot);
tree.getSelectionModel().
setSelectionMode(DefaultTreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
add(p2, BorderLayout.NORTH);
add(new JScrollPane(tree), BorderLayout.CENTER);
+ add(choice, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent e)
Index: javax/swing/JTree.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/JTree.java,v
retrieving revision 1.65
diff -u -r1.65 JTree.java
--- javax/swing/JTree.java 26 Apr 2006 12:31:07 -0000 1.65
+++ javax/swing/JTree.java 27 Apr 2006 08:13:36 -0000
@@ -1953,9 +1953,19 @@
if (rootVisible == flag)
return;
+ // If the root is currently selected, unselect it
+ if (rootVisible && !flag)
+ {
+ TreeSelectionModel model = getSelectionModel();
+ // The root is always shown in the first row
+ TreePath rootPath = getPathForRow(0);
+ model.removeSelectionPath(rootPath);
+ }
+
boolean oldValue = rootVisible;
rootVisible = flag;
firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
+
}
public boolean getShowsRootHandles()
Index: javax/swing/plaf/basic/BasicTreeUI.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/plaf/basic/BasicTreeUI.java,v
retrieving revision 1.134
diff -u -r1.134 BasicTreeUI.java
--- javax/swing/plaf/basic/BasicTreeUI.java 26 Apr 2006 19:34:12 -0000 1.134
+++ javax/swing/plaf/basic/BasicTreeUI.java 27 Apr 2006 08:13:45 -0000
@@ -2470,7 +2470,7 @@
}// NodeDimensionsHandler
/**
- * PropertyChangeListener for the tree. Updates the appropriate varaible, or
+ * PropertyChangeListener for the tree. Updates the appropriate variable, or
* TreeState, based on what changes.
*/
public class PropertyChangeHandler
@@ -3030,9 +3030,11 @@
else
{
// If the node is not expanded (also, if it is a leaf node),
- // we just select the parent.
+ // we just select the parent. We do not select the root if it
+ // is not visible.
TreePath parent = current.getParentPath();
- if (parent != null)
+ if (parent != null &&
+ !(parent.getPathCount()==1 && !tree.isRootVisible()) )
tree.setSelectionPath(parent);
}
}
Index: javax/swing/tree/DefaultTreeSelectionModel.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/tree/DefaultTreeSelectionModel.java,v
retrieving revision 1.29
diff -u -r1.29 DefaultTreeSelectionModel.java
--- javax/swing/tree/DefaultTreeSelectionModel.java 26 Apr 2006 16:18:38 -0000 1.29
+++ javax/swing/tree/DefaultTreeSelectionModel.java 27 Apr 2006 08:13:50 -0000
@@ -442,9 +442,14 @@
- index - 1);
selection = new TreePath[temp.length];
System.arraycopy(temp, 0, selection, 0, temp.length);
+
+ // If the removed path was the lead path, set the lead path to null.
+ TreePath oldLead = leadPath;
+ if (path!=null && leadPath!=null && path.equals(leadPath))
+ leadPath = null;
- fireValueChanged(new TreeSelectionEvent(this, path, false, leadPath,
- path));
+ fireValueChanged(new TreeSelectionEvent(this, path, false, oldLead,
+ leadPath));
insureRowContinuity();
}
}
@@ -463,6 +468,7 @@
{
int index = - 1;
TreePath v0 = null;
+ TreePath oldLead = leadPath;
for (int i = 0; i < paths.length; i++)
{
v0 = paths[i];
@@ -475,6 +481,8 @@
index = x;
break;
}
+ if (leadPath != null && leadPath.equals(v0))
+ leadPath = null;
}
TreePath[] temp = new TreePath[selection.length - 1];
System.arraycopy(selection, 0, temp, 0, index);
@@ -484,7 +492,7 @@
System.arraycopy(temp, 0, selection, 0, temp.length);
fireValueChanged(new TreeSelectionEvent(this, v0, false,
- leadPath, paths[0]));
+ oldLead, leadPath));
}
}
insureRowContinuity();
Index: javax/swing/tree/FixedHeightLayoutCache.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/tree/FixedHeightLayoutCache.java,v
retrieving revision 1.15
diff -u -r1.15 FixedHeightLayoutCache.java
--- javax/swing/tree/FixedHeightLayoutCache.java 26 Apr 2006 19:34:12 -0000 1.15
+++ javax/swing/tree/FixedHeightLayoutCache.java 27 Apr 2006 08:13:51 -0000
@@ -121,26 +121,33 @@
*/
TreePath getPath()
{
- boolean lastChild = false;
- if (parent!=null)
+ if (path == null)
{
- int nc = treeModel.getChildCount(parent);
- if (nc > 0)
+ boolean lastChild = false;
+ if (parent != null)
{
- int n = treeModel.getIndexOfChild(parent, node);
- if (n == nc-1)
- lastChild = true;
+ int nc = treeModel.getChildCount(parent);
+ if (nc > 0)
+ {
+ int n = treeModel.getIndexOfChild(parent, node);
+ if (n == nc - 1)
+ lastChild = true;
+ }
}
- }
- if (path == null)
- {
+
LinkedList lpath = new LinkedList();
NodeRecord rp = this;
while (rp != null)
{
lpath.addFirst(rp.node);
if (rp.parent != null)
- rp = (NodeRecord) nodes.get(rp.parent);
+ {
+ Object parent = rp.parent;
+ rp = (NodeRecord) nodes.get(parent);
+ // Add the root node, even if it is not visible.
+ if (rp == null)
+ lpath.addFirst(parent);
+ }
else
rp = null;
}
@@ -238,7 +245,7 @@
for (int i = 0; i < sc; i++)
{
Object child = treeModel.getChild(root, i);
- countRows(child, root, 1);
+ countRows(child, root, 0);
}
}
dirty = false;
Index: javax/swing/tree/TreePath.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/tree/TreePath.java,v
retrieving revision 1.10
diff -u -r1.10 TreePath.java
--- javax/swing/tree/TreePath.java 10 Apr 2006 09:06:46 -0000 1.10
+++ javax/swing/tree/TreePath.java 27 Apr 2006 08:13:51 -0000
@@ -57,6 +57,11 @@
* assumes that the TreePath is immutable, so it is marked final here.
*/
private final Object[] path;
+
+ /**
+ * The parent path (to be reused).
+ */
+ private transient TreePath parentPath;
/**
@@ -294,7 +299,12 @@
// is what the JDK does.
if (path.length <= 1)
return null;
-
- return new TreePath(this.getPath(), path.length - 1);
+
+ // Reuse the parent path, if possible. The parent path is requested
+ // during the tree repainting, so reusing generates a lot less garbage.
+ if (parentPath == null)
+ parentPath = new TreePath(this.getPath(), path.length - 1);
+
+ return parentPath;
}
}
Index: javax/swing/tree/VariableHeightLayoutCache.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/tree/VariableHeightLayoutCache.java,v
retrieving revision 1.13
diff -u -r1.13 VariableHeightLayoutCache.java
--- javax/swing/tree/VariableHeightLayoutCache.java 26 Apr 2006 19:34:12 -0000 1.13
+++ javax/swing/tree/VariableHeightLayoutCache.java 27 Apr 2006 08:13:52 -0000
@@ -115,31 +115,38 @@
private TreePath path;
/**
- * Get the path for this node. The derived class is returned,
- * making check for the last child of some parent easier.
+ * Get the path for this node. The derived class is returned, making check
+ * for the last child of some parent easier.
*/
TreePath getPath()
{
- boolean lastChild = false;
- if (parent!=null)
+ if (path == null)
{
- int nc = treeModel.getChildCount(parent);
- if (nc > 0)
+ boolean lastChild = false;
+ if (parent != null)
{
- int n = treeModel.getIndexOfChild(parent, node);
- if (n == nc-1)
- lastChild = true;
+ int nc = treeModel.getChildCount(parent);
+ if (nc > 0)
+ {
+ int n = treeModel.getIndexOfChild(parent, node);
+ if (n == nc - 1)
+ lastChild = true;
+ }
}
- }
- if (path == null)
- {
+
LinkedList lpath = new LinkedList();
NodeRecord rp = this;
while (rp != null)
{
lpath.addFirst(rp.node);
if (rp.parent != null)
- rp = (NodeRecord) nodes.get(rp.parent);
+ {
+ Object parent = rp.parent;
+ rp = (NodeRecord) nodes.get(parent);
+ // Add the root node, even if it is not visible.
+ if (rp == null)
+ lpath.addFirst(parent);
+ }
else
rp = null;
}
@@ -237,7 +244,7 @@
for (int i = 0; i < sc; i++)
{
Object child = treeModel.getChild(root, i);
- countRows(child, root, 1);
+ countRows(child, root, 0);
}
}
dirty = false;