Revision: 8387
Author: rj...@google.com
Date: Fri Jul 16 08:13:31 2010
Log: Adds UiBinder support for Grid

Patch by markovuksano...@gmail.com
Review by rj...@google.com
http://gwt-code-reviews.appspot.com/154810

Review by: robertvaw...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=8387

Added:
 /trunk/user/src/com/google/gwt/uibinder/elementparsers/GridParser.java
 /trunk/user/test/com/google/gwt/uibinder/elementparsers/GridParserTest.java
 /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java.rej
Modified:
 /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
 /trunk/user/src/com/google/gwt/user/client/ui/Grid.java
 /trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
 /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
 /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
 /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
 /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/GridParser.java Fri Jul 16 08:13:31 2010
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2009 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.uibinder.elementparsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.uibinder.rebind.UiBinderWriter;
+import com.google.gwt.uibinder.rebind.XMLElement;
+import com.google.gwt.user.client.ui.Grid;
+
+import java.util.Vector;
+
+/**
+ * A parser for Grid rows and cells.
+ */
+public class GridParser implements ElementParser {
+
+  private static class CellContent {
+    private String tagName;
+    private String content;
+
+    public CellContent(String tagName, String content) {
+      this.tagName = tagName;
+      this.content = content;
+    }
+
+    public String getConent() {
+      return this.content;
+    }
+
+    public String getTagName() {
+      return this.tagName;
+    }
+  }
+
+  private static class Size {
+    private int rows;
+    private int columns;
+
+    public Size() {
+      this.rows = 0;
+      this.columns = 0;
+    }
+
+    public int getColumns() {
+      return this.columns;
+    }
+
+    public int getRows() {
+      return this.rows;
+    }
+
+    public void setColumns(int cols) {
+      this.columns = cols;
+    }
+
+    public void setRows(int rows) {
+      this.rows = rows;
+    }
+  }
+
+  private static final String ROW_TAG = "row";
+
+  private static final String CELL_TAG = "cell";
+
+  private static final String CUSTOMCELL_TAG = "customCell";
+
+  public void parse(XMLElement elem, String fieldName, JClassType type,
+      UiBinderWriter writer) throws UnableToCompleteException {
+
+    Vector<Vector<CellContent>> matrix = new Vector<Vector<CellContent>>();
+
+    parseRows(elem, fieldName, writer, matrix);
+
+    Size size = getMatrixSize(matrix);
+
+    writer.setFieldInitializerAsConstructor(fieldName,
+        writer.getOracle().findType(Grid.class.getName()),
+ Integer.toString(size.getRows()), Integer.toString(size.getColumns()));
+    for (Vector<CellContent> row : matrix) {
+      for (CellContent column : row) {
+        if (column.getTagName().equals(CELL_TAG)) {
+          writer.addStatement("%s.setHTML(%s, %s, \"%s\");", fieldName,
+              Integer.toString(matrix.indexOf(row)),
+              Integer.toString(row.indexOf(column)), column.getConent());
+        }
+        if (column.getTagName().equals(CUSTOMCELL_TAG)) {
+          writer.addStatement("%s.setWidget(%s, %s, %s);", fieldName,
+              Integer.toString(matrix.indexOf(row)),
+              Integer.toString(row.indexOf(column)), column.getConent());
+        }
+      }
+    }
+  }
+
+  private Size getMatrixSize(Vector<Vector<CellContent>> matrix) {
+    Size size = new Size();
+
+    size.setRows(matrix.size());
+
+    int maxColumns = 0;
+    for (Vector<CellContent> column : matrix) {
+ maxColumns = (column.size() > maxColumns) ? column.size() : maxColumns;
+    }
+    size.setColumns(maxColumns);
+
+    return size;
+  }
+
+  private void parseColumns(String fieldName, UiBinderWriter writer,
+      Vector<Vector<CellContent>> matrix, XMLElement child)
+      throws UnableToCompleteException {
+
+    String tagName;
+    for (XMLElement cell : child.consumeChildElements()) {
+      tagName = cell.getLocalName();
+      if (!tagName.equals(CELL_TAG) && !tagName.equals(CUSTOMCELL_TAG)
+          || !cell.getPrefix().equals(child.getPrefix())) {
+ writer.die("Grid's row tag in %s may only contain %s or %s element.",
+            fieldName, CELL_TAG, CUSTOMCELL_TAG);
+      }
+      CellContent newColumn = null;
+      if (tagName.equals(CELL_TAG)) {
+ HtmlInterpreter htmlInt = HtmlInterpreter.newInterpreterForUiObject(
+            writer, fieldName);
+        String html = cell.consumeInnerHtml(htmlInt);
+        newColumn = new CellContent(tagName, html);
+      }
+      if (tagName.equals(CUSTOMCELL_TAG)) {
+        newColumn = new CellContent(tagName,
+            writer.parseElementToField(cell.consumeSingleChildElement()));
+      }
+      matrix.get(matrix.size() - 1).add(newColumn);
+    }
+  }
+
+  private void parseRows(XMLElement elem, String fieldName,
+      UiBinderWriter writer, Vector<Vector<CellContent>> matrix)
+      throws UnableToCompleteException {
+
+    for (XMLElement child : elem.consumeChildElements()) {
+      String tagName = child.getLocalName();
+      if (!tagName.equals(ROW_TAG)
+          || !elem.getPrefix().equals(child.getPrefix())) {
+        writer.die(
+ "%1$s:Grid elements must contain only %1$s:%2$s children, found %3$s:%4$s",
+            elem.getPrefix(), ROW_TAG, child.getPrefix(), tagName);
+      }
+      Vector<CellContent> newRow = new Vector<CellContent>();
+      matrix.add(newRow);
+      parseColumns(fieldName, writer, matrix, child);
+    }
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/uibinder/elementparsers/GridParserTest.java Fri Jul 16 08:13:31 2010
@@ -0,0 +1,159 @@
+/*
+ * 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.uibinder.elementparsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.uibinder.rebind.FieldWriter;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXException;
+
+import java.util.Iterator;
+
+/**
+ * GridParser unit tests.
+ */
+public class GridParserTest extends TestCase {
+ private static final String PARSED_TYPE = "com.google.gwt.user.client.ui.Grid";
+
+  private ElementParserTester tester;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    tester = new ElementParserTester(PARSED_TYPE, new GridParser());
+  }
+
+  public void testCellWithWhitespaces() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:Grid>");
+    b.append("  <g:row>");
+    b.append("    <g:customCell>    </g:customCell>");
+    b.append("  </g:row>");
+    b.append("</g:Grid>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertNotNull(tester.logger.died);
+    }
+  }
+
+  public void testEmtpyChild() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:Grid>");
+    b.append("  <g:row>");
+    b.append("    <g:customCell></g:customCell>");
+    b.append("  </g:row>");
+    b.append("</g:Grid>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertNotNull(tester.logger.died);
+    }
+  }
+
+  public void testInvalidChild() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:Grid>");
+    b.append("  <foo/>");
+    b.append("</g:Grid>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertNotNull(tester.logger.died);
+    }
+  }
+
+ public void testValidChild() throws UnableToCompleteException, SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:Grid>");
+    b.append("  <g:row>");
+    b.append("    <g:cell>");
+    b.append("      <div>foo HTML element</div>");
+    b.append("    </g:cell>");
+    b.append("    <g:cell>");
+    b.append("      <div>bar HTML element</div>");
+    b.append("    </g:cell>");
+    b.append("  </g:row>");
+    b.append("  <g:row>");
+    b.append("    <g:customCell>");
+    b.append("      <g:Label/>");
+    b.append("    </g:customCell>");
+    b.append("    <g:customCell>");
+    b.append("      <g:Label/>");
+    b.append("    </g:customCell>");
+    b.append("  </g:row>");
+    b.append("</g:Grid>");
+
+    String[] expected = {
+        "fieldName.setHTML(0, 0, \"<div>foo HTML element</div>\");",
+        "fieldName.setHTML(0, 1, \"<div>bar HTML element</div>\");",
+        "fieldName.setWidget(1, 0, <g:Label>);",
+        "fieldName.setWidget(1, 1, <g:Label>);" };
+
+    FieldWriter w = tester.parse(b.toString());
+    assertEquals("new " + PARSED_TYPE + "(2, 2)", w.getInitializer());
+
+    Iterator<String> i = tester.writer.statements.iterator();
+    for (String e : expected) {
+      assertEquals(e, i.next());
+    }
+    assertFalse(i.hasNext());
+    assertNull(tester.logger.died);
+  }
+
+ public void testValidChildWithDifferentNumberOfElementsInRows() throws UnableToCompleteException, SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:Grid>");
+    b.append("  <g:row>");
+    b.append("    <g:cell>");
+    b.append("      <div>foo HTML element</div>");
+    b.append("    </g:cell>");
+    b.append("  </g:row>");
+    b.append("  <g:row>");
+    b.append("    <g:customCell>");
+    b.append("      <g:Label/>");
+    b.append("    </g:customCell>");
+    b.append("    <g:customCell>");
+    b.append("      <g:Label/>");
+    b.append("    </g:customCell>");
+    b.append("  </g:row>");
+    b.append("</g:Grid>");
+
+    String[] expected = {
+        "fieldName.setHTML(0, 0, \"<div>foo HTML element</div>\");",
+        "fieldName.setWidget(1, 0, <g:Label>);",
+        "fieldName.setWidget(1, 1, <g:Label>);" };
+
+    FieldWriter w = tester.parse(b.toString());
+    assertEquals("new " + PARSED_TYPE + "(2, 2)", w.getInitializer());
+
+    Iterator<String> i = tester.writer.statements.iterator();
+    for (String e : expected) {
+      assertEquals(e, i.next());
+    }
+    assertFalse(i.hasNext());
+    assertNull(tester.logger.died);
+  }
+
+}
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java.rej Fri Jul 16 08:13:31 2010
@@ -0,0 +1,16 @@
+***************
+*** 34,39 ****
+  import com.google.gwt.user.client.ui.Composite;
+  import com.google.gwt.user.client.ui.DisclosurePanel;
+  import com.google.gwt.user.client.ui.DockPanel;
+  import com.google.gwt.user.client.ui.HTML;
+  import com.google.gwt.user.client.ui.HTMLPanel;
+  import com.google.gwt.user.client.ui.HasHTML;
+--- 34,40 ----
+  import com.google.gwt.user.client.ui.Composite;
+  import com.google.gwt.user.client.ui.DisclosurePanel;
+  import com.google.gwt.user.client.ui.DockPanel;
++ import com.google.gwt.user.client.ui.Grid;
+  import com.google.gwt.user.client.ui.HTML;
+  import com.google.gwt.user.client.ui.HTMLPanel;
+  import com.google.gwt.user.client.ui.HasHTML;
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java Thu Jul 15 04:01:13 2010 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java Fri Jul 16 08:13:31 2010
@@ -980,6 +980,7 @@
     addWidgetParser("TabLayoutPanel");
     addWidgetParser("Image");
     addWidgetParser("ListBox");
