Remove type parameter on TreeView and use TreeModel as a source of ListModels.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7604 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/AbstractTreeNodeFactory.java b/bikeshed/src/com/google/gwt/sample/tree/client/AbstractTreeNodeFactory.java
new file mode 100644
index 0000000..9e13f74
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/AbstractTreeNodeFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.tree.client;
+
+import com.google.gwt.cells.client.Cell;
+import com.google.gwt.list.shared.ListModel;
+
+/**
+ * A factory for generating tree nodes.
+ * 
+ * @param <C> the type of children in the tree node.
+ */
+public abstract class AbstractTreeNodeFactory<C> implements TreeNodeFactory<C> {
+
+  private ListModel<C> listModel;
+  private Cell<C> cell;
+
+  /**
+   * Construct a new {@link AbstractTreeNodeFactory}.
+   * 
+   * @param listModel the {@link ListModel} used to generate child values
+   * @param cell the {@link Cell} used to render children
+   */
+  public AbstractTreeNodeFactory(ListModel<C> listModel, Cell<C> cell) {
+    this.listModel = listModel;
+    this.cell = cell;
+  }
+
+  /**
+   * Get the {@link Cell} used to render child nodes.
+   * 
+   * @return the cell
+   */
+  public Cell<C> getCell() {
+    return cell;
+  }
+
+  /**
+   * Get the {@link ListModel} used to retrieve child node values.
+   * 
+   * @return the list model
+   */
+  public ListModel<C> getListModel() {
+    return listModel;
+  }
+}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/DefaultTreeNodeFactory.java b/bikeshed/src/com/google/gwt/sample/tree/client/DefaultTreeNodeFactory.java
new file mode 100644
index 0000000..a5b7bb7
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/DefaultTreeNodeFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.tree.client;
+
+import com.google.gwt.cells.client.Cell;
+import com.google.gwt.list.shared.ListModel;
+
+/**
+ * Default implementation of a {@link TreeNodeFactory}.
+ * 
+ * @param <C> the type of children in the tree node.
+ */
+public class DefaultTreeNodeFactory<C> extends AbstractTreeNodeFactory<C> {
+
+  private TreeModel treeModel;
+
+  /**
+   * Construct a new {@link DefaultTreeNodeFactory}.
+   * 
+   * @param listModel the {@link ListModel} used to generate child values
+   * @param cell the {@link Cell} used to render children
+   * @param treeModel the {@link TreeModel} used to generate factories
+   */
+  public DefaultTreeNodeFactory(ListModel<C> listModel, Cell<C> cell,
+      TreeModel treeModel) {
+    super(listModel, cell);
+    this.treeModel = treeModel;
+  }
+
+  public TreeNodeFactory<?> createChildFactory(C value) {
+    return treeModel.createTreeNodeFactory(value);
+  }
+}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/MyTreeModel.java b/bikeshed/src/com/google/gwt/sample/tree/client/MyTreeModel.java
new file mode 100644
index 0000000..0c6777a
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/MyTreeModel.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.tree.client;
+
+import com.google.gwt.cells.client.Cell;
+import com.google.gwt.cells.client.TextCell;
+import com.google.gwt.list.shared.AsyncListModel;
+import com.google.gwt.list.shared.ListModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A factory for generating {@link AbstractTreeNodeFactory} based on the value
+ * type.
+ */
+public class MyTreeModel implements TreeModel {
+
+  private static final int FANOUT = 5;
+
+  /**
+   * The cell used to render integers.
+   */
+  private static final Cell<Integer> INTEGER_CELL = new Cell<Integer>() {
+    @Override
+    public void render(Integer value, StringBuilder sb) {
+      sb.append(value);
+    }
+  };
+
+  /**
+   * The cell used to render strings.
+   */
+  private static final Cell<String> STRING_CELL = new TextCell();
+
+  /**
+   * A list of strings.
+   */
+  private static class StringListModel extends AsyncListModel<String> {
+
+    public StringListModel(final String value, final String delim) {
+      super(new DataSource<String>() {
+        public void requestData(AsyncListModel<String> listModel) {
+          listModel.updateDataSize(FANOUT, true);
+          List<String> values = new ArrayList<String>();
+          for (int i = 0; i < FANOUT; i++) {
+            values.add(value + delim + i);
+          }
+          listModel.updateViewData(0, FANOUT, values);
+        }
+      });
+    }
+  }
+
+  /**
+   * A list of integers.
+   */
+  private static class IntegerListModel extends AsyncListModel<Integer> {
+
+    public IntegerListModel() {
+      super(new DataSource<Integer>() {
+        public void requestData(AsyncListModel<Integer> listModel) {
+          listModel.updateDataSize(FANOUT, true);
+          List<Integer> values = new ArrayList<Integer>();
+          for (int i = 0; i < FANOUT; i++) {
+            values.add(i);
+          }
+          listModel.updateViewData(0, FANOUT, values);
+        }
+      });
+    }
+  }
+
+  public TreeNodeFactory<?> createTreeNodeFactory(Object value) {
+    if (value instanceof String) {
+      return createTreeNodeFactoryHelper((String) value);
+    } else if (value instanceof Integer) {
+      return createTreeNodeFactoryHelper((Integer) value);
+    }
+
+    // Unhandled type.
+    String type = value.getClass().getName();
+    throw new IllegalArgumentException("Unsupported object type: " + type);
+  }
+
+  private TreeNodeFactory<?> createTreeNodeFactoryHelper(final Integer value) {
+    ListModel<String> listModel = new StringListModel(value.toString(), ".");
+    return new DefaultTreeNodeFactory<String>(listModel, STRING_CELL, this);
+  }
+
+  private TreeNodeFactory<?> createTreeNodeFactoryHelper(final String value) {
+    if (value.endsWith("2")) {
+      ListModel<String> listModel = new StringListModel(value.toString(), "-");
+      return new DefaultTreeNodeFactory<String>(listModel, STRING_CELL, this);
+    } else {
+      ListModel<Integer> listModel = new IntegerListModel();
+      return new DefaultTreeNodeFactory<Integer>(listModel, INTEGER_CELL, this);
+    }
+  }
+}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/SimpleTreeNodeView.java b/bikeshed/src/com/google/gwt/sample/tree/client/SimpleTreeNodeView.java
deleted file mode 100644
index bb4803f..0000000
--- a/bikeshed/src/com/google/gwt/sample/tree/client/SimpleTreeNodeView.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.tree.client;
-
-import com.google.gwt.cells.client.Cell;
-import com.google.gwt.sample.tree.shared.SimpleTreeNodeModel;
-
-/**
- * A tree view that uses a single data type for all of its nodes.
- * 
- * @param <T> the data type of each tree node.
- */
-public class SimpleTreeNodeView<T> extends TreeNodeView<T,T> {
-
-  private Cell<T> cell;
-  private SimpleTreeNodeModel<T> model;
-
-  public SimpleTreeNodeView(T value, final SimpleTreeNodeModel<T> model, Cell<T> cell) {
-    super(value, model, cell);
-    this.model = model;
-    this.cell = cell;
-  }
-
-  @Override
-  protected TreeNodeView<T, T> createChildView(T value) {
-    return new SimpleTreeNodeView<T>(value, model.createChildModel(value), cell);
-  }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java b/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java
index 40ab6b6..889efd2 100644
--- a/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java
@@ -15,64 +15,16 @@
  */
 package com.google.gwt.sample.tree.client;
 
-import com.google.gwt.cells.client.TextCell;
 import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.list.shared.AsyncListModel;
-import com.google.gwt.list.shared.ListModel;
-import com.google.gwt.list.shared.AsyncListModel.DataSource;
-import com.google.gwt.sample.tree.shared.SimpleTreeNodeModel;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Tree;
-
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * A demo of the asynchronous Tree model.
  */
 public class TreeEntryPoint implements EntryPoint {
 
-  static class StringTreeNodeModel extends SimpleTreeNodeModel<String> {
-    private static final int FANOUT = 5;
-    private String nodeData;
-
-    StringTreeNodeModel(final String nodeData) {
-      super();
-      this.nodeData = nodeData;
-    }
-
-    @Override
-    public StringTreeNodeModel createChildModel(String nodeData) {
-      if (Math.random() < 0.2) {
-        return null;
-      } else {
-        return new StringTreeNodeModel(nodeData);
-      }
-    }
-
-    @Override
-    protected ListModel<String> createListModel() {
-      return new AsyncListModel<String>(new DataSource<String>() {
-        public void requestData(AsyncListModel<String> listModel) {
-          listModel.updateDataSize(FANOUT, true);
-          List<String> values = new ArrayList<String>();
-          for (int i = 0; i < FANOUT; i++) {
-            values.add(nodeData + "." + i);
-          }
-          listModel.updateViewData(0, FANOUT, values);
-        }
-      });
-    }
-  }
-    
   public void onModuleLoad() {
-    Tree tree = new Tree();
-
-    StringTreeNodeModel model = new StringTreeNodeModel("Node 0");
-    SimpleTreeNodeView<String> rootView = new SimpleTreeNodeView<String>("",
-        model, new TextCell());
-    tree.addItem(rootView.getTreeItem());
-
+    TreeView tree = new TreeView(new MyTreeModel(), -1);
     RootPanel.get().add(tree);
   }
 }
diff --git a/bikeshed/src/com/google/gwt/sample/tree/shared/SimpleTreeNodeModel.java b/bikeshed/src/com/google/gwt/sample/tree/client/TreeModel.java
similarity index 63%
rename from bikeshed/src/com/google/gwt/sample/tree/shared/SimpleTreeNodeModel.java
rename to bikeshed/src/com/google/gwt/sample/tree/client/TreeModel.java
index 2a9869d..329280b 100644
--- a/bikeshed/src/com/google/gwt/sample/tree/shared/SimpleTreeNodeModel.java
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/TreeModel.java
@@ -13,14 +13,19 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.tree.shared;
+package com.google.gwt.sample.tree.client;
 
 /**
- * A model describing a node in a Tree of uniformly typed nodes.
- * 
- * @param <T> the data type contained in all nodes of the tree.
+ * A model of a tree.
  */
-public abstract class SimpleTreeNodeModel<T> extends TreeNodeModel<T> {
+public interface TreeModel {
 
-  public abstract SimpleTreeNodeModel<T> createChildModel(T value);
+  /**
+   * Create a {@link TreeNodeFactory} that will provide the children of the
+   * given value.
+   * 
+   * @param value the parent value
+   * @return the {@link TreeNodeFactory}
+   */
+  TreeNodeFactory<?> createTreeNodeFactory(Object value);
 }
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeFactory.java b/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeFactory.java
new file mode 100644
index 0000000..3f9e614
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.tree.client;
+
+import com.google.gwt.cells.client.Cell;
+import com.google.gwt.list.shared.ListModel;
+
+/**
+ * A factory for generating tree nodes.
+ * 
+ * @param <C> the type of children in the tree node.
+ */
+public interface TreeNodeFactory<C> {
+
+  /**
+   * Create the {@link AbstractTreeNodeFactory} for a given child value that
+   * will generate grand-children.
+   * 
+   * @param value the value of the child
+   * @return the {@link AbstractTreeNodeFactory} that will generate
+   *         grand-children
+   */
+  TreeNodeFactory<?> createChildFactory(C value);
+
+  /**
+   * Get the {@link Cell} used to render child nodes.
+   * 
+   * @return the cell
+   */
+  Cell<C> getCell();
+
+  /**
+   * Get the {@link ListModel} used to retrieve child node values.
+   * 
+   * @return the list model
+   */
+  ListModel<C> getListModel();
+}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java b/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java
index 4dd104d..eb44264 100644
--- a/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java
@@ -16,61 +16,88 @@
 package com.google.gwt.sample.tree.client;
 
 import com.google.gwt.cells.client.Cell;
+import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.list.shared.ListEvent;
 import com.google.gwt.list.shared.ListHandler;
+import com.google.gwt.list.shared.ListModel;
 import com.google.gwt.list.shared.ListRegistration;
 import com.google.gwt.list.shared.SizeChangeEvent;
-import com.google.gwt.sample.tree.shared.TreeNodeModel;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.TreeItem;
 
 /**
- * A tree view.
- * 
- * @param <T> the data type of each tree node.
+ * A view of a tree node.
  */
-public abstract class TreeNodeView<T,C> extends Composite {
-  
-  private TreeItem treeItem;
+public class TreeNodeView extends Composite {
+
+  /**
+   * A {@link TreeItem} that fires value change events when the state changes.
+   */
+  public static class ExtraTreeItem extends TreeItem implements
+      HasValueChangeHandlers<Boolean> {
+
+    private HandlerManager handlerManager = new HandlerManager(this);
+
+    public ExtraTreeItem(String value) {
+      super(value);
+    }
+
+    public HandlerRegistration addValueChangeHandler(
+        ValueChangeHandler<Boolean> handler) {
+      return handlerManager.addHandler(ValueChangeEvent.getType(), handler);
+    }
+
+    public void fireEvent(GwtEvent<?> event) {
+      handlerManager.fireEvent(event);
+    }
+
+    @Override
+    public void setState(boolean open, boolean fireEvents) {
+      super.setState(open, fireEvents);
+      if (open) {
+        ValueChangeEvent.fire(this, true);
+      } else {
+        ValueChangeEvent.fire(this, false);
+      }
+    }
+  }
+
+  /**
+   * The list registration for the list of children.
+   */
   private ListRegistration listReg;
 
-  @SuppressWarnings("unused")
-  public TreeNodeView(T value, final TreeNodeModel<C> childModel, Cell<C> cell) {
-    this.treeItem = new TreeItem(value.toString()) {
-      @Override
-      public void setState(boolean open, boolean fireEvents) {
-        super.setState(open, fireEvents);
-        if (open) {
-          listReg = childModel.getListModel().addListHandler(new ListHandler<C>() {
-            public void onDataChanged(ListEvent<C> event) {
-              // TODO - handle event start and length
-              treeItem.removeItems();
+  /**
+   * The TreeItem that displays this node.
+   */
+  private ExtraTreeItem treeItem;
 
-              for (C value : event.getValues()) {
-                TreeNodeView<C,?> childView = createChildView(value);
-                treeItem.addItem(childView.treeItem);
-              }
-            }
+  /**
+   * Construct a {@link TreeNodeView}.
+   * 
+   * @param treeItem this nodes view
+   * @param factory the factory used to generate child nodes
+   */
+  public TreeNodeView(ExtraTreeItem treeItem, final TreeNodeFactory<?> factory) {
+    this.treeItem = treeItem;
 
-            public void onSizeChanged(SizeChangeEvent event) {
-              int size = event.getSize();
-              treeItem.removeItems();
-              if (size > 0) {
-                treeItem.addItem(""); // placeholder
-              }
-            }
-          });
-          listReg.setRangeOfInterest(0, 100);
-        } else {
-          if (listReg != null) {
-            listReg.removeHandler();
-            listReg = null;
+    // Force a + icon if this node might have children.
+    if (factory != null) {
+      treeItem.addItem("loading...");
+      treeItem.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
+        public void onValueChange(ValueChangeEvent<Boolean> event) {
+          if (event.getValue()) {
+            onOpen(factory);
+          } else {
+            onClose();
           }
         }
-      }
-    };
-    if (childModel != null) {
-      treeItem.addItem("loading...");
+      });
     }
   }
 
@@ -78,5 +105,51 @@
     return treeItem;
   }
 
-  protected abstract TreeNodeView<C, ?> createChildView(C nodeData);
+  /**
+   * Cleanup when the node is closed.
+   */
+  private void onClose() {
+    if (listReg != null) {
+      listReg.removeHandler();
+      listReg = null;
+    }
+  }
+
+  /**
+   * Setup the node when it is opened.
+   * 
+   * @param factory the factory used to generate child nodes
+   * @param <C> the child data type of the node.
+   */
+  private <C> void onOpen(final TreeNodeFactory<C> factory) {
+    ListModel<C> listModel = factory.getListModel();
+    listReg = listModel.addListHandler(new ListHandler<C>() {
+      public void onDataChanged(ListEvent<C> event) {
+        // TODO - handle event start and length
+        treeItem.removeItems();
+
+        // Add child tree items.
+        Cell<C> cell = factory.getCell();
+        for (C value : event.getValues()) {
+          // TODO(jlabanca): Use one StringBuilder.
+          StringBuilder sb = new StringBuilder();
+          cell.render(value, sb);
+          ExtraTreeItem child = new ExtraTreeItem(sb.toString());
+          treeItem.addItem(child);
+          new TreeNodeView(child, factory.createChildFactory(value));
+        }
+      }
+
+      public void onSizeChanged(SizeChangeEvent event) {
+        // TODO (jlabanca): Handle case when item is over.
+        int size = event.getSize();
+        treeItem.removeItems();
+        if (size > 0) {
+          // Add a placeholder to force a + icon.
+          treeItem.addItem("loading...");
+        }
+      }
+    });
+    listReg.setRangeOfInterest(0, 100);
+  }
 }
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java b/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java
new file mode 100644
index 0000000..240299d
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.tree.client;
+
+import com.google.gwt.sample.tree.client.TreeNodeView.ExtraTreeItem;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Tree;
+
+/**
+ * A view of a tree.
+ */
+public class TreeView extends Composite {
+
+  /**
+   * Construct a new {@link TreeView}.
+   * 
+   * @param treeModel the model that supplies the data
+   * @param rootData the data object that will be passed to the
+   *          {@link TreeModel} to create the first factory
+   */
+  public TreeView(TreeModel treeModel, Object rootData) {
+    this(treeModel.createTreeNodeFactory(rootData));
+  }
+
+  /**
+   * Construct a new {@link TreeView}.
+   * 
+   * @param factory the factory that supplies the data
+   */
+  public TreeView(TreeNodeFactory<?> factory) {
+    Tree tree = new Tree();
+    initWidget(tree);
+
+    // Add the root item.
+    ExtraTreeItem rootItem = new ExtraTreeItem("Dummy UI Root");
+    tree.addItem(rootItem);
+
+    // Associate a view with the item.
+    new TreeNodeView(rootItem, factory);
+  }
+}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNodeModel.java b/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNodeModel.java
deleted file mode 100644
index ee199b5..0000000
--- a/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNodeModel.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.tree.shared;
-
-import com.google.gwt.list.shared.ListModel;
-
-/**
- * A model describing a node in a Tree.
- * 
- * @param <C> the data type contained in the children of the node.
- */
-public abstract class TreeNodeModel<C> {
-  private ListModel<C> listModel = null;
-
-  public TreeNodeModel() {
-  }
-  
-  public abstract TreeNodeModel<?> createChildModel(C value);
-
-  public ListModel<C> getListModel() {
-    if (listModel == null) {
-      listModel = createListModel();
-    }
-    return listModel;
-  }
-  
-  protected abstract ListModel<C> createListModel();
-}