Wicket の tree を学ぶ(1)

Wicket tree のデモを見て学びたく読んでみた。
デモ用に書かれているので、これを実践で使うのにどうすれば良いか苦労する。

f:id:posturan:20160313174155j:plain


treeコンポーネントを使用するのに、org.apache.wicket.model.IDetachable として実装するのが鍵みたいだ。
デモでは、org.apache.wicket.examples.tree.content.Content
というのが作ってあってこれが、以下の様に抽象メソッドを宣言してる。

public abstract Component newContentComponent(String id, AbstractTree<Foo> tree,
IModel<Foo> model);

これでは、Foo オブジェクト依存で実用向きではない。
簡単なことで、総称型にして、名前も Content ではあんまりなので、以下のようにする。

import org.apache.wicket.Component;
import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
import org.apache.wicket.model.IDetachable;
import org.apache.wicket.model.IModel;
/**
 * TreeContent
 */

public abstract class TreeContent<T> implements IDetachable{

   public abstract Component newContentComponent(String id, AbstractTree<T> tree, IModel<T> model);

   @Override
   public void detach(){
   }

}

Wicket のデモを参考に、以下のようなサンプルを作ることができる。

public class SamplePage extends WebPage{
   Logger logger = LoggerFactory.getLogger(this.getClass());

   NestedTree<Foo> tree;
   TreeContent<Foo> content;

   public BasicTreePage(){

      tree = new NestedTree<Foo>("tree", new FooProvider(), new FooExpansionModel()){
         @Override
         protected Component newContentComponent(String _id, IModel<Foo> _model){
            return BasicTreePage.this.newContentComponent(_id, _model);
         }
      };
      // Windowsデザインのテーマを使用するように設定
      tree.add(new WindowsTheme());

      content = new TreeContent<Foo>(){
         @Override
         public Component newContentComponent(String id, AbstractTree<Foo> _tree, IModel<Foo> model) {

            return new Folder<Foo>(id, tree, model){
               @Override
               protected MarkupContainer newLinkComponent(String _id, final IModel<Foo> _model){
                  Foo foo = _model.getObject();
                  if (tree.getProvider().hasChildren(foo)){
                     // ツリー node をクリックした時
                     return super.newLinkComponent(_id, _model);
                  }
                  // ツリー leaf をクリックした時の動作
                  return new AjaxLink<Foo>(_id, _model){
                     @Override
                     public void onClick(AjaxRequestTarget target){
                        logger.debug("# click object = " + _model.getObject().id );
                     }
                  };
               }
            };
         }
      };
      
      add(tree);

      add(new Link<Void>("expandAll"){
         @Override
         public void onClick(){
            FooExpansion.get().expandAll();

         }
      });
      add(new Link<Void>("collapseAll"){
         @Override
         public void onClick(){
            FooExpansion.get().collapseAll();
         }
      });
   }
   protected Component newContentComponent(String id, IModel<Foo> model){
      return content.newContentComponent(id, tree, model);
   }
   /* expandAll と collapseAll を動作させるために状態を持つ FooExpansion を返す */
   private class FooExpansionModel extends AbstractReadOnlyModel<Set<Foo>>{
      @Override
      public Set<Foo> getObject(){
         return FooExpansion.get();
      }
   }

}