+    addWidgetParser("Grid");
   }

   /**
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/Grid.java Fri Apr 9 11:02:02 2010 +++ /trunk/user/src/com/google/gwt/user/client/ui/Grid.java Fri Jul 16 08:13:31 2010
@@ -29,6 +29,40 @@
  * <h3>Example</h3>
  * {...@example com.google.gwt.examples.GridExample}
  * </p>
+ *
+ * <h3>Use in UiBinder Templates</h3>
+ * <p>
+ * Grid widget consists of &lt;g:row> elements. Each &lt;g:row> element
+ * can contain one or more &lt;g:cell> or &lt;g:customCell> elements.
+ * Using &lt;g:cell> attribute it is possible to place pure HTML content.
+ * &lt;g:customCell> is used as a container for
+ * {...@link com.google.gwt.user.client.ui.Widget} type objects. (Note that the
+ * tags of the row, cell and customCell elements are not capitalized. This
+ * is meant to signal that the item is not a runtime object, and so cannot
+ * have a <code>ui:field</code> attribute.)
+ * <p>
+ * For example:
+ *
+ * <pre>
+ * &lt;g:Grid>
+ *  &lt;g:row>
+ *    &lt;g:customCell>
+ *      &lt;g:Label>foo&lt;/g:Label>
+ *    &lt;/g:customCell>
+ *    &lt;g:customCell>
+ *      &lt;g:Label>bar&lt;/g:Label>
+ *    &lt;/g:customCell>
+ *  &lt;/g:row>
+ *  &lt;g:row>
+ *    &lt;g:cell>
+ *      &lt;div>foo&lt;/div>
+ *    &lt;/g:cell>
+ *    &lt;g:cell>
+ *      &lt;div>bar&lt;/div>
+ *    &lt;/g:cell>
+ *  &lt;/g:row>
+ * &lt;/g:Grid>
+ * </pre>
  */
 public class Grid extends HTMLTable {

=======================================
--- /trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java Thu Jul 15 04:01:13 2010 +++ /trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java Fri Jul 16 08:13:31 2010
@@ -27,6 +27,7 @@
import com.google.gwt.uibinder.attributeparsers.VerticalAlignmentConstantParserTest;
 import com.google.gwt.uibinder.elementparsers.DialogBoxParserTest;
 import com.google.gwt.uibinder.elementparsers.DockLayoutPanelParserTest;
+import com.google.gwt.uibinder.elementparsers.GridParserTest;
 import com.google.gwt.uibinder.elementparsers.ImageParserTest;
 import com.google.gwt.uibinder.elementparsers.IsEmptyParserTest;
 import com.google.gwt.uibinder.elementparsers.LayoutPanelParserTest;
@@ -82,6 +83,7 @@
     // elementparsers
     suite.addTestSuite(DialogBoxParserTest.class);
     suite.addTestSuite(DockLayoutPanelParserTest.class);
+    suite.addTestSuite(GridParserTest.class);
     suite.addTestSuite(ImageParserTest.class);
     suite.addTestSuite(IsEmptyParserTest.class);
     suite.addTestSuite(LayoutPanelParserTest.class);
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Fri Jul 2 04:56:18 2010 +++ /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Fri Jul 16 08:13:31 2010
@@ -105,6 +105,17 @@
       code.append("}\n");
       return code;
     }
