Revision: 9765
Author: [email protected]
Date: Thu Feb 24 13:46:49 2011
Log: Edited wiki page CellBackedWIdgets through web user interface.
http://code.google.com/p/google-web-toolkit/source/detail?r=9765

Modified:
 /wiki/CellBackedWIdgets.wiki

=======================================
--- /wiki/CellBackedWIdgets.wiki        Thu Feb 24 13:09:51 2011
+++ /wiki/CellBackedWIdgets.wiki        Thu Feb 24 13:46:49 2011
@@ -20,12 +20,143 @@
   * Offer an identical Cell equivalent of every (most) new widgets
     * Shared code between Cell and Widget

-New Widgets in GWT will be backed by a Cell, so users can call upon common view components for CellTable and the rest of their application. GWT already provides the {{{CellWidget}} wrapper class that can convert any Cell into a Widget. More details on this appear toward the end of the document. +New Widgets in GWT will be backed by a Cell, so users can call upon common view components for CellTable and the rest of their application. GWT already provides the {{{CellWidget}} wrapper class that can convert any Cell into a Widget. More details on this appear toward the end of the document, but understand that when we refer to Cells throughout this document, all Cells will have an equivalent Widget.
+


 = Appearance Pattern =

-
-
-= Cell Backed Widgets =
-
+Each Cell will expose an abstract Appearance class that plays two important roles:
+  # Renders the view as a SafeHtml string.
+ # Updates the view in response to state changes of the widget, such as by applying styles to elements.
+
+In this way, the Cell becomes the presenter for the Appearance (the view). Cells will be written such that they do not rely on a specific DOM structure. For example, in {{{ButtonCell}}} below, the Appearance could be rendered as a {{{button}}} element or a series of nested divs, but the Cell would still respond to click events in the same way.
+
+{{{
+public class ButtonCell extends AbstractCell<String> {
+
+  // The appearance of this cell.
+  public abstract static class Appearance {
+
+    // Called when the user hovers the button with the mouse.
+    public void onHover(Context context, Element parent, String value) {}
+
+    // Called when the user pushes the button down.
+    public void onPush(Context context, Element parent, String value) {}
+
+    // Called when the user unhovers the button with the mouse.
+    public void onUnhover(Context context, Element parent, String value) {}
+
+    // Called when the user releases the button from being pushed.
+    public void onUnpush(Context context, Element parent, String value) {}
+
+    // Render the DOM structure of the cell.
+ public abstract void render(Context context, SafeHtml data, SafeHtmlBuilder sb);
+  }
+
+  // The default implementation of the appearance.
+  public static class DefaultAppearance extends Appearance {
+
+    public static interface Resources extends ClientBundle {
+      @Source(Style.DEFAULT_CSS)
+      Style buttonCellStyle();
+    }
+
+    @ImportedWithPrefix("gwt-ButtonCell")
+    public interface Style extends CssResource {
+      String DEFAULT_CSS = "com/google/gwt/cell/client/ButtonCell.css";
+
+      String hover();
+
+      String push();
+    }
+
+    private final Resources resources;
+
+    public DefaultAppearance() {
+      this(GWT.create(Resources.class));
+    }
+
+    public DefaultAppearance(Resources resources) {
+      this.resources = resources;
+      resources.buttonCellStyle().ensureInjected();
+    }
+
+    @Override
+    public void onHover(Context context, Element parent, String value) {
+      addClassName(parent, resources.buttonCellStyle().hover());
+    }
+
+    @Override
+    public void onPush(Context context, Element parent, String value) {
+      addClassName(parent, resources.buttonCellStyle().push());
+    }
+
+    @Override
+    public void onUnhover(Context context, Element parent, String value) {
+      removeClassName(parent, resources.buttonCellStyle().hover());
+    }
+
+    @Override
+    public void onUnpush(Context context, Element parent, String value) {
+      removeClassName(parent, resources.buttonCellStyle().push());
+    }
+
+    @Override
+ public void render(Context context, SafeHtml data, SafeHtmlBuilder sb) {
+      sb.appendHtmlConstant("<button type=\"button\" tabindex=\"-1\">");
+      if (data != null) {
+        sb.append(data);
+      }
+      sb.appendHtmlConstant("</button>");
+    }
+
+    protected void addClassName(Element parent, String styleName) {
+      parent.getFirstChildElement().addClassName(styleName);
+    }
+
+    protected void removeClassName(Element parent, String styleName) {
+      parent.getFirstChildElement().removeClassName(styleName);
+    }
+  }
+
+  private final Appearance appearance;
+
+  // Use the default look and feel of the Cell.
+  public ButtonCell() {
+    this(GWT.create(Appearance.class));
+  }
+
+  // Replace the styles used by this cell instance.
+  public ButtonCell(DefaultAppearance.Resources resources) {
+    this(new DefaultAppearance(resources));
+  }
+
+  // Replace the appearance used by this cell instance.
+  public ButtonCell(Appearance appearance) {
+    this.appearance = appearance;
+  }
+
+  ...
+}
+}}}
+
+First, notice that the Appearance class does not provide any view implementations, and thus the Cell does not make any assumptions about the structure of the Appearance. Even the Resources and Styles live in the default implementation of the appearance, instead of in the Cell itself. In the DefaultAppearence, we update state by simply applying a class name to the outer {{{button}}} element. A more complex Appearance may apply class names not just to the outer element, but to inner elements as well.
+
+Now take a look at the constructors for ButtonCell. The default constructor calls {{{GWT.create(Appearance.class)}}}, which is bound to the DefaultAppearance. However, users can use the third constructor to provide a specific appearance for this instance of the Cell. Alternatively, the second constructor (which is just there for convenience) takes a {{{DefaultAppearance.Resources}}}, which allows users to replace just the styles of the DefaultAppearance.
+
+As mentioned, we call {{{GWT.create(Appearance.class)}}} by default. The DefaultAppearance is bound in a gwt.xml file:
+{{{
+  <!-- Bind the default ButtonCell.Appearance. -->
+ <replace-with class="com.google.gwt.cell.client.ButtonCell.DefaultAppearance"> + <when-type-is class="com.google.gwt.cell.client.ButtonCell.Appearance"/>
+  </replace-with>
+}}}
+
+By overriding the deferred binding rule, a user can reskin a Cell for an entire application. Alternatively, third party libraries can provide skins for multiple widgets, which would be applied by inheriting a single Module containing a bunch of deferred binding overrides.
+
+Finally, note that Appearance is an abstract class. This allows us to add more state logic in the future without breaking existing Appearances. For example, we could add new methods "setRightFlush()" and "setLeftFlush()" which would make the right and left edges of the button flat, such that they could be lined up next to each other. Existing appearances may not support the new feature, but they would still work.
+
+
+
+= Cell Backed Widgets =

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

Reply via email to