Revision: 8454
Author: tomer...@google.com
Date: Mon Aug 2 09:47:24 2010
Log: Adds integral BiDi support to Label.java and its descendants.
Introduces a new interface, HasAutoHorizontalAlignment.
Review at http://gwt-code-reviews.appspot.com/642803
http://code.google.com/p/google-web-toolkit/source/detail?r=8454
Added:
/trunk/user/src/com/google/gwt/user/client/ui/HasAutoHorizontalAlignment.java
/trunk/user/test/com/google/gwt/user/client/ui/HTMLTest.java
/trunk/user/test/com/google/gwt/user/client/ui/LabelTest.java
Modified:
/trunk/user/src/com/google/gwt/i18n/shared/BidiFormatter.java
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/HorizontalAlignmentConstantParser.java
/trunk/user/src/com/google/gwt/user/client/ui/HTML.java
/trunk/user/src/com/google/gwt/user/client/ui/HasHorizontalAlignment.java
/trunk/user/src/com/google/gwt/user/client/ui/InlineHTML.java
/trunk/user/src/com/google/gwt/user/client/ui/InlineLabel.java
/trunk/user/src/com/google/gwt/user/client/ui/Label.java
/trunk/user/test/com/google/gwt/uibinder/attributeparsers/HorizontalAlignmentConstantParserTest.java
/trunk/user/test/com/google/gwt/user/UISuite.java
=======================================
--- /dev/null
+++
/trunk/user/src/com/google/gwt/user/client/ui/HasAutoHorizontalAlignment.java
Mon Aug 2 09:47:24 2010
@@ -0,0 +1,79 @@
+/*
+ * 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.user.client.ui;
+
+/**
+ * A widget that implements this interface can be configured to be aligned
+ * according to its contents' direction, in addition to the static
alignment
+ * options offered by {...@link HasHorizontalAlignment}.
+ */
+public interface HasAutoHorizontalAlignment extends HasHorizontalAlignment
{
+
+ /**
+ * Specifies that the widget's contents should be aligned left for LTR
+ * content, right for RTL content, and if the content's direction is
DEFAULT,
+ * like {...@link #ALIGN_LOCALE_START}.
+ */
+ AutoHorizontalAlignmentConstant ALIGN_CONTENT_START =
+ new AutoHorizontalAlignmentConstant();
+
+ /**
+ * Specifies that the widget's contents should be aligned right for LTR
+ * content, left for RTL content, and if the content's direction is
DEFAULT,
+ * like {...@link #ALIGN_LOCALE_END}.
+ */
+ AutoHorizontalAlignmentConstant ALIGN_CONTENT_END =
+ new AutoHorizontalAlignmentConstant();
+
+ /**
+ * Gets the horizontal auto-alignment setting. This may be one of the
+ * auto-alignment values above that depend on content direction (e.g.
+ * {...@link HasAutoHorizontalAlignment#ALIGN_CONTENT_START}), or one of the
+ * "static" {...@link HasHorizontalAlignment.HorizontalAlignmentConstant}
+ * alignment values (e.g. {...@link
HasHorizontalAlignment#ALIGN_LOCALE_START}).
+ * It may be set by either {...@code setAutoHorizontalAlignment} or {...@code
+ * HasHorizontalAlignment#setHorizontalAlignment}. The default is null,
+ * indicating that no specific horizontal alignment has been set,
allowing it
+ * to be determined by the usual HTML and CSS mechanisms.
+ *
+ * @return the current automatic horizontal alignment policy.
+ */
+ AutoHorizontalAlignmentConstant getAutoHorizontalAlignment();
+
+ /**
+ * Sets the horizontal alignment, allowing in addition to the "static"
+ * {...@link HasHorizontalAlignment.HorizontalAlignmentConstant} values, the
+ * "automatic" {...@link
HasHorizontalAlignment.AutoHorizontalAlignmentConstant}
+ * values that depend on the content direction. Determines the values
returned
+ * by both {...@link #getAutoHorizontalAlignment} and
+ * {...@link HasHorizontalAlignment#getHorizontalAlignment()}.
+ * <p> For the {...@code ALIGN_CONTENT_START} and {...@code
ALIGN_CONTENT_END}
+ * values, sets the horizontal alignment (including the value of {...@code
+ * HasHorizontalAlignment#getHorizontalAlignment()}) to the start or end
edge
+ * of the current content's direction, respectively, and continues to
+ * automatically update it whenever the content direction changes.
+ * <p> For other values, operates like {...@link #setHorizontalAlignment}.
+ * <p> For {...@code null}, the horizontal alignment is cleared, allowing
it to
+ * be determined by the standard HTML mechanisms such as inheritance and
CSS
+ * rules.
+ * @see HasHorizontalAlignment
+ *
+ * @param autoHorizontalAlignment the new automatic horizontal alignment
+ * policy
+ */
+ void setAutoHorizontalAlignment(AutoHorizontalAlignmentConstant
+ autoHorizontalAlignment);
+}
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/user/client/ui/HTMLTest.java Mon Aug 2
09:47:24 2010
@@ -0,0 +1,168 @@
+/*
+ * 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.user.client.ui;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.i18n.client.BidiUtils;
+import com.google.gwt.i18n.client.HasDirection.Direction;
+import com.google.gwt.i18n.client.LocaleInfo;
+
+/**
+ * Tests {...@link HTML}.
+ * Note: tests only the direction and alignment logic.
+ */
+public class HTMLTest extends LabelTest {
+
+ private final String EN_HTML = "<b style=\"color: red;\">" + EN_TEXT
+ "</b>";
+ private final String IW_HTML = "<b style=\"color: red;\">" + IW_TEXT
+ "</b>";
+ private HTML label;
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ // setDirection is deprecated; this only assures backwards compatibility.
+ public void testSetDirection() {
+ for (int i = 0; i < 2; i++) {
+ String id = i == 0 ? "div label: " : "span label: ";
+ label = HTML.wrap(i == 0 ? createAttachedDivElement() :
+ createAttachedSpanElement());
+ label.setDirection(Direction.RTL);
+ assertLabelDirection(id + "label's direction is incorrect after " +
+ "setDirection", Direction.RTL);
+
+ label.setText(EN_TEXT, Direction.LTR);
+ assertLabelDirection(id + "label's direction is incorrect after " +
+ "setText with a specific direction", Direction.LTR);
+
+ label.setText(EN_TEXT);
+ assertLabelDirection(id + "label's direction wasn't reverted to
the " +
+ "direction set by last setDirection when calling setText with
no " +
+ "direction argument and without a directionEstimator",
Direction.RTL);
+ if (i == 1) {
+ // For span element, we also specifically assert that the
direction of
+ // the topmost element matches the last setDirection.
+ assertEquals(id + "element's direction does not match the
direction " +
+ "set by last setDirection when calling setText with no
direction " +
+ "argument and without a directionEstimator", Direction.RTL,
+ BidiUtils.getDirectionOnElement(label.getElement()));
+ }
+ }
+ }
+
+ public void testSetDirectionEstimatorAndSetHtml() {
+ testSetDirectionEstimatorAndSetTextOrHtml(true);
+ }
+
+ public void testSetDirectionEstimatorAndSetText() {
+ testSetDirectionEstimatorAndSetTextOrHtml(false);
+ }
+
+ /**
+ * Asserts that both the {...@link Label#getContentDirection} and the
physical
+ * dir attribute match the expected direction.
+ *
+ * @param message Assertion message
+ * @param expected Expected direction
+ */
+ private void assertLabelDirection(String message, Direction expected) {
+ assertTrue("attribute mismatch: " + message,
+ expected == getLabelDirection() ||
+ /* For inline elements, empty dir attribute is acceptable if LTR is
+ * expected and the locale is not RTL. */
+ isSpanWrapped() && getLabelDirection() == Direction.DEFAULT &&
+ expected == Direction.LTR
&& !LocaleInfo.getCurrentLocale().isRTL());
+
+ assertEquals("contentDir mismatch: " + message, expected,
+ label.getContentDirection());
+ }
+
+ private Direction getLabelDirection() {
+ Element element = isSpanWrapped() ?
+ label.getElement().getFirstChildElement() : label.getElement();
+
+ return BidiUtils.getDirectionOnElement(element);
+ }
+
+ // This will not work generally. It assumes that the label's content
isn't
+ // consist of a span tag.
+ private boolean isSpanWrapped() {
+ Element inner = label.getElement().getFirstChildElement();
+ return inner != null && inner.getTagName().equalsIgnoreCase("span");
+ }
+
+ private void setLabelTextOrHtml(String content, boolean isHtml) {
+ if (isHtml) {
+ label.setHTML(content);
+ } else {
+ label.setText(content);
+ }
+ }
+
+ private void setLabelTextOrHtml(String content, Direction dir, boolean
isHtml) {
+ if (isHtml) {
+ label.setHTML(content, dir);
+ } else {
+ label.setText(content, dir);
+ }
+ }
+
+ private void testSetDirectionEstimatorAndSetTextOrHtml(boolean isHtml) {
+ String enContent = isHtml ? EN_HTML : EN_TEXT;
+ String iwContent = isHtml ? IW_HTML : IW_TEXT;
+ for (int i = 0; i < 2; i++) {
+ String id = i == 0 ? "div label: " : "span label: ";
+ label = HTML.wrap(i == 0 ? createAttachedDivElement() :
+ createAttachedSpanElement());
+
+ setLabelTextOrHtml(enContent, isHtml);
+ assertLabelDirection(id + "label's direction is not DEFAULT upon " +
+ "standard initialization", Direction.DEFAULT);
+
+ setLabelTextOrHtml(iwContent, Direction.RTL, isHtml);
+ assertLabelDirection(id + "label's direction is not RTL after it
was" +
+ " explicitly set to RTL", Direction.RTL);
+
+ setLabelTextOrHtml(enContent, isHtml);
+ assertLabelDirection(id + "label's direction was not specified, and
no" +
+ " estimator specified, thus should return to initial value
(DEFAULT)",
+ Direction.DEFAULT);
+
+ label.setDirectionEstimator(true);
+ assertLabelDirection(id + "label's direction wasn't instantly
updated" +
+ " to LTR on switching direction estimation on", Direction.LTR);
+
+ setLabelTextOrHtml(iwContent, isHtml);
+ assertLabelDirection(id + "label's direction wasn't estimated as
RTL",
+ Direction.RTL);
+
+ setLabelTextOrHtml(iwContent, Direction.LTR, isHtml);
+ assertLabelDirection(id + "label's direction is not LTR after it
was" +
+ " explicitly set to LTR (direction estimation is on)",
Direction.LTR);
+
+ setLabelTextOrHtml(iwContent, Direction.DEFAULT, isHtml);
+ assertLabelDirection(id + "label's direction is not DEFAULT after
it" +
+ " was explicitly set to DEFAULT (direction estimation is on)",
+ Direction.DEFAULT);
+
+ assertEquals(id + "retreived html is incorrect", iwContent,
+ label.getHTML());
+ assertEquals(id + "retreived text is incorrect", IW_TEXT,
+ label.getText());
+ }
+ }
+}
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/user/client/ui/LabelTest.java Mon Aug
2 09:47:24 2010
@@ -0,0 +1,167 @@
+/*
+ * 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.user.client.ui;
+
+import com.google.gwt.dom.client.DivElement;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.SpanElement;
+import com.google.gwt.i18n.client.BidiUtils;
+import com.google.gwt.i18n.client.HasDirection.Direction;
+import com.google.gwt.junit.client.GWTTestCase;
+import
com.google.gwt.user.client.ui.HasHorizontalAlignment.AutoHorizontalAlignmentConstant;
+import
com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;
+
+/**
+ * Tests {...@link Label}.
+ * Note: tests only the alignment logic. direction logic is tested at
+ * {...@link HTMLTest}, and other stuff remains currently untested.
+ */
+public class LabelTest extends GWTTestCase {
+
+ protected final String EN_TEXT = "abc";
+ protected final String IW_TEXT = "\u05e0\u05e1\u05e2";
+ private Label label;
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ public void testSetAutoHorizontalAlignmentNoDirectionEstimator() {
+ Element elem = createAttachedDivElement();
+ // Initialize the div with a specific direction, to verify it
remembers its
+ // original direction on setText with no direction argument.
+ BidiUtils.setDirectionOnElement(elem, Direction.LTR);
+ label = Label.wrap(elem);
+
+ label.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
+ assertAlign("horizontal alignment was set to left by " +
+ "setHorizontalAlignment, but is not",
+ HasHorizontalAlignment.ALIGN_LEFT);
+
+ label.setAutoHorizontalAlignment(null);
+ assertEquals("text-align is not empty after " +
+ "setAutoHorizontalAlignment(null)", "",
+ label.getElement().getStyle().getProperty("textAlign"));
+
+ label.setAutoHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
+ assertAlign("horizontal alignment was set to right by " +
+ "setAutoHorizontalAlignment, but is not",
+ HasHorizontalAlignment.ALIGN_RIGHT);
+
+ label.setText(IW_TEXT, Direction.RTL);
+ label.setAutoHorizontalAlignment(
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_END);
+ assertAlign("automatic horizontal alignment was set to
ALIGN_CONTENT_END," +
+ " content was declared RTL", HasHorizontalAlignment.ALIGN_LEFT,
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_END);
+
+ label.setText(EN_TEXT);
+ assertAlign("automatic horizontal alignment was set to
ALIGN_CONTENT_END," +
+ " content direction was reset to the original LTR after calling " +
+ "setText with no direction argument",
+ HasHorizontalAlignment.ALIGN_RIGHT,
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_END);
+
+ label.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_JUSTIFY);
+ assertAlign("horizontal alignment was set to justify by " +
+ "setHorizontalAlignment, but is not",
+ HasHorizontalAlignment.ALIGN_JUSTIFY);
+ }
+
+ public void testSetAutoHorizontalAlignmentWithDirectionEstimator() {
+ Element elem = createAttachedDivElement();
+ // Initialize the div with a specific direction, to verify it
remembers its
+ // original direction on turning direction estimator off.
+ BidiUtils.setDirectionOnElement(elem, Direction.LTR);
+ label = Label.wrap(createAttachedDivElement());
+
+ label.setAutoHorizontalAlignment(
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_END);
+ label.setDirectionEstimator(true);
+ label.setText(IW_TEXT);
+ assertAlign("automatic horizontal alignment was set to
ALIGN_CONTENT_END," +
+ " and content is supposedly estimated as RTL",
+ HasHorizontalAlignment.ALIGN_LEFT,
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_END);
+
+ label.setAutoHorizontalAlignment(
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_END);
+ assertAlign("automatic horizontal alignment was set (again) to " +
+ "ALIGN_CONTENT_END, and content is estimated as RTL",
+ HasHorizontalAlignment.ALIGN_LEFT,
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_END);
+
+ label.setAutoHorizontalAlignment(
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_START);
+ assertAlign("automatic horizontal alignment was set to " +
+ "ALIGN_CONTENT_START, content is estimated as RTL",
+ HasHorizontalAlignment.ALIGN_RIGHT,
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_START);
+
+ label.setDirectionEstimator(false);
+ assertAlign("direction was supposed to be reset to the original " +
+ "ALIGN_LEFT after turning off direction estimator, and automatic "
+
+ "horizontal alignment was to ALIGN_CONTENT_START",
+ HasHorizontalAlignment.ALIGN_LEFT,
+ HasAutoHorizontalAlignment.ALIGN_CONTENT_START);
+ }
+
+ /**
+ * Create a div and attach it to the {...@link RootPanel}.
+ *
+ * @return the new div
+ */
+ protected Element createAttachedDivElement() {
+ DivElement elem = Document.get().createDivElement();
+ RootPanel.getBodyElement().appendChild(elem);
+ return elem;
+ }
+
+ /**
+ * Create a span and attach it to the {...@link RootPanel}.
+ *
+ * @return the new span
+ */
+ protected Element createAttachedSpanElement() {
+ SpanElement elem = Document.get().createSpanElement();
+ RootPanel.getBodyElement().appendChild(elem);
+ return elem;
+ }
+
+ private void assertAlign(String msg, HorizontalAlignmentConstant
expected) {
+ assertAlign(msg, expected, expected);
+ }
+
+ /**
+ * Asserts that everything is fine with the alignment.
+ *
+ * @param msg assertion message
+ * @param expected expected horizontal alignment
+ * @param expectedAuto expected auto horizontal alignment
+ */
+ private void assertAlign(String msg, HorizontalAlignmentConstant
expected,
+ AutoHorizontalAlignmentConstant expectedAuto) {
+ assertEquals(msg + " (text-align property value is incorrect)",
+ expected.getTextAlignString(),
+ label.getElement().getStyle().getProperty("textAlign"));
+ assertEquals(msg + " (getHorizontalAlignment return value is
incorrect)",
+ expected, label.getHorizontalAlignment());
+ assertEquals(msg + " (getAutoHorizontalAlignment return value is
incorrect)",
+ expectedAuto, label.getAutoHorizontalAlignment());
+ }
+}
=======================================
--- /trunk/user/src/com/google/gwt/i18n/shared/BidiFormatter.java Tue Jul
20 08:04:29 2010
+++ /trunk/user/src/com/google/gwt/i18n/shared/BidiFormatter.java Mon Aug
2 09:47:24 2010
@@ -17,6 +17,7 @@
package com.google.gwt.i18n.shared;
import com.google.gwt.i18n.client.HasDirection.Direction;
+import com.google.gwt.i18n.client.LocaleInfo;
/**
* Utility class for formatting text for display in a potentially
@@ -182,7 +183,31 @@
boolean alwaysSpan) {
return new BidiFormatter(contextDir, alwaysSpan);
}
-
+
+ /**
+ * Factory for creating an instance of BidiFormatter whose context
direction
+ * matches the current locale's direction. The default behavior of {...@link
+ * #spanWrap} and its variations is set to avoid span wrapping unless
it's
+ * necessary ('dir' attribute needs to be set).
+ */
+ public static BidiFormatter getInstanceForCurrentLocale() {
+ return getInstanceForCurrentLocale(false);
+ }
+
+ /**
+ * Factory for creating an instance of BidiFormatter whose context
direction
+ * matches the current locale's direction, and given the desired span
wrapping
+ * behavior (see below).
+ *
+ * @param alwaysSpan Whether {...@link #spanWrap} (and its variations)
should
+ * always use a 'span' tag, even when the input direction is
neutral
+ * or matches the context, so that the DOM structure of the
output
+ * does not depend on the combination of directions
+ */
+ public static BidiFormatter getInstanceForCurrentLocale(boolean
alwaysSpan) {
+ return getInstance(LocaleInfo.getCurrentLocale().isRTL(), alwaysSpan);
+ }
+
private boolean alwaysSpan;
private Direction contextDir;
@@ -623,3 +648,4 @@
return
str.replace("&", "&").replace("<", "<").replace(">", ">").replace("\n", "<br>");
}
}
+
=======================================
---
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/HorizontalAlignmentConstantParser.java
Fri Jul 2 04:56:18 2010
+++
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/HorizontalAlignmentConstantParser.java
Mon Aug 2 09:47:24 2010
@@ -37,9 +37,11 @@
values.put("LEFT", PREFIX + "LEFT");
values.put("CENTER", PREFIX + "CENTER");
values.put("RIGHT", PREFIX + "RIGHT");
+ values.put("JUSTIFY", PREFIX + "JUSTIFY");
values.put("ALIGN_LEFT", PREFIX + "LEFT");
values.put("ALIGN_CENTER", PREFIX + "CENTER");
values.put("ALIGN_RIGHT", PREFIX + "RIGHT");
+ values.put("ALIGN_JUSTIFY", PREFIX + "JUSTIFY");
}
HorizontalAlignmentConstantParser(FieldReferenceConverter converter,
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/HTML.java Tue Jul 8
12:08:40 2008
+++ /trunk/user/src/com/google/gwt/user/client/ui/HTML.java Mon Aug 2
09:47:24 2010
@@ -1,12 +1,12 @@
/*
* Copyright 2006 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,25 +17,26 @@
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.i18n.client.HasDirection.Direction;
/**
* A widget that can contain arbitrary HTML.
- *
+ *
* This widget uses a <div> element, causing it to be displayed with
block
* layout.
- *
+ *
* <p>
* If you only need a simple label (text, but not HTML), then the
* {...@link com.google.gwt.user.client.ui.Label} widget is more appropriate,
as it
* disallows the use of HTML, which can lead to potential security issues
if not
* used properly.
* </p>
- *
+ *
* <h3>CSS Style Rules</h3>
* <ul class='css'>
* <li>.gwt-HTML { }</li>
* </ul>
- *
+ *
* <p>
* <h3>Example</h3>
* {...@example com.google.gwt.examples.HTMLExample}
@@ -46,11 +47,11 @@
/**
* Creates an HTML widget that wraps an existing <div> or
<span>
* 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 HTML wrap(Element element) {
@@ -76,18 +77,31 @@
/**
* Creates an HTML widget with the specified HTML contents.
- *
+ *
* @param html the new widget's HTML contents
*/
public HTML(String html) {
this();
setHTML(html);
}
+
+ /**
+ * Creates an HTML widget with the specified HTML contents and with the
+ * specified direction.
+ *
+ * @param html the new widget's HTML contents
+ * @param dir the content's direction. Note: {...@code Direction.DEFAULT}
means
+ * direction should be inherited from the widget's parent element.
+ */
+ public HTML(String html, Direction dir) {
+ this();
+ setHTML(html, dir);
+ }
/**
* Creates an HTML widget with the specified contents, optionally
treating it
* as HTML, and optionally disabling word wrapping.
- *
+ *
* @param html the widget's contents
* @param wordWrap <code>false</code> to disable word wrapping
*/
@@ -99,20 +113,41 @@
/**
* This constructor may be used by subclasses to explicitly use an
existing
* element. This element must be either a <div> or <span>
element.
- *
+ *
* @param element the element to be used
*/
protected HTML(Element element) {
+ // super(element) asserts that element is either a <div> or
+ // <span>.
super(element);
- assert element.getTagName().equalsIgnoreCase("div")
- || element.getTagName().equalsIgnoreCase("span");
}
public String getHTML() {
- return getElement().getInnerHTML();
+ return getTextOrHtml(true);
}
+ /**
+ * Sets the label's content to the given HTML.
+ * See {...@link #setText(String)} for details on potential effects on
direction
+ * and alignment.
+ *
+ * @param html the new widget's HTML content
+ */
public void setHTML(String html) {
- getElement().setInnerHTML(html);
+ setTextOrHtml(html, true);
+ }
+
+
+ /**
+ * Sets the label's content to the given HTML, applying the given
direction.
+ * See {...@link #setText(String, Direction)} for details on potential
effects on
+ * alignment.
+ *
+ * @param html the new widget's HTML content
+ * @param dir the content's direction. Note: {...@code Direction.DEFAULT}
means
+ * direction should be inherited from the widget's parent element.
+ */
+ public void setHTML(String html, Direction dir) {
+ setTextOrHtml(html, dir, true);
}
}
=======================================
---
/trunk/user/src/com/google/gwt/user/client/ui/HasHorizontalAlignment.java
Fri Jul 2 04:56:18 2010
+++
/trunk/user/src/com/google/gwt/user/client/ui/HasHorizontalAlignment.java
Mon Aug 2 09:47:24 2010
@@ -16,6 +16,7 @@
package com.google.gwt.user.client.ui;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.HasDirection.Direction;
import com.google.gwt.i18n.client.LocaleInfo;
/**
@@ -27,7 +28,7 @@
* <p>
* The names of the static members of {...@link HorizontalAlignmentConstant},
as
* well as simple alignment names (<code>left</code>, <code>center</code>,
- * <code>right</code>), can be used as values for a
+ * <code>right</code>, <code>justify</code>), can be used as values for a
* <code>horizontalAlignment</code> attribute of any widget that
implements this
* interface. (In fact, this will work for any widget method that takes a
single
* HorizontalAlignmentConstant value.)
@@ -42,9 +43,37 @@
public interface HasHorizontalAlignment {
/**
- * Horizontal alignment constant.
+ * Type for values defined and used in {...@link
HasAutoHorizontalAlignment}.
+ * Defined here so that HorizontalAlignmentConstant can be derived from
it,
+ * thus allowing HasAutoHorizontalAlignment methods to accept and return
both
+ * AutoHorizontalAlignmentConstant and HorizontalAlignmentConstant
values -
+ * without allowing the methods defined here to accept or return
+ * AutoHorizontalAlignmentConstant values.
*/
- public static class HorizontalAlignmentConstant {
+ public static class AutoHorizontalAlignmentConstant {
+ // The constructor is package-private to prevent uncontrolled
inheritance
+ // and instantiation of this class.
+ AutoHorizontalAlignmentConstant() {
+ }
+ }
+
+ /**
+ * Possible return values for {...@link #getHorizontalAlignment}, and
parameter
+ * values for {...@link #setHorizontalAlignment}.
+ */
+ public static class HorizontalAlignmentConstant extends
+ AutoHorizontalAlignmentConstant {
+
+ public static HorizontalAlignmentConstant endOf(Direction direction) {
+ return direction == Direction.LTR ? ALIGN_RIGHT :
+ direction == Direction.RTL ? ALIGN_LEFT : ALIGN_LOCALE_END;
+ }
+
+ public static HorizontalAlignmentConstant startOf(Direction direction)
{
+ return direction == Direction.LTR ? ALIGN_LEFT :
+ direction == Direction.RTL ? ALIGN_RIGHT : ALIGN_LOCALE_START;
+ }
+
private final String textAlignString;
private HorizontalAlignmentConstant(String textAlignString) {
@@ -53,7 +82,7 @@
/**
* Gets the CSS 'text-align' string associated with this constant.
- *
+ *
* @return the CSS 'text-align' value
*/
public String getTextAlignString() {
@@ -67,6 +96,12 @@
HorizontalAlignmentConstant ALIGN_CENTER = new
HorizontalAlignmentConstant(
"center");
+ /**
+ * Specifies that the widget's contents should be aligned as justify.
+ */
+ HorizontalAlignmentConstant ALIGN_JUSTIFY = new
HorizontalAlignmentConstant(
+ "justify");
+
/**
* Specifies that the widget's contents should be aligned to the left.
*/
@@ -84,24 +119,47 @@
* the right. In a LTR layout, specifies that the widget's constants
should be
* aligned to the left.
*/
- HorizontalAlignmentConstant ALIGN_DEFAULT = GWT.isClient()
+ HorizontalAlignmentConstant ALIGN_LOCALE_START = GWT.isClient()
&& LocaleInfo.getCurrentLocale().isRTL() ? ALIGN_RIGHT : ALIGN_LEFT;
+ /**
+ * In a RTL layout, specifies that the widget's contents should be
aligned to
+ * the left. In a LTR layout, specifies that the widget's constants
should be
+ * aligned to the right.
+ */
+ HorizontalAlignmentConstant ALIGN_LOCALE_END = GWT.isClient()
+ && LocaleInfo.getCurrentLocale().isRTL() ? ALIGN_LEFT : ALIGN_RIGHT;
+
+ /**
+ * Synonym of {...@link #ALIGN_LOCALE_START}.
+ */
+ HorizontalAlignmentConstant ALIGN_DEFAULT = ALIGN_LOCALE_START;
+
/**
* Gets the horizontal alignment.
- *
- * @return the current horizontal alignment.
+ *
+ * @return the current horizontal alignment (
+ * {...@link HasHorizontalAlignment#ALIGN_LEFT},
+ * {...@link HasHorizontalAlignment#ALIGN_CENTER},
+ * {...@link HasHorizontalAlignment#ALIGN_RIGHT},
+ * {...@link HasHorizontalAlignment#ALIGN_JUSTIFY}, or
+ * null).
*/
HorizontalAlignmentConstant getHorizontalAlignment();
/**
* Sets the horizontal alignment.
- *
+ * <p> Use {...@code null} to clear horizontal alignment, allowing it to be
+ * determined by the standard HTML mechanisms such as inheritance and CSS
+ * rules.
+ *
* @param align the horizontal alignment (
- * {...@link HasHorizontalAlignment#ALIGN_LEFT},
- * {...@link HasHorizontalAlignment#ALIGN_CENTER},
- * {...@link HasHorizontalAlignment#ALIGN_RIGHT}), or
- * {...@link HasHorizontalAlignment#ALIGN_DEFAULT}).
+ * {...@link HasHorizontalAlignment#ALIGN_LEFT},
+ * {...@link HasHorizontalAlignment#ALIGN_CENTER},
+ * {...@link HasHorizontalAlignment#ALIGN_RIGHT},
+ * {...@link HasHorizontalAlignment#ALIGN_JUSTIFY},
+ * {...@link HasHorizontalAlignment#ALIGN_LOCALE_START}, or
+ * {...@link HasHorizontalAlignment#ALIGN_LOCALE_END}).
*/
void setHorizontalAlignment(HorizontalAlignmentConstant align);
}
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/InlineHTML.java Wed Oct
28 09:10:53 2009
+++ /trunk/user/src/com/google/gwt/user/client/ui/InlineHTML.java Mon Aug
2 09:47:24 2010
@@ -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
@@ -17,20 +17,21 @@
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.i18n.client.HasDirection.Direction;
/**
* A widget that can contain arbitrary HTML.
- *
+ *
* This widget uses a <span> element, causing it to be displayed with
* inline layout.
- *
+ *
* <p>
* If you only need a simple label (text, but not HTML), then the
* {...@link com.google.gwt.user.client.ui.Label} widget is more appropriate,
as it
* disallows the use of HTML, which can lead to potential security issues
if not
* used properly.
* </p>
- *
+ *
* <h3>CSS Style Rules</h3>
* <ul class='css'>
* <li>.gwt-InlineHTML { }</li>
@@ -41,11 +42,11 @@
/**
* Creates an InlineHTML widget that wraps an existing <div> or
* <span> 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 InlineHTML wrap(Element element) {
@@ -71,23 +72,36 @@
/**
* Creates an HTML widget with the specified HTML contents.
- *
+ *
* @param html the new widget's HTML contents
*/
public InlineHTML(String html) {
this();
setHTML(html);
}
+
+ /**
+ * Creates an HTML widget with the specified HTML contents and with the
+ * specified direction.
+ *
+ * @param html the new widget's HTML contents
+ * @param dir the content's direction. Note: {...@code Direction.DEFAULT}
means
+ * direction should be inherited from the widget's parent element.
+ */
+ public InlineHTML(String html, Direction dir) {
+ this();
+ setHTML(html, dir);
+ }
/**
* This constructor may be used by subclasses to explicitly use an
existing
* element. This element must be either a <div> <span>
element.
- *
+ *
* @param element the element to be used
*/
protected InlineHTML(Element element) {
+ // super(element) also asserts that element is either a <div> or
+ // <span>.
super(element);
- assert element.getTagName().equalsIgnoreCase("div")
- || element.getTagName().equalsIgnoreCase("span");
}
}
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/InlineLabel.java Wed Oct
28 09:10:53 2009
+++ /trunk/user/src/com/google/gwt/user/client/ui/InlineLabel.java Mon Aug
2 09:47:24 2010
@@ -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
@@ -17,13 +17,14 @@
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.i18n.client.HasDirection.Direction;
/**
* A widget that contains arbitrary text, <i>not</i> interpreted as HTML.
- *
+ *
* This widget uses a <span> element, causing it to be displayed with
* inline layout.
- *
+ *
* <h3>CSS Style Rules</h3>
* <ul class='css'>
* <li>.gwt-InlineLabel { }</li>
@@ -34,11 +35,11 @@
/**
* Creates a InlineLabel widget that wraps an existing <div> or
* <span> 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 InlineLabel wrap(Element element) {
@@ -64,23 +65,35 @@
/**
* Creates a label with the specified text.
- *
+ *
* @param text the new label's text
*/
public InlineLabel(String text) {
this();
setText(text);
}
+
+ /**
+ * Creates a label with the specified text and direction.
+ *
+ * @param text the new label's text
+ * @param dir the text's direction. Note: {...@code Direction.DEFAULT} means
+ * direction should be inherited from the widget's parent element.
+ */
+ public InlineLabel(String text, Direction dir) {
+ this();
+ setText(text, dir);
+ }
/**
* This constructor may be used by subclasses to explicitly use an
existing
* element. This element must be either a <div> <span>
element.
- *
+ *
* @param element the element to be used
*/
protected InlineLabel(Element element) {
+ // super(element) also asserts that element is either a <div> or
+ // <span>.
super(element);
- assert element.getTagName().equalsIgnoreCase("div")
- || element.getTagName().equalsIgnoreCase("span");
}
}
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/Label.java Fri Mar 20
11:33:42 2009
+++ /trunk/user/src/com/google/gwt/user/client/ui/Label.java Mon Aug 2
09:47:24 2010
@@ -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
@@ -36,36 +36,40 @@
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.BidiUtils;
import com.google.gwt.i18n.client.HasDirection;
+import com.google.gwt.i18n.shared.BidiFormatter;
+import com.google.gwt.i18n.shared.DirectionEstimator;
+import com.google.gwt.i18n.shared.HasDirectionEstimator;
+import com.google.gwt.i18n.shared.WordCountDirectionEstimator;
/**
* A widget that contains arbitrary text, <i>not</i> interpreted as HTML.
- *
+ *
* This widget uses a <div> element, causing it to be displayed with
block
* layout.
- *
+ *
* <h3>CSS Style Rules</h3>
* <ul class='css'>
* <li>.gwt-Label { }</li>
* </ul>
- *
+ *
* <p>
* <h3>Example</h3>
* {...@example com.google.gwt.examples.HTMLExample}
* </p>
*/
@SuppressWarnings("deprecation")
-public class Label extends Widget implements HasHorizontalAlignment,
HasText,
- HasWordWrap, HasDirection, HasClickHandlers, SourcesClickEvents,
- SourcesMouseEvents, HasAllMouseHandlers {
+public class Label extends Widget implements HasText, HasWordWrap,
HasDirection,
+ HasClickHandlers, SourcesClickEvents, SourcesMouseEvents,
+ HasAllMouseHandlers, HasDirectionEstimator, HasAutoHorizontalAlignment
{
/**
* Creates a Label widget that wraps an existing <div> or
<span>
* 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 Label wrap(Element element) {
@@ -81,29 +85,96 @@
return label;
}
+ /**
+ * The widget's auto horizontal alignment policy.
+ * @see HasAutoHorizontalAlignment
+ */
+ private AutoHorizontalAlignmentConstant autoHorizontalAlignment;
+
+ /**
+ * The direction of the widget's content.
+ * Note: this may not match the direction of the widget's top DOM element
+ * ({...@code getElement()}).
+ * See {...@link #setTextOrHtml(String, Direction, boolean)} for details.
+ */
+ private Direction contentDir;
+
+ /**
+ * The widget's DirectionEstimator object.
+ */
+ private DirectionEstimator directionEstimator;
+
+ /**
+ * The widget's horizontal alignment.
+ */
private HorizontalAlignmentConstant horzAlign;
+ /**
+ * The initial direction of the widget's element.
+ */
+ private Direction initialElementDir;
+
+ /**
+ * Whether the widget is inline (a <span> element).
+ * This is needed because direction is handled differently for inline
elements
+ * and for non-inline elements.
+ * <p>
+ * In case Label supports types of elements other than span and div, this
+ * should get true for any element that is inline by default. Another
approach
+ * could be calculating the element's display property, but this may
have some
+ * overhead, and is problematic when the element is yet unattached.
+ */
+ private boolean isElementInline;
+
+ /**
+ * Whether the widget contains a nested <span> element used to
+ * indicate the content's direction.
+ * <p>
+ * The widget's top element is used for this purpose when it is a
<div>,
+ * but doing so on an inline element often results in garbling what
follows
+ * it. Thus, when the widget's top element is a <span>, a nested
+ * <span> must be used to carry the content's direction, with an
LRM or
+ * RLM character afterwards to prevent the garbling.
+ */
+ private boolean isSpanWrapped;
+
/**
* Creates an empty label.
*/
public Label() {
setElement(Document.get().createDivElement());
setStyleName("gwt-Label");
+ isElementInline = false;
+ isSpanWrapped = false;
+ contentDir = Direction.DEFAULT;
+ initialElementDir = Direction.DEFAULT;
}
/**
* Creates a label with the specified text.
- *
+ *
* @param text the new label's text
*/
public Label(String text) {
this();
setText(text);
}
+
+ /**
+ * Creates a label with the specified text and direction.
+ *
+ * @param text the new label's text
+ * @param dir the text's direction. Note that {...@code DEFAULT} means
direction
+ * should be inherited from the widget's parent element.
+ */
+ public Label(String text, Direction dir) {
+ this();
+ setText(text, dir);
+ }
/**
* Creates a label with the specified text.
- *
+ *
* @param text the new label's text
* @param wordWrap <code>false</code> to disable word wrapping
*/
@@ -115,13 +186,17 @@
/**
* This constructor may be used by subclasses to explicitly use an
existing
* element. This element must be either a <div> or <span>
element.
- *
+ *
* @param element the element to be used
*/
protected Label(Element element) {
setElement(element);
- assert element.getTagName().equalsIgnoreCase("div")
- || element.getTagName().equalsIgnoreCase("span");
+ String tagName = element.getTagName();
+ isElementInline = tagName.equalsIgnoreCase("span");
+ assert isElementInline || tagName.equalsIgnoreCase("div");
+ isSpanWrapped = false;
+ initialElementDir = BidiUtils.getDirectionOnElement(element);
+ contentDir = initialElementDir;
}
public HandlerRegistration addClickHandler(ClickHandler handler) {
@@ -141,9 +216,9 @@
}
/**
- * @deprecated Use {...@link #addMouseOverHandler} {...@link
- * #addMouseMoveHandler}, {...@link #addMouseDownHandler}, {...@link
- * #addMouseUpHandler} and {...@link #addMouseOutHandler} instead
+ * @deprecated Use {...@link #addMouseOverHandler},
+ * {...@link #addMouseMoveHandler}, {...@link #addMouseDownHandler},
+ * {...@link #addMouseUpHandler} and {...@link #addMouseOutHandler} instead
*/
@Deprecated
public void addMouseListener(MouseListener listener) {
@@ -178,16 +253,39 @@
ListenerWrapper.WrappedMouseWheelListener.add(this, listener);
}
+ /**
+ * {...@inheritdoc}
+ */
+ public AutoHorizontalAlignmentConstant getAutoHorizontalAlignment() {
+ return autoHorizontalAlignment;
+ }
+
+ public Direction getContentDirection() {
+ return contentDir;
+ }
+
+ /**
+ * Gets the widget element's direction.
+ * @deprecated Use {...@link #getContentDirection} instead
+ */
+ @Deprecated
public Direction getDirection() {
return BidiUtils.getDirectionOnElement(getElement());
}
+ public DirectionEstimator getDirectionEstimator() {
+ return directionEstimator;
+ }
+
+ /**
+ * {...@inheritdoc}
+ */
public HorizontalAlignmentConstant getHorizontalAlignment() {
return horzAlign;
}
public String getText() {
- return getElement().getInnerText();
+ return getTextOrHtml(false);
}
public boolean getWordWrap() {
@@ -195,7 +293,7 @@
}
/**
- * @deprecated Use the {...@link HandlerRegistration#removeHandler} method
on
+ * @deprecated Use the {...@link HandlerRegistration#removeHandler} method
on
* the object returned by {...@link #addClickHandler} instead
*/
@Deprecated
@@ -221,21 +319,217 @@
ListenerWrapper.WrappedMouseWheelListener.remove(this, listener);
}
+ /**
+ * {...@inheritdoc}
+ */
+ public void setAutoHorizontalAlignment(AutoHorizontalAlignmentConstant
+ autoAlignment) {
+ autoHorizontalAlignment = autoAlignment;
+ updateHorizontalAlignment();
+ }
+
+ /**
+ * Sets the widget element's direction.
+ * @deprecated Use {...@link #setDirectionEstimator} and / or pass explicit
+ * direction to {...@link #setText} instead
+ */
+ @Deprecated
public void setDirection(Direction direction) {
BidiUtils.setDirectionOnElement(getElement(), direction);
+ initialElementDir = direction;
+
+ // For backwards compatibility, assure there's no span wrap, and
update the
+ // content direction.
+ setInnerTextOrHtml(getTextOrHtml(true), true);
+ isSpanWrapped = false;
+ contentDir = initialElementDir;
+ updateHorizontalAlignment();
}
+ /**
+ * {...@inheritdoc}
+ * <p>
+ * See note at {...@link #setDirectionEstimator(DirectionEstimator)}.
+ */
+ public void setDirectionEstimator(boolean enabled) {
+ setDirectionEstimator(enabled ? WordCountDirectionEstimator.get() :
null);
+ }
+
+ /**
+ * {...@inheritdoc}
+ * <p>
+ * Note: if the widget already has non-empty content, this will update
+ * its direction according to the new estimator's result. This may cause
+ * flicker, and thus should be avoided; DirectionEstimator should be set
+ * before the widget has any content.
+ */
+ public void setDirectionEstimator(DirectionEstimator directionEstimator)
{
+ this.directionEstimator = directionEstimator;
+ // Refresh appearance
+ setTextOrHtml(getTextOrHtml(true), true);
+ }
+
+ /**
+ * {...@inheritdoc}
+ *
+ * <p> Note: A subsequent call to {...@link #setAutoHorizontalAlignment} may
+ * override the horizontal alignment set by this method.
+ * <p> Note: For {...@code null}, the horizontal alignment is cleared,
allowing
+ * it to be determined by the standard HTML mechanisms such as
inheritance and
+ * CSS rules.
+ * @see #setAutoHorizontalAlignment
+ */
public void setHorizontalAlignment(HorizontalAlignmentConstant align) {
- horzAlign = align;
- getElement().getStyle().setProperty("textAlign",
align.getTextAlignString());
+ setAutoHorizontalAlignment(align);
}
+ /**
+ * Sets the label's content to the given text.
+ * <p>
+ * Doesn't change the widget's direction or horizontal alignment if
+ * {...@code directionEstimator} is null. Otherwise, the widget's direction
is
+ * set using the estimator, and its alignment may therefore change as
+ * described in {...@link #setText(String, Direction)}.
+ *
+ * @param text the widget's new text
+ */
public void setText(String text) {
- getElement().setInnerText(text);
+ setTextOrHtml(text, false);
+ }
+
+ /**
+ * Sets the label's content to the given text, applying the given
direction.
+ * <p>
+ * This will have the following effect on the horizontal alignment:
+ * <ul>
+ * <li> If the automatic alignment setting is ALIGN_CONTENT_START or
+ * ALIGN_CONTENT_END, the horizontal alignment will be set to match the
start
+ * or end edge, respectively, of the new direction (the {...@code dir}
+ * parameter). If that is DEFAULT, the locale direction is used.
+ * <li> Otherwise, the horizontal alignment value is not changed, but the
+ * effective alignment may nevertheless change according to the usual
HTML
+ * rules, i.e. it will match the start edge of the new direction if the
widget
+ * element is a <div> and has no explicit alignment value even by
+ * inheritance.
+ * </ul>
+ *
+ * @param text the widget's new text
+ * @param dir the text's direction. Note: {...@code Direction.DEFAULT} means
+ * direction should be inherited from the widget's parent element.
+ */
+ public void setText(String text, Direction dir) {
+ setTextOrHtml(text, dir, false);
}
public void setWordWrap(boolean wrap) {
getElement().getStyle().setProperty("whiteSpace",
wrap ? "normal" : "nowrap");
}
-}
+
+ protected String getTextOrHtml(boolean isHtml) {
+ Element element = isSpanWrapped ? getElement().getFirstChildElement()
+ : getElement();
+ return isHtml ? element.getInnerHTML() : element.getInnerText();
+ }
+
+ /**
+ * Sets the label's content to the given value (either plain text or
HTML).
+ * See {...@link #setText(String)} for details on potential effects on
direction
+ * and alignment.
+ *
+ * @param content the widget's new content
+ * @param isHtml whether the content is HTML
+ */
+ protected void setTextOrHtml(String content, boolean isHtml) {
+ if (directionEstimator == null) {
+ isSpanWrapped = false;
+ setInnerTextOrHtml(content, isHtml);
+
+ // Preserves the initial direction of the widget. This is different
from
+ // passing the direction parameter explicitly as DEFAULT, which
forces the
+ // widget to inherit the direction from its parent.
+ if (contentDir != initialElementDir) {
+ contentDir = initialElementDir;
+ BidiUtils.setDirectionOnElement(getElement(), initialElementDir);
+ updateHorizontalAlignment();
+ }
+ } else {
+ setTextOrHtml(content, directionEstimator.estimateDirection(content,
+ isHtml), isHtml);
+ }
+ }
+
+ /**
+ * Sets the label's content to the given value (either plain text or
HTML),
+ * applying the given direction.
+ * See {...@link #setText(String, Direction)} for details on potential
effects on
+ * alignment.
+ * <p>
+ * Implementation details:
+ * <ul>
+ * <li> If the widget's element is a <div>, sets its dir attribute
+ * according to the given direction.
+ * <li> Otherwise (i.e. the widget's element is a <span>), the
direction
+ * is set using a nested <span dir=...> element which holds the
content
+ * of the widget. This nested span may be followed by a zero-width
Unicode
+ * direction character (LRM or RLM). This manipulation is necessary to
prevent
+ * garbling in case the direction of the widget is opposite to the
direction
+ * of its context. See {...@link com.google.gwt.i18n.shared.BidiFormatter}
for
+ * more details.
+ * </ul>
+ *
+ * @param content the widget's new content
+ * @param dir the content's direction
+ * @param isHtml whether the content is HTML
+ */
+ protected void setTextOrHtml(String content, Direction dir, boolean
isHtml) {
+ contentDir = dir;
+
+ // Set the text and the direction.
+ if (isElementInline) {
+ isSpanWrapped = true;
+ getElement().setInnerHTML(BidiFormatter.getInstanceForCurrentLocale(
+ true /* alwaysSpan */).spanWrapWithKnownDir(dir, content,
isHtml));
+ } else {
+ isSpanWrapped = false;
+ BidiUtils.setDirectionOnElement(getElement(), dir);
+ setInnerTextOrHtml(content, isHtml);
+ }
+
+ // Update the horizontal alignment if needed.
+ updateHorizontalAlignment();
+ }
+
+ private void setInnerTextOrHtml(String content, boolean isHtml) {
+ if (isHtml) {
+ getElement().setInnerHTML(content);
+ } else {
+ getElement().setInnerText(content);
+ }
+ }
+
+ /**
+ * Sets the horizontal alignment of the widget according to the current
+ * AutoHorizontalAlignment setting.
+ */
+ private void updateHorizontalAlignment() {
+ HorizontalAlignmentConstant align;
+ if (autoHorizontalAlignment == null) {
+ align = null;
+ } else if (autoHorizontalAlignment instanceof
HorizontalAlignmentConstant) {
+ align = (HorizontalAlignmentConstant) autoHorizontalAlignment;
+ } else {
+ /* autoHorizontalAlignment is a truly automatic policy, i.e. either
+ ALIGN_CONTENT_START or ALIGN_CONTENT_END */
+ align = autoHorizontalAlignment == ALIGN_CONTENT_START ?
+ HorizontalAlignmentConstant.startOf(contentDir) :
+ HorizontalAlignmentConstant.endOf(contentDir);
+ }
+
+ if (align != horzAlign) {
+ horzAlign = align;
+ getElement().getStyle().setProperty("textAlign", horzAlign ==
null ? ""
+ : horzAlign.getTextAlignString());
+ }
+ }
+}
=======================================
---
/trunk/user/test/com/google/gwt/uibinder/attributeparsers/HorizontalAlignmentConstantParserTest.java
Fri Jul 2 04:56:18 2010
+++
/trunk/user/test/com/google/gwt/uibinder/attributeparsers/HorizontalAlignmentConstantParserTest.java
Mon Aug 2 09:47:24 2010
@@ -49,16 +49,19 @@
assertEquals(HHA + ".ALIGN_LEFT", parser.parse("left"));
assertEquals(HHA + ".ALIGN_CENTER", parser.parse("center"));
assertEquals(HHA + ".ALIGN_RIGHT", parser.parse("right"));
+ assertEquals(HHA + ".ALIGN_JUSTIFY", parser.parse("justify"));
// capitalized
assertEquals(HHA + ".ALIGN_LEFT", parser.parse("Left"));
assertEquals(HHA + ".ALIGN_CENTER", parser.parse("Center"));
assertEquals(HHA + ".ALIGN_RIGHT", parser.parse("Right"));
+ assertEquals(HHA + ".ALIGN_JUSTIFY", parser.parse("Justify"));
}
public void testUglyNames() throws UnableToCompleteException {
assertEquals(HHA + ".ALIGN_LEFT", parser.parse("ALIGN_LEFT"));
assertEquals(HHA + ".ALIGN_CENTER", parser.parse("ALIGN_CENTER"));
assertEquals(HHA + ".ALIGN_RIGHT", parser.parse("ALIGN_RIGHT"));
+ assertEquals(HHA + ".ALIGN_JUSTIFY", parser.parse("ALIGN_JUSTIFY"));
}
public void testBad() {
=======================================
--- /trunk/user/test/com/google/gwt/user/UISuite.java Mon Jun 7 12:20:31
2010
+++ /trunk/user/test/com/google/gwt/user/UISuite.java Mon Aug 2 09:47:24
2010
@@ -55,12 +55,14 @@
import com.google.gwt.user.client.ui.FormPanelTest;
import com.google.gwt.user.client.ui.GridTest;
import com.google.gwt.user.client.ui.HTMLPanelTest;
+import com.google.gwt.user.client.ui.HTMLTest;
import com.google.gwt.user.client.ui.HiddenTest;
import com.google.gwt.user.client.ui.HistoryTest;
import com.google.gwt.user.client.ui.HorizontalPanelTest;
import com.google.gwt.user.client.ui.HorizontalSplitPanelTest;
import com.google.gwt.user.client.ui.HyperlinkTest;
import com.google.gwt.user.client.ui.ImageTest;
+import com.google.gwt.user.client.ui.LabelTest;
import com.google.gwt.user.client.ui.LazyPanelTest;
import com.google.gwt.user.client.ui.LinearPanelTest;
import com.google.gwt.user.client.ui.ListBoxTest;
@@ -150,9 +152,11 @@
suite.addTestSuite(HorizontalPanelTest.class);
suite.addTestSuite(HorizontalSplitPanelTest.class);
suite.addTestSuite(HTMLPanelTest.class);
+ suite.addTestSuite(HTMLTest.class);
suite.addTestSuite(HyperlinkTest.class);
suite.addTestSuite(ImageBundleGeneratorTest.class);
suite.addTestSuite(ImageTest.class);
+ suite.addTestSuite(LabelTest.class);
suite.addTestSuite(LayoutTest.class);
suite.addTestSuite(LazyPanelTest.class);
suite.addTestSuite(LinearPanelTest.class);
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors