DefaultNestedTree,正如它的描述,解决90%使用nestedtree的场景。先看3个模板,wicket的模板直观地展示了组件之间的关系。
NestedTree.html
<wicket:panel xmlns:wicket="http://wicket.apache.org"> <div wicket:id="subtree">[subtree]</div> </wicket:panel>
Node.html
<wicket:panel xmlns:wicket="http://wicket.apache.org"> <a wicket:id="junction"> </a> <span wicket:id="content" class="tree-content">[content]</span> </wicket:panel>
SubTree.html
<wicket:panel xmlns:wicket="http://wicket.apache.org"> <div wicket:id="branches"> <div wicket:id="node" class="tree-node">[node]</div> <div wicket:id="subtree" class="tree-subtree">[subtree]</div> </div> </wicket:panel>
把牵涉到的组件列出来:
1、subtree-》SubTree
2、junction-》
3、content-》
4、branches-》
5、node-》Node
上面有部分id没有写出对应的Class,需要分析源代码才能填上,大多数时候我们深入分析,是为了选择合适的点,实现对组件的个性化的需求。
从NestedTree可以看到,添加了一个subtree。看看subtree做了什么?
可以看到branches对应的是RefreshingView(一个repeater组件),
RefreshingView<T> branches = new RefreshingView<T>("branches") { private static final long serialVersionUID = 1L; @Override protected Iterator<IModel<T>> getItemModels() { return new ModelIterator(); } @Override protected Item<T> newItem(String id, int index, IModel<T> model) { return newBranchItem(id, index, model); } @Override protected void populateItem(Item<T> item) { IModel<T> model = item.getModel(); Component node = tree.newNodeComponent("node", model); item.add(node); item.add(tree.newSubtree("subtree", model)); } }; branches.setItemReuseStrategy(new IItemReuseStrategy() { private static final long serialVersionUID = 1L; @Override public <S> Iterator<Item<S>> getItems(IItemFactory<S> factory, Iterator<IModel<S>> newModels, Iterator<Item<S>> existingItems) { return tree.getItemReuseStrategy().getItems(factory, newModels, existingItems); } }); add(branches);
在populateItem方法中,呼叫了tree的两个方法,同时在方法的末端,产生了递归的调用。
请看:tree.newNodeComponent("node", model)
public Component newNodeComponent(String id, final IModel<T> model) { return new Node<T>(id, this, model) { private static final long serialVersionUID = 1L; @Override protected Component createContent(String id, IModel<T> model) { return AbstractTree.this.newContentComponent(id, model); } }; }
最后变成了呼叫newContentComponent,DefaultNestedTree正是复写了这个方法,这是一个可以个性化的点。如果要更大程度的个性化,那就直接复写newNodeComponent方法。
看看DefaultNestedTree 的newContentComponent方法:
@Override protected Component newContentComponent(String id, IModel<T> node) { return new Folder<T>(id, this, node); }
再来看看folder,既然是组件,只要查看它的类链条中的add,就可以找对模板中对应的子组件。果然在StyledLinkLabel中找到了:
protected Component newLabelComponent(String id, IModel<T> model) { return new Label(id, newLabelModel(model)); } /** * Create the model for the label, defaults to the model itself. * * @param model * @return wrapping model */ protected IModel<?> newLabelModel(IModel<T> model) { return model; }
可以继承Folder,然后复写上面的其中一个方法,就可以修改label的方法,比如userGroup树,默认标签显示的是对象xx.xxx.UserGroup@55373,如果将newLabelModel改成,return model.getName(),就可以了。