Revision: 9582
Author: rj...@google.com
Date: Thu Jan 20 14:28:08 2011
Log: Public (larse...@gmail.com):
Adds the ability to set a DialogBox caption widget.

Review by jlba...@google.com, rj...@google.com

http://gwt-code-reviews.appspot.com/1149803

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

Modified:
 /trunk/user/src/com/google/gwt/uibinder/elementparsers/DialogBoxParser.java
 /trunk/user/src/com/google/gwt/user/client/ui/DialogBox.java
/trunk/user/test/com/google/gwt/uibinder/elementparsers/DialogBoxParserTest.java
 /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
 /trunk/user/test/com/google/gwt/user/client/ui/DialogBoxTest.java

=======================================
--- /trunk/user/src/com/google/gwt/uibinder/elementparsers/DialogBoxParser.java Mon Jun 7 12:20:31 2010 +++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/DialogBoxParser.java Thu Jan 20 14:28:08 2011
@@ -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
@@ -20,26 +20,43 @@
 import com.google.gwt.uibinder.rebind.UiBinderWriter;
 import com.google.gwt.uibinder.rebind.XMLElement;
 import com.google.gwt.user.client.ui.DialogBox;
+import com.google.gwt.user.client.ui.DialogBox.Caption;
+
+import java.util.Set;

 /**
  * Parses {@link DialogBox} widgets.
  */
 public class DialogBoxParser implements ElementParser {
+
+  private static final String CAPTION = "caption";
+  private static final String CUSTOM_CAPTION = "customCaption";
   public void parse(XMLElement elem, String fieldName, JClassType type,
       UiBinderWriter writer) throws UnableToCompleteException {
-
+
     String caption = null;
     String body = null;
+    XMLElement customCaption = null;
+
+    String prefix = elem.getPrefix();

     for (XMLElement child : elem.consumeChildElements()) {
-      if ("caption".equals(child.getLocalName())) {
+      if (CAPTION.equals(child.getLocalName())) {
         if (caption != null) {
- writer.die(elem, "May have only one <%s:caption>", elem.getPrefix());
+          writer.die(elem, "May have only one <%s:%s>", prefix,
+              CAPTION);
         }

HtmlInterpreter interpreter = HtmlInterpreter.newInterpreterForUiObject(
             writer, fieldName);
         caption = child.consumeInnerHtml(interpreter);
+      } else if (CUSTOM_CAPTION.equals(child.getLocalName())) {
+        if (customCaption != null) {
+          writer.die(elem, "May only have one <%s:%s>", prefix,
+              CUSTOM_CAPTION);
+        }
+        customCaption = child.consumeSingleChildElement();
+
       } else {
         if (body != null) {
           writer.die(elem, "May have only one widget, but found %s and %s",
@@ -52,8 +69,13 @@
       }
     }

-    handleConstructorArgs(elem, fieldName, type, writer);
-
+    if (caption != null && customCaption != null) {
+      writer.die("Must choose between <%s:%s> or <%s:%s>", prefix, CAPTION,
+          prefix, CUSTOM_CAPTION);
+    }
+
+    handleConstructorArgs(elem, fieldName, type, writer, customCaption);
+
     if (caption != null) {
       writer.addStatement("%s.setHTML(\"%s\");", fieldName, caption);
     }
@@ -63,20 +85,60 @@
   }

   /**
-   * If this is DialogBox (not a subclass), parse constructor args
-   * and generate the constructor call. For subtypes do nothing.
+   * Determines if the element implements Caption.
+   *
+   * @throws UnableToCompleteException
    */
-  private void handleConstructorArgs(XMLElement elem, String fieldName,
- JClassType type, UiBinderWriter writer) throws UnableToCompleteException {
-    boolean custom = !type.equals(writer.getOracle().findType(
+  protected boolean isCaption(UiBinderWriter writer, XMLElement element)
+      throws UnableToCompleteException {
+    JClassType type = writer.findFieldType(element);
+
+ Set<? extends JClassType> classes = type.getFlattenedSupertypeHierarchy();
+    JClassType captionType = writer.getOracle().findType(
+        Caption.class.getCanonicalName());
+    return classes.contains(captionType);
+  }
+
+  /**
+   * Checks to see if the widget extends DialogBox or is DialogBox proper.
+   */
+ protected boolean isCustomWidget(UiBinderWriter writer, JClassType type) {
+    return !type.equals(writer.getOracle().findType(
         DialogBox.class.getCanonicalName()));
+  }
+
+  /**
+ * If this is DialogBox (not a subclass), parse constructor args and generate
+   * the constructor call. For subtypes do nothing.
+   */
+  void handleConstructorArgs(XMLElement elem, String fieldName,
+      JClassType type, UiBinderWriter writer, XMLElement customCaption)
+      throws UnableToCompleteException {
+    boolean custom = isCustomWidget(writer, type);
     if (!custom) {
       String autoHide = elem.consumeBooleanAttribute("autoHide", false);
       String modal = elem.consumeBooleanAttribute("modal", true);

-      writer.setFieldInitializerAsConstructor(fieldName,
+      if (customCaption != null) {
+        if (!writer.isWidgetElement(customCaption)) {
+          writer.die(customCaption, "<%s:%s> must be a widget",
+              customCaption.getPrefix(), CUSTOM_CAPTION);
+        }
+        if (!isCaption(writer, customCaption)) {
+          writer.die(customCaption, "<%s:%s> must implement %s",
+              customCaption.getPrefix(), CUSTOM_CAPTION,
+              Caption.class.getCanonicalName());
+        }
+        String fieldElement = writer.parseElementToField(customCaption);
+
+        writer.setFieldInitializerAsConstructor(fieldName,
+ writer.getOracle().findType(DialogBox.class.getCanonicalName()),
+            autoHide, modal, fieldElement);
+      } else {
+        writer.setFieldInitializerAsConstructor(fieldName,
           writer.getOracle().findType(DialogBox.class.getCanonicalName()),
           autoHide, modal);
+      }
     }
   }
 }
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/DialogBox.java Tue Sep 21 07:53:19 2010 +++ /trunk/user/src/com/google/gwt/user/client/ui/DialogBox.java Thu Jan 20 14:28:08 2011
@@ -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
@@ -34,11 +34,12 @@
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.safehtml.client.HasSafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Window;

 /**
* A form of popup that has a caption area at the top and can be dragged by the
@@ -84,14 +85,17 @@
  *
  * <h3>Use in UiBinder Templates</h3>
  * <p>
- * DialogBox elements in
- * {@link com.google.gwt.uibinder.client.UiBinder UiBinder} templates can
- * have one widget child and one &lt;g:caption> child. (Note the lower case
- * "c", meant to signal that the caption is not a runtime object, and so cannot
- * have a <code>ui:field</code> attribute.) The body of the
- * caption can be html.
+ * DialogBox elements in {@link com.google.gwt.uibinder.client.UiBinder
+ * UiBinder} templates can have one widget child and one &lt;g:caption> child. + * (Note the lower case "c", meant to signal that the caption is not a runtime + * object, and so cannot have a <code>ui:field</code> attribute.) The body of
+ * the caption can be html.
+ *
  * <p>
- * For example: <pre>
+ *
+ * For example:
+ *
+ * <pre>
  * &lt;g:DialogBox autoHide="true" modal="true">
  *   &lt;g:caption>&lt;b>Caption text&lt;/b>&lt;/g:caption>
  *   &lt;g:HTMLPanel>
@@ -101,20 +105,51 @@
  *   &lt;/g:HTMLPanel>
  * &lt;/g:DialogBox>
  * </pre>
+ *
+ * You may also create your own header caption. The caption must implement
+ * {@link Caption}.
+ *
+ * <p>
+ *
+ * For example:
+ *
+ * <p>
+ *
+ * <pre>
+ * &lt;g:DialogBox autoHide="true" modal="true">
+ * &lt;-- foo is your prefix and Bar is a class that implements {@link Caption}-->
+ *   &lt;g:customCaption>&lt;foo:Bar/>&lt;/g:customCaption>
+ *   &lt;g:HTMLPanel>
+ *     Body text
+ *     &lt;g:Button ui:field='cancelButton'>Cancel&lt;/g:Button>
+ *     &lt;g:Button ui:field='okButton'>Okay&lt;/g:Button>
+ *   &lt;/g:HTMLPanel>
+ * &lt;/g:DialogBox>
+ * </pre>
+ *
  */
 @SuppressWarnings("deprecation")
 public class DialogBox extends DecoratedPopupPanel implements HasHTML,
     HasSafeHtml, MouseListener {
   /**
- * Set of characteristic interfaces supported by the {@link DialogBox} caption
-   *
- * Note that this set might expand over time, so implement this interface at
-   * your own risk.
+   * Set of characteristic interfaces supported by the {@link DialogBox}
+   * caption.
+   *
    */
-  public interface Caption extends HasAllMouseHandlers {
+ public interface Caption extends HasAllMouseHandlers, HasHTML, HasSafeHtml,
+      IsWidget {
   }

-  private static class CaptionImpl extends HTML implements Caption {
+  /**
+ * Default implementation of Caption. This will be created as the header if
+   * there isn't a header specified.
+   */
+  public static class CaptionImpl extends HTML implements Caption {
+
+    public CaptionImpl() {
+      super();
+      setStyleName("Caption");
+    }
   }

   private class MouseHandler implements MouseDownHandler, MouseUpHandler,
@@ -129,11 +164,11 @@
     }

     public void onMouseOut(MouseOutEvent event) {
-      DialogBox.this.onMouseLeave(caption);
+      DialogBox.this.onMouseLeave(caption.asWidget());
     }

     public void onMouseOver(MouseOverEvent event) {
-      DialogBox.this.onMouseEnter(caption);
+      DialogBox.this.onMouseEnter(caption.asWidget());
     }

     public void onMouseUp(MouseUpEvent event) {
@@ -146,7 +181,7 @@
    */
   private static final String DEFAULT_STYLENAME = "gwt-DialogBox";

-  private CaptionImpl caption = new CaptionImpl();
+  private Caption caption;
   private boolean dragging;
   private int dragStartX, dragStartY;
   private int windowWidth;
@@ -167,7 +202,7 @@
* Creates an empty dialog box specifying its "auto-hide" property. It should
    * not be shown until its child widget has been added using
    * {@link #add(Widget)}.
-   *
+   *
* @param autoHide <code>true</code> if the dialog should be automatically
    *          hidden when the user clicks outside of it
    */
@@ -176,24 +211,53 @@
   }

   /**
- * Creates an empty dialog box specifying its "auto-hide" property. It should
-   * not be shown until its child widget has been added using
-   * {@link #add(Widget)}.
-   *
+ * Creates an empty dialog box specifying its {@link Caption}. It should not + * be shown until its child widget has been added using {@link #add(Widget)}.
+   *
+   * @param captionWidget the widget that is the DialogBox's header.
+   */
+  public DialogBox(Caption captionWidget) {
+    this(false, true, captionWidget);
+  }
+
+  /**
+   * Creates an empty dialog box specifying its "auto-hide" and "modal"
+ * properties. It should not be shown until its child widget has been added
+   * using {@link #add(Widget)}.
+   *
* @param autoHide <code>true</code> if the dialog should be automatically
    *          hidden when the user clicks outside of it
* @param modal <code>true</code> if keyboard and mouse events for widgets not
    *          contained by the dialog should be ignored
    */
   public DialogBox(boolean autoHide, boolean modal) {
+    this(autoHide, modal, new CaptionImpl());
+  }
+
+  /**
+   *
+ * Creates an empty dialog box specifying its "auto-hide", "modal" properties
+   * and an implementation a custom {@link Caption}. It should not be shown
+   * until its child widget has been added using {@link #add(Widget)}.
+   *
+ * @param autoHide <code>true</code> if the dialog should be automatically
+   *          hidden when the user clicks outside of it
+ * @param modal <code>true</code> if keyboard and mouse events for widgets not
+   *          contained by the dialog should be ignored
+   * @param captionWidget the widget that is the DialogBox's header.
+   */
+ public DialogBox(boolean autoHide, boolean modal, Caption captionWidget) {
     super(autoHide, modal, "dialog");

+    assert captionWidget != null : "The caption must not be null";
+    captionWidget.asWidget().removeFromParent();
+    caption = captionWidget;
+
     // Add the caption to the top row of the decorator panel. We need to
     // logically adopt the caption so we can catch mouse events.
     Element td = getCellElement(0, 1);
-    DOM.appendChild(td, caption.getElement());
-    adopt(caption);
-    caption.setStyleName("Caption");
+    DOM.appendChild(td, caption.asWidget().getElement());
+    adopt(caption.asWidget());

     // Set the style name
     setStyleName(DEFAULT_STYLENAME);
@@ -212,14 +276,10 @@

   /**
    * Provides access to the dialog's caption.
-   *
- * This method is final because the Caption interface will expand. Therefore - * it is highly likely that subclasses which implemented this method would end
-   * up breaking.
-   *
+   *
    * @return the logical caption for this dialog box
    */
-  public final Caption getCaption() {
+  public Caption getCaption() {
     return caption;
   }

@@ -259,15 +319,22 @@
   }

   /**
-   * @deprecated Use {@link #beginDragging} and {@link #getCaption}
-   *             instead
+   * @deprecated Use {@link #beginDragging} and {@link #getCaption} instead
    */
   @Deprecated
   public void onMouseDown(Widget sender, int x, int y) {
-    dragging = true;
-    DOM.setCapture(getElement());
-    dragStartX = x;
-    dragStartY = y;
+    if (DOM.getCaptureElement() == null) {
+      /*
+ * Need to check to make sure that we aren't already capturing an element + * otherwise events will not fire as expected. If this check isn't here, + * any class which extends custom button will not fire its click event for
+       * example.
+       */
+      dragging = true;
+      DOM.setCapture(getElement());
+      dragStartX = x;
+      dragStartY = y;
+    }
   }

   /**
@@ -314,31 +381,35 @@
   }

   /**
-   * Sets the html string inside the caption.
-   *
+   * Sets the html string inside the caption by calling its
+   * {@link #setHTML(SafeHTML)} method.
+   *
    * Use {@link #setWidget(Widget)} to set the contents inside the
    * {@link DialogBox}.
-   *
+   *
    * @param html the object's new HTML
    */
-  public void setHTML(String html) {
+  public void setHTML(SafeHtml html) {
     caption.setHTML(html);
   }

   /**
-   * Sets the html string inside the caption.
+   * Sets the html string inside the caption by calling its
+ * {@link #setHTML(SafeHtml)} method. Only known safe HTML should be inserted
+   * in here.
    *
    * Use {@link #setWidget(Widget)} to set the contents inside the
    * {@link DialogBox}.
    *
    * @param html the object's new HTML
    */
-  public void setHTML(SafeHtml html) {
-    setHTML(html.asString());
+  public void setHTML(String html) {
+    caption.setHTML(SafeHtmlUtils.fromTrustedString(html));
   }

   /**
-   * Sets the text inside the caption.
+ * Sets the text inside the caption by calling its {@link #setText(String)}
+   * method.
    *
    * Use {@link #setWidget(Widget)} to set the contents inside the
    * {@link DialogBox}.
@@ -364,25 +435,25 @@
   /**
    * Called on mouse down in the caption area, begins the dragging loop by
    * turning on event capture.
-   *
+   *
    * @see DOM#setCapture
    * @see #continueDragging
    * @param event the mouse down event that triggered dragging
    */
   protected void beginDragging(MouseDownEvent event) {
-    onMouseDown(caption, event.getX(), event.getY());
+    onMouseDown(caption.asWidget(), event.getX(), event.getY());
   }

   /**
    * Called on mouse move in the caption area, continues dragging if it was
    * started by {@link #beginDragging}.
-   *
+   *
    * @see #beginDragging
    * @see #endDragging
    * @param event the mouse move event that continues dragging
    */
   protected void continueDragging(MouseMoveEvent event) {
-    onMouseMove(caption, event.getX(), event.getY());
+    onMouseMove(caption.asWidget(), event.getX(), event.getY());
   }

   @Override
@@ -391,7 +462,7 @@
       super.doAttachChildren();
     } finally {
       // See comment in doDetachChildren for an explanation of this call
-      caption.onAttach();
+      caption.asWidget().onAttach();
     }
   }

@@ -400,26 +471,28 @@
     try {
       super.doDetachChildren();
     } finally {
- // We need to detach the caption specifically because it is not part of the - // iterator of Widgets that the {@link SimplePanel} super class returns. - // This is similar to a {@link ComplexPanel}, but we do not want to expose
-      // the caption widget, as its just an internal implementation.
-      caption.onDetach();
+      /*
+ * We need to detach the caption specifically because it is not part of
+       * the iterator of Widgets that the {@link SimplePanel} super class
+ * returns. This is similar to a {@link ComplexPanel}, but we do not want + * to expose the caption widget, as its just an internal implementation.
+       */
+      caption.asWidget().onDetach();
     }
   }

   /**
    * Called on mouse up in the caption area, ends dragging by ending event
    * capture.
-   *
+   *
    * @param event the mouse up event that ended dragging
-   *
+   *
    * @see DOM#releaseCapture
    * @see #beginDragging
    * @see #endDragging
    */
   protected void endDragging(MouseUpEvent event) {
-    onMouseUp(caption, event.getX(), event.getY());
+    onMouseUp(caption.asWidget(), event.getX(), event.getY());
   }

   /**
@@ -428,13 +501,13 @@
    * <li>-caption = text at the top of the {@link DialogBox}.</li>
    * <li>-content = the container around the content.</li>
    * </ul>
-   *
+   *
    * @see UIObject#onEnsureDebugId(String)
    */
   @Override
   protected void onEnsureDebugId(String baseID) {
     super.onEnsureDebugId(baseID);
-    caption.ensureDebugId(baseID + "-caption");
+    caption.asWidget().ensureDebugId(baseID + "-caption");
     ensureDebugId(getCellElement(1, 1), baseID, "content");
   }

@@ -445,8 +518,7 @@
     // is dragged.
     NativeEvent nativeEvent = event.getNativeEvent();

-    if (!event.isCanceled()
-        && (event.getTypeInt() == Event.ONMOUSEDOWN)
+    if (!event.isCanceled() && (event.getTypeInt() == Event.ONMOUSEDOWN)
         && isCaptionEvent(nativeEvent)) {
       nativeEvent.preventDefault();
     }
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/elementparsers/DialogBoxParserTest.java Wed Dec 2 10:02:31 2009 +++ /trunk/user/test/com/google/gwt/uibinder/elementparsers/DialogBoxParserTest.java Thu Jan 20 14:28:08 2011
@@ -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
@@ -18,6 +18,7 @@
 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.dev.javac.impl.MockJavaResource;
 import com.google.gwt.uibinder.rebind.FieldWriter;
+import com.google.gwt.user.client.ui.DialogBox;

 import junit.framework.TestCase;

@@ -32,7 +33,20 @@
 public class DialogBoxParserTest extends TestCase {

private static final String PARSED_TYPE = "com.google.gwt.user.client.ui.DialogBox";
-
+ private static final MockJavaResource CAPTION_SUBCLASS = new MockJavaResource(
+      "my.MyCaption") {
+    @Override
+    protected CharSequence getContent() {
+      StringBuffer code = new StringBuffer();
+      code.append("package my;\n");
+      code.append("import com.google.gwt.user.client.ui.DialogBox;\n");
+      code.append("import com.google.gwt.user.client.ui.Widget;\n");
+ code.append("public class MyCaption extends Widget implements DialogBox.Caption {\n");
+      code.append("  public MyCaption() { super(); } \n");;
+      code.append("}\n");
+      return code;
+    }
+  };
private static final MockJavaResource DIALOG_SUBCLASS = new MockJavaResource(
       "my.MyDialogBox") {
     @Override
@@ -109,6 +123,33 @@
     assertFalse(i.hasNext());
     assertNull(tester.logger.died);
   }
+
+ public void testCustomCaptionAndCaption() throws SAXException, IOException,
+      UnableToCompleteException {
+    StringBuffer b = new StringBuffer();
+
+    DialogBoxParser parser = new DialogBoxParser();
+    String typeName = DialogBox.class.getCanonicalName();
+    tester = new ElementParserTester(typeName, parser, CAPTION_SUBCLASS);
+
+ b.append("<ui:UiBinder xmlns:ui='" + ElementParserTester.BINDER_URI + "'");
+    b.append("    xmlns:my='urn:import:my'");
+    b.append("    xmlns:g='urn:import:com.google.gwt.user.client.ui'>");
+    b.append("  <g:DialogBox autoHide='true' modal='true'>");
+    b.append("    <g:caption>Hello, I <b>caption</b>you.</g:caption>");
+    b.append("    <g:customCaption><my:MyCaption/></g:customCaption>");
+    b.append("    <g:Label>And your little dog, too!</g:Label>");
+    b.append("  </g:DialogBox> ");
+    b.append("</ui:UiBinder>");
+
+    try {
+ parser.parse(tester.getElem(b.toString(), "g:DialogBox"), "fieldName",
+          tester.parsedType, tester.writer);
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertNotNull(tester.logger.died);
+    }
+  }

   public void testWidgetInCaption() throws SAXException, IOException {
     StringBuffer b = new StringBuffer();
@@ -119,6 +160,86 @@
     b.append("  </g:caption> ");
     b.append("</g:DialogBox> ");

+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertNotNull(tester.logger.died);
+    }
+  }
+
+  public void testTooManyCaptionWidgets() throws SAXException, IOException,
+      UnableToCompleteException {
+
+    StringBuffer b = new StringBuffer();
+    DialogBoxParser parser = new DialogBoxParser();
+    String typeName = DialogBox.class.getCanonicalName();
+    tester = new ElementParserTester(typeName, parser, CAPTION_SUBCLASS);
+
+ b.append("<ui:UiBinder xmlns:ui='" + ElementParserTester.BINDER_URI + "'");
+    b.append("    xmlns:my='urn:import:my'");
+    b.append("    xmlns:g='urn:import:com.google.gwt.user.client.ui'>");
+    b.append("  <g:DialogBox autoHide='true' modal='true'>");
+    b.append("    <g:customCaption><my:MyCaption/></g:customCaption>");
+    b.append("    <g:customCaption><my:MyCaption/></g:customCaption>");
+    b.append("  </g:DialogBox> ");
+    b.append("</ui:UiBinder>");
+
+    try {
+ parser.parse(tester.getElem(b.toString(), "g:DialogBox"), "fieldName",
+          tester.parsedType, tester.writer);
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertNotNull(tester.logger.died);
+    }
+  }
+
+  public void testCustomCaption() throws SAXException, IOException,
+      UnableToCompleteException {
+    StringBuffer b = new StringBuffer();
+
+    DialogBoxParser parser = new DialogBoxParser();
+    String typeName = DialogBox.class.getCanonicalName();
+    tester = new ElementParserTester(typeName, parser, CAPTION_SUBCLASS);
+
+ b.append("<ui:UiBinder xmlns:ui='" + ElementParserTester.BINDER_URI + "'");
+    b.append("    xmlns:my='urn:import:my'");
+    b.append("    xmlns:g='urn:import:com.google.gwt.user.client.ui'>");
+    b.append("  <g:DialogBox autoHide='true' modal='true'>");
+    b.append("    <g:customCaption><my:MyCaption/></g:customCaption>");
+    b.append("    <g:Label>And your little dog, too!</g:Label>");
+    b.append("  </g:DialogBox> ");
+    b.append("</ui:UiBinder>");
+
+    parser.parse(tester.getElem(b.toString(), "g:DialogBox"), "fieldName",
+        tester.parsedType, tester.writer);
+
+    String[] expected = {"fieldName.setWidget(<g:Label>);",};
+
+    FieldWriter w = tester.fieldManager.lookup("fieldName");
+
+    assertEquals("new " + PARSED_TYPE + "(true, true, <my:MyCaption>)",
+        w.getInitializer());
+
+    Iterator<String> i = tester.writer.statements.iterator();
+    for (String e : expected) {
+      assertEquals(e, i.next());
+    }
+    assertFalse(i.hasNext());
+    assertNull(tester.logger.died);
+  }
+
+ public void testCaptionWidgetDoesntImplementCaption() throws SAXException,
+      IOException {
+
+    StringBuffer b = new StringBuffer();
+
+    b.append("<g:DialogBox autoHide='true' modal='true'>");
+    b.append("  <g:customCaption> ");
+    b.append("    <g:Label>And your little dog, too!</g:Label>");
+    b.append("  </g:customCaption> ");
+    b.append("</g:DialogBox> ");
+
     try {
       tester.parse(b.toString());
       fail();
@@ -151,6 +272,24 @@
     b.append("  <g:caption>Hello, I <b>caption</b>you.</g:caption>");
     b.append("</g:DialogBox> ");

+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertNotNull(tester.logger.died);
+    }
+  }
+
+ public void testBadCaptionWidgetContent() throws SAXException, IOException {
+
+    StringBuffer b = new StringBuffer();
+
+    b.append("<g:DialogBox autoHide='true' modal='true'>");
+    b.append("  <g:customCaption>");
+    b.append("    <div>Oops</div>");
+    b.append("  </g:customCaption>");
+    b.append("</g:DialogBox> ");
+
     try {
       tester.parse(b.toString());
       fail();
@@ -195,8 +334,7 @@
       SAXException, IOException {
     DialogBoxParser parser = new DialogBoxParser();
     String typeName = "my.MyDialogBox";
-    tester = new ElementParserTester(typeName, parser,
-        DIALOG_SUBCLASS);
+    tester = new ElementParserTester(typeName, parser, DIALOG_SUBCLASS);

     StringBuffer b = new StringBuffer();

@@ -208,15 +346,15 @@
     b.append("    <g:Label>And your little dog, too!</g:Label>");
     b.append("  </my:MyDialogBox> ");
     b.append("</ui:UiBinder>");
-
+
     String[] expected = {
         "fieldName.setHTML(\"Hello, I <b>caption</b>you.\");",
         "fieldName.setWidget(<g:Label>);",};

- parser.parse(tester.getElem(b.toString(), "my:MyDialogBox"), "fieldName", + parser.parse(tester.getElem(b.toString(), "my:MyDialogBox"), "fieldName",
         tester.parsedType, tester.writer);
     FieldWriter w = tester.fieldManager.lookup("fieldName");
-
+
     assertNull(w.getInitializer());

     Iterator<String> i = tester.writer.statements.iterator();
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Fri Jan 7 08:26:38 2011 +++ /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Thu Jan 20 14:28:08 2011
@@ -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
@@ -150,7 +150,9 @@
       StringBuffer code = new StringBuffer();
       code.append("package com.google.gwt.user.client.ui;\n");
       code.append("public class DialogBox extends Widget {\n");
- code.append(" public DialogBox(boolean autoHide, boolean modal) {} ");
+      code.append(" public interface Caption {} \n");
+ code.append(" public DialogBox(boolean autoHide, boolean modal) {} \n"); + code.append(" public DialogBox(boolean autoHide, boolean modal, Caption caption) {} ");
       code.append("}\n");
       return code;
     }
=======================================
--- /trunk/user/test/com/google/gwt/user/client/ui/DialogBoxTest.java Thu Dec 16 05:45:53 2010 +++ /trunk/user/test/com/google/gwt/user/client/ui/DialogBoxTest.java Thu Jan 20 14:28:08 2011
@@ -19,15 +19,83 @@
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.dom.client.MouseWheelHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.junit.DoNotRunWith;
 import com.google.gwt.junit.Platform;
+import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlUtils;
 import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;

 /**
  * Unit test for {@link DialogBox}.
  */
 public class DialogBoxTest extends PopupTest {
+
+  /**
+   * An implementation of Caption which is used for testing.
+   */
+  private static class CaptionForTesting extends Composite implements
+      DialogBox.Caption, HasHTML {
+
+    private FocusPanel panel = new FocusPanel();
+    private HTML htmlWidget = new HTML();
+
+    public CaptionForTesting() {
+      panel.add(htmlWidget);
+      initWidget(panel);
+    }
+
+ public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
+      return panel.addMouseDownHandler(handler);
+    }
+
+ public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
+      return panel.addMouseMoveHandler(handler);
+    }
+
+ public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
+      return panel.addMouseOutHandler(handler);
+    }
+
+ public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
+      return panel.addMouseOverHandler(handler);
+    }
+
+    public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
+      return panel.addMouseUpHandler(handler);
+    }
+
+ public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
+      return panel.addMouseWheelHandler(handler);
+    }
+
+    public String getHTML() {
+      return htmlWidget.getHTML();
+    }
+
+    public String getText() {
+      return htmlWidget.getText();
+    }
+
+    public void setHTML(SafeHtml html) {
+      htmlWidget.setHTML(html);
+    }
+
+    public void setHTML(String html) {
+      this.htmlWidget.setHTML(html);
+    }
+
+    public void setText(String text) {
+      htmlWidget.setText(text);
+    }
+  }

   private static final String html = "<b>hello</b><i>world</i>";

@@ -75,20 +143,6 @@
     assertEquals("text", dialogBox.getText());
     assertTrue(dialogBox.getHTML().equalsIgnoreCase("<b>text</b>"));
   }
-
-  public void testSimpleCloseButtonOnModalDialog() {
-    final DialogBox dialogBox = new DialogBox(false, true);
-    Button button = new Button();
-    button.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        dialogBox.hide();
-      }
-    });
-    dialogBox.add(button);
-    dialogBox.show();
-    button.click();
-    assertFalse(dialogBox.isShowing());
-  }

   public void testDebugId() {
     DialogBox dBox = new DialogBox();
@@ -109,7 +163,7 @@
     Scheduler.get().scheduleDeferred(new ScheduledCommand() {
       public void execute() {
         UIObjectTest.assertDebugIdContents("myDialogBox-caption",
-            "test caption");
+        "test caption");
         finishTest();
       }
     });
@@ -150,6 +204,37 @@

     assertEquals(html, box.getHTML().toLowerCase());
   }
+
+  /**
+   * Test setting the caption.
+   */
+  public void testSetCaption() {
+    CaptionForTesting caption = new CaptionForTesting();
+    DialogBox dialogBox = new DialogBox(caption);
+    caption.setText("text");
+    Element td = dialogBox.getCellElement(0, 1);
+    assertEquals(dialogBox.getText(), "text");
+    caption.setHTML("<b>text</b>");
+    assertEquals("<b>text</b>", dialogBox.getHTML().toLowerCase());
+    dialogBox.show();
+    assertTrue(dialogBox.getCaption() == caption);
+    assertTrue(caption.asWidget().getElement() == DOM.getChild(td, 0));
+    dialogBox.hide();
+  }
+
+  public void testSimpleCloseButtonOnModalDialog() {
+    final DialogBox dialogBox = new DialogBox(false, true);
+    Button button = new Button();
+    button.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        dialogBox.hide();
+      }
+    });
+    dialogBox.add(button);
+    dialogBox.show();
+    button.click();
+    assertFalse(dialogBox.isShowing());
+  }

   @Override
   protected PopupPanel createPopupPanel() {

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

Reply via email to