UITree binding and other issues
christian.bauer Mar 19, 2007 11:44 AMYou guys should use the Swing TreeModel/TreeNode combo and not invent your own model.
The RichFaces TreeNode concept seems to be limited to exactly what the demo is doing - read an XML file and implement a separate class that represents the root node. I found no example with more dynamic tree adapters (what you usually do with a custom TreeModel in Swing).
This is how it looks. Most people want lazy loading of children on the server. So what you need to support is this:
- Composite Pattern: Node(Directory -to-many-> Document, Document)
- The following code loads the root "node", imagine a C:/ directory
- On-demand loading of subdirectories of C:/ and wrapping when the tree is expanded
- No "files" are shown
@Name("treeNodeAdapter") public static class TreeNodeAdapter { @Factory(value = "directoryTree", scope = ScopeType.CONVERSATION, autoCreate = true) public TreeNode loadReadableDirectoryTree() { Directory wikiroot = (Directory) Component.getInstance("wikiRoot"); return new WikiTreeNode(wikiroot); } class WikiTreeNode implements TreeNode { private Node wikiNode; private Map<Object, TreeNode> childrenMap = new LinkedHashMap<Object,TreeNode>(); public WikiTreeNode(Node wikiNode) { if (wikiNode != null) { this.wikiNode = wikiNode; for (Node childNode : wikiNode.getChildren()) { if (!WikiUtil.isDirectory(childNode)) continue; childrenMap.put(childNode.getId(), new WikiTreeNode(childNode)); } } } public Object getData() { return wikiNode; } public void setData(Object node) { this.wikiNode = (Node)node; } public boolean isLeaf() { return childrenMap.size() == 0; } public Iterator getChildren() { return childrenMap.entrySet().iterator(); } public TreeNode getChild(Object identifier) { return childrenMap.get( identifier ); } public void addChild(Object identifier, TreeNode treeNode) { childrenMap.put(identifier, treeNode); } public void removeChild(Object identifier) { // Immutable } public TreeNode getParent() { return new WikiTreeNode(wikiNode.getParent()); } public void setParent(TreeNode treeNode) { // Immutable } } }
If you render #{directoryTree} with <rich:tree>, you get the C:/ ROOT shown - after all that is what is returned from this factory. There doesn't seem to be a way to hide the ROOT node. That wouldn't be really bad, what is bad is that you get a NullPointerException when you try to collapse the ROOT node. The rest of the tree seems to work fine (which is better than what I ever got in Icefaces or Oracle ADF after 2 hours of work).
You should also as soon as possible extend the Tree documentation with an example for selection - nobody cares about drag and drop, people want to select a node first. Also, the word "cashing" is really spelled "caching".
Please put this in an appropriate JIRA entry.
Thanks