Expanding Wickets TreeTable nodes when initializing a tree - java

I'm pretty new to wicket and I'm trying to create a simple wicket tree that holds information about mailinglists. This mailinglist is related to a certain letter.
MailingListDto 1
User 1
User 2
MailingListDto 2
User 3
User 4
If we are editing an existing letter, the mailinglists related to that letter are fetched into mailingListCollection and the corresponding nodes on the tree should be selected and expanded. For some reason I don't seem to get this workin.
The selected and expanded nodes do not show as selected nor expanded in the UI, but if I go through the selected nodes programmatically for example in onAfterRender() and log the selected and expanded values, the nodes are expanded and selected.
tree = new TreeTable("treeTable", treeModel, treeColumns) {
#Override
public void onBeforeRender() {
super.onBeforeRender();
if (!mailingListCollection.isEmpty()) {
for (MailingListDto mailingList : mailingListCollection) {
tree.getTreeState().expandNode(mailingList);
tree.getTreeState().selectNode(mailingList, true);
}
}
tree.updateTree();
}
#Override
protected void onAfterRender() {
super.onAfterRender();
if (LOG.isDebugEnabled()) {
LOG.debug("onAfterRender: " + tree.getTreeState().getSelectedNodes().size());
for (Object obj : tree.getTreeState().getSelectedNodes()) {
LOG.debug(tree.getTreeState().isNodeSelected(obj) + " " + tree.getTreeState().isNodeExpanded(obj));
}
}
}
};
tree.setRootLess(true);
tree.getTreeState().setAllowSelectMultiple(true);
add(tree);

To expand only the root node of your tree:
Object rootObj = myTree.getModelObject().getRoot();
myTree.getTreeState().expandNode(rootObj);
To expand also the first child of the root node add the following line to the previous ones:
myTree.getTreeState().expandNode(myTree.getModelObject().getChild(rootObj, 0));
Note that you have to expand all parent nodes of the "target" node otherwise on the screen the target node will be hidden because of a collapsed parent.

wicket 1.5.10
wicket 6
Look at source code. In class FooExpansion.java is a method expandAll().
FooExpansion.java is used in private class FooExpansionModel.java is used in AdvancedTreePage.java.
So a simple solution, when init your tree (in AdvancedTreePage.java), could be:
FooExansionModel model = new FooExpansionModell()
tree = createTree(provider, model);
((FooExpansion)model.getObject()).expandAll();

Related

Disable dragging of selected object in Piccolo2d?

I know Piccolo2d is an old project, but I have a couple of questions.
1) Is it possible to disable dragging a selected object? For this particular use case, I only want to select an object, not move or delete it. I know I can disable deletion using:
this.selector.setDeleteKeyActive(false);
But I don't see an option to disable dragging. Is the only option to override the drag functionality in the event handler?
2) Is there no way to have the selection handler active at the same time as the pan/zoom handlers? It seems a bit archaic to disable pan/zoom when you want to support object picking. Or do I have to create my own handlers?
My current code is:
...
this.pluginContext.getCanvas().setPanEventHandler(null);
this.selector = new PSelectionEventHandler(this.mapLayer.getNode(), this.mapLayer.getNode()) {
};
this.selector.setDeleteKeyActive(false);
this.pluginContext.getCanvas().addInputEventListener(this.selector);
PNotificationCenter.defaultCenter().addListener(this, "nodeSelected",
PSelectionEventHandler.SELECTION_CHANGED_NOTIFICATION, this.selector);
...
public void nodeSelected(final PNotification notification) {
logger.debug("Selection - " + this.selector.getSelection().toString());
}
In true developer tradition, I found an answer.
My pickable nodes are all grouped under individual grouping nodes. This lets me add an event listener on the grouping node, like this:
groupNode.addInputEventListener(new PBasicInputEventHandler() {
public void mouseReleased(final PInputEvent event) {
PNode node = event.getPickedNode();
if (node != null) {
onNodeSelected(node); // your logic here
}
}
});
The beauty of this is that the event contains the picked node that is grouped under that group node. Perfect! Also, you don't have to disable the pan/zoom handlers.
The only downside is that this doesn't give you the selection decorator around the node. Can't win 'em all!

