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));
    }
  }

}

Reply via email to