Revision: 7030
Author: j...@google.com
Date: Thu Nov 19 12:57:33 2009
Log: Adds parsers for LayoutPanel and Length attributes.
Review: http://gwt-code-reviews.appspot.com/103806
http://code.google.com/p/google-web-toolkit/source/detail?r=7030

Added:
   
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/LengthAttributeParser.java
   
/trunk/user/src/com/google/gwt/uibinder/elementparsers/LayoutPanelParser.java
   
/trunk/user/test/com/google/gwt/uibinder/attributeparsers/LengthAttributeParserTest.java
   
/trunk/user/test/com/google/gwt/uibinder/elementparsers/LayoutPanelParserTest.java
Modified:
  /trunk/user/javadoc/com/google/gwt/examples/StackLayoutPanelExample.java
   
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/AttributeParsers.java
  /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
  /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
  /trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
  /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java

=======================================
--- /dev/null
+++  
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/LengthAttributeParser.java
      
Thu Nov 19 12:57:33 2009
@@ -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;
+  }
+}
=======================================
--- /dev/null
+++  
/trunk/user/src/com/google/gwt/uibinder/elementparsers/LayoutPanelParser.java   
 
Thu Nov 19 12:57:33 2009
@@ -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;
+  }
+}
=======================================
--- /dev/null
+++  
/trunk/user/test/com/google/gwt/uibinder/attributeparsers/LengthAttributeParserTest.java
         
Thu Nov 19 12:57:33 2009
@@ -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;
+  }
+}
=======================================
--- /dev/null
+++  
/trunk/user/test/com/google/gwt/uibinder/elementparsers/LayoutPanelParserTest.java
       
Thu Nov 19 12:57:33 2009
@@ -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"));
+    }
+  }
+}
=======================================
---  
/trunk/user/javadoc/com/google/gwt/examples/StackLayoutPanelExample.java        
 
Tue Nov  3 14:14:13 2009
+++  
/trunk/user/javadoc/com/google/gwt/examples/StackLayoutPanelExample.java        
 
Thu Nov 19 12:57:33 2009
@@ -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
=======================================
---  
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/AttributeParsers.java  
 
Wed Nov 11 22:08:47 2009
+++  
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/AttributeParsers.java  
 
Thu Nov 19 12:57:33 2009
@@ -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);
      }
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java  Mon  
Nov 16 10:04:26 2009
+++ /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java  Thu  
Nov 19 12:57:33 2009
@@ -941,6 +941,7 @@
      addWidgetParser("CellPanel");
      addWidgetParser("CustomButton");
      addWidgetParser("DialogBox");
+    addWidgetParser("LayoutPanel");
      addWidgetParser("DockLayoutPanel");
      addWidgetParser("StackLayoutPanel");
      addWidgetParser("TabLayoutPanel");
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java      Mon Nov 
 
16 10:04:26 2009
+++ /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java      Thu Nov 
 
19 12:57:33 2009
@@ -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 });
    }

    /**
@@ -442,6 +444,21 @@
      clearChildren(elem);
      return buf.toString().trim();
    }
+
+  /**
+   * 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
@@ -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();
+  }
+}
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java      Mon Nov 
 
16 15:06:51 2009
+++ /trunk/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java      Thu Nov 
 
19 12:57:33 2009
@@ -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);
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java  Wed  
Nov 11 22:08:47 2009
+++ /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java  Thu  
Nov 19 12:57:33 2009
@@ -87,6 +87,17 @@
        code.append("}\n");
        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") {
@@ -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);

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

Reply via email to