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