+  };
+  public static final MockJavaResource GRID = new MockJavaResource(
+    "com.google.gwt.user.client.ui.Grid") {
+  @Override
+  protected CharSequence getContent() {
+      StringBuffer code = new StringBuffer();
+      code.append("package com.google.gwt.user.client.ui;\n");
+      code.append("public class Grid extends Widget {\n");
+      code.append("}\n");
+      return code;
+    }
   };
   public static final MockJavaResource GWT_EVENT = new MockJavaResource(
       "com.google.gwt.event.shared.GwtEvent") {
@@ -377,6 +388,7 @@
     rtn.add(DIALOG_BOX);
     rtn.add(DOCK_LAYOUT_PANEL);
     rtn.add(EVENT_HANDLER);
+    rtn.add(GRID);
     rtn.add(GWT_EVENT);
     rtn.add(IMAGE);
     rtn.add(IMAGE_RESOURCE);
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java Tue Jul 13 09:51:15 2010 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java Fri Jul 16 08:13:31 2010
@@ -26,6 +26,7 @@
 import com.google.gwt.resources.client.CssResource.NotStrict;
 import com.google.gwt.uibinder.test.client.EnumeratedLabel.Suffix;
 import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.DisclosurePanel;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HTMLPanel;
@@ -292,6 +293,13 @@
   public void testFieldInPlaceholderedElement() {
     assertEquals("named portions", widgetUi.spanInMsg.getInnerText());
   }
+
+  public void testGrid() {
+    assertTrue(widgetUi.fooGrid.getWidget(0, 0) instanceof Label);
+    assertTrue(widgetUi.fooGrid.getWidget(0, 1) instanceof Button);
+    assertEquals(2, widgetUi.fooGrid.getColumnCount());
+    assertEquals(1, widgetUi.fooGrid.getRowCount());
+  }

   public void testListBox() {
     assertEquals(2, widgetUi.fooListBox.getItemCount());
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java Wed Jul 14 07:07:23 2010 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java Fri Jul 16 08:13:31 2010
@@ -33,6 +33,7 @@
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.DisclosurePanel;
+import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HTMLPanel;
 import com.google.gwt.user.client.ui.HasHTML;
@@ -160,6 +161,7 @@
   @UiField HTML styleLess;
   @UiField FooDialog fooDialog;
   @UiField ListBox fooListBox;
+  @UiField Grid fooGrid;

   public WidgetBasedUi() {
     external.style().ensureInjected();
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml Wed Jul 14 07:07:23 2010 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml Fri Jul 16 08:13:31 2010
@@ -606,6 +606,17 @@
      <gwt:item>bar</gwt:item>
      <gwt:item value='bar2'>bar 2</gwt:item>
    </gwt:ListBox>
+
+   <gwt:Grid ui:field='fooGrid'>
+     <gwt:row>
+       <gwt:customCell>
+            <gwt:Label>foo</gwt:Label>
+          </gwt:customCell>
+          <gwt:customCell>
+            <gwt:Button>bar</gwt:Button>
+          </gwt:customCell>
+     </gwt:row>
+   </gwt:Grid>

    </gwt:HTMLPanel>
   </gwt:Dock>

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

Reply via email to