Hi,
I'm using an extendet wicket tree with an own tree model. I want to insert
child into the tree and want to update the tree with Ajax, but nothing
worked for me. I tried invalidateAll() and updateTree(). What can i do to
insert the childs with Ajax?
Kai
/* *************************************
* code snippet: create and setup tree
************************************ */
TreeModel treeModel = null;
HwSubCategoryEnvironmentTree root = hwSubCategoryEnvironmentTreeSer
vice.loadPathToRoot(this.hwSubCategoryEnvironmentTree).get(0);
if (root != null) {
NestedSetNodeWrapper<HwSubCategoryEnvironmentTree> node =
hwSubCategoryEnvironmentTreeService.loadSubtree(root);
treeModel = node.convertToTreeModel();
}
tree = new IconTree("hwSubCategoryEnvironmentTree", treeModel) {
private static final long serialVersionUID = -4004667936606595008L;
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode
node)
{
...
}
};
tree.setRootLess(false);
ResourceReference icon = new ResourceReference(IconTree.class,
"square_orange.png");
tree.setFolderClosedResource(icon);
tree.setFolderOpenResource(icon);
tree.setItemResource(new ResourceReference(IconTree.class,
"square_orange.png"));
selectNode(this.hwSubCategoryEnvironmentTree);
tree.setOutputMarkupId(true);
// add tree
add(tree);
/* *************************************
* code snippet: update tree
************************************ */
AjaxSubmitLink saveButton = new AjaxSubmitLink("saveRootButton"){
...
protected void onSubmit(AjaxRequestTarget target, Form form) {
...
hwSubCategoryEnvironmentTreeService.save(hwSubCategoryEnvironmentTree);
tree.invalidateAll();
target.addComponent(tree);
}
}
/* *************************************
* IconTree class
************************************ */
package com.nsn.forlabs.front.components;
import java.io.Serializable;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import org.apache.wicket.Component;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.extensions.markup.html.tree.Tree;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.tree.ITreeStateListener;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.lang.PropertyResolver;
/**
* Subclass of [EMAIL PROTECTED] wicket.extensions.markup.html.tree.Tree}
* <ol>
* <li>to tweak its appearance</li>
* <li>to allow for easy setting and retrieval of selected nodes</li>
* <li>to override a TooltipExtractor</li>
* <li>to provide for event callbacks on changes to the tree</li>
* </ol>
* @author Marco Holmer
*/
@SuppressWarnings("deprecation")
public class IconTree extends Tree implements Serializable
{
private static final long serialVersionUID = 0L;
/** Reference to the icon of open tree folder */
private static final ResourceReference FOLDER_OPEN = new
ResourceReference(
IconTree.class, "res/node-open.gif");
/** Reference to the icon of closed tree folder */
private static final ResourceReference FOLDER_CLOSED = new
ResourceReference(
IconTree.class, "res/node-closed.gif");
/** Reference to the icon of tree item (not a folder) */
private static final ResourceReference ITEM = new ResourceReference(
IconTree.class, "res/item.gif");
private TreeStateCallback treeStateCallback;
private static final Comparator NODE_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
return (o1.equals(o2))? 0 : 1;
}
};
private static final TooltipExtractor TOOLTIP_EXTRACTOR = new
DefaultTooltipExtractor();
private ResourceReference itemResource = ITEM;
private ResourceReference folderClosedResource = FOLDER_CLOSED;
private ResourceReference folderOpenResource = FOLDER_OPEN;
private boolean showIcons = true;
private TooltipExtractor tooltipExtractor = TOOLTIP_EXTRACTOR;
/**
* Tree constructor.
* @param id The component id
*/
public IconTree(String id)
{
super(id);
init();
}
/**
* Tree constructor.
* @param id The component id
* @param model The tree model
*/
public IconTree(String id, IModel model)
{
super(id, model);
init();
}
/**
* Tree constructor.
* @param id The component id
* @param treeModel The tree model
*/
public IconTree(String id, TreeModel treeModel)
{
super(id, treeModel);
init();
}
private void init() {
//getTreeState().addTreeStateListener(new
TreeStateListenerToTreeStateEventConverter());
}
protected void populateTreeItem(WebMarkupContainer item, int level)
{
super.populateTreeItem(item, level);
final TreeNode node = (TreeNode)item.getModelObject();
Iterator iterator = item.iterator();
Component component = null;
while (iterator.hasNext())
{
component = (Component)iterator.next();
if (component instanceof Link && component.getId().equals("nodeLink"))
{
component.add(new AbstractBehavior()
{
private static final long serialVersionUID = 1L;
public void onComponentTag(Component component, ComponentTag tag)
{
super.onComponentTag(component, tag);
String tooltip = getTooltipText(node);
if (tooltip != null && tooltip.trim().length() > 0) {
tag.put("title", tooltip);
tag.put("showtooltip", "true");
}
}
});
}
}
}
/**
* Sets the enabeled state of all sub components.
* @param enabled
*/
@SuppressWarnings("unchecked")
public void setChildrenEnabledState(final boolean enabled) {
this.visitChildren(new IVisitor() {
public Object component(Component component) {
component.setEnabled(enabled);
return component;
}
});
}
/**
* Extracts the tooltip text for a given node. If the node is an instance
of
* DefaultMutableTreeNode, the nodes user object is extracted and the
given
* tooltipExtractor callback is called.
* @param node the given tree node
* @param tooltipExtractor a supplied TooltipExtractor implementation for
customization.
* @return a tooltip or an empty string.
*/
protected String getTooltipText(TreeNode node) {
if (node instanceof DefaultMutableTreeNode) {
Object obj = ((DefaultMutableTreeNode)node).getUserObject();
return getTooltipExtractor().getTooltip(obj);
}
return "";
}
/**
* Returns the currently set TooltipExtractor implementation.
* The default implementation returns a TooltipExtractor that tries to
find a description property.
* A callback pattern is not applicable here as the TooltipExtractor ist
already needed in the constructor.
* @return the [EMAIL PROTECTED] TooltipExtractor} to use.
*/
public TooltipExtractor getTooltipExtractor() {
return tooltipExtractor;
}
public void setTooltipExtractor(TooltipExtractor tooltipExtractor) {
this.tooltipExtractor = tooltipExtractor;
}
/**
* Selects a node based on a Comparator implementation. All nodes of the
tree are searched until the given
* Comparator yields '0' (that is zero). The search is stopped and the
node selected.
* @param nodeObjToSelect the given object to search the tree for (user
object of a DefaultMutableTreeNode)
* @param comparator the comparator to use for the search
*/
@SuppressWarnings("unchecked")
public void selectNode(Object nodeObjToSelect, Comparator comparator) {
Object modelObj = this.getModel().getObject();
if (modelObj instanceof TreeModel) {
TreeModel treeModel = (TreeModel)modelObj;
if (treeModel.getRoot() instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode root =
(DefaultMutableTreeNode)treeModel.getRoot();
Enumeration allNodes = root.depthFirstEnumeration();
DefaultMutableTreeNode node;
Object obj;
while(allNodes.hasMoreElements()) {
obj = allNodes.nextElement();
if (obj instanceof DefaultMutableTreeNode) {
node = (DefaultMutableTreeNode)obj;
if (comparator.compare(nodeObjToSelect, node.getUserObject()) ==
0) {
this.getTreeState().selectNode(node, true);
return;
}
}
}
}
}
}
/**
* Selects a node with a user object that equals the given object.
* The default implementation compares using the equals implementation.
* @param selectedObj
*/
public void selectNode(Object selectedObj) {
selectNode(selectedObj, NODE_COMPARATOR);
}
/**
* Helper method that returns the selected DefaultMutableTreeNode.
*/
public DefaultMutableTreeNode getSelectedNode() {
Object selected = null;
try {
selected = this.getTreeState().getSelectedNodes().iterator().next();
} catch (NoSuchElementException nseEx) { }
return (selected instanceof DefaultMutableTreeNode)?
(DefaultMutableTreeNode)selected : null;
}
public void setShowIcons(boolean showIcons) {
this.showIcons = showIcons;
}
public boolean getShowIcons() {
return showIcons;
}
protected ResourceReference getItem() {
return itemResource;
}
public void setItemResource(ResourceReference res) {
this.itemResource = res;
}
protected ResourceReference getFolderClosed() {
return folderClosedResource;
}
public void setFolderClosedResource(ResourceReference res) {
this.folderClosedResource = res;
}
protected ResourceReference getFolderOpen() {
return folderOpenResource;
}
public void setFolderOpenResource(ResourceReference res) {
this.folderOpenResource = res;
}
/**
* For simplicity there is no listener approach but rather a single
callback implementation.
*/
public void setTreeStateCallback(TreeStateCallback callback) {
this.treeStateCallback = callback;
}
protected void fireTreeEvent(TreeStateEvent event) {
if (treeStateCallback != null)
treeStateCallback.onTreeStateEvent(event);
}
/**
* A callback interface to generate tooltip texts for the user object of
tree nodes.
*/
public interface TooltipExtractor {
String getTooltip(Object obj);
}
/**
* A default implementation of of the TooltipExtractor interface that
tries to
* extract the tooltip text from a description property of the underlying
object.
*/
public static class DefaultTooltipExtractor implements TooltipExtractor,
Serializable {
private static final long serialVersionUID = 0L;
public String getTooltip(Object obj) {
Object description = null;
try {
description = PropertyResolver.getValue("description", obj);
} catch (Throwable t) { }
return (description != null)? description.toString() : "";
}
}
/**
* Implement to get notified of TreeStateEvents.
*/
public interface TreeStateCallback extends Serializable {
public void onTreeStateEvent(TreeStateEvent event);
}
/**
* Differentiates the TreeStateEvents with a certain type.
*/
public enum TreeStateEventType {
ALL_NODES_COLLAPSED, ALL_NODES_EXPANDED, NODE_COLLAPSE, NODE_EXPAND,
NODE_SELECT, NODE_UNSELECT
}
/**
* TreeStateEvents are generated on any change to the underlying tree
model of the IconTree.
*/
public class TreeStateEvent implements Serializable {
private static final long serialVersionUID = 0L;
TreeStateEventType event;
TreeNode node;
public TreeStateEvent(TreeStateEventType event, TreeNode node) {
this.event = event;
this.node = node;
}
}
/**
* Execute some javascript in case of AJAX links that fixes the mess left
behind by the DOM changes.
*/
@Override
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node)
{
if (target != null) {
target.appendJavascript("sweetTitles.tipOut(); sweetTitles.init();");
}
}
/**
* Dispatch TreeState changes to a simpler callback event ([EMAIL PROTECTED]
TreeStateEvent}).
*/
private class TreeStateListenerToTreeStateEventConverter implements
ITreeStateListener, Serializable {
private static final long serialVersionUID = 0L;
public void allNodesCollapsed() {
fireTreeEvent(new
TreeStateEvent(TreeStateEventType.ALL_NODES_COLLAPSED, null));
}
public void allNodesExpanded() {
fireTreeEvent(new
TreeStateEvent(TreeStateEventType.ALL_NODES_EXPANDED, null));
}
public void nodeCollapsed(TreeNode node) {
fireTreeEvent(new TreeStateEvent(TreeStateEventType.NODE_COLLAPSE,
node));
}
public void nodeExpanded(TreeNode node) {
fireTreeEvent(new
TreeStateEvent(TreeStateEventType.ALL_NODES_EXPANDED, node));
}
public void nodeSelected(TreeNode node) {
fireTreeEvent(new TreeStateEvent(TreeStateEventType.NODE_SELECT,
node));
}
public void nodeUnselected(TreeNode node) {
fireTreeEvent(new TreeStateEvent(TreeStateEventType.NODE_UNSELECT,
node));
}
}
}