Public (larsenje@gmail.com): Adds the ability to set a DialogBox caption widget. Review by jlbanca@google.com, rjrjr@google.com http://gwt-code-reviews.appspot.com/1149803 Review by: jlabanca@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9582 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/uibinder/elementparsers/DialogBoxParser.java b/user/src/com/google/gwt/uibinder/elementparsers/DialogBoxParser.java index 5853e95..7a96ec4 100644 --- a/user/src/com/google/gwt/uibinder/elementparsers/DialogBoxParser.java +++ b/user/src/com/google/gwt/uibinder/elementparsers/DialogBoxParser.java
@@ -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); + } } } }
diff --git a/user/src/com/google/gwt/user/client/ui/DialogBox.java b/user/src/com/google/gwt/user/client/ui/DialogBox.java index acb5056..313995d 100644 --- a/user/src/com/google/gwt/user/client/ui/DialogBox.java +++ b/user/src/com/google/gwt/user/client/ui/DialogBox.java
@@ -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 <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 <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> * <g:DialogBox autoHide="true" modal="true"> * <g:caption><b>Caption text</b></g:caption> * <g:HTMLPanel> @@ -101,20 +105,51 @@ * </g:HTMLPanel> * </g:DialogBox> * </pre> + * + * You may also create your own header caption. The caption must implement + * {@link Caption}. + * + * <p> + * + * For example: + * + * <p> + * + * <pre> + * <g:DialogBox autoHide="true" modal="true"> + * <-- foo is your prefix and Bar is a class that implements {@link Caption}--> + * <g:customCaption><foo:Bar/></g:customCaption> + * <g:HTMLPanel> + * Body text + * <g:Button ui:field='cancelButton'>Cancel</g:Button> + * <g:Button ui:field='okButton'>Okay</g:Button> + * </g:HTMLPanel> + * </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,19 +381,8 @@ } /** - * Sets the html string inside the caption. - * - * Use {@link #setWidget(Widget)} to set the contents inside the - * {@link DialogBox}. - * - * @param html the object's new HTML - */ - public void setHTML(String 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. * * Use {@link #setWidget(Widget)} to set the contents inside the * {@link DialogBox}. @@ -334,11 +390,26 @@ * @param html the object's new HTML */ public void setHTML(SafeHtml html) { - setHTML(html.asString()); + caption.setHTML(html); } /** - * Sets the text 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(String html) { + caption.setHTML(SafeHtmlUtils.fromTrustedString(html)); + } + + /** + * 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(); }
diff --git a/user/test/com/google/gwt/uibinder/elementparsers/DialogBoxParserTest.java b/user/test/com/google/gwt/uibinder/elementparsers/DialogBoxParserTest.java index 3f8bda0..a2aee24 100644 --- a/user/test/com/google/gwt/uibinder/elementparsers/DialogBoxParserTest.java +++ b/user/test/com/google/gwt/uibinder/elementparsers/DialogBoxParserTest.java
@@ -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 @@ -110,6 +124,33 @@ 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(); @@ -127,6 +168,86 @@ } } + 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(); + } catch (UnableToCompleteException e) { + assertNotNull(tester.logger.died); + } + } + public void testTooManyBodies() throws SAXException, IOException { StringBuffer b = new StringBuffer(); @@ -159,6 +280,24 @@ } } + 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(); + } catch (UnableToCompleteException e) { + assertNotNull(tester.logger.died); + } + } + public void testBadElemContent() throws SAXException, IOException { StringBuffer b = new StringBuffer(); @@ -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();
diff --git a/user/test/com/google/gwt/uibinder/test/UiJavaResources.java b/user/test/com/google/gwt/uibinder/test/UiJavaResources.java index a606cc9..5d218e9 100644 --- a/user/test/com/google/gwt/uibinder/test/UiJavaResources.java +++ b/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
@@ -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; }
diff --git a/user/test/com/google/gwt/user/client/ui/DialogBoxTest.java b/user/test/com/google/gwt/user/client/ui/DialogBoxTest.java index d31230e..adc45b8 100644 --- a/user/test/com/google/gwt/user/client/ui/DialogBoxTest.java +++ b/user/test/com/google/gwt/user/client/ui/DialogBoxTest.java
@@ -19,16 +19,84 @@ 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>"; @Override @@ -76,20 +144,6 @@ 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(); dBox.setAnimationEnabled(false); @@ -109,7 +163,7 @@ Scheduler.get().scheduleDeferred(new ScheduledCommand() { public void execute() { UIObjectTest.assertDebugIdContents("myDialogBox-caption", - "test caption"); + "test caption"); finishTest(); } }); @@ -151,6 +205,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() { return new DialogBox();