SOLVED: Check a specific node while building the tree

This is the forum for JIDE Common Layer which is open sourced at https://github.com/jidesoft/jide-oss. Please note, JIDE technical support doesn't monitor this forum as often as other forums. Please consider subscribe for technical support for JIDE Common Layer so that you can use customer only forum to get a timely response.

Moderator: JIDE Support

Forum rules
Community driven forum for open source JIDE Common Layer. JIDE technical support doesn't monitor this forum as often as other forums. If you only use JIDE Common Layer, please consider subscribing for technical support for JIDE Common Layer so that you can use customer only forum to get a timely response.

SOLVED: Check a specific node while building the tree

Postby Meldric » Mon Jan 17, 2011 4:46 am

Hi!

I am using CheckBoxTree in a project and it works well. Still, I have a problem with checking specific nodes after the tree was created. It should be something easy and I am pretty sure to miss something... but I am completly stuck on it and can't figure it out. :(

I am creating a checkBoxTree from a path to enable the user to check several paths. The path "hotfix" (if present) needs to be checked by default and the node should be disabled (the code below does not do anything to disable the checkbox, though).

What I am doing is:
Code: Select all
      // Prepare the tree
      root = new File(DataRepository.getNewPath());
      rootNode = new FileSystemTreeNode(root);
      DefaultTreeModel myModel = new DefaultTreeModel(rootNode);
      checkboxTree = new CheckBoxTree(myModel);
      checkboxTree.setRootVisible(false);
      checkboxTree.setShowsRootHandles(false);
      checkboxTree.getCheckBoxTreeSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
      checkboxTree.getCheckBoxTreeSelectionModel().setSingleEventMode(false);
      checkboxTree.getCheckBoxTreeSelectionModel().setDigIn(false);
      
      // Mark the hotfix folder to be patched by default
      FileSystemTreeNode hotfixNode = null;
      int c = 0;
      while (c < rootNode.getChildCount()) {
         FileSystemTreeNode nodeToCheck = rootNode.getChildAt(c);
         if ((nodeToCheck.toString().toLowerCase()).equals("hotfix")) {
            hotfixNode = nodeToCheck;
            
            TreePath hotfixTreePath = new TreePath(hotfixNode.getPath());
            checkboxTree.getCheckBoxTreeSelectionModel().addSelectionPath(hotfixTreePath);
         }
         c++;
      }

This seems to be logical. The change handler looks like this:
Code: Select all
      checkboxTree.getCheckBoxTreeSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
         public void valueChanged(TreeSelectionEvent e) {
            
            TreePath[] treePaths = checkboxTree.getCheckBoxTreeSelectionModel().getSelectionPaths();
            DefaultListModel selectedModel = new DefaultListModel();
            filesArray = new ArrayList<File>();
            filesArray.clear();
            
            if (treePaths != null) {
               mContinueAction.setEnabled(true);
               for (TreePath path : treePaths) {
                  selectedModel.addElement(path);
                  filesArray.add(f);
               }
            } else {
               mContinueAction.setEnabled(false);
            }
            selectedList.setModel(selectedModel);
         }
      });

I use a JList to display the currently selected paths (selectedList).
When I run this, the path "hotfix" is never selected. Never the less, the hotfix folder is found by my code, but the node that is added looks different to the once that are added by a click on the control.

If I click on the folder hotfix, the entry in the list looks like:
Code: Select all
[D:\Test\Source, hotfix]
(where "D:\Test\Source" is the root node)

the one that is added by my code looks like:
Code: Select all
[hotfix]
(obviously missing the root)


I am coming to think that the reason the checkbox is not "ticked" is because the path is wrong (missing root?). But what I did was a .getPath on the node. Shouldn't this be complete? Because the ticked path is stored in the List, the software is doing the right thing, but the tree does not reflect it...

Any hint is much appreciated! I have been fiddling with this for hours and google brought me as far as I am now. Its beginning to drive me crazy...
Using jide-oss-2.9.7.jar.

Many thanks and greetings,
Christian

EDIT:
Code: Select all
TreePath hotfixTreePath = new TreePath(nodeToCheck.getPath());

does always return the a TreePath with only the last node, not the full path (as expected).
I have no idea what is going wrong here...

EDIT 2:
Code: Select all
TreePath hotfixTreePath = new TreePath(nodeToCheck.getPath());
checkboxTree.getCheckBoxTreeSelectionModel().addSelectionPath(hotfixTreePath);
Does not work for me, while:
Code: Select all
TreePath path = checkboxTree.getPathForRow(c);
checkboxTree.getCheckBoxTreeSelectionModel().addSelectionPath(path);
solved it.

I do not understand, why the other doesn't work, but for now I am happy it works.
Maybe a bug?
So, nevermind, folks!
Meldric
 
Posts: 5
Joined: Mon Jan 17, 2011 4:30 am

Re: SOLVED: Check a specific node while building the tree

Postby JIDE Support » Tue Jan 18, 2011 5:23 pm

It's an inherited behavior from DefaultTreeSelectionModel. The reason is that, it has a map to store the selected path. Hence, you have to use the same INSTANCE of tree path with that stored inside the JTree to mark one tree path to be selected. Any tree path created by new TreePath() would not work.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: SOLVED: Check a specific node while building the tree

Postby Meldric » Wed Jan 19, 2011 1:46 am

Thank you for the reply!
That would mean that I need to write my own method to achieve the desired behaviour? I mean to get a valid path if I only have the node at hand?
Meldric
 
Posts: 5
Joined: Mon Jan 17, 2011 4:30 am

Re: SOLVED: Check a specific node while building the tree

Postby Walter Laan » Wed Jan 19, 2011 2:40 am

