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 <g:row> elements. Each <g:row> element
+ * can contain one or more <g:cell> or <g:customCell> elements.
+ * Using <g:cell> attribute it is possible to place pure HTML content.
+ * <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>
+ * <g:Grid>
+ * <g:row>
+ * <g:customCell>
+ * <g:Label>foo</g:Label>
+ * </g:customCell>
+ * <g:customCell>
+ * <g:Label>bar</g:Label>
+ * </g:customCell>
+ * </g:row>
+ * <g:row>
+ * <g:cell>
+ * <div>foo</div>
+ * </g:cell>
+ * <g:cell>
+ * <div>bar</div>
+ * </g:cell>
+ * </g:row>
+ * </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