TreeModel with CheckBoxTree

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.

TreeModel with CheckBoxTree

Postby robross0606 » Wed Nov 02, 2011 5:16 pm

I'm having a helluva time getting CheckBoxTree to update with an attached TreeModel, or to have a TreeModelListener trigger when the underlying model changes. If I pass a TreeModel into the constructor, the model data appears. However, subsequent updates to the model don't trigger updates to the GUI elements or listener callbacks. Help!
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby JIDE Support » Wed Nov 02, 2011 6:24 pm

How do you update the model? Did you ever fire model change event to update UI?

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

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 7:53 am

My model extends DefaultTreeModel and makes calls to that class' insert/update methods. Those methods in turn fire model change events as per standard DefaultTreeModel behavior.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 9:30 am

Okay, figured this out. The tree model was calling node.add() rather than the model's insertInto() method so the events weren't firing.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 9:32 am

Now for the next question: How can I get the TreeModel to inform whether the CheckBoxTree selects the checkbox or not? The current node mode has a field for whether it should be selected, but I'm not sure how the CheckBoxTree handles that. Right now, it does not appear to handle it at all.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 10:09 am

Just to be clear, I'm looking to use the TreeModel to determine whether the checkbox of particular node types should be checked, partial or unchecked. I don't see a way to programatically check or uncheck nodes.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby JIDE Support » Thu Nov 03, 2011 10:33 am

Please invoke CheckBoxTree#getCheckBoxTreeSelectionModel()#addSelectionPath()/removeSelectionPath() to check/uncheck a node.

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

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 10:42 am

Not exactly model-driven design. What is the difference between #addSelectionPath() and #setSelectionPath()?
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 10:54 am

Neither of those functions appears to do anything to the actual tree. Since there doesn't appear to be a model-driven way to do this, I am attempting to update the checkbox state in the TreeModelListener instead. Both functions complete without any error indication but the tree checkboxes remain unchecked.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 11:00 am

Here is the code I am attempting to run when an node is inserted:

Code: Select all
   @Override
   public void treeNodesInserted(TreeModelEvent e)
   {
//      LayerTreeNode node = (LayerTreeNode) (e.getTreePath().getLastPathComponent());

      for(Object childObj : e.getChildren())
      {
         if(childObj instanceof LayerTreeGroupNode)
         {
            LayerTreeGroupNode node = (LayerTreeGroupNode)childObj;
         }
         else if(childObj instanceof LayerTreeNode)
         {
            LayerTreeNode node = (LayerTreeNode)childObj;
            System.out.println("The user has finished adding the node " + node.getTitle());
            
            if(node.isSelected())
            {
               TreePath childPath = e.getTreePath().pathByAddingChild(childObj);
               CheckBoxTreeSelectionModel selectionModel = layerTree.getCheckBoxTreeSelectionModel();
               selectionModel.addSelectionPath(childPath);
            }
         }
      }
   }
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby JIDE Support » Thu Nov 03, 2011 11:06 am

addSelectionPath() adds new selection path while keeping the old selections while setSelectionPath() clears the existing selections.

The following code does work for me in JIDE CheckBoxTreeDemo. Please make sure the tree path is already part of your JTree before you invoke this method. Some of our customers failed to check the tree nodes because they passed in a tree path that is not exactly inside the JTree.
Code: Select all
        _tree.getCheckBoxTreeSelectionModel().addSelectionPath(_tree.getPathForRow(2));

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

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 11:13 am

Does the listener trigger before or after the nodes are actually added to the tree? The function is called "treeNodesInserted()". The past tense of the method name indicates to me that the nodes have already been inserted into the tree by the time this callback is triggered. Is that not the case?
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 11:19 am

The JavaDocs for this callback say:

Invoked after nodes have been inserted into the tree.


Therefore, the nodes should have been inserted into the tree by the time this callback is triggered.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 11:24 am

I might add that passing in tree path that is not inside the JTree should probably be grounds for a thrown exception. Simply returning without so much as a notification is very hard to debug.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 11:30 am

After testing I have found that this method does appear to be misleadingly named. Using #getRowForPath() I was able to determine that it always returns -1 while in this callback. That means the nodes have NOT been added to the tree already.

Using the TreeModelListener doesn't appear to be a solution. Is there any way someone could suggest to have nodes checked when they are loaded by the underlying TreeModel?
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby JIDE Support » Thu Nov 03, 2011 11:37 am

I believe the node is already inserted into the TreeModel at that time. However, your listener gets executed first before the JTree creates TreePath for the new node. That's why the issue arises. Please try to insert your listener to the first so that it would be executed the last. Below is a fraction of code how we insert a table model listener FYI. You could try to write a code to insert a tree model listener and check if that works for you.
Code: Select all
    public static void insertTableModelListener(TableModel model, TableModelListener l, int index) {
        if (!(model instanceof AbstractTableModel)) {
            model.addTableModelListener(l);
            return;
        }
        TableModelListener[] listeners = ((AbstractTableModel) model).getTableModelListeners();
        for (TableModelListener listener : listeners) {
            model.removeTableModelListener(listener);
        }
        for (int i = 0; i < listeners.length; i++) {
            TableModelListener listener = listeners[i];
            if (index == i) {
                model.addTableModelListener(l);
            }
            model.addTableModelListener(listener);
        }
        // index is too large, add to the end.
        if (index < 0 || index > listeners.length - 1) {
            model.addTableModelListener(l);
        }
    }

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

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 11:45 am

Thanks for the suggestion. I will definitely try this out, but I'm not quite sure what you mean by:

Please try to insert your listener to the first so that it would be executed the last.


Could you restate that so I'm sure I understand what you mean?
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 11:57 am

Given what you said, I've tried adding this to my custom TreeModel implementation:
Code: Select all
   public void insertTreeModelListener(TreeModelListener l, int index)
   {
      TreeModelListener[] listeners = getTreeModelListeners();
      for (TreeModelListener listener : listeners)
      {
         removeTreeModelListener(listener);
      }
      for (int i = 0; i < listeners.length; i++)
      {
         TreeModelListener listener = listeners[i];
         if (index == i)
         {
            addTreeModelListener(l);
         }
         addTreeModelListener(listener);
      }
      // index is too large, add to the end.
      if (index < 0 || index > listeners.length - 1)
      {
         addTreeModelListener(l);
      }
   }

I then changed my setup calls from this:
Code: Select all
layerTreeModel.addTreeModelListener(new CnpLayerTreeModelListener(this));

to this:
Code: Select all
layerTreeModel.insertTreeModelListener(new CnpLayerTreeModelListener(this), 0);


Is this what you had in mind? If so, this didn't make a difference in execution. The checkboxes remain unchecked and the TreePath unavailable.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 1:44 pm

I figured this out. Turns out the chidlren were being called for #insertInto() on the TreeModel before the parent was called as an insert to the root. Because of this, the treepath was invalid. Would still recommend throwing an exception for this in your classes. Simply returning without any documented behavior is not very helpful.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby JIDE Support » Thu Nov 03, 2011 2:43 pm

That's a behavior inherited from Swing DefaultTreeSelectionModel#addSelectionPath(). I believe the idea is that, JIDE or Swing, as a component provider, is not supposed to throw exception unexpectedly. Otherwise, we might get more complaints.

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

Re: TreeModel with CheckBoxTree

Postby robross0606 » Thu Nov 03, 2011 3:57 pm

LOL, "unexpectedly" is not unexpected if the exception is documented with a "throws" and I catch it. Pretty sure that's a Java standard behavior. Not doing anything leaves us with... undocumented? Oh well.
robross0606
 
Posts: 23
Joined: Wed Nov 02, 2011 5:14 pm

Re: TreeModel with CheckBoxTree

Postby JIDE Support » Thu Nov 03, 2011 4:49 pm

Because we override Swing's DefaultTreeSelectionModel's addSelectionPaths and setSelectionPaths method, so we are not allowed to change the signature to throw non-RuntimeException. We could throw a runtime exception which doesn't require user to catch it. However I think that'll cause more complains. Please also keep in mind, as a general rule in our design, we try to keep the API as similar as Swing. If Swing doesn't throw exception for non-existed path, generally speaking, we won't do it either in the similar case as that's the way Swing developers expected. Hope you can understand.
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am


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

Who is online

Users browsing this forum: No registered users and 13 guests

cron