views:

291

answers:

3

Hi,

I seems to me that when i call

JTree.expandPath( path )

That by default all its parents are expanded as well. But what i actually want to do is, set up specific invisible children to be expanded in advance. So that when a node is expanded that its complete sub-tree pops-out.

I've found that internally in JTree expandedState.put(path, Boolean.TRUE); records the expanded nodes, but i can't get access to it. (p.s. i don't want to use reflection :)

Installing listener for the expansion event, would result in a lot of run-time updates beeing fired. That's why i prefer to let JTree record the expanded states.

Hope that there are other ways of doing it.
Any help is appreciated?

Accepted the Listener solution. Option 2

Option 1 Overriding :

One nasty drawBack..it is depending on the implementation of setExpandedState()

private boolean cIsExpandingHidden = false;
private TreePath cExpandingPath;

public void expandBranchHidden(DefaultMutableTreeNode node) {
  TreeNode[] mPathSections = mNode.getPath();
  TreePath mPath = new TreePath(mPathSections);
  //
  if (!cTree.isVisible(mPath)){
    cIsExpandingHidden = true;
  }
  cExpandingPath = mPath;
  try{
    expandPath(mPath);
  }finally{
    cExpandingPath = null;
    cIsExpandingHidden = false;
  }
}

@Override
public boolean isExpanded(TreePath path) {
  // override the questions whether the node parents of
  //  'the currently expanded node' to return TRUE
  if (cIsExpandingHidden){
    if (path.isDescendant(cExpandingPath)){
      return true; // just claim it doesn't need expanding
    }
  }
  return super.isExpanded(path);
}

@Override
public void fireTreeExpanded(TreePath path) {
  // the treeUI must not to know.. bad luck for any other listeners 
  if (!cIsExpandingHidden){
    super.fireTreeExpanded(path);
  }
}

Option 2 Listener

/* code where new nodes are received */
{
  // only if direct parent is expanded.. else expansionListener will pick it up
  if (cTree.isExpanded(mCreator.getParentTreeNode())){
    for (TreeNode mNode : mAddNodes) {
      if (mNode.isDefaultExpanded()) {
        cTree.expandBranch(mNode);
        mNode.setDefaultExpanded(false);
      }
    }
  }
}

/*  expansion listener */
{
  if (cRecursiveExpand){
    return;
  }
  // walk through children, expand and clear its preference
  cRecursiveExpand = true;
  IExtendedTreeNode[] mNodes = cTree.getChildrenOfCurrentNode();
  for (IExtendedTreeNode mNode : mNodes) {
    TreeNode mTreeNode = (TreeNode)mNode;
    if (mTreeNode.isDefaultExpanded()){
      cTree.expandBranch(mTreeNode);
      mTreeNode.setDefaultExpanded(false);
    }
  }
  cRecursiveExpand = false;
}
+1  A: 

You'll have an easier time calling

addTreeExpansionListener(TreeExpansionListener tel)

When the treeExpanded(TreeExpansionEvent event) method in your TreeExpansionListener gets called, you can check to see if you should recursively expand all children for the newly expanded TreePath.

Sam Barnum
This is true, but the question specifically mentions this approach and is asking if there is an alternative that would let the tree record the states vs firing lots of updates when things expand.
CarlG
Still is a valid answer. Could be that he's been down my path.. Sam, have you?
Houtman
The overhead of firing these TreeExpansionEvents is going to be very minimal, and they'll only be fired when a node is expanded or collapsed. The code would likely be more concise as well.
Sam Barnum
Works out pretty nice actually..i've included the Listener solution in my question as well
Houtman
Is actually less time consuming :) Since i only have to visit the direct children of the newly expanded node, instead of ALL incoming/created treeNodes.
Houtman
+1  A: 

One easy way of doing it is subclass JTree and override the method

setExpandedState(TreePath path, boolean state)

In this method instead of expanding all parents, expand only the subpaths that you want to expand. That's exactly why the method is protected :)

Suraj Chandran
I agree that this would be handy since it is protected, but. the 'expandedState' variable is private :( But...I think i could escape its upward recursive expansion by Also overriding the 'isExpanded()' since this is used for building up the to-do stack :)
Houtman
So where's my upvote ;)
Suraj Chandran
have to test it first :)
Houtman
private static class MyTree extends JTree { int rows[]; public MyTree(int rows[]) { this.rows = rows; } protected void setExpandedState(TreePath path, boolean state) { TreePath []paths = new TreePath[rows.length]; for (int i = 0; i < rows.length; i++) { paths[i] = this.getPathForRow(rows[i]); if (paths[i].isDescendant(path)) { super.setExpandedState(path, state); } else { // do nothing } } } }Ok...now you should give me that vote :)
Suraj Chandran
Ok, here you go :) Although your solution is not exactly what i needed.
Houtman
A: 

My answer is appended to the question

Houtman