Only handling tree will expand but not tree selection in JTree - Java Swing

I am doing lazy loading for my app. I want a node to load only user click to it's icon. The point is i don't know that node have it's children or not.My temporary solution is to define a node having children then loading them based on selection event, i don't use tree will expand event for lazy loading. Is there any ways for me to just implement treeWillExpand event. You can reference in TreeWillExpanListener and TreeExpandEventDemo2.
// Have a tree with some unexpanded root items
// When an item is expanded, add some children
tree.addListener(new Tree.ExpandListener() {
public void nodeExpand(ExpandEvent event) {
// No children for the first node
if (!hasChildren(event.getItemId())) {
tree.setChildrenAllowed(event.getItemId(), false);
} else {
// Add a few new child nodes to the expanded node
tree.addItem(childId);
tree.setParent(childId, event.getItemId());
}
}
});
you can implement hasChildren to find the child based on tree node being expanded and then find child and add

Why does node selection not work properly after TreeModel reload?

I have a Swing application that uses a JTree. I want some of the nodes of the tree to be hidden, so I have implemented two DefaultTreeModels, one with every node and a filtered one with only the ones that should be displayed. The latter is set as the actual model.
At some points I must change the filtered nodes, and when I do, the items in the tree update properly, but their behavior is wrong. Nodes do not get highlighted when they are selected (even though they are indeed selected) and the user can no longer double-click to expand a node, they must click the little '+' button.
Below is a generalization of my code, two methods from my custom class that extends JTree.
updateFilter gets called when the filter needs to be updated.
populateFilteredNode recursively populates the root node of my filtered model. For simplicity, filteredRoot is a class member variable (of type DefaultMutableTreeNode) and is the root of the filtered model. fullModel and filteredModel are of type DefaultTreeModel
public void updateFilter() {
// Get current expansion state
ArrayList<Integer> expansionState = getExpansionState();
DefaultMutableTreeNode fullModelRoot = fullModel.getRoot();
// Remove existing nodes in the filtered model
while(filteredRoot.getChildCount() > 0) {
filteredModel.removeNodeFromParent(filteredRoot.getFirstChild());
}
populateFilteredNode(fullModelRoot, filteredRoot);
// Repaint tree and restore expansion state
repaint();
setExpansionState(expansionState);
}
private void populateFilteredNode(DefaultMutableTreeNode fullNode, DefaultMutableTreeNode filteredNode) {
int index = 0;
for(int n = 0; n < fullNode.getChildCount(); n++) {
DefaultMutableTreeNode fullChildNode = fullNode.getChildAt(n);
// Show the item and its children if one of many cases is true
if(shouldShowItem(fullChildNode.getItem())) {
DefaultMutableTreeNode filteredChildNode = fullChildNode.clone();
filteredModel.insertNodeInto(filteredChildNode, filteredNode, index++);
populateFilteredNode(fullChildNode, filteredChildNode);
}
}
}
If anyone has a similar experience or knows why the selected node will not appear highlighted, please let me know. Or if there is a better way to accomplish filtering. Or if more code would help provide an answer.
I found something that works for my case, although it's quick and dirty and I don't necessarily understand why it works. This 12-year-old post on Code Ranch somehow got me headed in the right direction. I'm just posting it here in case anyone has a similar problem and it might be of help.
I save the selection path before making any changes to the table model, and then call this new function findNewSelectionPath after the changes were made. Below is a generalized version of the function (I use several custom classes so I did my best to make it look generically usable).
private TreePath findNewSelectionPath(TreePath oldSelectionPath) {
TreePath newSelectionPath = null;
if(oldSelectionPath != null) {
Object[] oldPathComponents = oldSelectionPath.getPath();
Object[] newPathComponents = new Object[oldPathComponents.length];
DefaultMutableTreeNode node = (DefaultMutableTreeNode) filteredModel.getRoot();
// Set the root
if(oldPathComponents[0].equals(node)) {
newPathComponents[0] = node;
}
// Set the rest of the path components
for(int n = 1; n < oldPathComponents.length; n++) {
for(int k = 0; k < node.getChildCount(); k++) {
if(oldPathComponents[n].equals(node.getChildAt(k))) {
newPathComponents[n] = node.getChildAt(k);
node = node.getChildAt(k);
break;
}
}
}
// Make sure that the last path component exists
if(newPathComponents[newPathComponents.length - 1] != null) {
newSelectionPath = new TreePath(newPathComponents);
}
}
return newSelectionPath;
}

