Adds parsers for LayoutPanel and Length attributes.
Review: http://gwt-code-reviews.appspot.com/103806
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7030 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/javadoc/com/google/gwt/examples/StackLayoutPanelExample.java b/user/javadoc/com/google/gwt/examples/StackLayoutPanelExample.java
index deee46b..b92878f 100644
--- a/user/javadoc/com/google/gwt/examples/StackLayoutPanelExample.java
+++ b/user/javadoc/com/google/gwt/examples/StackLayoutPanelExample.java
@@ -26,9 +26,9 @@
public void onModuleLoad() {
// Create a three-item stack, with headers sized in EMs.
StackLayoutPanel p = new StackLayoutPanel(Unit.EM);
- p.add(new HTML("this"), new HTML("[this]"), 128);
- p.add(new HTML("that"), new HTML("[that]"), 384);
- p.add(new HTML("the other"), new HTML("[the other]"), 0);
+ p.add(new HTML("this"), new HTML("[this]"), 4);
+ p.add(new HTML("that"), new HTML("[that]"), 4);
+ p.add(new HTML("the other"), new HTML("[the other]"), 4);
// Attach the LayoutPanel to the RootLayoutPanel. The latter will listen for
// resize events on the window to ensure that its children are informed of
diff --git a/user/src/com/google/gwt/uibinder/attributeparsers/AttributeParsers.java b/user/src/com/google/gwt/uibinder/attributeparsers/AttributeParsers.java
index d097769..36fdf79 100644
--- a/user/src/com/google/gwt/uibinder/attributeparsers/AttributeParsers.java
+++ b/user/src/com/google/gwt/uibinder/attributeparsers/AttributeParsers.java
@@ -37,6 +37,7 @@
private static final String STRING = String.class.getCanonicalName();
private static final String DOUBLE = "double";
private static final String BOOLEAN = "boolean";
+ private static final String UNIT = "com.google.gwt.dom.client.Style.Unit";
private final MortalLogger logger;
private final FieldReferenceConverter converter;
@@ -77,6 +78,11 @@
addAttributeParser(STRING, new StringAttributeParser(converter,
types.parse(STRING)));
+
+ EnumAttributeParser unitParser = new EnumAttributeParser(converter,
+ (JEnumType) types.parse(UNIT), logger);
+ addAttributeParser(DOUBLE + "," + UNIT, new LengthAttributeParser(
+ doubleParser, unitParser, logger));
} catch (TypeOracleException e) {
throw new RuntimeException(e);
}
diff --git a/user/src/com/google/gwt/uibinder/attributeparsers/LengthAttributeParser.java b/user/src/com/google/gwt/uibinder/attributeparsers/LengthAttributeParser.java
new file mode 100644
index 0000000..d111e67
--- /dev/null
+++ b/user/src/com/google/gwt/uibinder/attributeparsers/LengthAttributeParser.java
@@ -0,0 +1,78 @@
+/*
+ * 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.attributeparsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.uibinder.rebind.MortalLogger;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Parses a CSS length value (e.g., "2em", "50%"), returning a comma-separated
+ * (double, Unit) pair.
+ */
+public class LengthAttributeParser implements AttributeParser {
+
+ static final String UNIT = "com.google.gwt.dom.client.Style.Unit";
+
+ // This regular expression matches CSS length patterns of the form
+ // (value)(unit), where the two may be separated by whitespace. Either part
+ // can be a {class.method} expression.
+ private static final Pattern pattern = Pattern.compile(
+ "((?:\\{[\\w\\.]+\\})|[\\d\\.]+)\\s*(\\{?[\\w\\.\\%]*\\}?)?");
+
+ private final MortalLogger logger;
+ private final DoubleAttributeParser doubleParser;
+ private final EnumAttributeParser enumParser;
+
+ public LengthAttributeParser(DoubleAttributeParser doubleParser,
+ EnumAttributeParser enumParser, MortalLogger logger) {
+ this.doubleParser = doubleParser;
+ this.enumParser = enumParser;
+ this.logger = logger;
+ }
+
+ public String parse(String lengthStr) throws UnableToCompleteException {
+ Matcher matcher = pattern.matcher(lengthStr);
+ if (!matcher.matches()) {
+ logger.die("Unable to parse %s as length", lengthStr);
+ }
+
+ String valueStr = matcher.group(1);
+ String value = doubleParser.parse(valueStr);
+
+ String unit = null;
+ String unitStr = matcher.group(2);
+ if (unitStr.length() > 0) {
+ if (!unitStr.startsWith("{")) {
+ // For non-refs, convert % => PCT, px => PX, etc.
+ if ("%".equals(unitStr)) {
+ unitStr = "PCT";
+ }
+ unitStr = unitStr.toUpperCase();
+ }
+
+ // Now let the default enum parser handle it.
+ unit = enumParser.parse(unitStr);
+ } else {
+ // Use PX by default.
+ unit = UNIT + ".PX";
+ }
+
+ return value + ", " + unit;
+ }
+}
diff --git a/user/src/com/google/gwt/uibinder/elementparsers/LayoutPanelParser.java b/user/src/com/google/gwt/uibinder/elementparsers/LayoutPanelParser.java
new file mode 100644
index 0000000..ccd20f5
--- /dev/null
+++ b/user/src/com/google/gwt/uibinder/elementparsers/LayoutPanelParser.java
@@ -0,0 +1,119 @@
+/*
+ * 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;
+
+/**
+ * Parses {@link LayoutPanel} widgets.
+ */
+public class LayoutPanelParser implements ElementParser {
+
+ private static final String ERR_PAIRING = "In %s %s, 'left' must be paired with 'right' or 'width'.";
+ private static final String ERR_TOO_MANY = "In %s %s, there are too many %s constraints.";
+ private static final String LAYER = "layer";
+
+ public void parse(XMLElement elem, String fieldName, JClassType type,
+ UiBinderWriter writer) throws UnableToCompleteException {
+
+ // Parse children.
+ for (XMLElement layerElem : elem.consumeChildElements()) {
+ // Get the layer element.
+ if (!isElementType(elem, layerElem, LAYER)) {
+ writer.die("In %s, only <%s:%s> children are allowed.", elem,
+ elem.getPrefix(), LAYER);
+ }
+
+ // Get the child widget element.
+ String childFieldName = writer.parseElementToField(
+ layerElem.consumeSingleChildElement());
+ writer.addStatement("%1$s.add(%2$s);", fieldName, childFieldName);
+
+ // Parse the horizontal layout constraints.
+ String left = maybeConsumeLengthAttribute(layerElem, "left");
+ String right = maybeConsumeLengthAttribute(layerElem, "right");
+ String width = maybeConsumeLengthAttribute(layerElem, "width");
+
+ if (left != null) {
+ if (right != null) {
+ if (width != null) {
+ writer.die(ERR_TOO_MANY, elem, layerElem, "horizontal");
+ }
+ generateConstraint(fieldName, childFieldName, "LeftRight", left,
+ right, writer);
+ } else if (width != null) {
+ generateConstraint(fieldName, childFieldName, "LeftWidth", left,
+ width, writer);
+ } else {
+ writer.die(ERR_PAIRING, elem, layerElem, "left", "right", "width");
+ }
+ } else if (right != null) {
+ if (width != null) {
+ generateConstraint(fieldName, childFieldName, "RightWidth", right,
+ width, writer);
+ } else {
+ writer.die(ERR_PAIRING, elem, layerElem, "right", "left", "width");
+ }
+ }
+
+ // Parse the vertical layout constraints.
+ String top = maybeConsumeLengthAttribute(layerElem, "top");
+ String bottom = maybeConsumeLengthAttribute(layerElem, "bottom");
+ String height = maybeConsumeLengthAttribute(layerElem, "height");
+
+ if (top != null) {
+ if (bottom != null) {
+ if (height != null) {
+ writer.die(ERR_TOO_MANY, elem, layerElem, "vertical");
+ }
+ generateConstraint(fieldName, childFieldName, "TopBottom", top,
+ bottom, writer);
+ } else if (height != null) {
+ generateConstraint(fieldName, childFieldName, "TopHeight", top,
+ height, writer);
+ } else {
+ writer.die(ERR_PAIRING, elem, layerElem, "top", "bottom", "height");
+ }
+ } else if (bottom != null) {
+ if (height != null) {
+ generateConstraint(fieldName, childFieldName, "BottomHeight", bottom,
+ height, writer);
+ } else {
+ writer.die(ERR_PAIRING, elem, layerElem, "bottom", "top", "height");
+ }
+ }
+ }
+ }
+
+ private void generateConstraint(String panelName, String widgetName,
+ String constraintName, String first, String second, UiBinderWriter writer) {
+ writer.addStatement("%s.setWidget%s(%s, %s, %s);", panelName,
+ constraintName, widgetName, first, second);
+ }
+
+ private boolean isElementType(XMLElement parent, XMLElement child, String type) {
+ return parent.getNamespaceUri().equals(child.getNamespaceUri())
+ && type.equals(child.getLocalName());
+ }
+
+ private String maybeConsumeLengthAttribute(XMLElement elem, String name)
+ throws UnableToCompleteException {
+ return elem.hasAttribute(name) ? elem.consumeLengthAttribute(name) : null;
+ }
+}
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
index 36e26fe..98133e7 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
@@ -941,6 +941,7 @@
addWidgetParser("CellPanel");
addWidgetParser("CustomButton");
addWidgetParser("DialogBox");
+ addWidgetParser("LayoutPanel");
addWidgetParser("DockLayoutPanel");
addWidgetParser("StackLayoutPanel");
addWidgetParser("TabLayoutPanel");
diff --git a/user/src/com/google/gwt/uibinder/rebind/XMLElement.java b/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
index 78ba5aa..8ca2495 100644
--- a/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
+++ b/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
@@ -16,9 +16,11 @@
package com.google.gwt.uibinder.rebind;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.core.ext.typeinfo.TypeOracleException;
+import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.uibinder.attributeparsers.AttributeParser;
import com.google.gwt.uibinder.attributeparsers.AttributeParsers;
@@ -223,7 +225,7 @@
*/
public String consumeAttributeWithDefault(String name, String defaultValue,
JType type) throws UnableToCompleteException {
- return consumeAttributeWithDefault(name, defaultValue, new JType[] {type});
+ return consumeAttributeWithDefault(name, defaultValue, new JType[] { type });
}
/**
@@ -444,6 +446,21 @@
}
/**
+ * Convenience method for parsing the named attribute as a CSS length value.
+ *
+ * @return a (double, Unit) pair literal, an expression that will evaluate to
+ * such a pair in the generated code, or "" if there is no such
+ * attribute
+ *
+ * @throws UnableToCompleteException on unparseable value
+ */
+ public String consumeLengthAttribute(String name)
+ throws UnableToCompleteException {
+ return consumeAttributeWithDefault(name, "", new JType[] { getDoubleType(),
+ getUnitType() });
+ }
+
+ /**
* Consumes all attributes, and returns a string representing the entire
* opening tag. E.g., "<div able='baker'>"
*/
@@ -516,10 +533,9 @@
public String consumeRequiredAttribute(String name, JType... types)
throws UnableToCompleteException {
/*
- * TODO(rjrjr) We have to get the attribute to
- * get the parser, and we must get the attribute before we consume the
- * value. This nasty subtlety is all down to BundleParsers, which we'll
- * hopefully kill off soon.
+ * TODO(rjrjr) We have to get the attribute to get the parser, and we must
+ * get the attribute before we consume the value. This nasty subtlety is all
+ * down to BundleParsers, which we'll hopefully kill off soon.
*/
XMLAttribute attribute = getAttribute(name);
if (attribute == null) {
@@ -807,7 +823,8 @@
private JType getImageResourceType() {
if (imageResourceType == null) {
- imageResourceType = oracle.findType(ImageResource.class.getCanonicalName());
+ imageResourceType = oracle.findType(
+ ImageResource.class.getCanonicalName());
}
return imageResourceType;
}
@@ -843,4 +860,8 @@
}
return stringType;
}
+
+ private JClassType getUnitType() {
+ return oracle.findType(Unit.class.getCanonicalName()).isEnum();
+ }
}
diff --git a/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java b/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
index a9d0fef..eac3f1c 100644
--- a/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
+++ b/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
@@ -18,11 +18,13 @@
import com.google.gwt.uibinder.attributeparsers.CssNameConverterTest;
import com.google.gwt.uibinder.attributeparsers.FieldReferenceConverterTest;
import com.google.gwt.uibinder.attributeparsers.IntAttributeParserTest;
+import com.google.gwt.uibinder.attributeparsers.LengthAttributeParserTest;
import com.google.gwt.uibinder.attributeparsers.StrictAttributeParserTest;
import com.google.gwt.uibinder.attributeparsers.StringAttributeParserTest;
import com.google.gwt.uibinder.elementparsers.DialogBoxParserTest;
import com.google.gwt.uibinder.elementparsers.DockLayoutPanelParserTest;
import com.google.gwt.uibinder.elementparsers.IsEmptyParserTest;
+import com.google.gwt.uibinder.elementparsers.LayoutPanelParserTest;
import com.google.gwt.uibinder.elementparsers.StackLayoutPanelParserTest;
import com.google.gwt.uibinder.elementparsers.TabLayoutPanelParserTest;
import com.google.gwt.uibinder.elementparsers.UIObjectParserTest;
@@ -61,11 +63,13 @@
suite.addTestSuite(FieldReferenceConverterTest.class);
suite.addTestSuite(StrictAttributeParserTest.class);
suite.addTestSuite(StringAttributeParserTest.class);
+ suite.addTestSuite(LengthAttributeParserTest.class);
// elementparsers
suite.addTestSuite(DialogBoxParserTest.class);
suite.addTestSuite(DockLayoutPanelParserTest.class);
suite.addTestSuite(IsEmptyParserTest.class);
+ suite.addTestSuite(LayoutPanelParserTest.class);
suite.addTestSuite(StackLayoutPanelParserTest.class);
suite.addTestSuite(TabLayoutPanelParserTest.class);
suite.addTestSuite(UIObjectParserTest.class);
diff --git a/user/test/com/google/gwt/uibinder/attributeparsers/LengthAttributeParserTest.java b/user/test/com/google/gwt/uibinder/attributeparsers/LengthAttributeParserTest.java
new file mode 100644
index 0000000..1e222d4
--- /dev/null
+++ b/user/test/com/google/gwt/uibinder/attributeparsers/LengthAttributeParserTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.attributeparsers;
+
+import static com.google.gwt.uibinder.attributeparsers.LengthAttributeParser.UNIT;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JEnumType;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.javac.CompilationState;
+import com.google.gwt.dev.javac.CompilationStateBuilder;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.uibinder.rebind.MortalLogger;
+import com.google.gwt.uibinder.test.UiJavaResources;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link LengthAttributeParser}.
+ */
+public class LengthAttributeParserTest extends TestCase {
+
+ private LengthAttributeParser parser;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ MortalLogger logger = MortalLogger.NULL;
+
+ CompilationState state = CompilationStateBuilder.buildFrom(
+ logger.getTreeLogger(), UiJavaResources.getUiResources());
+ TypeOracle types = state.getTypeOracle();
+
+ FieldReferenceConverter converter = new FieldReferenceConverter(null);
+ DoubleAttributeParser doubleParser = new DoubleAttributeParser(converter,
+ types.parse("double"), logger);
+
+ JEnumType enumType = (JEnumType) types.findType(
+ Unit.class.getCanonicalName()).isEnum();
+ EnumAttributeParser enumParser = new EnumAttributeParser(converter,
+ enumType, logger);
+ parser = new LengthAttributeParser(doubleParser, enumParser, logger);
+ }
+
+ public void testGood() throws UnableToCompleteException {
+ assertEquals(lengthString("0", "PX"), parser.parse("0"));
+ assertEquals(lengthString("0", "PT"), parser.parse("0pt"));
+
+ assertEquals(lengthString("1", "PX"), parser.parse("1"));
+
+ assertEquals(lengthString("1", "PX"), parser.parse("1px"));
+ assertEquals(lengthString("1", "PCT"), parser.parse("1%"));
+ assertEquals(lengthString("1", "CM"), parser.parse("1cm"));
+ assertEquals(lengthString("1", "MM"), parser.parse("1mm"));
+ assertEquals(lengthString("1", "IN"), parser.parse("1in"));
+ assertEquals(lengthString("1", "PC"), parser.parse("1pc"));
+ assertEquals(lengthString("1", "PT"), parser.parse("1pt"));
+ assertEquals(lengthString("1", "EM"), parser.parse("1em"));
+ assertEquals(lengthString("1", "EX"), parser.parse("1ex"));
+
+ assertEquals(lengthString("1", "PX"), parser.parse("1PX"));
+ assertEquals(lengthString("1", "PCT"), parser.parse("1PCT"));
+ assertEquals(lengthString("1", "CM"), parser.parse("1CM"));
+ assertEquals(lengthString("1", "MM"), parser.parse("1MM"));
+ assertEquals(lengthString("1", "IN"), parser.parse("1IN"));
+ assertEquals(lengthString("1", "PC"), parser.parse("1PC"));
+ assertEquals(lengthString("1", "PT"), parser.parse("1PT"));
+ assertEquals(lengthString("1", "EM"), parser.parse("1EM"));
+ assertEquals(lengthString("1", "EX"), parser.parse("1EX"));
+
+ assertEquals(lengthString("2.5", "EM"), parser.parse("2.5em"));
+
+ assertEquals(lengthString("1", "EM"), parser.parse("1 em"));
+
+ assertEquals("(double)foo.value(), " + UNIT + ".PX",
+ parser.parse("{foo.value}px"));
+ assertEquals("1, foo.unit()",
+ parser.parse("1{foo.unit}"));
+ assertEquals("(double)foo.value(), foo.unit()",
+ parser.parse("{foo.value}{foo.unit}"));
+ }
+
+ public void testBad() {
+ // Garbage.
+ try {
+ parser.parse("fnord");
+ fail("Expected UnableToCompleteException");
+ } catch (UnableToCompleteException e) {
+ /* pass */
+ }
+
+ // Non-decimal value.
+ try {
+ parser.parse("xpx");
+ fail("Expected UnableToCompleteException");
+ } catch (UnableToCompleteException e) {
+ /* pass */
+ }
+
+ // Raw unit, no value.
+ try {
+ parser.parse("px");
+ fail("Expected UnableToCompleteException");
+ } catch (UnableToCompleteException e) {
+ /* pass */
+ }
+
+ // 0, but with invalid unit.
+ try {
+ parser.parse("0foo");
+ fail("Expected UnableToCompleteException");
+ } catch (UnableToCompleteException e) {
+ /* pass */
+ }
+
+ // Too many braces cases.
+ try {
+ parser.parse("{{foo.value}px");
+ fail("Expected UnableToCompleteException");
+ } catch (UnableToCompleteException e) {
+ /* pass */
+ }
+
+ try {
+ parser.parse("1{{foo.unit}");
+ fail("Expected UnableToCompleteException");
+ } catch (UnableToCompleteException e) {
+ /* pass */
+ }
+ }
+
+ private String lengthString(String value, String unit) {
+ return value + ", " + UNIT + "." + unit;
+ }
+}
diff --git a/user/test/com/google/gwt/uibinder/elementparsers/LayoutPanelParserTest.java b/user/test/com/google/gwt/uibinder/elementparsers/LayoutPanelParserTest.java
new file mode 100644
index 0000000..02aa182
--- /dev/null
+++ b/user/test/com/google/gwt/uibinder/elementparsers/LayoutPanelParserTest.java
@@ -0,0 +1,216 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+/**
+ * A unit test. Guess what of.
+ */
+public class LayoutPanelParserTest extends TestCase {
+
+ private static final String PARSED_TYPE = "com.google.gwt.user.client.ui.LayoutPanel";
+
+ private ElementParserTester tester;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ tester = new ElementParserTester(PARSED_TYPE, new LayoutPanelParser());
+ }
+
+ public void testBadChild() throws SAXException, IOException {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:LayoutPanel>");
+ b.append(" <g:blah/>");
+ b.append("</g:LayoutPanel>");
+
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ assertTrue("expect \"only g:layer\" error",
+ tester.logger.died.contains("only <g:layer> children"));
+ }
+ }
+
+ public void testBadValue() throws SAXException, IOException {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:LayoutPanel>");
+ b.append(" <g:layer left='goosnarg'><g:HTML/></g:layer>");
+ b.append("</g:LayoutPanel>");
+
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ assertTrue("expect \"Unable to parse\" error",
+ tester.logger.died.contains("Unable to parse"));
+ }
+ }
+
+ public void testHappy() throws UnableToCompleteException, SAXException,
+ IOException {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:LayoutPanel>");
+ b.append(" <g:layer>");
+ b.append(" <g:Label id='foo0'>nada</g:Label>");
+ b.append(" </g:layer>");
+
+ b.append(" <g:layer left='1em' width='1px'>");
+ b.append(" <g:Label id='foo1'>left-width</g:Label>");
+ b.append(" </g:layer>");
+ b.append(" <g:layer right='1em' width='1px'>");
+ b.append(" <g:Label id='foo2'>right-width</g:Label>");
+ b.append(" </g:layer>");
+ b.append(" <g:layer left='1em' right='1px'>");
+ b.append(" <g:Label id='foo3'>left-right</g:Label>");
+ b.append(" </g:layer>");
+
+ b.append(" <g:layer top='1em' height='50%'>");
+ b.append(" <g:Label id='foo4'>top-height</g:Label>");
+ b.append(" </g:layer>");
+ b.append(" <g:layer bottom='1em' height='50%'>");
+ b.append(" <g:Label id='foo5'>bottom-height</g:Label>");
+ b.append(" </g:layer>");
+ b.append(" <g:layer top='1em' bottom='50%'>");
+ b.append(" <g:Label id='foo6'>top-bottom</g:Label>");
+ b.append(" </g:layer>");
+
+ b.append(" <g:layer top='{foo.value}em' height='50{foo.unit}'>");
+ b.append(" <g:Label id='foo7'>top-height</g:Label>");
+ b.append(" </g:layer>");
+ b.append("</g:LayoutPanel>");
+
+ String[] expected = {
+ "fieldName.add(<g:Label id='foo0'>);",
+
+ "fieldName.add(<g:Label id='foo1'>);",
+ "fieldName.setWidgetLeftWidth(<g:Label id='foo1'>, 1, "
+ + "com.google.gwt.dom.client.Style.Unit.EM, 1, com.google.gwt.dom.client.Style.Unit.PX);",
+ "fieldName.add(<g:Label id='foo2'>);",
+ "fieldName.setWidgetRightWidth(<g:Label id='foo2'>, 1, "
+ + "com.google.gwt.dom.client.Style.Unit.EM, 1, com.google.gwt.dom.client.Style.Unit.PX);",
+ "fieldName.add(<g:Label id='foo3'>);",
+ "fieldName.setWidgetLeftRight(<g:Label id='foo3'>, 1, "
+ + "com.google.gwt.dom.client.Style.Unit.EM, 1, com.google.gwt.dom.client.Style.Unit.PX);",
+
+ "fieldName.add(<g:Label id='foo4'>);",
+ "fieldName.setWidgetTopHeight(<g:Label id='foo4'>, 1, "
+ + "com.google.gwt.dom.client.Style.Unit.EM, 50, com.google.gwt.dom.client.Style.Unit.PCT);",
+ "fieldName.add(<g:Label id='foo5'>);",
+ "fieldName.setWidgetBottomHeight(<g:Label id='foo5'>, 1, "
+ + "com.google.gwt.dom.client.Style.Unit.EM, 50, com.google.gwt.dom.client.Style.Unit.PCT);",
+ "fieldName.add(<g:Label id='foo6'>);",
+ "fieldName.setWidgetTopBottom(<g:Label id='foo6'>, 1, "
+ + "com.google.gwt.dom.client.Style.Unit.EM, 50, com.google.gwt.dom.client.Style.Unit.PCT);",
+
+ "fieldName.add(<g:Label id='foo7'>);",
+ "fieldName.setWidgetTopHeight(<g:Label id='foo7'>, (double)foo.value(), "
+ + "com.google.gwt.dom.client.Style.Unit.EM, 50, foo.unit());" };
+
+ tester.parse(b.toString());
+
+ Iterator<String> i = tester.writer.statements.iterator();
+ for (String e : expected) {
+ assertEquals(e, i.next());
+ }
+ assertFalse(i.hasNext());
+ assertNull(tester.logger.died);
+ }
+
+ public void testLonelyBottom() throws SAXException, IOException {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:LayoutPanel>");
+ b.append(" <g:layer bottom='0'><g:HTML/></g:layer>");
+ b.append("</g:LayoutPanel>");
+
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ assertTrue("expect \"must be paired\" error",
+ tester.logger.died.contains("must be paired"));
+ }
+ }
+
+ public void testLonelyLeft() throws SAXException, IOException {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:LayoutPanel>");
+ b.append(" <g:layer left='0'><g:HTML/></g:layer>");
+ b.append("</g:LayoutPanel>");
+
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ assertTrue("expect \"must be paired\" error",
+ tester.logger.died.contains("must be paired"));
+ }
+ }
+
+ public void testLonelyRight() throws SAXException, IOException {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:LayoutPanel>");
+ b.append(" <g:layer right='0'><g:HTML/></g:layer>");
+ b.append("</g:LayoutPanel>");
+
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ assertTrue("expect \"must be paired\" error",
+ tester.logger.died.contains("must be paired"));
+ }
+ }
+
+ public void testLonelyTop() throws SAXException, IOException {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:LayoutPanel>");
+ b.append(" <g:layer top='0'><g:HTML/></g:layer>");
+ b.append("</g:LayoutPanel>");
+
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ assertTrue("expect \"must be paired\" error",
+ tester.logger.died.contains("must be paired"));
+ }
+ }
+
+ public void testOverConstrained() throws SAXException, IOException {
+ StringBuffer b = new StringBuffer();
+ b.append("<g:LayoutPanel>");
+ b.append(" <g:layer left='0' width='0' right='0'><g:HTML/></g:layer>");
+ b.append("</g:LayoutPanel>");
+
+ try {
+ tester.parse(b.toString());
+ fail();
+ } catch (UnableToCompleteException e) {
+ assertTrue("expect \"too many\" error",
+ tester.logger.died.contains("too many"));
+ }
+ }
+}
diff --git a/user/test/com/google/gwt/uibinder/test/UiJavaResources.java b/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
index 8e4401f..82969c2 100644
--- a/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
+++ b/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
@@ -88,6 +88,17 @@
return code;
}
};
+ public static final MockJavaResource LAYOUT_PANEL = new MockJavaResource(
+ "com.google.gwt.user.client.ui.LayoutPanel") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuffer code = new StringBuffer();
+ code.append("package com.google.gwt.user.client.ui;\n");
+ code.append("public class LayoutPanel extends Widget {\n");
+ code.append("}\n");
+ return code;
+ }
+ };
public static final MockJavaResource SPLIT_LAYOUT_PANEL = new MockJavaResource(
"com.google.gwt.user.client.ui.SplitLayoutPanel") {
@Override
@@ -117,7 +128,7 @@
StringBuffer code = new StringBuffer();
code.append("package com.google.gwt.dom.client;\n");
code.append("public class Style {\n");
- code.append(" public enum Unit { PX, PT, EM };\n");
+ code.append(" public enum Unit { PX, PCT, EM, EX, PT, PC, IN, CM, MM };\n");
code.append("}\n");
return code;
}
@@ -179,6 +190,7 @@
rtn.add(HAS_HORIZONTAL_ALIGNMENT);
rtn.add(HAS_VERTICAL_ALIGNMENT);
rtn.add(LABEL);
+ rtn.add(LAYOUT_PANEL);
rtn.add(SPLIT_LAYOUT_PANEL);
rtn.add(STACK_LAYOUT_PANEL);
rtn.add(STYLE);