Adding an example of creating a Cell that handles events. Also updated the existing Cell example to use SafeHtmlTemplates, which is a better alternative to manually appending HTML strings.  Add a comment in the Cell interface explaining that we may modify the Cell API in the future, and users should always extend AbstractCell.

Review by: rjrjr@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10566 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/javadoc/com/google/gwt/examples/cell/CellExample.java b/user/javadoc/com/google/gwt/examples/cell/CellExample.java
index 524889d..0161f8b 100644
--- a/user/javadoc/com/google/gwt/examples/cell/CellExample.java
+++ b/user/javadoc/com/google/gwt/examples/cell/CellExample.java
@@ -18,6 +18,10 @@
 import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.cell.client.Cell;
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.safecss.shared.SafeStyles;
+import com.google.gwt.safecss.shared.SafeStylesUtils;
+import com.google.gwt.safehtml.client.SafeHtmlTemplates;
 import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
 import com.google.gwt.safehtml.shared.SafeHtmlUtils;
@@ -36,7 +40,30 @@
    * A custom {@link Cell} used to render a string that contains the name of a
    * color.
    */
-  private static class ColorCell extends AbstractCell<String> {
+  static class ColorCell extends AbstractCell<String> {
+
+    /**
+     * The HTML templates used to render the cell.
+     */
+    interface Templates extends SafeHtmlTemplates {
+      /**
+       * The template for this Cell, which includes styles and a value.
+       * 
+       * @param styles the styles to include in the style attribute of the div
+       * @param value the safe value. Since the value type is {@link SafeHtml},
+       *          it will not be escaped before including it in the template.
+       *          Alternatively, you could make the value type String, in which
+       *          case the value would be escaped.
+       * @return a {@link SafeHtml} instance
+       */
+      @SafeHtmlTemplates.Template("<div style=\"{0}\">{1}</div>")
+      SafeHtml cell(SafeStyles styles, SafeHtml value);
+    }
+
+    /**
+     * Create a singleton instance of the templates used to render the cell.
+     */
+    private static Templates templates = GWT.create(Templates.class);
 
     @Override
     public void render(Context context, String value, SafeHtmlBuilder sb) {
@@ -52,20 +79,20 @@
       // If the value comes from the user, we escape it to avoid XSS attacks.
       SafeHtml safeValue = SafeHtmlUtils.fromString(value);
 
-      // Append some HTML that sets the text color.
-      sb.appendHtmlConstant("<div style=\"color:" + safeValue.asString()
-          + "\">");
-      sb.append(safeValue);
-      sb.appendHtmlConstant("</div>");
+      // Use the template to create the Cell's html.
+      SafeStyles styles = SafeStylesUtils.forTrustedColor(safeValue.asString());
+      SafeHtml rendered = templates.cell(styles, safeValue);
+      sb.append(rendered);
     }
   }
 
   /**
    * The list of data to display.
    */
-  private static final List<String> COLORS = Arrays.asList("red", "green",
-      "blue", "violet", "black", "gray");
+  private static final List<String> COLORS = Arrays.asList("red", "green", "blue", "violet",
+      "black", "gray");
 
+  @Override
   public void onModuleLoad() {
     // Create a cell to render each value.
     ColorCell cell = new ColorCell();
diff --git a/user/javadoc/com/google/gwt/examples/cell/CellWithEventsExample.java b/user/javadoc/com/google/gwt/examples/cell/CellWithEventsExample.java
new file mode 100644
index 0000000..aab4e8f
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cell/CellWithEventsExample.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2011 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.examples.cell;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.cell.client.Cell;
+import com.google.gwt.cell.client.ValueUpdater;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.EventTarget;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.safecss.shared.SafeStyles;
+import com.google.gwt.safecss.shared.SafeStylesUtils;
+import com.google.gwt.safehtml.client.SafeHtmlTemplates;
+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.RootPanel;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Example of creating a custom {@link Cell} that responds to events.
+ */
+public class CellWithEventsExample implements EntryPoint {
+
+  /**
+   * A custom {@link Cell} used to render a string that contains the name of a
+   * color.
+   */
+  static class ColorCell extends AbstractCell<String> {
+
+    /**
+     * The HTML templates used to render the cell.
+     */
+    interface Templates extends SafeHtmlTemplates {
+      /**
+       * The template for this Cell, which includes styles and a value.
+       * 
+       * @param styles the styles to include in the style attribute of the div
+       * @param value the safe value. Since the value type is {@link SafeHtml},
+       *          it will not be escaped before including it in the template.
+       *          Alternatively, you could make the value type String, in which
+       *          case the value would be escaped.
+       * @return a {@link SafeHtml} instance
+       */
+      @SafeHtmlTemplates.Template("<div style=\"{0}\">{1}</div>")
+      SafeHtml cell(SafeStyles styles, SafeHtml value);
+    }
+
+    /**
+     * Create a singleton instance of the templates used to render the cell.
+     */
+    private static Templates templates = GWT.create(Templates.class);
+
+    public ColorCell() {
+      /*
+       * Sink the click and keydown events. We handle click events in this
+       * class. AbstractCell will handle the keydown event and call
+       * onEnterKeyDown() if the user presses the enter key while the cell is
+       * selected.
+       */
+      super("click", "keydown");
+    }
+
+    /**
+     * Called when an event occurs in a rendered instance of this Cell. The
+     * parent element refers to the element that contains the rendered cell, NOT
+     * to the outermost element that the Cell rendered.
+     */
+    @Override
+    public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event,
+        ValueUpdater<String> valueUpdater) {
+      // Let AbstractCell handle the keydown event.
+      super.onBrowserEvent(context, parent, value, event, valueUpdater);
+
+      // Handle the click event.
+      if ("click".equals(event.getType())) {
+        // Ignore clicks that occur outside of the outermost element.
+        EventTarget eventTarget = event.getEventTarget();
+        if (parent.getFirstChildElement().isOrHasChild(Element.as(eventTarget))) {
+          doAction(value, valueUpdater);
+        }
+      }
+    }
+
+    @Override
+    public void render(Context context, String value, SafeHtmlBuilder sb) {
+      /*
+       * Always do a null check on the value. Cell widgets can pass null to
+       * cells if the underlying data contains a null, or if the data arrives
+       * out of order.
+       */
+      if (value == null) {
+        return;
+      }
+
+      // If the value comes from the user, we escape it to avoid XSS attacks.
+      SafeHtml safeValue = SafeHtmlUtils.fromString(value);
+
+      // Use the template to create the Cell's html.
+      SafeStyles styles = SafeStylesUtils.forTrustedColor(safeValue.asString());
+      SafeHtml rendered = templates.cell(styles, safeValue);
+      sb.append(rendered);
+    }
+
+    /**
+     * onEnterKeyDown is called when the user presses the ENTER key will the
+     * Cell is selected. You are not required to override this method, but its a
+     * common convention that allows your cell to respond to key events.
+     */
+    @Override
+    protected void onEnterKeyDown(Context context, Element parent, String value, NativeEvent event,
+        ValueUpdater<String> valueUpdater) {
+      doAction(value, valueUpdater);
+    }
+
+    private void doAction(String value, ValueUpdater<String> valueUpdater) {
+      // Alert the user that they selected a value.
+      Window.alert("You selected the color " + value);
+
+      // Trigger a value updater. In this case, the value doesn't actually
+      // change, but we use a ValueUpdater to let the app know that a value
+      // was clicked.
+      valueUpdater.update(value);
+    }
+  }
+
+  /**
+   * The list of data to display.
+   */
+  private static final List<String> COLORS = Arrays.asList("red", "green", "blue", "violet",
+      "black", "gray");
+
+  @Override
+  public void onModuleLoad() {
+    // Create a cell to render each value.
+    ColorCell cell = new ColorCell();
+
+    // Use the cell in a CellList.
+    CellList<String> cellList = new CellList<String>(cell);
+
+    // Push the data into the widget.
+    cellList.setRowData(0, COLORS);
+
+    // Add it to the root panel.
+    RootPanel.get().add(cellList);
+  }
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/cell/client/AbstractCell.java b/user/src/com/google/gwt/cell/client/AbstractCell.java
index e98f6af..738cb6a 100644
--- a/user/src/com/google/gwt/cell/client/AbstractCell.java
+++ b/user/src/com/google/gwt/cell/client/AbstractCell.java
@@ -33,6 +33,8 @@
  * <dl>
  * <dt>Read only cell</dt>
  * <dd>{@example com.google.gwt.examples.cell.CellExample}</dd>
+ * <dt>Cell with events</dt>
+ * <dd>{@example com.google.gwt.examples.cell.CellWithEventsExample}</dd>
  * <dt>Interactive cell</dt>
  * <dd>{@example com.google.gwt.examples.cell.InteractionCellExample}</dd>
  * <dt>Editable cell</dt>
diff --git a/user/src/com/google/gwt/cell/client/Cell.java b/user/src/com/google/gwt/cell/client/Cell.java
index 66e02ca..1388cd8 100644
--- a/user/src/com/google/gwt/cell/client/Cell.java
+++ b/user/src/com/google/gwt/cell/client/Cell.java
@@ -63,6 +63,12 @@
  * {@example com.google.gwt.examples.cell.CellExample}
  * </p>
  * 
+ * <p>
+ * <span style="color:red;">Warning: The Cell interface may change in subtle but breaking ways as we
+ * continuously seek to improve performance. You should always subclass {@link AbstractCell} instead
+ * of implementing {@link Cell} directly.</span>
+ * </p>
+ * 
  * @param <C> the type that this Cell represents
  */
 public interface Cell<C> {