JIDE Support wrote:It's an inherited behavior from DefaultTreeSelectionModel. The reason is that, it has a map to store the selected path. Hence, you have to use the same INSTANCE of tree path with that stored inside the JTree to mark one tree path to be selected. Any tree path created by new TreePath() would not work.

That's not entirely true. The TreePath equals/hashcode is based on the TreeNode's equals/hashcode so using a new TreePath is fine.

The trick is that DefaultMutableTreeNode does not override equals/hashcode to delegate to it's user object equals/hashcode.

The following code print 3xtrue but the last one is false.
Code: Select all
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.tree.*;

import com.jidesoft.swing.CheckBoxTree;

public class TestTreePath {
    public static void main(String[] args) {
        TreePath path1 = new TreePath(new Object[] { "one", "two", "three" });
        TreePath path2 = new TreePath(new Object[] { "one", "two", "three" });
        TreePath path3 = new TreePath(new Object[] { new String("one"), new String("two"), new String("three") });

        DefaultTreeSelectionModel model = new DefaultTreeSelectionModel();
        model.addSelectionPath(path1);

        System.out.println(model.isPathSelected(path2));
        System.out.println(model.isPathSelected(path3));

        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
        final DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("child1");
        final DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("child2");
        root.add(child1);
        root.add(child2);

        model.clearSelection();
        model.addSelectionPath(new TreePath(child1.getPath()));

        System.out.println(model.isPathSelected(new TreePath(new Object[] { root, child1 } )));
        System.out.println(model.isPathSelected(new TreePath(new Object[] {
                new DefaultMutableTreeNode("root"), new DefaultMutableTreeNode("child1") } )));

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                CheckBoxTree tree = new CheckBoxTree(new DefaultTreeModel(root));
                tree.getCheckBoxTreeSelectionModel().addSelectionPath(new TreePath(child1.getPath()));
                tree.setRootVisible(false);
                tree.setShowsRootHandles(false);
                tree.getCheckBoxTreeSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
                tree.getCheckBoxTreeSelectionModel().setSingleEventMode(false);
                tree.getCheckBoxTreeSelectionModel().setDigIn(false);

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.getContentPane().add(new JScrollPane(tree));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}


The actual problem is the dig in mode: in this mode if all children of a node are selected, the actual selection path will be the parent and not all the paths to the children. See the difference when you don't add child2 to the root in the above sample code.
Solution is to select the parent path if hotfix is the only child.
Walter Laan
 
Posts: 383
Joined: Mon May 01, 2006 12:13 am

Re: SOLVED: Check a specific node while building the tree

Postby Meldric » Wed Jan 19, 2011 3:36 am

In my special case, digin was disabled...

Wouldn't it be a good thing to add a new method like:
Code: Select all
TreePath path = checkboxTree.getPathForNode(node);
analog to:
Code: Select all
TreePath path = checkboxTree.getPathForRow(c);

?
Meldric
 
Posts: 5
Joined: Mon Jan 17, 2011 4:30 am

Re: SOLVED: Check a specific node while building the tree

Postby Walter Laan » Wed Jan 19, 2011 5:04 am

Meldric wrote:In my special case, digin was disabled...

If I disable the digin then it works for me (child1 is selected) so the problem must be somewhere else in your code. Is FileSystemTreeNode a DefaultMutableTreeNode? Does the hotfix node toString actually contain the text "hotfix"?
Walter Laan
 
Posts: 383
Joined: Mon May 01, 2006 12:13 am

Re: SOLVED: Check a specific node while building the tree

Postby Meldric » Wed Jan 19, 2011 7:38 am

The .toString() contains the name ("hotfix").
FileSystemTreeNode is not default, it is:
Code: Select all
   public class FileSystemTreeNode extends DefaultMutableTreeNode {
      
      private static final long serialVersionUID = 1L;
      private File f = null;
      private File[] fl = null;
      
      public FileSystemTreeNode(File file) {
         setUserObject(file);
         f = (File) getUserObject();
         fl = f.listFiles(new DIRFilter());
      }
      
      public File getFile() {
         return (File) getUserObject();
      }
      
      public int getChildCount() {   
         if (fl == null) {
            return 0;
         }
         
         return fl.length;
      }
      
      public FileSystemTreeNode getChildAt(int index) {
         return new FileSystemTreeNode(fl[index]);
      }
      
      public boolean isLeaf() {
         if (f.isFile()) {
            return true;
         }
         return false;
      }
      
      public String toString() {
         String string = f.getName();
         if (f == root) {
            string = f.getAbsolutePath();
         }
         return string;
      }
   }
Meldric
 
Posts: 5
Joined: Mon Jan 17, 2011 4:30 am

Re: SOLVED: Check a specific node while building the tree

Postby Walter Laan » Wed Jan 19, 2011 7:49 am

Meldric wrote:FileSystemTreeNode is not default, it is:
Code: Select all
   public FileSystemTreeNode getChildAt(int index) {
         return new FileSystemTreeNode(fl[index]);
      }

That's your problem: you return a new node each time getChildAt() is called so the tree paths created with different calls will never be equal.
Either override equals/hashcode of your tree node or cache the child nodes and return the same instance each time.
Walter Laan
 
Posts: 383
Joined: Mon May 01, 2006 12:13 am

Re: SOLVED: Check a specific node while building the tree

Postby Meldric » Wed Jan 19, 2011 9:12 am

Thanks for the hint, I will try to change the code accordingly when I get to it. For now it is working ok, although it is VERY slow on a network drive, but I guess that might be as well a problem of the network.

I need to investigate that...
Meldric
 
Posts: 5
Joined: Mon Jan 17, 2011 4:30 am


Return to JIDE Common Layer Open Source Project Discussion (Community Driven)

Who is online

Users browsing this forum: No registered users and 67 guests