Intruducing AutoDirHandler, a handler for automatically adjusting the direction of an object (typically a TextBox variant) while text is being entered. This handler is then used to add BiDi support to TextBox and TextArea. Review at http://gwt-code-reviews.appspot.com/386803 Review by: jat@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8286 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/CwBasicText.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/CwBasicText.java index d6979c8..7533b09 100644 --- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/CwBasicText.java +++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/CwBasicText.java
@@ -22,6 +22,7 @@ import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.i18n.client.Constants; +import com.google.gwt.i18n.shared.AnyRtlDirectionEstimator; import com.google.gwt.sample.showcase.client.ContentWidget; import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData; import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource; @@ -103,6 +104,10 @@ // Add a normal and disabled text box TextBox normalText = new TextBox(); normalText.ensureDebugId("cwBasicText-textbox"); + // Set the normal text box to automatically adjust its direction according + // to the input text. Use the Any-RTL heuristic, which sets an RTL direction + // iff the text contains at least one RTL character. + normalText.setDirectionEstimator(AnyRtlDirectionEstimator.get()); TextBox disabledText = new TextBox(); disabledText.ensureDebugId("cwBasicText-textbox-disabled"); disabledText.setText(constants.cwBasicTextReadOnly());
diff --git a/user/src/com/google/gwt/i18n/I18N.gwt.xml b/user/src/com/google/gwt/i18n/I18N.gwt.xml index 23d1c29..9d0c77a 100644 --- a/user/src/com/google/gwt/i18n/I18N.gwt.xml +++ b/user/src/com/google/gwt/i18n/I18N.gwt.xml
@@ -17,7 +17,7 @@ <module> <inherits name="com.google.gwt.regexp.RegExp"/> <source path="" includes="client/,shared/" /> - + <!-- Browser-sensitive code should use the 'locale' client property. --> <!-- 'default' is always defined. --> <define-property name="locale" values="default" /> @@ -54,7 +54,7 @@ } else { $wnd['__gwt_Locale'] = locale || defaultLocale; } - + if (locale == null) { return defaultLocale; } @@ -95,7 +95,7 @@ the locale of the current permutation will actually be included. Note that currently only number/date format constants, locale names, and currency data will support runtime locales - everything else will just - reference the compile-time locale set in the "locale" property. + reference the compile-time locale set in the "locale" property. --> <define-configuration-property name="runtime.locales" is-multi-valued="true"/> <set-configuration-property name="runtime.locales" value=""/> @@ -111,4 +111,17 @@ be generated as the locale specified here. --> <set-property-fallback name="locale" value="default"/> + + <!-- Force BiDi policy to be enabled --> + <define-property name="gwt.forceBidi" values="true, false"/> + + <!-- Default to not forced --> + <set-property name="gwt.forceBidi" value="false"/> + + <!-- Replace the BidiPolicyImpl --> + <replace-with class="com.google.gwt.i18n.client.BidiPolicy.BidiPolicyImplOn"> + <when-type-is class="com.google.gwt.i18n.client.BidiPolicy.BidiPolicyImpl"/> + <when-property-is name="gwt.forceBidi" value="true"/> + </replace-with> </module> +
diff --git a/user/src/com/google/gwt/i18n/client/AutoDirectionHandler.java b/user/src/com/google/gwt/i18n/client/AutoDirectionHandler.java new file mode 100644 index 0000000..09ad8b7 --- /dev/null +++ b/user/src/com/google/gwt/i18n/client/AutoDirectionHandler.java
@@ -0,0 +1,180 @@ +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.i18n.client; + +import com.google.gwt.event.dom.client.HasKeyUpHandlers; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.i18n.client.HasDirection.Direction; +import com.google.gwt.i18n.shared.DirectionEstimator; +import com.google.gwt.i18n.shared.HasDirectionEstimator; +import com.google.gwt.i18n.shared.WordCountDirectionEstimator; +import com.google.gwt.user.client.ui.HasText; + +/** + * Utility class for handling auto-direction adjustment. + * + * This class is useful for automatically adjusting the direction of an object + * that takes text input, while the text is being entered. + */ +public class AutoDirectionHandler implements KeyUpHandler, + HasDirectionEstimator { + + /** + * The interface an object must implement in order to add an + * AutoDirectionHandler to it. + * + * TODO(tomerigo): add Paste and Input events once they're available in GWT. + */ + public interface Target extends HasText, HasDirection, HasKeyUpHandlers { + } + + /** + * Operates like {@link #addTo(Target, DirectionEstimator)}, but always uses + * a default DirectionEstimator, {@link + * com.google.gwt.i18n.shared.WordCountDirectionEstimator}. + * + * @param target Object whose direction should be automatically adjusted on + * relevant events. + * @return AutoDirectionHandler An instance of AutoDirectionHandler for the + * given object. + */ + public static AutoDirectionHandler addTo(Target target) { + return addTo(target, true); + } + + /** + * Operates like {@link #addTo(Target, DirectionEstimator)}, but uses a + * default DirectionEstimator, {@link + * com.google.gwt.i18n.shared.WordCountDirectionEstimator} if {@code enabled}, + * or else a null DirectionEstimator, which means disabling direction + * estimation. + * + * @param target Object whose direction should be automatically adjusted on + * relevant events. + * @param enabled Whether the handler is enabled upon creation. + * @return AutoDirectionHandler An instance of AutoDirectionHandler for the + * given object. + */ + public static AutoDirectionHandler addTo(Target target, boolean enabled) { + return addTo(target, enabled ? WordCountDirectionEstimator.get() : null); + } + + /** + * Adds auto-direction adjustment to a given object: + * - Creates an AutoDirectionHandler. + * - Initializes it with the given DirectionEstimator. + * - Adds it as an event handler for the relevant events on the given object. + * - Returns the AutoDirectionHandler, so its setAutoDir() method can be + * called when the object's text changes by means other than the handled + * events. + * + * @param target Object whose direction should be automatically adjusted on + * relevant events. + * @param directionEstimator A DirectionEstimator object used for direction + * estimation (use null to disable direction estimation). + * @return AutoDirectionHandler An instance of AutoDirectionHandler for the + * given object. + */ + public static AutoDirectionHandler addTo(Target target, DirectionEstimator + directionEstimator) { + AutoDirectionHandler autoDirHandler = new AutoDirectionHandler(target, + directionEstimator); + return autoDirHandler; + } + + /** + * A DirectionEstimator object used for direction estimation. + */ + private DirectionEstimator directionEstimator; + + /** + * A HandlerRegistration object used to remove this handler. + */ + private HandlerRegistration handlerRegistration; + + /** + * The object being handled. + */ + private Target target; + + /** + * Private constructor. Instantiate using one of the addTo() methods. + * + * @param target Object whose direction should be automatically adjusted on + * relevant events. + * @param directionEstimator A DirectionEstimator object used for direction + * estimation. + */ + private AutoDirectionHandler(Target target, DirectionEstimator + directionEstimator) { + this.target = target; + this.handlerRegistration = null; + setDirectionEstimator(directionEstimator); + } + + /** + * Returns the DirectionEstimator object. + */ + public DirectionEstimator getDirectionEstimator() { + return directionEstimator; + } + + /** + * Automatically adjusts hasDirection's direction on KeyUpEvent events. + * Implementation of KeyUpHandler interface method. + */ + public void onKeyUp(KeyUpEvent event) { + refreshDirection(); + } + + /** + * Adjusts target's direction according to the estimated direction of the text + * it supplies. + */ + public void refreshDirection() { + if (directionEstimator != null) { + Direction dir = directionEstimator.estimateDirection(target.getText()); + if (dir != target.getDirection()) { + target.setDirection(dir); + } + } + } + + /** + * Toggles direction estimation on (using a default estimator) and off. + */ + public void setDirectionEstimator(boolean enabled) { + setDirectionEstimator(enabled ? WordCountDirectionEstimator.get() : null); + } + + /** + * Sets the DirectionEstimator object. + */ + public void setDirectionEstimator(DirectionEstimator directionEstimator) { + this.directionEstimator = directionEstimator; + if ((directionEstimator == null) != (handlerRegistration == null)) { + if (directionEstimator == null) { + handlerRegistration.removeHandler(); + handlerRegistration = null; + } else { + handlerRegistration = target.addKeyUpHandler(this); + } + } + refreshDirection(); + } +}
diff --git a/user/src/com/google/gwt/i18n/client/BidiPolicy.java b/user/src/com/google/gwt/i18n/client/BidiPolicy.java new file mode 100644 index 0000000..5a0427e --- /dev/null +++ b/user/src/com/google/gwt/i18n/client/BidiPolicy.java
@@ -0,0 +1,52 @@ +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.i18n.client; + +import com.google.gwt.core.client.GWT; + +/** + * Provides low-level functionality to determine whether to support bidi. + */ +public class BidiPolicy { + /** + * Implementation class for {@link BidiPolicy}. + */ + public static class BidiPolicyImpl { + public boolean isBidiEnabled() { + return LocaleInfo.hasAnyRTL(); + } + } + + /** + * Implementation class for {@link BidiPolicy} used when bidi is always on. + */ + @SuppressWarnings("unused") + public static class BidiPolicyImplOn extends BidiPolicyImpl { + @Override + public boolean isBidiEnabled() { + return true; + } + } + + private static BidiPolicyImpl impl = GWT.create(BidiPolicyImpl.class); + + /** + * @return true if bidi is enabled, false if disabled. + */ + public static boolean isBidiEnabled() { + return impl.isBidiEnabled(); + } +}
diff --git a/user/src/com/google/gwt/user/client/ui/TextArea.java b/user/src/com/google/gwt/user/client/ui/TextArea.java index 09c7fff..0cd79a4 100644 --- a/user/src/com/google/gwt/user/client/ui/TextArea.java +++ b/user/src/com/google/gwt/user/client/ui/TextArea.java
@@ -1,12 +1,12 @@ /* * Copyright 2008 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,36 +18,34 @@ import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.TextAreaElement; -import com.google.gwt.i18n.client.HasDirection; -import com.google.gwt.i18n.client.BidiUtils; /** * A text box that allows multiple lines of text to be entered. - * + * * <p> * <img class='gallery' src='doc-files/TextArea.png'/> * </p> - * + * * <h3>CSS Style Rules</h3> * <ul class='css'> * <li>.gwt-TextArea { primary style }</li> * <li>.gwt-TextArea-readonly { dependent style set when the text area is read-only }</li> * </ul> - * + * * <p> * <h3>Example</h3> {@example com.google.gwt.examples.TextBoxExample} * </p> */ -public class TextArea extends TextBoxBase implements HasDirection { +public class TextArea extends TextBoxBase { /** * Creates a TextArea widget that wraps an existing <textarea> * element. - * + * * This element must already be attached to the document. If the element is * removed from the document, you must call * {@link RootPanel#detachNow(Widget)}. - * + * * @param element the element to be wrapped */ public static TextArea wrap(Element element) { @@ -74,7 +72,7 @@ /** * This constructor may be used by subclasses to explicitly use an existing * element. This element must be a <textarea> element. - * + * * @param element the element to be used */ protected TextArea(Element element) { @@ -85,7 +83,7 @@ /** * Gets the requested width of the text box (this is not an exact value, as * not all characters are created equal). - * + * * @return the requested width, in characters */ public int getCharacterWidth() { @@ -97,10 +95,6 @@ return getImpl().getTextAreaCursorPos(getElement()); } - public Direction getDirection() { - return BidiUtils.getDirectionOnElement(getElement()); - } - @Override public int getSelectionLength() { return getImpl().getTextAreaSelectionLength(getElement()); @@ -108,7 +102,7 @@ /** * Gets the number of text lines that are visible. - * + * * @return the number of visible lines */ public int getVisibleLines() { @@ -118,20 +112,16 @@ /** * Sets the requested width of the text box (this is not an exact value, as * not all characters are created equal). - * + * * @param width the requested width, in characters */ public void setCharacterWidth(int width) { getTextAreaElement().setCols(width); } - public void setDirection(Direction direction) { - BidiUtils.setDirectionOnElement(getElement(), direction); - } - /** * Sets the number of text lines that are visible. - * + * * @param lines the number of visible lines */ public void setVisibleLines(int lines) {
diff --git a/user/src/com/google/gwt/user/client/ui/TextBox.java b/user/src/com/google/gwt/user/client/ui/TextBox.java index bfcff46..baec618 100644 --- a/user/src/com/google/gwt/user/client/ui/TextBox.java +++ b/user/src/com/google/gwt/user/client/ui/TextBox.java
@@ -1,12 +1,12 @@ /* * Copyright 2008 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,38 +18,36 @@ import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.InputElement; -import com.google.gwt.i18n.client.BidiUtils; -import com.google.gwt.i18n.client.HasDirection; /** * A standard single-line text box. - * + * * <p> * <img class='gallery' src='doc-files/TextBox.png'/> * </p> - * + * * <h3>CSS Style Rules</h3> * <ul class='css'> * <li>.gwt-TextBox { primary style }</li> * <li>.gwt-TextBox-readonly { dependent style set when the text box is * read-only }</li> * </ul> - * + * * <p> * <h3>Example</h3> * {@example com.google.gwt.examples.TextBoxExample} * </p> */ -public class TextBox extends TextBoxBase implements HasDirection { +public class TextBox extends TextBoxBase { /** * Creates a TextBox widget that wraps an existing <input type='text'> * element. - * + * * This element must already be attached to the document. If the element is * removed from the document, you must call * {@link RootPanel#detachNow(Widget)}. - * + * * @param element the element to be wrapped */ public static TextBox wrap(Element element) { @@ -76,7 +74,7 @@ * This constructor may be used by subclasses to explicitly use an existing * element. This element must be an <input> element whose type is * 'text'. - * + * * @param element the element to be used */ protected TextBox(Element element) { @@ -91,13 +89,9 @@ } } - public Direction getDirection() { - return BidiUtils.getDirectionOnElement(getElement()); - } - /** * Gets the maximum allowable length of the text box. - * + * * @return the maximum length, in characters */ public int getMaxLength() { @@ -106,20 +100,16 @@ /** * Gets the number of visible characters in the text box. - * + * * @return the number of visible characters */ public int getVisibleLength() { return getInputElement().getSize(); } - public void setDirection(Direction direction) { - BidiUtils.setDirectionOnElement(getElement(), direction); - } - /** * Sets the maximum allowable length of the text box. - * + * * @param length the maximum length, in characters */ public void setMaxLength(int length) { @@ -128,7 +118,7 @@ /** * Sets the number of visible characters in the text box. - * + * * @param length the number of visible characters */ public void setVisibleLength(int length) {
diff --git a/user/src/com/google/gwt/user/client/ui/ValueBoxBase.java b/user/src/com/google/gwt/user/client/ui/ValueBoxBase.java index 10e7199..dbee95f 100644 --- a/user/src/com/google/gwt/user/client/ui/ValueBoxBase.java +++ b/user/src/com/google/gwt/user/client/ui/ValueBoxBase.java
@@ -23,6 +23,12 @@ import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.i18n.client.AutoDirectionHandler; +import com.google.gwt.i18n.client.BidiPolicy; +import com.google.gwt.i18n.client.BidiUtils; +import com.google.gwt.i18n.client.HasDirection; +import com.google.gwt.i18n.shared.DirectionEstimator; +import com.google.gwt.i18n.shared.HasDirectionEstimator; import com.google.gwt.text.shared.Parser; import com.google.gwt.text.shared.Renderer; import com.google.gwt.user.client.DOM; @@ -43,10 +49,13 @@ */ @SuppressWarnings("deprecation") public class ValueBoxBase<T> extends FocusWidget implements - SourcesChangeEvents, HasChangeHandlers, HasText, HasName, HasValue<T> { + SourcesChangeEvents, HasChangeHandlers, HasText, HasName, HasDirection, + HasDirectionEstimator, HasValue<T>, AutoDirectionHandler.Target { private static TextBoxImpl impl = GWT.create(TextBoxImpl.class); + private AutoDirectionHandler autoDirHandler; + private final Parser<T> parser; private final Renderer<T> renderer; @@ -61,6 +70,8 @@ */ protected ValueBoxBase(Element elem, Renderer<T> renderer, Parser<T> parser) { super(elem); + autoDirHandler = AutoDirectionHandler.addTo(this, + BidiPolicy.isBidiEnabled()); this.renderer = renderer; this.parser = parser; } @@ -111,6 +122,17 @@ return impl.getCursorPos(getElement()); } + public Direction getDirection() { + return BidiUtils.getDirectionOnElement(getElement()); + } + + /** + * Gets the direction estimation model of the auto-dir handler. + */ + public DirectionEstimator getDirectionEstimator() { + return autoDirHandler.getDirectionEstimator(); + } + public String getName() { return DOM.getElementProperty(getElement(), "name"); } @@ -229,6 +251,24 @@ setSelectionRange(pos, 0); } + public void setDirection(Direction direction) { + BidiUtils.setDirectionOnElement(getElement(), direction); + } + + /** + * Toggles on / off direction estimation. + */ + public void setDirectionEstimator(boolean enabled) { + autoDirHandler.setDirectionEstimator(enabled); + } + + /** + * Sets the direction estimation model of the auto-dir handler. + */ + public void setDirectionEstimator(DirectionEstimator directionEstimator) { + autoDirHandler.setDirectionEstimator(directionEstimator); + } + /** * If a keyboard event is currently being handled by the text box, this method * replaces the unicode character or key code associated with it. This allows @@ -302,6 +342,7 @@ */ public void setText(String text) { DOM.setElementProperty(getElement(), "value", text != null ? text : ""); + autoDirHandler.refreshDirection(); } /** @@ -330,4 +371,10 @@ protected TextBoxImpl getImpl() { return impl; } + + @Override + protected void onLoad() { + super.onLoad(); + autoDirHandler.refreshDirection(); + } }
diff --git a/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java b/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java index ee46262..4ab8784 100644 --- a/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java +++ b/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java
@@ -1,12 +1,12 @@ /* * Copyright 2007 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 @@ -17,6 +17,7 @@ import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; +import com.google.gwt.i18n.client.HasDirection.Direction; import com.google.gwt.junit.DoNotRunWith; import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; @@ -27,34 +28,11 @@ */ public abstract class TextBoxBaseTestBase extends GWTTestCase { - public String getModuleName() { - return "com.google.gwt.user.User"; - } + private static class Handler implements ValueChangeHandler<String> { + String received = null; - protected abstract TextBoxBase createTextBoxBase(); - - /** - * Tests that {@link TextArea#setText(String)} appropriately converts nulls to - * empty strings. - */ - public void testNullMeansEmptyString() { - TextBoxBase area = createTextBoxBase(); - area.setText(null); - assertEquals("setText(null) should result in empty string", "", - area.getText()); - } - - /** - * Tests that {@link TextArea#setCursorPos(int)} updates the cursor position - * correctly. - */ - public void testMovingCursor() { - TextBoxBase area = createTextBoxBase(); - RootPanel.get().add(area); - area.setText("abcd"); - for (int i = 0; i < 4; i++) { - area.setCursorPos(i); - assertEquals(i, area.getCursorPos()); + public void onValueChange(ValueChangeEvent<String> event) { + received = event.getValue(); } } @@ -97,23 +75,79 @@ area.selectAll(); } } - + + @Override + public String getModuleName() { + return "com.google.gwt.user.User"; + } + /** - * Failed in all modes due to HtmlUnit bug. + * Tests that auto-dir works correctly. + */ + public void testAutoDir() { + TextBoxBase tb = createTextBoxBase(); + String rtlText = "\u05e0\u05e1"; + String ltrText = "left to right"; + + // Direction should not be affected when auto-dir is disabled. + tb.setDirectionEstimator(false); + tb.setText(rtlText); + assertEquals("Direction should not be affected when auto-dir is disabled", + tb.getDirection(), Direction.DEFAULT); + + // Direction should be instantly updated as auto-dir is enabled. + tb.setDirectionEstimator(true); + assertEquals("Direction should be instantly updated as auto-dir is enabled", + tb.getDirection(), Direction.RTL); + + // Direction should be updated on setText when auto-dir is enabled. + tb.setText(ltrText); + assertEquals( + "Direction should be updated on setText when auto-dir is enabled", + tb.getDirection(), Direction.LTR); + } + + /** + * Tests that {@link TextArea#setCursorPos(int)} updates the cursor position + * correctly. + */ + public void testMovingCursor() { + TextBoxBase area = createTextBoxBase(); + RootPanel.get().add(area); + area.setText("abcd"); + for (int i = 0; i < 4; i++) { + area.setCursorPos(i); + assertEquals(i, area.getCursorPos()); + } + } + + /** + * Tests that {@link TextArea#setText(String)} appropriately converts nulls to + * empty strings. + */ + public void testNullMeansEmptyString() { + TextBoxBase area = createTextBoxBase(); + area.setText(null); + assertEquals("setText(null) should result in empty string", "", + area.getText()); + } + + /** + * Failed in all modes due to HtmlUnit bug: */ @DoNotRunWith({Platform.HtmlUnitBug}) public void testValueChangeEvent() { TextBoxBase tb = createTextBoxBase(); // To work cross-platform, the tb must be added to the root panel. RootPanel.get().add(tb); - + Handler h = new Handler(); tb.addValueChangeHandler(h); - + tb.setValue(null); assertEquals("", tb.getValue()); assertNull(h.received); - + tb.setText("able"); assertEquals("able", tb.getValue()); assertNull(h.received); @@ -135,12 +169,6 @@ tb.setValue("baker", true); assertEquals("baker", h.received); } - - private static class Handler implements ValueChangeHandler<String> { - String received = null; - - public void onValueChange(ValueChangeEvent<String> event) { - received = event.getValue(); - } - } + + protected abstract TextBoxBase createTextBoxBase(); }