Revision: 8676
Author: gwt.mirror...@gmail.com
Date: Tue Aug 31 12:33:22 2010
Log: Tests and tweaks for DisclosurePanel and StackLayoutPanel parsers.
1. Problems in assertFirstHeader().
1.1. invalid condition;
1.2. invalid reference on second argument.
2. Use addStatement() instead of addInitStatement(), because same is done
everywhere.
3. Small tweaks.
4. Set of tests, including all bad cases.
Patch by konstantin.scheg...@gmail.com
Review by rj...@google.com
http://gwt-code-reviews.appspot.com/736801/show
Review by: robertvaw...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=8676
Added:
/trunk/user/test/com/google/gwt/uibinder/elementparsers/DisclosurePanelParserTest.java
/trunk/user/test/com/google/gwt/uibinder/elementparsers/StackPanelParserTest.java
/trunk/user/test/com/google/gwt/uibinder/elementparsers/TabPanelParserTest.java
Modified:
/trunk/user/src/com/google/gwt/uibinder/elementparsers/DisclosurePanelParser.java
/trunk/user/src/com/google/gwt/uibinder/elementparsers/StackLayoutPanelParser.java
/trunk/user/src/com/google/gwt/uibinder/elementparsers/TabLayoutPanelParser.java
/trunk/user/src/com/google/gwt/uibinder/elementparsers/TabPanelParser.java
/trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
/trunk/user/test/com/google/gwt/uibinder/elementparsers/StackLayoutPanelParserTest.java
/trunk/user/test/com/google/gwt/uibinder/elementparsers/TabLayoutPanelParserTest.java
/trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
=======================================
--- /dev/null
+++
/trunk/user/test/com/google/gwt/uibinder/elementparsers/DisclosurePanelParserTest.java
Tue Aug 31 12:33:22 2010
@@ -0,0 +1,192 @@
+/*
+ * 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 java.util.Iterator;
+
+/**
+ * Test for {...@link DisclosurePanelParser}.
+ */
+public class DisclosurePanelParserTest extends TestCase {
+
+ private static final String PARSED_TYPE
= "com.google.gwt.user.client.ui.DisclosurePanel";
+
+ private ElementParserTester tester;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ tester = new ElementParserTester(PARSED_TYPE, new
DisclosurePanelParser());
+ }
+
+ public void testBad_notWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <div/>");
+ b.append("</g:DisclosurePanel>");
+
+ parseAndFail(b, "Must be a widget");
+ }
+
+ public void testBad_twoWidgets() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:Button id='1'/>");
+ b.append(" <g:Button id='2'/>");
+ b.append("</g:DisclosurePanel>");
+
+ parseAndFail(b, "May have only one body element");
+ }
+
+ public void testBad_twoHeaders() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:header>111</g:header>");
+ b.append(" <g:header>222</g:header>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ parseAndFail(b, "May have only one <g:header> or <g:customHeader>");
+ }
+
+ public void testBad_twoCustomHeaders() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:customHeader><g:Label>111</g:Label></g:customHeader>");
+ b.append(" <g:customHeader><g:Label>222</g:Label></g:customHeader>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ parseAndFail(b, "May have only one <g:header> or <g:customHeader>");
+ }
+
+ public void testBad_withHeader_onlyOpenImage() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:header openImage='{open}'>foo</g:header>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ parseAndFail(b,
+ "Both openImage and closedImage must be specified, or neither");
+ }
+
+ public void testBad_withHeader_onlyClosedImage() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:header closedImage='{closed}'>foo</g:header>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ parseAndFail(b,
+ "Both openImage and closedImage must be specified, or neither");
+ }
+
+ public void testBad_withCustomHeader_notWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:customHeader><div/></g:customHeader>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ parseAndFail(b, "Must be a widget", "<div>");
+ }
+
+ /**
+ * Parses bad code in given {...@link StringBuffer} and asserts that failure
+ * message has expected strings.
+ */
+ private void parseAndFail(StringBuffer b, String... expectedFailures)
+ throws Exception {
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ String died = tester.logger.died;
+ for (String expectedFailure : expectedFailures) {
+ assertTrue(died, died.contains(expectedFailure));
+ }
+ }
+ }
+
+ public void testGood_onlyWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ tester.parse(b.toString());
+
+ assertStatements("fieldName.add(<g:Button>);");
+ }
+
+ public void testGood_withHeader() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:header>foo</g:header>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ FieldWriter w = tester.parse(b.toString());
+ assertEquals("new
com.google.gwt.user.client.ui.DisclosurePanel(\"foo\")",
+ w.getInitializer());
+
+ assertStatements("fieldName.add(<g:Button>);");
+ }
+
+ public void testGood_withHeader_withImages() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:header openImage='{open}'
closedImage='{closed}'>foo</g:header>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ FieldWriter w = tester.parse(b.toString());
+ assertEquals(
+ "new com.google.gwt.user.client.ui.DisclosurePanel(open, closed,
\"foo\")",
+ w.getInitializer());
+
+ assertStatements("fieldName.add(<g:Button>);");
+ }
+
+ public void testGood_withCustomHeader() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:DisclosurePanel>");
+ b.append(" <g:customHeader><g:Label>foo</g:Label></g:customHeader>");
+ b.append(" <g:Button/>");
+ b.append("</g:DisclosurePanel>");
+
+ FieldWriter w = tester.parse(b.toString());
+ assertEquals(null, w.getInitializer());
+
+ assertStatements("fieldName.add(<g:Button>);",
+ "fieldName.setHeader(<g:Label>);");
+ }
+
+ private void assertStatements(String... expected) {
+ 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/elementparsers/StackPanelParserTest.java
Tue Aug 31 12:33:22 2010
@@ -0,0 +1,67 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import java.util.Iterator;
+
+/**
+ * Test for {...@link StackPanelParser}.
+ */
+public class StackPanelParserTest extends TestCase {
+
+ private static final String PARSED_TYPE
= "com.google.gwt.user.client.ui.StackPanel";
+
+ private ElementParserTester tester;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ tester = new ElementParserTester(PARSED_TYPE, new StackPanelParser());
+ }
+
+ public void testHappy_noStackText() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackPanel>");
+ b.append(" <g:Button/>");
+ b.append("</g:StackPanel>");
+
+ tester.parse(b.toString());
+
+ assertStatements("fieldName.add(<g:Button>);");
+ }
+
+ public void testHappy_hasStackText() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackPanel>");
+ b.append(" <g:Button g:StackPanel-text='Foo'/>");
+ b.append("</g:StackPanel>");
+
+ tester.parse(b.toString());
+
+ assertStatements("fieldName.add(<g:Button>, \"Foo\");");
+ }
+
+ private void assertStatements(String... expected) {
+ 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/elementparsers/TabPanelParserTest.java
Tue Aug 31 12:33:22 2010
@@ -0,0 +1,160 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import java.util.Iterator;
+
+/**
+ * Test for {...@link TabPanelParser}.
+ */
+public class TabPanelParserTest extends TestCase {
+
+ private static final String PARSED_TYPE
= "com.google.gwt.user.client.ui.TabPanel";
+
+ private ElementParserTester tester;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ tester = new ElementParserTester(PARSED_TYPE, new TabPanelParser());
+ }
+
+ public void testBad_notTab() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabPanel>");
+ b.append(" <div/>");
+ b.append("</g:TabPanel>");
+
+ parseAndFail(b, "Only <g:Tab> children are allowed");
+ }
+
+ public void testBad_noWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabPanel>");
+ b.append(" <g:Tab>");
+ b.append(" </g:Tab>");
+ b.append("</g:TabPanel>");
+
+ parseAndFail(b, "Must have a child widget");
+ }
+
+ public void testBad_notWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabPanel>");
+ b.append(" <g:Tab>");
+ b.append(" <div/>");
+ b.append(" </g:Tab>");
+ b.append("</g:TabPanel>");
+
+ parseAndFail(b, "Must be a widget");
+ }
+
+ public void testBad_twoWidgets() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabPanel>");
+ b.append(" <g:Tab>");
+ b.append(" <g:Button/>");
+ b.append(" <g:Button/>");
+ b.append(" </g:Tab>");
+ b.append("</g:TabPanel>");
+
+ parseAndFail(b, "May only have a single child widget");
+ }
+
+ public void testBad_noHeader() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabPanel>");
+ b.append(" <g:Tab>");
+ b.append(" <g:Button/>");
+ b.append(" </g:Tab>");
+ b.append("</g:TabPanel>");
+
+ parseAndFail(b, "Requires either a \"text\" attribute or <g:TabHTML>");
+ }
+
+ public void testBad_twoHeaders() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabPanel>");
+ b.append(" <g:Tab text='Foo'>");
+ b.append(" <g:TabHTML>Bar</g:TabHTML>");
+ b.append(" <g:Button/>");
+ b.append(" </g:Tab>");
+ b.append("</g:TabPanel>");
+
+ parseAndFail(b, "May have only one \"text\" attribute or <g:TabHTML>");
+ }
+
+ public void testBad_twoCustomHeaders() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabPanel>");
+ b.append(" <g:Tab>");
+ b.append(" <g:TabHTML>Foo</g:TabHTML>");
+ b.append(" <g:TabHTML>Bar</g:TabHTML>");
+ b.append(" <g:Button/>");
+ b.append(" </g:Tab>");
+ b.append("</g:TabPanel>");
+
+ parseAndFail(b, "May have only one \"text\" attribute or <g:TabHTML>");
+ }
+
+ /**
+ * Parses bad code in given {...@link StringBuffer} and asserts that failure
+ * message has expected strings.
+ */
+ private void parseAndFail(StringBuffer b, String... expectedFailures)
+ throws Exception {
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ String died = tester.logger.died;
+ for (String expectedFailure : expectedFailures) {
+ assertTrue(died, died.contains(expectedFailure));
+ }
+ }
+ }
+
+ public void testHappy() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabPanel>");
+ b.append(" <g:Tab text='Foo'>");
+ b.append(" <g:Label id='0'/>");
+ b.append(" </g:Tab>");
+ b.append(" <g:Tab>");
+ b.append(" <g:TabHTML>B<b>a</b>r</g:TabHTML>");
+ b.append(" <g:Label id='1'/>");
+ b.append(" </g:Tab>");
+ b.append("</g:TabPanel>");
+
+ tester.parse(b.toString());
+
+ assertStatements("fieldName.add(<g:Label id='0'>, \"Foo\");",
+ "fieldName.add(<g:Label id='1'>, \"B<b>a</b>r\", true);");
+ }
+
+ private void assertStatements(String... expected) {
+ Iterator<String> i = tester.writer.statements.iterator();
+ for (String e : expected) {
+ assertEquals(e, i.next());
+ }
+ assertFalse(i.hasNext());
+ assertNull(tester.logger.died);
+ }
+}
=======================================
---
/trunk/user/src/com/google/gwt/uibinder/elementparsers/DisclosurePanelParser.java
Mon Jun 7 12:20:31 2010
+++
/trunk/user/src/com/google/gwt/uibinder/elementparsers/DisclosurePanelParser.java
Tue Aug 31 08:46:42 2010
@@ -41,16 +41,16 @@
throws UnableToCompleteException {
Children children = findChildren(panelElem, writer);
- if (null != children.body) {
+ if (children.body != null) {
if (!writer.isWidgetElement(children.body)) {
writer.die(children.body, "Must be a widget");
}
String bodyField = writer.parseElementToField(children.body);
- writer.addInitStatement("%s.add(%s);", panelField, bodyField);
+ writer.addStatement("%s.add(%s);", panelField, bodyField);
}
- if (null != children.customHeader) {
+ if (children.customHeader != null) {
XMLElement headerElement =
children.customHeader.consumeSingleChildElement();
if (!writer.isWidgetElement(headerElement)) {
@@ -58,16 +58,16 @@
}
String headerField = writer.parseElementToField(headerElement);
- writer.addInitStatement("%s.setHeader(%s);", panelField,
headerField);
+ writer.addStatement("%s.setHeader(%s);", panelField, headerField);
}
- if (null != children.header) {
+ if (children.header != null) {
String openImage =
children.header.consumeImageResourceAttribute(OPEN_IMAGE);
String closedImage =
children.header.consumeImageResourceAttribute(CLOSED_IMAGE);
String headerText =
children.header.consumeInnerTextEscapedAsHtmlStringLiteral(new
TextInterpreter(
writer));
- if ((openImage == null) ^ (closedImage == null)) {
+ if (openImage == null ^ closedImage == null) {
writer.die(children.header,
"Both %s and %s must be specified, or neither", OPEN_IMAGE,
CLOSED_IMAGE);
@@ -79,8 +79,8 @@
"new %s(%s, %s, \"%s\")", panelTypeName, openImage,
closedImage,
headerText));
} else {
- writer.setFieldInitializer(panelField,
String.format("new %s(\"%s\")",
- panelTypeName, headerText));
+ writer.setFieldInitializer(panelField,
+ String.format("new %s(\"%s\")", panelTypeName, headerText));
}
}
}
@@ -93,20 +93,20 @@
public Boolean interpretElement(XMLElement child)
throws UnableToCompleteException {
- if (hasAttribute(child, HEADER)) {
+ if (hasTag(child, HEADER)) {
assertFirstHeader();
children.header = child;
return true;
}
- if (hasAttribute(child, CUSTOM)) {
+ if (hasTag(child, CUSTOM)) {
assertFirstHeader();
children.customHeader = child;
return true;
}
// Must be the body, then
- if (null != children.body) {
+ if (children.body != null) {
writer.die(elem, "May have only one body element");
}
@@ -115,18 +115,15 @@
}
void assertFirstHeader() throws UnableToCompleteException {
- if ((null != children.header) && (null != children.customHeader)) {
- writer.die(elem, "May have only one %2$s:header "
- + "or %2$s:customHeader", elem.getPrefix());
+ if (children.header != null || children.customHeader != null) {
+ writer.die(elem, "May have only one <%1$s:header> "
+ + "or <%1$s:customHeader>", elem.getPrefix());
}
}
- private boolean hasAttribute(XMLElement child, final String
attribute) {
- return rightNamespace(child) &&
child.getLocalName().equals(attribute);
- }
-
- private boolean rightNamespace(XMLElement child) {
- return child.getNamespaceUri().equals(elem.getNamespaceUri());
+ private boolean hasTag(XMLElement child, String tag) {
+ return elem.getNamespaceUri().equals(child.getNamespaceUri())
+ && tag.equals(child.getLocalName());
}
});
=======================================
---
/trunk/user/src/com/google/gwt/uibinder/elementparsers/StackLayoutPanelParser.java
Mon Jun 7 12:20:31 2010
+++
/trunk/user/src/com/google/gwt/uibinder/elementparsers/StackLayoutPanelParser.java
Tue Aug 31 08:46:42 2010
@@ -1,12 +1,12 @@
/*
* 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
@@ -47,17 +47,16 @@
unitEnumType);
writer.setFieldInitializerAsConstructor(fieldName,
- writer.getOracle().findType(StackLayoutPanel.class.getName()),
- unit);
+ writer.getOracle().findType(StackLayoutPanel.class.getName()),
unit);
// Parse children.
for (XMLElement stackElem : panelElem.consumeChildElements()) {
// Get the stack element.
if (!isElementType(panelElem, stackElem, STACK)) {
- writer.die(stackElem, "Only <%s:%s> children are allowed.",
+ writer.die(stackElem, "Only <%s:%s> children are allowed.",
panelElem.getPrefix(), STACK);
}
-
+
// Find all the children of the <stack>.
Children children = findChildren(stackElem, writer);
@@ -79,8 +78,7 @@
writer.addStatement("%s.add(%s, \"%s\", true, %s);", fieldName,
childFieldName, html, size);
} else if (children.customHeader != null) {
- XMLElement headerElement =
- children.customHeader.consumeSingleChildElement();
+ XMLElement headerElement =
children.customHeader.consumeSingleChildElement();
String size =
children.customHeader.consumeRequiredDoubleAttribute("size");
if (!writer.isWidgetElement(headerElement)) {
writer.die(headerElement, "Is not a widget");
@@ -97,53 +95,45 @@
}
}
-private Children findChildren(final XMLElement elem,
- final UiBinderWriter writer) throws UnableToCompleteException {
- final Children children = new Children();
-
- elem.consumeChildElements(new XMLElement.Interpreter<Boolean>() {
- public Boolean interpretElement(XMLElement child)
- throws UnableToCompleteException {
-
- if (hasTag(child, HEADER)) {
- assertFirstHeader();
- children.header = child;
- return true;
- }
-
- if (hasTag(child, CUSTOM)) {
- assertFirstHeader();
- children.customHeader = child;
+ private Children findChildren(final XMLElement elem,
+ final UiBinderWriter writer) throws UnableToCompleteException {
+ final Children children = new Children();
+
+ elem.consumeChildElements(new XMLElement.Interpreter<Boolean>() {
+ public Boolean interpretElement(XMLElement child)
+ throws UnableToCompleteException {
+
+ if (isElementType(elem, child, HEADER)) {
+ assertFirstHeader();
+ children.header = child;
+ return true;
+ }
+
+ if (isElementType(elem, child, CUSTOM)) {
+ assertFirstHeader();
+ children.customHeader = child;
+ return true;
+ }
+
+ // Must be the body, then
+ if (children.body != null) {
+ writer.die(children.body, "May have only one body element");
+ }
+
+ children.body = child;
return true;
}
- // Must be the body, then
- if (null != children.body) {
- writer.die(children.body, "May have only one body element");
- }
-
- children.body = child;
- return true;
- }
-
- void assertFirstHeader() throws UnableToCompleteException {
- if ((null != children.header) && (null != children.customHeader)) {
- writer.die(elem, "May have only one %2$s:header "
- + "or %2$s:customHeader", elem.getPrefix());
- }
- }
-
- private boolean hasTag(XMLElement child, final String attribute) {
- return rightNamespace(child) &&
child.getLocalName().equals(attribute);
- }
-
- private boolean rightNamespace(XMLElement child) {
- return child.getNamespaceUri().equals(elem.getNamespaceUri());
- }
- });
-
- return children;
-}
+ void assertFirstHeader() throws UnableToCompleteException {
+ if (children.header != null || children.customHeader != null) {
+ writer.die(elem, "May have only one <%1$s:header> "
+ + "or <%1$s:customHeader>", elem.getPrefix());
+ }
+ }
+ });
+
+ return children;
+ }
private boolean isElementType(XMLElement parent, XMLElement child,
String type) {
return parent.getNamespaceUri().equals(child.getNamespaceUri())
=======================================
---
/trunk/user/src/com/google/gwt/uibinder/elementparsers/TabLayoutPanelParser.java
Mon Jun 7 12:20:31 2010
+++
/trunk/user/src/com/google/gwt/uibinder/elementparsers/TabLayoutPanelParser.java
Tue Aug 31 08:46:42 2010
@@ -43,9 +43,6 @@
// TabLayoutPanel requires tabBar size and unit ctor args.
String size = panelElem.consumeRequiredDoubleAttribute("barHeight");
- if ("".equals(size)) {
- writer.die(panelElem, "barHeight attribute is required");
- }
JEnumType unitEnumType = writer.getOracle().findType(
Unit.class.getCanonicalName()).isEnum();
@@ -84,8 +81,7 @@
writer.addStatement("%s.add(%s, \"%s\", true);", fieldName,
childFieldName, html);
} else if (children.customHeader != null) {
- XMLElement headerElement =
- children.customHeader.consumeSingleChildElement();
+ XMLElement headerElement =
children.customHeader.consumeSingleChildElement();
if (!writer.isWidgetElement(headerElement)) {
writer.die(headerElement, "Is not a widget");
@@ -110,20 +106,20 @@
public Boolean interpretElement(XMLElement child)
throws UnableToCompleteException {
- if (hasTag(child, HEADER)) {
+ if (isElementType(elem, child, HEADER)) {
assertFirstHeader();
children.header = child;
return true;
}
- if (hasTag(child, CUSTOM)) {
+ if (isElementType(elem, child, CUSTOM)) {
assertFirstHeader();
children.customHeader = child;
return true;
}
// Must be the body, then
- if (null != children.body) {
+ if (children.body != null) {
writer.die(children.body, "May have only one body element");
}
@@ -132,19 +128,11 @@
}
void assertFirstHeader() throws UnableToCompleteException {
- if ((null != children.header) && (null != children.customHeader)) {
- writer.die(elem, "May have only one %1$s:header "
- + "or %1$s:customHeader", elem.getPrefix());
+ if (children.header != null || children.customHeader != null) {
+ writer.die(elem, "May have only one <%1$s:header> "
+ + "or <%1$s:customHeader>", elem.getPrefix());
}
}
-
- private boolean hasTag(XMLElement child, final String attribute) {
- return rightNamespace(child) &&
child.getLocalName().equals(attribute);
- }
-
- private boolean rightNamespace(XMLElement child) {
- return child.getNamespaceUri().equals(elem.getNamespaceUri());
- }
});
return children;
=======================================
---
/trunk/user/src/com/google/gwt/uibinder/elementparsers/TabPanelParser.java
Mon Jun 7 12:20:31 2010
+++
/trunk/user/src/com/google/gwt/uibinder/elementparsers/TabPanelParser.java
Tue Aug 31 08:46:42 2010
@@ -28,57 +28,65 @@
private static final String TAG_TAB = "Tab";
private static final String TAG_TABHTML = "TabHTML";
- public void parse(XMLElement elem, String fieldName, JClassType type,
+ public void parse(XMLElement panelElem, String fieldName, JClassType
type,
UiBinderWriter writer) throws UnableToCompleteException {
- writer.warn(elem,
+ writer.warn(panelElem,
"%1$s:%2$s is deprecated. Use the %1$s:TabLayoutPanel instead.",
- elem.getPrefix(), elem.getLocalName());
+ panelElem.getPrefix(), panelElem.getLocalName());
// Parse children.
- for (XMLElement child : elem.consumeChildElements()) {
+ for (XMLElement tabElem : panelElem.consumeChildElements()) {
// TabPanel can only contain Tab elements.
- String ns = child.getNamespaceUri();
- String tagName = child.getLocalName();
-
- if (!ns.equals(elem.getNamespaceUri())) {
- writer.die(elem, "Invalid TabPanel child namespace: " + ns);
- }
- if (!tagName.equals(TAG_TAB)) {
- writer.die(elem, "Invalid TabPanel child element: " + tagName);
+ if (!isElementType(panelElem, tabElem, TAG_TAB)) {
+ writer.die(tabElem, "Only <%s:%s> children are allowed.",
+ panelElem.getPrefix(), TAG_TAB);
}
- // Get the caption, if any.
- String tabCaption = "";
- if (child.hasAttribute("text")) {
- tabCaption = child.consumeRawAttribute("text");
- }
+ // Get the caption, or null if there is none
+ String tabCaption = tabElem.consumeStringAttribute("text");
// Get the single required child widget.
String tabHTML = null;
String childFieldName = null;
- for (XMLElement tabChild : child.consumeChildElements()) {
+ for (XMLElement tabChild : tabElem.consumeChildElements()) {
if (tabChild.getLocalName().equals(TAG_TABHTML)) {
+ if (tabCaption != null || tabHTML != null) {
+ writer.die(tabElem,
+ "May have only one \"text\" attribute or <%1$s:%2$s>",
+ tabElem.getPrefix(), TAG_TABHTML);
+ }
HtmlInterpreter interpreter =
HtmlInterpreter.newInterpreterForUiObject(
writer, fieldName);
tabHTML = tabChild.consumeInnerHtml(interpreter);
} else {
if (childFieldName != null) {
- writer.die(elem, "%s may only have a single child widget",
child);
+ writer.die(tabChild, "May only have a single child widget");
+ }
+ if (!writer.isWidgetElement(tabChild)) {
+ writer.die(tabChild, "Must be a widget");
}
childFieldName = writer.parseElementToField(tabChild);
}
}
if (childFieldName == null) {
- writer.die(elem, "%s must have a child widget", child);
- }
-
+ writer.die(tabElem, "Must have a child widget");
+ }
if (tabHTML != null) {
writer.addStatement("%1$s.add(%2$s, \"%3$s\", true);", fieldName,
childFieldName, tabHTML);
+ } else if (tabCaption != null) {
+ writer.addStatement("%1$s.add(%2$s, %3$s);", fieldName,
childFieldName,
+ tabCaption);
} else {
- writer.addStatement("%1$s.add(%2$s, \"%3$s\");", fieldName,
- childFieldName, tabCaption);
+ writer.die(tabElem,
+ "Requires either a \"text\" attribute or <%1$s:%2$s>",
+ tabElem.getPrefix(), TAG_TABHTML);
}
}
}
-}
+
+ private boolean isElementType(XMLElement parent, XMLElement child,
String type) {
+ return parent.getNamespaceUri().equals(child.getNamespaceUri())
+ && type.equals(child.getLocalName());
+ }
+}
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java Mon Aug
2 18:45:49 2010
+++ /trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java Tue Aug
31 08:46:42 2010
@@ -27,6 +27,7 @@
import
com.google.gwt.uibinder.attributeparsers.VerticalAlignmentConstantParserTest;
import com.google.gwt.uibinder.elementparsers.AbsolutePanelParserTest;
import com.google.gwt.uibinder.elementparsers.DialogBoxParserTest;
+import com.google.gwt.uibinder.elementparsers.DisclosurePanelParserTest;
import com.google.gwt.uibinder.elementparsers.DockLayoutPanelParserTest;
import com.google.gwt.uibinder.elementparsers.GridParserTest;
import com.google.gwt.uibinder.elementparsers.ImageParserTest;
@@ -36,7 +37,9 @@
import com.google.gwt.uibinder.elementparsers.MenuBarParserTest;
import com.google.gwt.uibinder.elementparsers.MenuItemParserTest;
import com.google.gwt.uibinder.elementparsers.StackLayoutPanelParserTest;
+import com.google.gwt.uibinder.elementparsers.StackPanelParserTest;
import com.google.gwt.uibinder.elementparsers.TabLayoutPanelParserTest;
+import com.google.gwt.uibinder.elementparsers.TabPanelParserTest;
import com.google.gwt.uibinder.elementparsers.UIObjectParserTest;
import com.google.gwt.uibinder.rebind.DesignTimeUtilsTest;
import
com.google.gwt.uibinder.rebind.FieldWriterOfGeneratedCssResourceTest;
@@ -86,6 +89,7 @@
// elementparsers
suite.addTestSuite(AbsolutePanelParserTest.class);
suite.addTestSuite(DialogBoxParserTest.class);
+ suite.addTestSuite(DisclosurePanelParserTest.class);
suite.addTestSuite(DockLayoutPanelParserTest.class);
suite.addTestSuite(GridParserTest.class);
suite.addTestSuite(ImageParserTest.class);
@@ -95,7 +99,9 @@
suite.addTestSuite(MenuBarParserTest.class);
suite.addTestSuite(MenuItemParserTest.class);
suite.addTestSuite(StackLayoutPanelParserTest.class);
+ suite.addTestSuite(StackPanelParserTest.class);
suite.addTestSuite(TabLayoutPanelParserTest.class);
+ suite.addTestSuite(TabPanelParserTest.class);
suite.addTestSuite(UIObjectParserTest.class);
return suite;
=======================================
---
/trunk/user/test/com/google/gwt/uibinder/elementparsers/StackLayoutPanelParserTest.java
Mon Jun 7 12:20:31 2010
+++
/trunk/user/test/com/google/gwt/uibinder/elementparsers/StackLayoutPanelParserTest.java
Tue Aug 31 08:46:42 2010
@@ -20,13 +20,10 @@
import junit.framework.TestCase;
-import org.xml.sax.SAXException;
-
-import java.io.IOException;
import java.util.Iterator;
/**
- * A unit test. Guess what of.
+ * Test for {...@link StackLayoutPanelParser}.
*/
public class StackLayoutPanelParserTest extends TestCase {
@@ -40,23 +37,115 @@
tester = new ElementParserTester(PARSED_TYPE, new
StackLayoutPanelParser());
}
- public void testBadChild() throws SAXException, IOException {
+ public void testBad_notStack() throws Exception {
StringBuffer b = new StringBuffer();
b.append("<g:StackLayoutPanel unit='EM'>");
- b.append(" <g:west><foo/></g:west>");
+ b.append(" <div/>");
b.append("</g:StackLayoutPanel>");
+ parseAndFail(b, "Only <g:stack> children are allowed");
+ }
+
+ public void testBad_noWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackLayoutPanel unit='EM'>");
+ b.append(" <g:stack>");
+ b.append(" </g:stack>");
+ b.append("</g:StackLayoutPanel>");
+
+ parseAndFail(b, "Must have a child widget");
+ }
+
+ public void testBad_notWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackLayoutPanel unit='EM'>");
+ b.append(" <g:stack>");
+ b.append(" <div/>");
+ b.append(" </g:stack>");
+ b.append("</g:StackLayoutPanel>");
+
+ parseAndFail(b, "Must be a widget");
+ }
+
+ public void testBad_twoWidgets() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackLayoutPanel unit='EM'>");
+ b.append(" <g:stack>");
+ b.append(" <g:Button/>");
+ b.append(" <g:Button/>");
+ b.append(" </g:stack>");
+ b.append("</g:StackLayoutPanel>");
+
+ parseAndFail(b, "May have only one body element");
+ }
+
+ public void testBad_noHeader() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackLayoutPanel unit='EM'>");
+ b.append(" <g:stack>");
+ b.append(" <g:Button/>");
+ b.append(" </g:stack>");
+ b.append("</g:StackLayoutPanel>");
+
+ parseAndFail(b, "Requires either a <g:header> or <g:customHeader>");
+ }
+
+ public void testBad_twoHeaders() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackLayoutPanel unit='EM'>");
+ b.append(" <g:stack>");
+ b.append(" <g:header size='3'>foo</g:header>");
+ b.append(" <g:header size='3'>bar</g:header>");
+ b.append(" <g:Button/>");
+ b.append(" </g:stack>");
+ b.append("</g:StackLayoutPanel>");
+
+ parseAndFail(b, "May have only one <g:header> or <g:customHeader>");
+ }
+
+ public void testBad_twoCustomHeaders() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackLayoutPanel unit='EM'>");
+ b.append(" <g:stack>");
+ b.append(" <g:customHeader
size='3'><g:Label>111</g:Label></g:customHeader>");
+ b.append(" <g:customHeader
size='3'><g:Label>222</g:Label></g:customHeader>");
+ b.append(" <g:Button/>");
+ b.append(" </g:stack>");
+ b.append("</g:StackLayoutPanel>");
+
+ parseAndFail(b, "May have only one <g:header> or <g:customHeader>");
+ }
+
+ public void testBad_withCustomHeader_notWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:StackLayoutPanel unit='EM'>");
+ b.append(" <g:stack>");
+ b.append(" <g:customHeader size='3'><div/></g:customHeader>");
+ b.append(" <g:Button/>");
+ b.append(" </g:stack>");
+ b.append("</g:StackLayoutPanel>");
+
+ parseAndFail(b, "Is not a widget", "<div>");
+ }
+
+ /**
+ * Parses bad code in given {...@link StringBuffer} and asserts that failure
+ * message has expected strings.
+ */
+ private void parseAndFail(StringBuffer b, String... expectedFailures)
+ throws Exception {
try {
tester.parse(b.toString());
fail();
} catch (UnableToCompleteException e) {
- assertTrue("expect \"Only g:stack\" error",
- tester.logger.died.contains("Only <g:stack> children"));
+ String died = tester.logger.died;
+ for (String expectedFailure : expectedFailures) {
+ assertTrue(died, died.contains(expectedFailure));
+ }
}
}
- public void testHappy() throws UnableToCompleteException, SAXException,
- IOException {
+ public void testHappy() throws Exception {
StringBuffer b = new StringBuffer();
b.append("<g:StackLayoutPanel unit='PX'>");
b.append(" <g:stack>");
@@ -71,24 +160,16 @@
b.append(" </g:stack>");
b.append("</g:StackLayoutPanel>");
- String[] expected = {
- "fieldName.add(<g:Label id='able'>, \"Re<b>mark</b>able\", true,
3);",
- "fieldName.add(<g:Label id='baker'>, " + "<g:Label id='custom'>,
3);",};
-
FieldWriter w = tester.parse(b.toString());
assertEquals("new " + PARSED_TYPE
+ "(com.google.gwt.dom.client.Style.Unit.PX)", w.getInitializer());
- Iterator<String> i = tester.writer.statements.iterator();
- for (String e : expected) {
- assertEquals(e, i.next());
- }
- assertFalse(i.hasNext());
- assertNull(tester.logger.died);
+ assertStatements(
+ "fieldName.add(<g:Label id='able'>, \"Re<b>mark</b>able\", true,
3);",
+ "fieldName.add(<g:Label id='baker'>, " + "<g:Label id='custom'>,
3);");
}
- public void testNoUnits() throws SAXException, IOException,
- UnableToCompleteException {
+ public void testNoUnits() throws Exception {
StringBuffer b = new StringBuffer();
b.append(" <g:StackLayoutPanel>");
b.append(" </g:StackLayoutPanel>");
@@ -97,7 +178,15 @@
assertEquals("new " + PARSED_TYPE
+ "(com.google.gwt.dom.client.Style.Unit.PX)", w.getInitializer());
+ assertStatements();
+ }
+
+ private void assertStatements(String... expected) {
Iterator<String> i = tester.writer.statements.iterator();
+ for (String e : expected) {
+ assertEquals(e, i.next());
+ }
assertFalse(i.hasNext());
+ assertNull(tester.logger.died);
}
}
=======================================
---
/trunk/user/test/com/google/gwt/uibinder/elementparsers/TabLayoutPanelParserTest.java
Tue Nov 10 12:33:30 2009
+++
/trunk/user/test/com/google/gwt/uibinder/elementparsers/TabLayoutPanelParserTest.java
Tue Aug 31 08:46:42 2010
@@ -20,13 +20,10 @@
import junit.framework.TestCase;
-import org.xml.sax.SAXException;
-
-import java.io.IOException;
import java.util.Iterator;
/**
- * A unit test. Guess what of.
+ * Test for {...@link TabLayoutPanelParser}.
*/
public class TabLayoutPanelParserTest extends TestCase {
@@ -40,22 +37,122 @@
tester = new ElementParserTester(PARSED_TYPE, new
TabLayoutPanelParser());
}
- public void testBadChild() throws SAXException, IOException {
+ public void testBad_noBarHeight() throws Exception {
StringBuffer b = new StringBuffer();
- b.append("<g:TabLayoutPanel unit='EM'>");
- b.append(" <g:west><foo/></g:west>");
+ b.append("<g:TabLayoutPanel/>");
+
+ parseAndFail(b, "Missing required attribute", "barHeight");
+ }
+
+ public void testBad_notTab() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabLayoutPanel barHeight='2'>");
+ b.append(" <div/>");
b.append("</g:TabLayoutPanel>");
+ parseAndFail(b, "Only <g:tab> children are allowed");
+ }
+
+ public void testBad_noWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabLayoutPanel barHeight='2'>");
+ b.append(" <g:tab>");
+ b.append(" </g:tab>");
+ b.append("</g:TabLayoutPanel>");
+
+ parseAndFail(b, "Must have a child widget");
+ }
+
+ public void testBad_notWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabLayoutPanel barHeight='2'>");
+ b.append(" <g:tab>");
+ b.append(" <div/>");
+ b.append(" </g:tab>");
+ b.append("</g:TabLayoutPanel>");
+
+ parseAndFail(b, "Must be a widget");
+ }
+
+ public void testBad_twoWidgets() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabLayoutPanel barHeight='2'>");
+ b.append(" <g:tab>");
+ b.append(" <g:Button/>");
+ b.append(" <g:Button/>");
+ b.append(" </g:tab>");
+ b.append("</g:TabLayoutPanel>");
+
+ parseAndFail(b, "May have only one body element");
+ }
+
+ public void testBad_noHeader() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabLayoutPanel barHeight='2'>");
+ b.append(" <g:tab>");
+ b.append(" <g:Button/>");
+ b.append(" </g:tab>");
+ b.append("</g:TabLayoutPanel>");
+
+ parseAndFail(b, "Requires either a <g:header> or <g:customHeader>");
+ }
+
+ public void testBad_twoHeaders() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabLayoutPanel barHeight='2'>");
+ b.append(" <g:tab>");
+ b.append(" <g:header size='3'>foo</g:header>");
+ b.append(" <g:header size='3'>bar</g:header>");
+ b.append(" <g:Button/>");
+ b.append(" </g:tab>");
+ b.append("</g:TabLayoutPanel>");
+
+ parseAndFail(b, "May have only one <g:header> or <g:customHeader>");
+ }
+
+ public void testBad_twoCustomHeaders() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabLayoutPanel barHeight='2'>");
+ b.append(" <g:tab>");
+ b.append(" <g:customHeader
size='3'><g:Label>foo</g:Label></g:customHeader>");
+ b.append(" <g:customHeader
size='3'><g:Label>bar</g:Label></g:customHeader>");
+ b.append(" <g:Button/>");
+ b.append(" </g:tab>");
+ b.append("</g:TabLayoutPanel>");
+
+ parseAndFail(b, "May have only one <g:header> or <g:customHeader>");
+ }
+
+ public void testBad_customHeader_notWidget() throws Exception {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:TabLayoutPanel barHeight='2'>");
+ b.append(" <g:tab>");
+ b.append(" <g:customHeader size='3'><div/></g:customHeader>");
+ b.append(" <g:Button/>");
+ b.append(" </g:tab>");
+ b.append("</g:TabLayoutPanel>");
+
+ parseAndFail(b, "Is not a widget", "<div>");
+ }
+
+ /**
+ * Parses bad code in given {...@link StringBuffer} and asserts that failure
+ * message has expected strings.
+ */
+ private void parseAndFail(StringBuffer b, String... expectedFailures)
+ throws Exception {
try {
tester.parse(b.toString());
fail();
} catch (UnableToCompleteException e) {
- assertNotNull(tester.logger.died);
+ String died = tester.logger.died;
+ for (String expectedFailure : expectedFailures) {
+ assertTrue(died, died.contains(expectedFailure));
+ }
}
}
- public void testHappy() throws UnableToCompleteException, SAXException,
- IOException {
+ public void testHappy() throws Exception {
StringBuffer b = new StringBuffer();
b.append("<g:TabLayoutPanel barUnit='PX' barHeight='30'>");
b.append(" <g:tab>");
@@ -86,8 +183,7 @@
assertNull(tester.logger.died);
}
- public void testNoUnits() throws SAXException, IOException,
- UnableToCompleteException {
+ public void testNoUnits() throws Exception {
StringBuffer b = new StringBuffer();
b.append("<g:TabLayoutPanel barHeight='3'>");
b.append(" </g:TabLayoutPanel>");
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Mon
Aug 2 18:45:49 2010
+++ /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Tue
Aug 31 08:46:42 2010
@@ -106,6 +106,17 @@
code.append("}\n");
return code;
}
+ };
+ public static final MockJavaResource DISCLOSURE_PANEL = new
MockJavaResource(
+ "com.google.gwt.user.client.ui.DisclosurePanel") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuffer code = new StringBuffer();
+ code.append("package com.google.gwt.user.client.ui;\n");
+ code.append("public class DisclosurePanel extends Widget {\n");
+ code.append("}\n");
+ return code;
+ }
};
public static final MockJavaResource DOCK_LAYOUT_PANEL = new
MockJavaResource(
"com.google.gwt.user.client.ui.DockLayoutPanel") {
@@ -362,6 +373,17 @@
code.append("}\n");
return code;
}
+ };
+ public static final MockJavaResource STACK_PANEL = new MockJavaResource(
+ "com.google.gwt.user.client.ui.StackPanel") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuffer code = new StringBuffer();
+ code.append("package com.google.gwt.user.client.ui;\n");
+ code.append("public class StackPanel extends Widget {\n");
+ code.append("}\n");
+ return code;
+ }
};
public static final MockJavaResource STYLE = new MockJavaResource(
"com.google.gwt.dom.client.Style") {
@@ -385,6 +407,17 @@
code.append("}\n");
return code;
}
+ };
+ public static final MockJavaResource TAB_PANEL = new MockJavaResource(
+ "com.google.gwt.user.client.ui.TabPanel") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuffer code = new StringBuffer();
+ code.append("package com.google.gwt.user.client.ui;\n");
+ code.append("public class TabPanel extends Widget {\n");
+ code.append("}\n");
+ return code;
+ }
};
public static final MockJavaResource TEXT_BOX_BASE = new
MockJavaResource(
"com.google.gwt.user.client.ui.TextBoxBase") {
@@ -459,6 +492,7 @@
rtn.add(CLICK_HANDLER);
rtn.add(COMMAND);
rtn.add(DIALOG_BOX);
+ rtn.add(DISCLOSURE_PANEL);
rtn.add(DOCK_LAYOUT_PANEL);
rtn.add(ELEMENT);
rtn.add(EVENT_HANDLER);
@@ -480,8 +514,10 @@
rtn.add(MOUSE_OVER_HANDLER);
rtn.add(SPLIT_LAYOUT_PANEL);
rtn.add(STACK_LAYOUT_PANEL);
+ rtn.add(STACK_PANEL);
rtn.add(STYLE);
rtn.add(TAB_LAYOUT_PANEL);
+ rtn.add(TAB_PANEL);
rtn.add(TEXT_BOX_BASE);
rtn.add(UI_OBJECT);
rtn.add(UI_BINDER);
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors