Tree Browse

Here we demonstrate Tapestry's Tree component.
Clear Expansions

For an example of a tree with more capabilities, see the example Tree From Database, With Zones.
For an example of a file system browser, try the Tree section of Java Magic: Tapestry 5.3+ : New Features.

References: Tree, TreeModel, DefaultTreeModel, TreeModelAdapter, ValueEncoder, @InjectComponent.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<!-- We need a doctype to allow us to use special characters like &nbsp; 
     We use a "strict" DTD to make IE follow the alignment rules. -->
<!-- Based on org.apache.tapestry5.integration.app1.pages.TreeDemo -->

<html xmlns:t="">
    <link rel="stylesheet" type="text/css" href="${asset:css/examples/examples.css}"/>
<body class="container">
    <h3>Tree Browse</h3>
    Here we demonstrate Tapestry's Tree component.
    <div class="eg">
        <t:eventlink event="clearExpansions">Clear Expansions</t:eventlink><br/><br/>
        <t:tree t:id="tree" model="stuffModel"/><br/>
        <t:pagelink page="examples/component/TreeBrowse">Refresh</t:pagelink>
    For an example of a tree with more capabilities, see the example Tree From Database, With Zones.<br/>
    For an example of a file system browser, try the Tree section of 
    <a href="">Java Magic: Tapestry 5.3+ : New Features</a>.<br/><br/>
    <a href="">Tree</a>, 
    <a href="">TreeModel</a>, 
    <a href="">DefaultTreeModel</a>, 
    <a href="">TreeModelAdapter</a>, 
    <a href="">ValueEncoder</a>, 
    <a href="">@InjectComponent</a>.<br/><br/> 

    <t:eventlink event="Home">Home</t:eventlink><br/><br/>

        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/component/TreeBrowse.tml"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/component/"/>
        <t:sourcecodetab src="/web/src/main/resources/META-INF/assets/css/examples/examples.css"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/models/examples/tree/"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/models/examples/tree/"/>

// Based on org.apache.tapestry5.integration.app1.pages.TreeDemo .

package jumpstart.web.pages.examples.component;

import jumpstart.web.models.examples.tree.Stuff;
import jumpstart.web.models.examples.tree.StuffTreeModelAdapter;
import jumpstart.web.pages.Index;

import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.corelib.components.Tree;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.tree.DefaultTreeModel;
import org.apache.tapestry5.tree.TreeModel;

public class TreeBrowse {

    // Screen fields
    private TreeModel<Stuff> stuffModel;

    // Generally useful bits and pieces

    private Tree tree;

    private ComponentResources componentResources;

    // The code

    void onClearExpansions() {

    // Getters and setters
    public TreeModel<Stuff> getStuffModel() {

        if (stuffModel == null) {
            ValueEncoder<Stuff> stuffEncoder = new ValueEncoder<Stuff>() {

                public String toClient(Stuff stuff) {
                    return stuff.uuid;

                public Stuff toValue(String uuid) {
                    return Stuff.ROOT.searchSubTree(uuid);

            stuffModel = new DefaultTreeModel<Stuff>(stuffEncoder, new StuffTreeModelAdapter(), Stuff.ROOT.children);
        return stuffModel;

    Object onHome() {
        return Index.class;

.eg {
                margin: 20px 0;
                padding: 14px;
                border: 1px solid #ddd;
                border-radius: 6px;
                -webkit-border-radius: 6px;
                -mox-border-radius: 6px;

// Based on org.apache.tapestry5.integration.app1.pages.TreeDemo

package jumpstart.web.models.examples.tree;

import java.util.List;

import org.apache.tapestry5.tree.TreeModelAdapter;

public class StuffTreeModelAdapter implements TreeModelAdapter<Stuff> {

    public boolean isLeaf(Stuff stuff) {
        return !hasChildren(stuff);

    public boolean hasChildren(Stuff stuff) {
        return stuff.children != null && !stuff.children.isEmpty();

    public List<Stuff> getChildren(Stuff stuff) {
        return stuff.children;

    public String getLabel(Stuff stuff) {


// Based on org.apache.tapestry5.integration.app1.pages.TreeDemo

package jumpstart.web.models.examples.tree;

import java.util.List;
import java.util.UUID;

import org.apache.tapestry5.ioc.internal.util.CollectionFactory;

public class Stuff {

    public static final Stuff ROOT = new Stuff("<root>");

    static {
        ROOT.addChild(new Stuff("Pets").addChildrenNamed("Oscar", "Gromit", "Max", "Roger", "Cooper"));

        ROOT.addChild(new Stuff("Games").addChild(
                new Stuff("Board Games").addChildrenNamed("Settlers of Catan", "Agricola", "Ra", "Risk", "Dvonn"))
                .addChild(new Stuff("Card Games").addChildrenNamed("Magic the Gathering", "Dominion", "Mu")));

        Stuff numbers = new Stuff("Numbers");
        for (int i = 0; i < 10000; i++) {
            numbers.addChild(new Stuff(Integer.toString(i)));

    public final String uuid = UUID.randomUUID().toString();
    public final String name;
    public List<Stuff> children;

    public Stuff(String name) { = name;

    public Stuff addChild(Stuff child) {
        if (children == null) {
            children = CollectionFactory.newList();


        return this;

    public Stuff addChildrenNamed(String... names) {
        for (String name : names) {
            addChild(new Stuff(name));

        return this;

    public Stuff searchSubTree(String uuid) {

        if (this.uuid.equals(uuid)) {
            return this;

        for (Stuff child : children) {
            Stuff match = child.searchSubTree(uuid);

            if (match != null) {
                return match;

        return null;