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> {