Checkpoint tree work


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7601 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/sample/tree/Tree.gwt.xml b/bikeshed/src/com/google/gwt/sample/tree/Tree.gwt.xml
index 5a35cf1..31e9531 100644
--- a/bikeshed/src/com/google/gwt/sample/tree/Tree.gwt.xml
+++ b/bikeshed/src/com/google/gwt/sample/tree/Tree.gwt.xml
@@ -15,7 +15,7 @@
   <!-- Other module inherits                                      -->
 
   <!-- Specify the app entry point class.                         -->
-  <entry-point class='com.google.gwt.sample.tree.client.Tree'/>
+  <entry-point class='com.google.gwt.sample.tree.client.TreeEntryPoint'/>
 
   <!-- Specify the paths for translatable code                    -->
   <source path='client'/>
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/SimpleTreeNodeView.java b/bikeshed/src/com/google/gwt/sample/tree/client/SimpleTreeNodeView.java
new file mode 100644
index 0000000..bb4803f
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/SimpleTreeNodeView.java
@@ -0,0 +1,41 @@
+/*
+ * 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/Tree.java b/bikeshed/src/com/google/gwt/sample/tree/client/Tree.java
deleted file mode 100644
index df03061..0000000
--- a/bikeshed/src/com/google/gwt/sample/tree/client/Tree.java
+++ /dev/null
@@ -1,60 +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.core.client.EntryPoint;
-import com.google.gwt.list.shared.ListEvent;
-import com.google.gwt.list.shared.ListHandler;
-import com.google.gwt.list.shared.SizeChangeEvent;
-import com.google.gwt.sample.tree.shared.TreeNode;
-import com.google.gwt.user.client.ui.RootPanel;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A demo of the asynchronous Tree model.
- */
-public class Tree implements EntryPoint {
-  
-  static class FakeTreeNode extends TreeNode<String> {
-    static int gensym = 1;
-    private static final int FANOUT = 5;
-
-    FakeTreeNode(int value) {
-      this.nodeData = "" + value;
-    }
-
-    @Override
-    protected void onRangeChanged(int start, int length) {
-      // TODO: use start, length
-      for (ListHandler<TreeNode<String>> handler : handlers) {
-        handler.onSizeChanged(new SizeChangeEvent(FANOUT, true));
-        List<TreeNode<String>> values = new ArrayList<TreeNode<String>>(FANOUT);
-        for (int i = 0; i < FANOUT; i++) {
-          values.add(new FakeTreeNode(gensym++));
-        }
-        handler.onDataChanged(new ListEvent<TreeNode<String>>(0, FANOUT, values));
-      }
-    }
-  }
-
-  public void onModuleLoad() {
-    TreeNode<String> root = new FakeTreeNode(0);
-    TreeView<String> treeView = new TreeView<String>(root);
-    RootPanel.get().add(treeView);
-  }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java b/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java
new file mode 100644
index 0000000..40ab6b6
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java
@@ -0,0 +1,78 @@
+/*
+ * 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.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());
+
+    RootPanel.get().add(tree);
+  }
+}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java b/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java
new file mode 100644
index 0000000..4dd104d
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java
@@ -0,0 +1,82 @@
+/*
+ * 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.ListEvent;
+import com.google.gwt.list.shared.ListHandler;
+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.
+ */
+public abstract class TreeNodeView<T,C> extends Composite {
+  
+  private TreeItem treeItem;
+  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();
+
+              for (C value : event.getValues()) {
+                TreeNodeView<C,?> childView = createChildView(value);
+                treeItem.addItem(childView.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;
+          }
+        }
+      }
+    };
+    if (childModel != null) {
+      treeItem.addItem("loading...");
+    }
+  }
+
+  TreeItem getTreeItem() {
+    return treeItem;
+  }
+
+  protected abstract TreeNodeView<C, ?> createChildView(C nodeData);
+}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java b/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java
deleted file mode 100644
index 2a5bbf2..0000000
--- a/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java
+++ /dev/null
@@ -1,96 +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.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.logical.shared.OpenEvent;
-import com.google.gwt.event.logical.shared.OpenHandler;
-import com.google.gwt.list.shared.ListEvent;
-import com.google.gwt.list.shared.ListHandler;
-import com.google.gwt.list.shared.ListRegistration;
-import com.google.gwt.list.shared.SizeChangeEvent;
-import com.google.gwt.sample.tree.shared.TreeNode;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Tree;
-import com.google.gwt.user.client.ui.TreeItem;
-
-import java.util.HashMap;
-
-/**
- * A tree view.
- * 
- * @param <T> the data type of each tree node.
- */
-public class TreeView<T> extends Composite {
-  
-  private HashMap<TreeItem, TreeNode<T>> nodeMap =
-    new HashMap<TreeItem, TreeNode<T>>();
-  private Tree tree;
-  
-  public TreeView(TreeNode<T> root) {
-    tree = new Tree();
-    tree.setAnimationEnabled(true);
-    
-    TreeItem rootItem = new TreeItem("root");
-    nodeMap.put(rootItem, root);
-    rootItem.addItem("");
-    tree.addItem(rootItem);
-
-    addHandler(rootItem).setRangeOfInterest(0, 10);
-    
-    tree.addOpenHandler(new OpenHandler<TreeItem>() {
-      public void onOpen(OpenEvent<TreeItem> event) {
-        TreeItem treeItem = event.getTarget();
-        addHandler(treeItem).setRangeOfInterest(0, 10);
-      }
-    });
-    tree.addCloseHandler(new CloseHandler<TreeItem>() {
-      public void onClose(CloseEvent<TreeItem> event) {
-        // TODO - remove list handler
-      }
-    });
-    initWidget(tree);
-  }
-
-  protected TreeNode<T> getNode(TreeItem treeItem) {
-    return nodeMap.get(treeItem);
-  }
-
-  private ListRegistration addHandler(final TreeItem item) {
-    TreeNode<T> node = getNode(item);
-    return node.addListHandler(new ListHandler<TreeNode<T>>() {
-      public void onDataChanged(ListEvent<TreeNode<T>> event) {
-        int idx = event.getStart();
-        for (TreeNode<T> node : event.getValues()) {
-          TreeItem treeItem = item.getChild(idx++);
-          nodeMap.put(treeItem, node);
-          treeItem.setText(node.getNodeData().toString());
-        }
-      }
-
-      public void onSizeChanged(SizeChangeEvent event) {
-        int size = event.getSize();
-        item.removeItems();
-        for (int i = 0; i < size; i++) {
-          TreeItem child = new TreeItem("");
-          item.addItem(child);
-          child.addItem("");
-        }
-      }
-    });
-  }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/shared/SimpleTreeNodeModel.java b/bikeshed/src/com/google/gwt/sample/tree/shared/SimpleTreeNodeModel.java
new file mode 100644
index 0000000..2a9869d
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/shared/SimpleTreeNodeModel.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * A model describing a node in a Tree of uniformly typed nodes.
+ * 
+ * @param <T> the data type contained in all nodes of the tree.
+ */
+public abstract class SimpleTreeNodeModel<T> extends TreeNodeModel<T> {
+
+  public abstract SimpleTreeNodeModel<T> createChildModel(T value);
+}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNode.java b/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNode.java
deleted file mode 100644
index d191155..0000000
--- a/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNode.java
+++ /dev/null
@@ -1,56 +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.ListHandler;
-import com.google.gwt.list.shared.ListRegistration;
-import com.google.gwt.list.shared.SizeChangeEvent;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A node in a Tree.
- *
- * @param <T> the data type contained in the node.
- */
-public abstract class TreeNode<T> {
-  
-    protected List<ListHandler<TreeNode<T>>> handlers =
-      new ArrayList<ListHandler<TreeNode<T>>>();
-    protected T nodeData;
-
-    public ListRegistration addListHandler(final ListHandler<TreeNode<T>> handler) {
-      handler.onSizeChanged(new SizeChangeEvent(5, true)); // TODO - unhack
-      handlers.add(handler);
-      
-      return new ListRegistration() {
-        public void removeHandler() {
-          handlers.remove(handler);
-        }
-
-        public void setRangeOfInterest(int start, int length) {
-          onRangeChanged(start, length);
-        }
-      };
-    }
-    
-    public T getNodeData() {
-      return nodeData;
-    }
-
-    protected abstract void onRangeChanged(int start, int length);
-}
diff --git a/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNodeModel.java b/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNodeModel.java
new file mode 100644
index 0000000..ee199b5
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/tree/shared/TreeNodeModel.java
@@ -0,0 +1,41 @@
+/*
+ * 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();
+}
diff --git a/bikeshed/war/Stocks.html b/bikeshed/war/Stocks.html
index 2b92c92..5ad342e 100644
--- a/bikeshed/war/Stocks.html
+++ b/bikeshed/war/Stocks.html
@@ -3,7 +3,7 @@
   <head>
     <meta http-equiv="content-type" content="text/html; charset=UTF-8">
     <link type="text/css" rel="stylesheet" href="Stocks.css">
-    <title>Data Backed Widgets Sample</title>
+    <title>Stock Game Sample</title>
     <script type="text/javascript" language="javascript" src="stocks/stocks.nocache.js"></script>
   </head>
 
diff --git a/bikeshed/war/Tree.html b/bikeshed/war/Tree.html
index c8c2ce8..17a1984 100644
--- a/bikeshed/war/Tree.html
+++ b/bikeshed/war/Tree.html
@@ -3,7 +3,7 @@
   <head>
     <meta http-equiv="content-type" content="text/html; charset=UTF-8">
     <link type="text/css" rel="stylesheet" href="Tree.css">
-    <title>Data Backed Widgets Sample</title>
+    <title>Tree Sample</title>
     <script type="text/javascript" language="javascript" src="tree/tree.nocache.js"></script>
   </head>
 
diff --git a/bikeshed/war/WEB-INF/web.xml b/bikeshed/war/WEB-INF/web.xml
index b41b49d..12013ea 100644
--- a/bikeshed/war/WEB-INF/web.xml
+++ b/bikeshed/war/WEB-INF/web.xml
@@ -6,6 +6,7 @@
 <web-app>
 
   <!-- Servlets -->
+  <!--
   <servlet>
     <servlet-name>stockServlet</servlet-name>
     <servlet-class>com.google.gwt.sample.stocks.server.StockServiceImpl</servlet-class>
@@ -15,10 +16,10 @@
     <servlet-name>stockServlet</servlet-name>
     <url-pattern>/stocks/stock</url-pattern>
   </servlet-mapping>
+  -->
 
   <!-- Default page to serve -->
   <welcome-file-list>
-    <welcome-file>Stocks.html</welcome-file>
     <welcome-file>Tree.html</welcome-file>
   </welcome-file-list>