Revision: 7608
Author: [email protected]
Date: Wed Feb 24 10:18:27 2010
Log: Changes TreeModel into TreeViewModel and adds the ability to fire events.

http://code.google.com/p/google-web-toolkit/source/detail?r=7608

Added:
 /trunk/bikeshed/src/com/google/gwt/sample/tree/client/MyTreeViewModel.java
 /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeViewModel.java
Deleted:
/trunk/bikeshed/src/com/google/gwt/sample/tree/client/AbstractTreeNodeFactory.java /trunk/bikeshed/src/com/google/gwt/sample/tree/client/DefaultTreeNodeFactory.java
 /trunk/bikeshed/src/com/google/gwt/sample/tree/client/MyTreeModel.java
 /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeModel.java
 /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeFactory.java
Modified:
 /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java
 /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java
 /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java

=======================================
--- /dev/null
+++ /trunk/bikeshed/src/com/google/gwt/sample/tree/client/MyTreeViewModel.java Wed Feb 24 10:18:27 2010
@@ -0,0 +1,123 @@
+/*
+ * 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.ButtonCell;
+import com.google.gwt.cells.client.Cell;
+import com.google.gwt.cells.client.TextCell;
+import com.google.gwt.cells.client.ValueUpdater;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.list.shared.AsyncListModel;
+import com.google.gwt.list.shared.ListModel;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A demo TreeModel.
+ */
+public class MyTreeViewModel implements TreeViewModel {
+
+  private static class IntegerListModel extends AsyncListModel<Integer> {
+    public IntegerListModel(final int length) {
+      super(new DataSource<Integer>() {
+        public void requestData(AsyncListModel<Integer> listModel) {
+          listModel.updateDataSize(1, true);
+          List<Integer> values = new ArrayList<Integer>(1);
+          values.add(length);
+          listModel.updateViewData(0, 1, values);
+        }
+      });
+    }
+  }
+
+  private static class StringListModel extends AsyncListModel<String> {
+    public StringListModel(final String value) {
+      super(new DataSource<String>() {
+        public void requestData(final AsyncListModel<String> listModel) {
+          String prefix = value.endsWith("...") ? value.substring(0,
+              value.length() - 3) : value;
+          dataService.getNext(prefix, new AsyncCallback<List<String>>() {
+            public void onFailure(Throwable caught) {
+              Window.alert("Error: " + caught);
+            }
+
+            public void onSuccess(List<String> result) {
+              listModel.updateDataSize(result.size(), true);
+              listModel.updateViewData(0, result.size(), result);
+            }
+          });
+        }
+      });
+    }
+  }
+
+ private static final TreeServiceAsync dataService = GWT.create(TreeService.class);
+
+  /**
+   * 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();
+
+ public <T> NodeInfo<?> getNodeInfo(T value, TreeNodeView<T> treeNodeView) {
+    if (value instanceof String) {
+      return getNodeInfoHelper((String) value);
+    } else if (value instanceof Integer) {
+      return getNodeInfoHelper((Integer) value);
+    }
+
+    // Unhandled type.
+    String type = value.getClass().getName();
+    throw new IllegalArgumentException("Unsupported object type: " + type);
+  }
+
+  @SuppressWarnings("unused")
+  private NodeInfo<?> getNodeInfoHelper(final Integer value) {
+    return null;
+  }
+
+  private NodeInfo<?> getNodeInfoHelper(final String value) {
+    if (value.endsWith("...")) {
+      ListModel<String> listModel = new StringListModel(value.toString());
+      return new DefaultNodeInfo<String>(listModel, new ButtonCell(),
+          new ValueUpdater<String>() {
+            public void update(String value) {
+              Window.alert("Clicked: " + value);
+            }
+          });
+    } else {
+      ListModel<Integer> listModel = new IntegerListModel(value.length());
+      return new DefaultNodeInfo<Integer>(listModel, INTEGER_CELL,
+          new ValueUpdater<Integer>() {
+            public void update(Integer value) {
+              Window.alert("Integer = " + value);
+            }
+          });
+    }
+  }
+}
=======================================
--- /dev/null
+++ /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeViewModel.java Wed Feb 24 10:18:27 2010
@@ -0,0 +1,112 @@
+/*
+ * 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.ValueUpdater;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.list.shared.ListModel;
+
+/**
+ * A model of a tree.
+ */
+public interface TreeViewModel {
+
+  /**
+   * The info needed to create a {...@link TreeNodeView}.
+   */
+  interface NodeInfo<C> {
+    /**
+     * 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();
+
+    /**
+     * Handle an event that is fired on one of the children of this item.
+     *
+     * @param elem the parent element of the item
+     * @param object the data value of the item
+     * @param event the event that was fired
+     */
+    void onBrowserEvent(Element elem, final C object, NativeEvent event);
+  }
+
+  /**
+   * Default implementation of {...@link NodeInfo}.
+   */
+  class DefaultNodeInfo<C> implements NodeInfo<C> {
+
+    private Cell<C> cell;
+    private ListModel<C> listModel;
+    private ValueUpdater<C> valueUpdater;
+
+    /**
+     * Construct a new {...@link DefaultNodeInfo}.
+     *
+ * @param listModel the {...@link ListModel} that provides the child values
+     * @param cell the {...@link Cell} used to render the child values
+     */
+    public DefaultNodeInfo(ListModel<C> listModel, Cell<C> cell) {
+      this.cell = cell;
+      this.listModel = listModel;
+    }
+
+    /**
+     * Construct a new {...@link DefaultNodeInfo}.
+     *
+ * @param listModel the {...@link ListModel} that provides the child values
+     * @param cell the {...@link Cell} used to render the child values
+     * @param valueUpdater the {...@link ValueUpdater}
+     */
+    public DefaultNodeInfo(ListModel<C> listModel, Cell<C> cell,
+        ValueUpdater<C> valueUpdater) {
+      this(listModel, cell);
+      this.valueUpdater = valueUpdater;
+    }
+
+    public Cell<C> getCell() {
+      return cell;
+    }
+
+    public ListModel<C> getListModel() {
+      return listModel;
+    }
+
+ public void onBrowserEvent(Element elem, final C object, NativeEvent event) {
+      cell.onBrowserEvent(elem, object, event, valueUpdater);
+    }
+  }
+
+  /**
+   * Get the {...@link NodeInfo} that will provide the {...@link ListModel} and
+   * {...@link Cell} to retrieve the children of the specified value.
+   *
+   * @param value the value in the parent node
+   * @param treeNodeView the {...@link TreeNodeView} that contains the value
+   * @return the {...@link NodeInfo}
+   */
+  <T> NodeInfo<?> getNodeInfo(T value, TreeNodeView<T> treeNodeView);
+}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/tree/client/AbstractTreeNodeFactory.java Mon Feb 22 11:51:55 2010
+++ /dev/null
@@ -1,59 +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.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;
-  }
-}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/tree/client/DefaultTreeNodeFactory.java Mon Feb 22 11:51:55 2010
+++ /dev/null
@@ -1,46 +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.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);
-  }
-}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/tree/client/MyTreeModel.java Wed Feb 24 06:46:02 2010
+++ /dev/null
@@ -1,110 +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.cells.client.TextCell;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.list.shared.AsyncListModel;
-import com.google.gwt.list.shared.ListModel;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A demo TreeModel.
- */
-public class MyTreeModel implements TreeModel {
-
-  private static class IntegerListModel extends AsyncListModel<Integer> {
-    public IntegerListModel(final int length) {
-      super(new DataSource<Integer>() {
-        public void requestData(AsyncListModel<Integer> listModel) {
-          listModel.updateDataSize(1, true);
-          List<Integer> values = new ArrayList<Integer>(1);
-          values.add(length);
-          listModel.updateViewData(0, 1, values);
-        }
-      });
-    }
-  }
-
-  private static class StringListModel extends AsyncListModel<String> {
-    public StringListModel(final String value) {
-      super(new DataSource<String>() {
-        public void requestData(final AsyncListModel<String> listModel) {
- String prefix = value.endsWith("...") ? value.substring(0, value.length() - 3) : value;
-          dataService.getNext(prefix, new AsyncCallback<List<String>>() {
-            public void onFailure(Throwable caught) {
-              Window.alert("Error: " + caught);
-            }
-
-            public void onSuccess(List<String> result) {
-              listModel.updateDataSize(result.size(), true);
-              listModel.updateViewData(0, result.size(), result);
-            }
-          });
-        }
-      });
-    }
-  }
-
- private static final TreeServiceAsync dataService = GWT.create(TreeService.class);
-
-  /**
-   * 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();
-
-  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);
-  }
-
-  @SuppressWarnings("unused")
- private TreeNodeFactory<?> createTreeNodeFactoryHelper(final Integer value) {
-    return null;
-  }
-
- private TreeNodeFactory<?> createTreeNodeFactoryHelper(final String value) {
-    if (value.endsWith("...")) {
-      ListModel<String> listModel = new StringListModel(value.toString());
- return new DefaultTreeNodeFactory<String>(listModel, STRING_CELL, this);
-    } else {
-      ListModel<Integer> listModel = new IntegerListModel(value.length());
- return new DefaultTreeNodeFactory<Integer>(listModel, INTEGER_CELL, this);
-    }
-  }
-}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeModel.java Mon Feb 22 11:51:55 2010
+++ /dev/null
@@ -1,31 +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;
-
-/**
- * A model of a tree.
- */
-public interface TreeModel {
-
-  /**
-   * 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);
-}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeFactory.java Mon Feb 22 11:51:55 2010
+++ /dev/null
@@ -1,51 +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.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();
-}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java Wed Feb 24 06:46:02 2010 +++ /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeEntryPoint.java Wed Feb 24 10:18:27 2010
@@ -24,7 +24,7 @@
 public class TreeEntryPoint implements EntryPoint {

   public void onModuleLoad() {
-    TreeView tree = new TreeView(new MyTreeModel(), "...");
+    TreeView tree = new TreeView(new MyTreeViewModel(), "...");
     RootPanel.get().add(tree);
   }
 }
=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java Mon Feb 22 11:51:55 2010 +++ /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeNodeView.java Wed Feb 24 10:18:27 2010
@@ -27,13 +27,19 @@
 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.client.TreeViewModel.NodeInfo;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.TreeItem;

+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * A view of a tree node.
+ *
+ * @param <T> the type that this {...@link TreeNodeView} contains
  */
-public class TreeNodeView extends Composite {
+public class TreeNodeView<T> extends Composite {

   /**
* A {...@link TreeItem} that fires value change events when the state changes.
@@ -77,22 +83,116 @@
    */
   private ExtraTreeItem treeItem;

+  /**
+   * This node's value.
+   */
+  private T value;
+
+  /**
+   * The parent {...@link TreeNodeView}.
+   */
+  private TreeNodeView<?> parent;
+
+  /**
+   * The containing {...@link TreeView}.
+   */
+  private TreeView tree;
+
+  /**
+   * The children of this {...@link TreeNodeView}.
+   */
+  private List<TreeNodeView<?>> children;
+
+  /**
+   * The info about the child nodes.
+   */
+  private NodeInfo<?> nodeInfo;
+
+  /**
+   * The info about this node.
+   */
+  private NodeInfo<T> parentNodeInfo;
+
   /**
    * Construct a {...@link TreeNodeView}.
    *
+   * @param value the value of this node
+   * @param tree the parent {...@link TreeView}
    * @param treeItem this nodes view
-   * @param factory the factory used to generate child nodes
    */
- public TreeNodeView(ExtraTreeItem treeItem, final TreeNodeFactory<?> factory) {
+  TreeNodeView(T value, final TreeView tree, final TreeNodeView<?> parent,
+      ExtraTreeItem treeItem, NodeInfo<T> parentNodeInfo) {
+    this.value = value;
+    this.tree = tree;
+    this.parent = parent;
     this.treeItem = treeItem;
-
+    this.parentNodeInfo = parentNodeInfo;
+  }
+
+  /**
+   * Get the child at the specified index.
+   *
+   * @return the child node
+   */
+  public TreeNodeView<?> getChild(int index) {
+    if ((index < 0) || (index >= getChildCount())) {
+      return null;
+    }
+    return children.get(index);
+  }
+
+  /**
+   * Get the number of children under this node.
+   *
+   * @return the child count
+   */
+  public int getChildCount() {
+    return children == null ? 0 : children.size();
+  }
+
+  /**
+   * Get the parent {...@link TreeNodeView}.
+   */
+  public TreeNodeView<?> getParentTreeNodeView() {
+    return parent;
+  }
+
+  /**
+   * Get the value contained in this node.
+   *
+   * @return the value of the node
+   */
+  public T getValue() {
+    return value;
+  }
+
+  NodeInfo<?> getNodeInfo() {
+    return nodeInfo;
+  }
+
+  NodeInfo<T> getParentNodeInfo() {
+    return parentNodeInfo;
+  }
+
+  TreeItem getTreeItem() {
+    return treeItem;
+  }
+
+  /**
+   * Initialize the node info.
+   *
+ * @param nodeInfo the {...@link NodeInfo} that provides information about the
+   *          child values
+   */
+  void initNodeInfo(final NodeInfo<?> nodeInfo) {
     // Force a + icon if this node might have children.
-    if (factory != null) {
+    if (nodeInfo != null) {
+      this.nodeInfo = nodeInfo;
       treeItem.addItem("loading...");
       treeItem.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
         public void onValueChange(ValueChangeEvent<Boolean> event) {
           if (event.getValue()) {
-            onOpen(factory);
+            onOpen(tree, nodeInfo);
           } else {
             onClose();
           }
@@ -100,10 +200,6 @@
       });
     }
   }
-
-  TreeItem getTreeItem() {
-    return treeItem;
-  }

   /**
    * Cleanup when the node is closed.
@@ -118,25 +214,29 @@
   /**
    * Setup the node when it is opened.
    *
-   * @param factory the factory used to generate child nodes
+   * @param tree the parent {...@link TreeView}
+ * @param nodeInfo the {...@link NodeInfo} that provides information about the
+   *          child values
    * @param <C> the child data type of the node.
    */
-  private <C> void onOpen(final TreeNodeFactory<C> factory) {
-    ListModel<C> listModel = factory.getListModel();
+ private <C> void onOpen(final TreeView tree, final NodeInfo<C> nodeInfo) {
+    ListModel<C> listModel = nodeInfo.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()) {
+        Cell<C> theCell = nodeInfo.getCell();
+        children = new ArrayList<TreeNodeView<?>>();
+        for (C childValue : event.getValues()) {
           // TODO(jlabanca): Use one StringBuilder.
           StringBuilder sb = new StringBuilder();
-          cell.render(value, sb);
+          theCell.render(childValue, sb);
           ExtraTreeItem child = new ExtraTreeItem(sb.toString());
           treeItem.addItem(child);
-          new TreeNodeView(child, factory.createChildFactory(value));
+          children.add(tree.createChildView(childValue, TreeNodeView.this,
+              child, nodeInfo));
         }
       }

=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java Mon Feb 22 11:51:55 2010 +++ /trunk/bikeshed/src/com/google/gwt/sample/tree/client/TreeView.java Wed Feb 24 10:18:27 2010
@@ -15,9 +15,17 @@
  */
 package com.google.gwt.sample.tree.client;

+import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.sample.tree.client.TreeNodeView.ExtraTreeItem;
+import com.google.gwt.sample.tree.client.TreeViewModel.NodeInfo;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
 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.ArrayList;

 /**
  * A view of a tree.
@@ -25,30 +33,128 @@
 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
+   * The {...@link TreeViewModel} that backs the tree.
    */
-  public TreeView(TreeModel treeModel, Object rootData) {
-    this(treeModel.createTreeNodeFactory(rootData));
-  }
+  private TreeViewModel model;
+
+  /**
+   * The hidden root node in the tree.
+   */
+  private TreeNodeView<?> rootNode;

   /**
    * Construct a new {...@link TreeView}.
    *
-   * @param factory the factory that supplies the data
+   * @param <T> the type of data in the root node
+   * @param viewModel the {...@link TreeViewModel} that backs the tree
+   * @param rootValue the hidden root value of the tree
    */
-  public TreeView(TreeNodeFactory<?> factory) {
-    Tree tree = new Tree();
+  public <T> TreeView(TreeViewModel viewModel, T rootValue) {
+    this.model = viewModel;
+
+    // Initialize the widget.
+    Tree tree = new Tree() {
+      @Override
+      public void onBrowserEvent(Event event) {
+        super.onBrowserEvent(event);
+
+        switch (event.getTypeInt()) {
+          case Event.ONMOUSEUP: {
+            if ((DOM.eventGetCurrentTarget(event) == getElement())
+                && (event.getButton() == Event.BUTTON_LEFT)) {
+              elementClicked(DOM.eventGetTarget(event), event);
+            }
+            break;
+          }
+        }
+      }
+    };
     initWidget(tree);
+    sinkEvents(Event.ONMOUSEUP);

     // Add the root item.
     ExtraTreeItem rootItem = new ExtraTreeItem("Dummy UI Root");
     tree.addItem(rootItem);

     // Associate a view with the item.
-    new TreeNodeView(rootItem, factory);
+    rootNode = createChildView(rootValue, null, rootItem, null);
+  }
+
+  public TreeViewModel getTreeViewModel() {
+    return model;
+  }
+
+  /**
+   * Create a child view for this tree.
+   *
+   * @param <C> the data type of the child
+   * @param childValue the value of the child
+   * @param parentTreeNodeView the parent {...@link TreeNodeView}
+   * @param childItem the DOM view of the child
+   * @return a {...@link TreeNodeView} for the child
+   */
+  <C> TreeNodeView<C> createChildView(C childValue,
+      TreeNodeView<?> parentTreeNodeView, ExtraTreeItem childItem,
+      NodeInfo<C> parentNodeInfo) {
+    TreeNodeView<C> childView = new TreeNodeView<C>(childValue, this,
+        parentTreeNodeView, childItem, parentNodeInfo);
+    NodeInfo<?> nodeInfo = model.getNodeInfo(childValue, childView);
+    childView.initNodeInfo(nodeInfo);
+    return childView;
+  }
+
+  /**
+ * Collects parents going up the element tree, terminated at the tree root.
+   */
+  private void collectElementChain(ArrayList<Element> chain, Element hRoot,
+      Element hElem) {
+    if ((hElem == null) || (hElem == hRoot)) {
+      return;
+    }
+
+    collectElementChain(chain, hRoot, DOM.getParent(hElem));
+    chain.add(hElem);
+  }
+
+  private boolean elementClicked(Element hElem, NativeEvent event) {
+    ArrayList<Element> chain = new ArrayList<Element>();
+    collectElementChain(chain, getElement(), hElem);
+
+    TreeNodeView<?> nodeView = findItemByChain(chain, 0, rootNode);
+    if (nodeView != null && nodeView != rootNode) {
+      TreeItem item = nodeView.getTreeItem();
+      if (DOM.isOrHasChild(item.getElement(), hElem)) {
+        fireEvent(nodeView, event);
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+ private TreeNodeView<?> findItemByChain(ArrayList<Element> chain, int idx,
+      TreeNodeView<?> parent) {
+    if (idx == chain.size()) {
+      return parent;
+    }
+
+    Element hCurElem = chain.get(idx);
+    for (int i = 0, n = parent.getChildCount(); i < n; ++i) {
+      TreeNodeView<?> child = parent.getChild(i);
+      if (child.getTreeItem().getElement() == hCurElem) {
+        TreeNodeView<?> retItem = findItemByChain(chain, idx + 1, child);
+        if (retItem == null) {
+          return child;
+        }
+        return retItem;
+      }
+    }
+
+    return findItemByChain(chain, idx + 1, parent);
+  }
+
+  private <T> void fireEvent(TreeNodeView<T> nodeView, NativeEvent event) {
+    nodeView.getParentNodeInfo().onBrowserEvent(
+        nodeView.getTreeItem().getElement(), nodeView.getValue(), event);
   }
 }

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to