001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.extensions.markup.html.repeater.tree.nested; 018 019import java.util.Iterator; 020 021import org.apache.wicket.Component; 022import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree.State; 023import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider; 024import org.apache.wicket.extensions.markup.html.repeater.tree.NestedTree; 025import org.apache.wicket.markup.html.panel.Panel; 026import org.apache.wicket.markup.repeater.IItemFactory; 027import org.apache.wicket.markup.repeater.IItemReuseStrategy; 028import org.apache.wicket.markup.repeater.Item; 029import org.apache.wicket.markup.repeater.RefreshingView; 030import org.apache.wicket.model.IModel; 031 032/** 033 * A subtree handles all children of a single node (or the root nodes if a <code>null</code> node 034 * was given to the constructor). 035 * 036 * @see ITreeProvider#getChildren(Object) 037 * @see ITreeProvider#getRoots() 038 * 039 * @author svenmeier 040 */ 041public class Subtree<T> extends Panel 042{ 043 044 private static final long serialVersionUID = 1L; 045 046 private NestedTree<T> tree; 047 048 /** 049 * Create a subtree for the children of the node contained in the given model or the root nodes 050 * if the model contains <code>null</code>. 051 * 052 * @param id 053 * component id 054 * @param tree 055 * the containing tree 056 * @param model 057 */ 058 public Subtree(String id, final NestedTree<T> tree, final IModel<T> model) 059 { 060 super(id, model); 061 062 if (tree == null) 063 { 064 throw new IllegalArgumentException("argument [tree] cannot be null"); 065 } 066 this.tree = tree; 067 068 RefreshingView<T> branches = new RefreshingView<T>("branches") 069 { 070 private static final long serialVersionUID = 1L; 071 072 @Override 073 protected Iterator<IModel<T>> getItemModels() 074 { 075 return new ModelIterator(); 076 } 077 078 @Override 079 protected Item<T> newItem(String id, int index, IModel<T> model) 080 { 081 return newBranchItem(id, index, model); 082 } 083 084 @Override 085 protected void populateItem(Item<T> item) 086 { 087 IModel<T> model = item.getModel(); 088 089 Component node = tree.newNodeComponent("node", model); 090 item.add(node); 091 092 item.add(tree.newSubtree("subtree", model)); 093 } 094 }; 095 branches.setItemReuseStrategy(new IItemReuseStrategy() 096 { 097 private static final long serialVersionUID = 1L; 098 099 @Override 100 public <S> Iterator<Item<S>> getItems(IItemFactory<S> factory, 101 Iterator<IModel<S>> newModels, Iterator<Item<S>> existingItems) 102 { 103 return tree.getItemReuseStrategy().getItems(factory, newModels, existingItems); 104 } 105 }); 106 add(branches); 107 } 108 109 @SuppressWarnings("unchecked") 110 public IModel<T> getModel() 111 { 112 return (IModel<T>)getDefaultModel(); 113 } 114 115 public T getModelObject() 116 { 117 return getModel().getObject(); 118 } 119 120 protected BranchItem<T> newBranchItem(String id, int index, IModel<T> model) 121 { 122 return new BranchItem<>(id, index, model); 123 } 124 125 @Override 126 public boolean isVisible() 127 { 128 T t = getModel().getObject(); 129 if (t == null) 130 { 131 // roots always visible 132 return true; 133 } 134 else 135 { 136 return tree.getState(t) == State.EXPANDED; 137 } 138 } 139 140 private final class ModelIterator implements Iterator<IModel<T>> 141 { 142 private Iterator<? extends T> children; 143 144 public ModelIterator() 145 { 146 T t = getModel().getObject(); 147 if (t == null) 148 { 149 children = tree.getProvider().getRoots(); 150 } 151 else 152 { 153 children = tree.getProvider().getChildren(t); 154 } 155 } 156 157 @Override 158 public void remove() 159 { 160 throw new UnsupportedOperationException(); 161 } 162 163 @Override 164 public boolean hasNext() 165 { 166 return children.hasNext(); 167 } 168 169 @Override 170 public IModel<T> next() 171 { 172 return tree.getProvider().model(children.next()); 173 } 174 } 175}