A editable JTree converts the tree nodes into Strings

I'm using a JTree that is populated from a database.
The tree is created by setting the root node and its childs with custom objects this way:
private DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Categorias");
...
ResultSet primaryCategories = dbm.fetchAllCategories();
while (primaryCategories.next()){
Category category = new Category(primaryCategories.getLong("_id"),
primaryCategories.getString("category"));
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(category);
rootNode.add(childNode);
ResultSet currentSubcategory = dbm.fetchChildSubcategories(category.getCatId());
while (currentSubcategory.next()){
Category subcategory = new Category(currentSubcategory.getLong("_id"),
currentSubcategory.getString("category"));
childNode.add(new DefaultMutableTreeNode(subcategory, false));
}
}
...
After this, the tree is perfectly created. Populated with "Category" Objects, every object has its own ID number and its name to use in toString() method.
The problem comes when it's set editable. Once the node is renamed, the Category node is also converted into a String Object, so I cant update the new Category name value to the database.
I've tried to capture the renaming event with treeNodesChanged(TreeModelEvent e) but, the userObject is already changed to a String Object, and can't get a referece of what object was edited.
What way can I solve this? Should I have a copy of the tree that's shown and another of the downloaded from the database and uptade both everytime a change occurs?
*PD: *
I also tried to capture the changed node from the model overriding the method:
public void nodeChanged(TreeNode newNode) {
DefaultMutableTreeNode parent = ((DefaultMutableTreeNode)newNode.getParent());
int index = getIndexOfChild(parent, newNode);
DefaultMutableTreeNode oldNode = (DefaultMutableTreeNode) getChild(parent, index);
System.out.println(parent.getUserObject().getClass().toString());
System.out.println(oldNode.getUserObject().getClass().toString());
}
this prints:
class com.giorgi.commandserver.entity.Category
class java.lang.String
So the old node here has already been changed to a String and I've lost completely the reference to the older Category and its ID so I cannot update it in the database.
Any help is wellcome.
Okay, that took a bit of digging.
Basically, when the editing is "stopped", the JTree will request the editor's value via editor's getCellEditorValue. This is then passed to the model via the valuesForPathChanged method, which finally calls the node's setUserObject method.
Presumably, you are using either the default editor or one based on text field. This will return a String value.
What you need to do is trap the change to the setUserObject method of your tree node, access the value coming (ie, check if it's a String or not) and update as required.
Final solution was as MadProgrammer said to get it in:
public void valueForPathChanged(TreePath path, Object newValue) {
DefaultMutableTreeNode aNode = (DefaultMutableTreeNode)path.getLastPathComponent();
Category catNode = (Category) aNode.getUserObject();
catNode.setCategory((String) newValue);
catNode.updateFromDatabase();
nodeChanged(aNode);
}

Programatically select a node in a SmartGWT treegrid

I have a smartgwt treegrid, which, when expanding a group, I need to automatically select the first childnode of that group. I can get to the child, but I fail to see how to select the node.
TreeGrid moduleTree = new TreeGrid();
final Tree tree = new Tree();
moduleTree.addFolderOpenedHandler(new FolderOpenedHandler() {
public void onFolderOpened(FolderOpenedEvent event) {
TreeNode[] children = tree.getChildren(event.getNode());
if (children.length > 0) {
// TODO
}
}
});
Any Ideas?
Thanks!
you can select a particular TreeNode using this property of TreeGrid:
treeGrid().selectRecord(record);
treeGrid().selectRecords(records);
Here record is the TreeNode you want to be selected. You can select multiple TreeNodes using the second property.

Categories

Resources