Adds support for RTL layout in GWT. Here are the specific changes:
-adds the dir="rtl" attribute to the <html> element on the first call to RootPanel.get(id) or RootPanel.get(), provided that the application's current locale is one with an RTL language
-Sets the default alignment of the HorizontalPanel to be "left" in LTR layout, and "right" in RTL layout
-DockPanel defines two new direction constants - LINE_START and LINE_END. They are bidi-friendly constants. In an RTL environment, LINE_START corresponds to the right side of the DockPanel. In an LTR environment, LINE_START corresponds to the left side of the DockPanel. WEST and EAST are now ALWAYS west and east - they do not vary based on directionality. WEST is always on the left, and EAST is always on the right.
-changes the layout of the Tree based on the directionality of the document - branches expand to the left when the layout is RTL. Also changed keyboard navigation - in an RTL layout, the left key expands branches, and the right key collapses them. Also added TreeImagesRTL, which extends TreeImages. This is a future extension point in case we end up using tree icons that are not direction-agnostic.
-changes the layout of Menus so that submenus pop out to the left in an RTL layout; also changed keyboard navigation so that the left key expands submenus in an RTL layout. Changed MenuBar so that it accepts an image bundle as input to its ctor for its images, and added the MenuImagesRTL bundle, which contains the rtl versions of the menu images.
-added the DisclosureImagesRTL image bundle, which contains rtl versions of DisclosurePanel's default images.
-adds support for HorizontalSplitPanel in an RTL layout. Two methods have been added to support the adding of widgets to the panel that is at the "start of the line layout" and "end of the line layout", as opposed to just LEFT and RIGHT (this is similar to the change that was made to DockPanel). Also, the positioning of widgets with HorizontalSplitPanel.add() is right pane first, and then left pane. setSplitPosition still sets the size of the left pane in RTL mode.
-TextArea, TextBox, and Label implement the HasDirection interface. This interface allows those widgets that implement it to set their own directionality, thereby overriding the global direction.
-KitchenSink's tabs have been modified to 'look pretty' in RTL mode. This required the addition of another rounded corner image for use in RTL mode. While making this change, I also cleaned up (hopefully) some of the style switching code for first vs. other tabs, selected vs. unselected tabs. The existing code did not take advantage of dependent style names, so I updated the code to do so.
-User.gwt.xml now includes the I18N module. This change was necessary in order to support the use of LocaleInfo in the user libraries without having to move the LocaleInfo class into the user.client package
-Removed LocaleInfo_none_Test. This test was used to test that LocaleInfo functioned correctly when the I18N module was not included. Due to the above-mentioned change, this test is no longer relevant
-Addition of BidiUtils.java. This utility class defines two static methods setDirectionOnElement(elem, Direction) and getDirection(elem). All of the current implementations of HasDirection basically delegate to these two helper methods.
-Added an RTL-version of the submenu icon. In the future, this bundle containing both images should probably be replaced by a locale-sensitive FooBundle
Patch By: adil.allawi, shanjian, rdayal, jgw, knorton, jat, ecc
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2350 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Panels.java b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Panels.java
index 5c26ca2..0c9f612 100644
--- a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Panels.java
+++ b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Panels.java
@@ -135,8 +135,8 @@
tabs.selectTab(0);
HorizontalSplitPanel hSplit = new HorizontalSplitPanel();
- hSplit.setLeftWidget(tabs);
- hSplit.setRightWidget(new HTML(
+ hSplit.setStartOfLineWidget(tabs);
+ hSplit.setEndOfLineWidget(new HTML(
"This is some text to make the right side of this " +
"splitter look a bit more interesting... " +
"This is some text to make the right side of this " +
diff --git a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Popups.java b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Popups.java
index 143c7ba..f6b098c 100644
--- a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Popups.java
+++ b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Popups.java
@@ -25,6 +25,7 @@
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.i18n.client.LocaleInfo;
/**
* Demonstrates {@link com.google.gwt.user.client.ui.PopupPanel} and
@@ -120,13 +121,23 @@
initWidget(panel);
}
- public void onClick(Widget sender) {
+ public void onClick(final Widget sender) {
if (sender == popupButton) {
- MyPopup p = new MyPopup();
- int left = sender.getAbsoluteLeft() + 10;
- int top = sender.getAbsoluteTop() + 10;
- p.setPopupPosition(left, top);
- p.show();
+
+ final MyPopup p = new MyPopup();
+
+ // Set the position relative to the button
+ p.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
+ public void setPosition(int offsetWidth, int offsetHeight) {
+ int left = popupButton.getAbsoluteLeft() + 10;
+ int top = popupButton.getAbsoluteTop() + 10;
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ left = popupButton.getAbsoluteLeft() +
+ popupButton.getOffsetWidth() - offsetWidth - 10;
+ }
+ p.setPopupPosition(left, top);
+ }
+ });
} else if (sender == dialogButton) {
DialogBox dlg = new MyDialog();
dlg.center();
diff --git a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/SinkList.java b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/SinkList.java
index 7d383b8..4c1a75f 100644
--- a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/SinkList.java
+++ b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/SinkList.java
@@ -22,6 +22,7 @@
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.i18n.client.LocaleInfo;
import java.util.ArrayList;
@@ -129,13 +130,27 @@
}
private void styleSink(int index, boolean selected) {
- String style = (index == 0) ? "ks-FirstSinkItem" : "ks-SinkItem";
- if (selected) {
- style += "-selected";
+ Widget w = list.getWidget(index + 1);
+
+ String primaryStyleName = "ks-SinkItem";
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ primaryStyleName += "-rtl";
}
- Widget w = list.getWidget(index + 1);
- w.setStyleName(style);
+ w.setStylePrimaryName(primaryStyleName);
+
+ if (index == 0) {
+ w.addStyleDependentName("first");
+ } else {
+ w.removeStyleDependentName("first");
+ }
+
+ if (selected) {
+ w.addStyleDependentName("selected");
+ } else {
+ w.removeStyleDependentName("selected");
+ }
colorSink(index, selected);
}
diff --git a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Widgets.java b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Widgets.java
index 5b1c585..bf37793 100644
--- a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Widgets.java
+++ b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/client/Widgets.java
@@ -112,7 +112,7 @@
MenuBar menu0 = new MenuBar(true);
menu0.addItem("<b>Bold</b>", true, this);
menu0.addItem("<i>Italicized</i>", true, this);
- menu0.addItem("More »", true, subMenu);
+ menu0.addItem("More", true, subMenu);
MenuBar menu1 = new MenuBar(true);
menu1.addItem("<font color='#FF0000'><b>Apple</b></font>", true, this);
menu1.addItem("<font color='#FFFF00'><b>Banana</b></font>", true, this);
diff --git a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/KitchenSink.css b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/KitchenSink.css
index b8812c9..2583b22 100644
--- a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/KitchenSink.css
+++ b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/KitchenSink.css
@@ -373,27 +373,14 @@
top: 8px;
}
-.ks-List .ks-SinkItem a {
+.ks-List .ks-SinkItem a,
+.ks-List .ks-SinkItem-rtl a {
text-decoration: none;
color: white;
}
-.ks-List .ks-SinkItem-selected a {
- text-decoration: none;
- color: white;
-}
-
-.ks-List .ks-FirstSinkItem a {
- text-decoration: none;
- color: white;
-}
-
-.ks-List .ks-FirstSinkItem-selected a {
- text-decoration: none;
- color: white;
-}
-
-.ks-List .ks-SinkItem {
+.ks-List .ks-SinkItem,
+.ks-List .ks-SinkItem-rtl {
background: #c6cab7;
padding: 4px;
padding-left: 16px;
@@ -404,33 +391,19 @@
cursor: hand;
}
-.ks-List .ks-SinkItem-selected {
- background: #c6cab7;
- padding: 4px;
- padding-left: 16px;
- padding-right: 16px;
- margin-right: 3px;
+.ks-List .ks-SinkItem-selected,
+.ks-List .ks-SinkItem-rtl-selected {
padding-bottom: 7px;
+ border-bottom: none;
+ cursor: auto;
}
-.ks-List .ks-FirstSinkItem {
+.ks-List .ks-SinkItem-first {
background: #c6cab7 url(images/corner.gif) no-repeat top left;
- padding: 4px;
- padding-left: 16px;
- padding-right: 16px;
- margin-right: 3px;
- border-bottom: 3px solid white;
- cursor: pointer;
- cursor: hand;
}
-.ks-List .ks-FirstSinkItem-selected {
- background: #c3d9ff url(images/corner.gif) no-repeat top left;
- padding: 4px;
- padding-left: 16px;
- padding-right: 16px;
- margin-right: 3px;
- padding-bottom: 7px;
+.ks-List .ks-SinkItem-rtl-first {
+ background: #c6cab7 url( images/corner_rtl.gif ) no-repeat top right;
}
.ks-images-Image {
diff --git a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/images/corner_rtl.gif b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/images/corner_rtl.gif
new file mode 100644
index 0000000..3d09da7
--- /dev/null
+++ b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/images/corner_rtl.gif
Binary files differ
diff --git a/user/src/com/google/gwt/i18n/client/BidiUtils.java b/user/src/com/google/gwt/i18n/client/BidiUtils.java
new file mode 100644
index 0000000..a51a489
--- /dev/null
+++ b/user/src/com/google/gwt/i18n/client/BidiUtils.java
@@ -0,0 +1,96 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.client;
+
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.i18n.client.HasDirection.Direction;
+
+/**
+ * A set of bidi-related utility methods.
+ */
+public class BidiUtils {
+
+ /**
+ * The name of the element property which controls element directionality.
+ */
+ public static final String DIR_PROPERTY_NAME = "dir";
+
+ /**
+ * The value for the directionality property which will set the element directionality
+ * to right-to-left.
+ */
+ private static final String DIR_PROPERTY_VALUE_RTL = "rtl";
+
+ /**
+ * The value for the directionality property which will set the element directionality
+ * to left-to-right.
+ */
+ private static final String DIR_PROPERTY_VALUE_LTR = "ltr";
+
+ /**
+ * Gets the directionality of an element.
+ *
+ * @param elem the element on which to check the directionality property
+ * @return <code>RTL</code> if the directionality is right-to-left,
+ * <code>LTR</code> if the directionality is left-to-right, or
+ * <code>DEFAULT</code> if the directionality is not explicitly set
+ */
+ public static HasDirection.Direction getDirectionOnElement(Element elem) {
+
+ String dirPropertyValue = DOM.getElementProperty(elem, DIR_PROPERTY_NAME);
+
+ if (DIR_PROPERTY_VALUE_RTL.equalsIgnoreCase(dirPropertyValue)) {
+ return HasDirection.Direction.RTL;
+ } else if (DIR_PROPERTY_VALUE_LTR.equalsIgnoreCase(dirPropertyValue)) {
+ return HasDirection.Direction.LTR;
+ }
+
+ return HasDirection.Direction.DEFAULT;
+ }
+
+ /**
+ * Sets the directionality property for an element.
+ *
+ * @param elem the element on which to set the property
+ * @param direction <code>RTL</code> if the directionality should be set to right-to-left,
+ * <code>LTR</code> if the directionality should be set to left-to-right
+ * <code>DEFAULT</code> if the directionality should be removed from the element
+ */
+ public static void setDirectionOnElement(Element elem, Direction direction) {
+
+ switch (direction) {
+ case RTL: {
+ DOM.setElementProperty(elem, DIR_PROPERTY_NAME, DIR_PROPERTY_VALUE_RTL);
+ break;
+ }
+
+ case LTR: {
+ DOM.setElementProperty(elem, DIR_PROPERTY_NAME, DIR_PROPERTY_VALUE_LTR);
+ break;
+ }
+
+ case DEFAULT: {
+ if (getDirectionOnElement(elem) != HasDirection.Direction.DEFAULT) {
+ // only clear out the the dir property if it has already been set to something
+ // explicitly
+ DOM.setElementProperty(elem, DIR_PROPERTY_NAME, "");
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/user/src/com/google/gwt/i18n/client/HasDirection.java b/user/src/com/google/gwt/i18n/client/HasDirection.java
new file mode 100644
index 0000000..587b87c
--- /dev/null
+++ b/user/src/com/google/gwt/i18n/client/HasDirection.java
@@ -0,0 +1,53 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.client;
+
+/**
+ * A widget that implements this interface has the ability to override
+ * the document directionality for its root element.
+ *
+ * Widgets that implement this interface should be leaf widgets. More
+ * specifically, they should not implement the
+ * {@link com.google.gwt.user.client.ui.HasWidgets} interface.
+ */
+public interface HasDirection {
+
+ /**
+ * Possible return values for {@link HasDirection#getDirection()} and parameter values for
+ * {@link HasDirection#setDirection(Direction)}.Widgets that implement this interface can
+ * either have a direction that is right-to-left (RTL), left-to-right (LTR), or default
+ * (which means that their directionality is inherited from their parent widget).
+ */
+ enum Direction { RTL, LTR, DEFAULT }
+
+ /**
+ * Sets the directionality for a widget.
+ *
+ * @param direction <code>RTL</code> if the directionality should be set to right-to-left,
+ * <code>LTR</code> if the directionality should be set to left-to-right
+ * <code>DEFAULT</code> if the directionality should not be explicitly set
+ */
+ void setDirection(Direction direction);
+
+ /**
+ * Gets the directionality of the widget.
+ *
+ * @return <code>RTL</code> if the directionality is right-to-left,
+ * <code>LTR</code> if the directionality is left-to-right, or
+ * <code>DEFAULT</code> if the directionality is not explicitly specified
+ */
+ Direction getDirection();
+}
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index d79a3da..4bac2f6 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -26,6 +26,7 @@
<inherits name="com.google.gwt.user.Window" />
<inherits name="com.google.gwt.user.HTTPRequest"/>
<inherits name="com.google.gwt.user.History"/>
+ <inherits name="com.google.gwt.i18n.I18N"/>
<inherits name="com.google.gwt.user.Popup"/>
<inherits name="com.google.gwt.user.Form"/>
<inherits name="com.google.gwt.user.TextBox"/>
diff --git a/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java b/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
index 5920238..c1ebab4 100644
--- a/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
@@ -20,6 +20,7 @@
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.animation.WidgetAnimation;
+import com.google.gwt.i18n.client.LocaleInfo;
import java.util.ArrayList;
import java.util.Iterator;
@@ -247,6 +248,9 @@
private static ContentAnimation contentAnimation;
private static DisclosurePanelImages createDefaultImages() {
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ return GWT.create(DisclosurePanelImagesRTL.class);
+ }
return GWT.create(DisclosurePanelImages.class);
}
diff --git a/user/src/com/google/gwt/user/client/ui/DisclosurePanelImages.java b/user/src/com/google/gwt/user/client/ui/DisclosurePanelImages.java
index 248c105..ac84430 100644
--- a/user/src/com/google/gwt/user/client/ui/DisclosurePanelImages.java
+++ b/user/src/com/google/gwt/user/client/ui/DisclosurePanelImages.java
@@ -34,3 +34,25 @@
*/
AbstractImagePrototype disclosurePanelClosed();
}
+
+
+/**
+ * A bundle containing the RTL versions of the images for DisclosurePanel. Right now, we
+ * only need to override the disclosurePanelClosed() method, as the image that we provide
+ * for disclosurePanelOpen() is direction-agnostic.
+ *
+ * Notice that this interface is package protected. This interface need not be
+ * publicly exposed, as it is only used by the DisclosurePanel class to provide RTL
+ * versions of the images in the case the the user does not pass in their own
+ * bundle. However, we cannot make this class private, because the generated
+ * class needs to be able to extend this class.
+ */
+interface DisclosurePanelImagesRTL extends DisclosurePanelImages {
+ /**
+ * An image indicating a closed disclosure panel for a RTL context.
+ *
+ * @return a prototype of this image
+ */
+ @Resource("disclosurePanelClosed_rtl.png")
+ AbstractImagePrototype disclosurePanelClosed();
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/client/ui/DockPanel.java b/user/src/com/google/gwt/user/client/ui/DockPanel.java
index f2096a6..bd32fe2 100644
--- a/user/src/com/google/gwt/user/client/ui/DockPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DockPanel.java
@@ -17,6 +17,7 @@
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
+import com.google.gwt.i18n.client.LocaleInfo;
import java.util.HashMap;
import java.util.Iterator;
@@ -26,9 +27,6 @@
* A panel that lays its child widgets out "docked" at its outer edges, and
* allows its last widget to take up the remaining space in its center.
*
- * <p>
- * <img class='gallery' src='DockPanel.png'/>
- * </p>
*/
public class DockPanel extends CellPanel implements HasAlignment {
@@ -46,10 +44,10 @@
*/
static class LayoutData {
public DockLayoutConstant direction;
- public String hAlign = "left";
+ public String hAlign = ALIGN_DEFAULT.getTextAlignString();
public String height = "";
public Element td;
- public String vAlign = "top";
+ public String vAlign = ALIGN_TOP.getVerticalAlignString();
public String width = "";
public LayoutData(DockLayoutConstant dir) {
@@ -68,6 +66,18 @@
public static final DockLayoutConstant CENTER = new DockLayoutConstant();
/**
+ * Specifies that a widget be added at the beginning of the line direction
+ * for the layout.
+ */
+ public static final DockLayoutConstant LINE_START = new DockLayoutConstant();
+
+ /**
+ * Specifies that a widget be added at the end of the line direction
+ * for the layout.
+ */
+ public static final DockLayoutConstant LINE_END = new DockLayoutConstant();
+
+ /**
* Specifies that a widget be added at the east edge of the dock.
*/
public static final DockLayoutConstant EAST = new DockLayoutConstant();
@@ -103,12 +113,16 @@
return "west" + count;
} else if (direction == EAST) {
return "east" + count;
- } else {
+ } else if (direction == LINE_START) {
+ return "linestart" + count;
+ } else if (direction == LINE_END) {
+ return "lineend" + count;
+ } else {
return "center";
}
}
-
- private HorizontalAlignmentConstant horzAlign = ALIGN_LEFT;
+
+ private HorizontalAlignmentConstant horzAlign = ALIGN_DEFAULT;
private VerticalAlignmentConstant vertAlign = ALIGN_TOP;
private Widget center;
@@ -214,7 +228,7 @@
LayoutData data = (LayoutData) w.getLayoutData();
data.hAlign = align.getTextAlignString();
if (data.td != null) {
- DOM.setElementProperty(data.td, "align", data.hAlign);
+ setCellHorizontalAlignment(data.td, align);
}
}
@@ -223,7 +237,7 @@
LayoutData data = (LayoutData) w.getLayoutData();
data.vAlign = align.getVerticalAlignString();
if (data.td != null) {
- DOM.setStyleAttribute(data.td, "verticalAlign", data.vAlign);
+ setCellVerticalAlignment(data.td, align);
}
}
@@ -318,7 +332,7 @@
DockLayoutConstant dir = ((LayoutData) child.getLayoutData()).direction;
if ((dir == NORTH) || (dir == SOUTH)) {
++rowCount;
- } else if ((dir == EAST) || (dir == WEST)) {
+ } else if ((dir == EAST) || (dir == WEST) || (dir == LINE_START) || (dir == LINE_END)) {
++colCount;
}
}
@@ -330,7 +344,7 @@
DOM.appendChild(bodyElem, rows[i].tr);
}
- int westCol = 0, eastCol = colCount - 1;
+ int logicalLeftCol = 0, logicalRightCol = colCount - 1;
int northRow = 0, southRow = rowCount - 1;
Element centerTd = null;
@@ -348,30 +362,30 @@
if (layout.direction == NORTH) {
DOM.insertChild(rows[northRow].tr, td, rows[northRow].center);
DOM.appendChild(td, child.getElement());
- DOM.setElementPropertyInt(td, "colSpan", eastCol - westCol + 1);
+ DOM.setElementPropertyInt(td, "colSpan", logicalRightCol - logicalLeftCol + 1);
++northRow;
} else if (layout.direction == SOUTH) {
DOM.insertChild(rows[southRow].tr, td, rows[southRow].center);
DOM.appendChild(td, child.getElement());
- DOM.setElementPropertyInt(td, "colSpan", eastCol - westCol + 1);
+ DOM.setElementPropertyInt(td, "colSpan", logicalRightCol - logicalLeftCol + 1);
--southRow;
- } else if (layout.direction == WEST) {
+ } else if (layout.direction == CENTER) {
+ // Defer adding the center widget, so that it can be added after all
+ // the others are complete.
+ centerTd = td;
+ } else if (shouldAddToLogicalLeftOfTable(layout.direction)) {
TmpRow row = rows[northRow];
DOM.insertChild(row.tr, td, row.center++);
DOM.appendChild(td, child.getElement());
DOM.setElementPropertyInt(td, "rowSpan", southRow - northRow + 1);
- ++westCol;
- } else if (layout.direction == EAST) {
+ ++logicalLeftCol;
+ } else if (shouldAddToLogicalRightOfTable(layout.direction)) {
TmpRow row = rows[northRow];
DOM.insertChild(row.tr, td, row.center);
DOM.appendChild(td, child.getElement());
DOM.setElementPropertyInt(td, "rowSpan", southRow - northRow + 1);
- --eastCol;
- } else if (layout.direction == CENTER) {
- // Defer adding the center widget, so that it can be added after all
- // the others are complete.
- centerTd = td;
- }
+ --logicalRightCol;
+ }
}
// If there is a center widget, add it at the end (centerTd is guaranteed
@@ -383,4 +397,51 @@
DOM.appendChild(centerTd, center.getElement());
}
}
+
+ private boolean shouldAddToLogicalLeftOfTable(DockLayoutConstant widgetDirection) {
+
+ assert (widgetDirection == LINE_START || widgetDirection == LINE_END ||
+ widgetDirection == EAST || widgetDirection == WEST);
+
+ // In a bidi-sensitive environment, adding a widget to the logical left
+ // column (think DOM order) means that it will be displayed at the start
+ // of the line direction for the current layout. This is because HTML
+ // tables are bidi-sensitive; the column order switches depending on
+ // the line direction.
+ if (widgetDirection == LINE_START) {
+ return true;
+ }
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ // In an RTL layout, the logical left columns will be displayed on the right hand
+ // side. When the direction for the widget is EAST, adding the widget to the logical
+ // left columns will have the desired effect of displaying the widget on the 'eastern'
+ // side of the screen.
+ return (widgetDirection == EAST);
+ }
+
+ // In an LTR layout, the logical left columns are displayed on the left hand
+ // side. When the direction for the widget is WEST, adding the widget to the
+ // logical left columns will have the desired effect of displaying the widget on the
+ // 'western' side of the screen.
+ return (widgetDirection == WEST);
+ }
+
+ private boolean shouldAddToLogicalRightOfTable(DockLayoutConstant widgetDirection) {
+
+ // See comments for shouldAddToLogicalLeftOfTable for clarification
+
+ assert (widgetDirection == LINE_START || widgetDirection == LINE_END ||
+ widgetDirection == EAST || widgetDirection == WEST);
+
+ if (widgetDirection == LINE_END) {
+ return true;
+ }
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ return (widgetDirection == WEST);
+ }
+
+ return (widgetDirection == EAST);
+ }
}
diff --git a/user/src/com/google/gwt/user/client/ui/HasHorizontalAlignment.java b/user/src/com/google/gwt/user/client/ui/HasHorizontalAlignment.java
index 5c5310c..ab187aa 100644
--- a/user/src/com/google/gwt/user/client/ui/HasHorizontalAlignment.java
+++ b/user/src/com/google/gwt/user/client/ui/HasHorizontalAlignment.java
@@ -15,6 +15,8 @@
*/
package com.google.gwt.user.client.ui;
+import com.google.gwt.i18n.client.LocaleInfo;
+
/**
* Characteristic interface which indicates that a widget can be aligned
* horizontally.
@@ -60,6 +62,14 @@
"right");
/**
+ * In a RTL layout, specifies that the widget's contents should be aligned
+ * to the right. In a LTR layout, specifies that the widget's constants
+ * should be aligned to the left.
+ */
+ HorizontalAlignmentConstant ALIGN_DEFAULT =
+ (LocaleInfo.getCurrentLocale().isRTL()) ? ALIGN_RIGHT : ALIGN_LEFT;
+
+ /**
* Gets the horizontal alignment.
*
* @return the current horizontal alignment.
@@ -71,8 +81,9 @@
*
* @param align the horizontal alignment (
* {@link HasHorizontalAlignment#ALIGN_LEFT},
- * {@link HasHorizontalAlignment#ALIGN_CENTER}, or
- * {@link HasHorizontalAlignment#ALIGN_RIGHT}).
+ * {@link HasHorizontalAlignment#ALIGN_CENTER},
+ * {@link HasHorizontalAlignment#ALIGN_RIGHT}), or
+ * {@link HasHorizontalAlignment#ALIGN_DEFAULT}).
*/
void setHorizontalAlignment(HorizontalAlignmentConstant align);
}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/client/ui/HorizontalPanel.java b/user/src/com/google/gwt/user/client/ui/HorizontalPanel.java
index f01112f..4df2d35 100644
--- a/user/src/com/google/gwt/user/client/ui/HorizontalPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/HorizontalPanel.java
@@ -27,7 +27,7 @@
*/
public class HorizontalPanel extends CellPanel implements HasAlignment {
- private HorizontalAlignmentConstant horzAlign = ALIGN_LEFT;
+ private HorizontalAlignmentConstant horzAlign = ALIGN_DEFAULT;
private Element tableRow;
private VerticalAlignmentConstant vertAlign = ALIGN_TOP;
diff --git a/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java b/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
index 6cc2488..2bc9dfc 100644
--- a/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
@@ -21,6 +21,7 @@
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Timer;
+import com.google.gwt.i18n.client.LocaleInfo;
/**
* A panel that arranges two widgets in a single horizontal row and allows the
@@ -58,16 +59,25 @@
DOM.setStyleAttribute(panel.getElement(), "position", "relative");
- final Element rightElem = panel.getElement(RIGHT);
-
expandToFitParentHorizontally(panel.getElement(LEFT));
- expandToFitParentHorizontally(rightElem);
+ expandToFitParentHorizontally(panel.getElement(RIGHT));
expandToFitParentHorizontally(panel.getSplitElement());
expandToFitParentUsingCssOffsets(panel.container);
- // Snap the right wrapper to the right side.
- setRight(rightElem, "0px");
+ // Right now, both panes are stacked on top of each other
+ // on either the left side or the right side of the containing
+ // panel. This happens because both panes have position:absolute
+ // and no left/top values. The panes will be on the left side
+ // if the directionality is LTR, and on the right side if the
+ // directionality is RTL. In the LTR case, we need to snap the
+ // right pane to the right of the container, and in the RTL case,
+ // we need to snap the left pane to the left of the container.
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ setLeft(panel.getElement(LEFT), "0px");
+ } else {
+ setRight(panel.getElement(RIGHT), "0px");
+ }
}
public void onAttach() {
@@ -77,10 +87,24 @@
}
public void onSplitResize(int px) {
- setSplitPosition(px);
+ setSplitPositionUsingPixels(px);
}
- public void setSplitPosition(int px) {
+ public void setSplitPosition(String pos) {
+ final Element leftElem = panel.getElement(LEFT);
+ setWidth(leftElem, pos);
+ setSplitPositionUsingPixels(getOffsetWidth(leftElem));
+ }
+
+ /**
+ * Set the splitter's position in units of pixels.
+ *
+ * px represents the splitter's position as a distance
+ * of px pixels from the left edge of the container. This is
+ * true even in a bidi environment. Callers of this method
+ * must be aware of this constraint.
+ */
+ public void setSplitPositionUsingPixels(int px) {
final Element splitElem = panel.getSplitElement();
final int rootElemWidth = getOffsetWidth(panel.container);
@@ -121,7 +145,10 @@
}
public void updateRightWidth(Element rightElem, int newRightWidth) {
- // Update is handled by CSS.
+ // No need to update the width of the right side; this will be
+ // recomputed automatically by CSS. This is helpful, as we do not
+ // have to worry about watching for resize events and adjusting the
+ // right-side width.
}
}
@@ -139,9 +166,17 @@
this.panel = panel;
final Element elem = panel.getElement();
+
// Prevents inherited text-align settings from interfering with the
- // panel's layout.
- DOM.setStyleAttribute(elem, "textAlign", "left");
+ // panel's layout. The setting we choose must be bidi-sensitive,
+ // as left-alignment is the default with LTR directionality, and
+ // right-alignment is the default with RTL directionality.
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ DOM.setStyleAttribute(elem, "textAlign", "right");
+ } else {
+ DOM.setStyleAttribute(elem, "textAlign", "left");
+ }
+
DOM.setStyleAttribute(elem, "position", "relative");
/*
@@ -154,6 +189,13 @@
addAbsolutePositoning(panel.getSplitElement());
expandToFitParentUsingPercentages(panel.container);
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ // Snap the left pane to the left edge of the container. We
+ // only need to do this when layout is RTL; if we don't, the
+ // left pane will overlap the right pane.
+ setLeft(panel.getElement(LEFT), "0px");
+ }
}
@Override
@@ -175,7 +217,7 @@
new Timer() {
@Override
public void run() {
- setSplitPosition(splitPosition);
+ setSplitPositionUsingPixels(splitPosition);
isResizeInProgress = false;
}
}.schedule(resizeUpdatePeriod);
@@ -183,6 +225,63 @@
splitPosition = px;
}
+ public void setSplitPositionUsingPixels(int px) {
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ final Element splitElem = panel.getSplitElement();
+
+ final int rootElemWidth = getOffsetWidth(panel.container);
+ final int splitElemWidth = getOffsetWidth(splitElem);
+
+ // This represents an invalid state where layout is incomplete. This
+ // typically happens before DOM attachment, but I leave it here as a
+ // precaution because negative width/height style attributes produce
+ // errors on IE.
+ if (rootElemWidth < splitElemWidth) {
+ return;
+ }
+
+ // Compute the new right side width.
+ int newRightWidth = rootElemWidth - px - splitElemWidth;
+
+ // Constrain the dragging to the physical size of the panel.
+ if (px < 0) {
+ px = 0;
+ newRightWidth = rootElemWidth - splitElemWidth;
+ } else if (newRightWidth < 0) {
+ px = rootElemWidth - splitElemWidth;
+ newRightWidth = 0;
+ }
+
+ // Set the width of the right side.
+ setWidth(panel.getElement(RIGHT), newRightWidth + "px");
+
+ // Move the splitter to the right edge of the left element.
+ setLeft(splitElem, px + "px");
+
+ // Update the width of the left side
+ if (px == 0) {
+
+ // This takes care of a qurky RTL layout bug with IE6.
+ // During DOM construction and layout, onResize events
+ // are fired, and this method is called with px == 0.
+ // If one tries to set the width of the LEFT element to
+ // before layout completes, the RIGHT element will
+ // appear to be blanked out.
+
+ DeferredCommand.addCommand(new Command() {
+ public void execute() {
+ setWidth(panel.getElement(LEFT), "0px");
+ }
+ });
+ } else {
+ setWidth(panel.getElement(LEFT), px + "px");
+ }
+
+ } else {
+ super.setSplitPositionUsingPixels(px);
+ }
+ }
+
@Override
public void updateRightWidth(Element rightElem, int newRightWidth) {
setWidth(rightElem, newRightWidth + "px");
@@ -203,7 +302,7 @@
setHeight(rightElem, height);
setHeight(panel.getSplitElement(), height);
setHeight(leftElem, height);
- setSplitPosition(getOffsetWidth(leftElem));
+ setSplitPositionUsingPixels(getOffsetWidth(leftElem));
}
}
@@ -257,6 +356,9 @@
/**
* Creates an empty horizontal split panel.
+ *
+ * @param images ImageBundle containing an image for the splitter's drag
+ * thumb
*/
public HorizontalSplitPanel(HorizontalSplitPanelImages images) {
super(DOM.createDiv(), DOM.createDiv(), preventBoxStyles(DOM.createDiv()),
@@ -277,11 +379,51 @@
}
/**
+ * Adds a widget to a pane in the HorizontalSplitPanel. The method
+ * will first attempt to add the widget to the left pane. If a
+ * widget is already in that position, it will attempt to add the
+ * widget to the right pane. If a widget is already in that position,
+ * an exception will be thrown, as a HorizontalSplitPanel can
+ * contain at most two widgets.
+ *
+ * Note that this method is bidi-sensitive. In an RTL environment,
+ * this method will first attempt to add the widget to the right pane,
+ * and if a widget is already in that position, it will attempt to add
+ * the widget to the left pane.
+ *
+ * @param w the widget to be added
+ * @throws IllegalStateException
+ */
+ @Override
+ public void add(Widget w) {
+ if (getStartOfLineWidget() == null) {
+ setStartOfLineWidget(w);
+ } else if (getEndOfLineWidget() == null) {
+ setEndOfLineWidget(w);
+ } else {
+ throw new IllegalStateException(
+ "A Splitter can only contain two Widgets.");
+ }
+ }
+
+ /**
+ * Gets the widget in the pane that is at the end of the line
+ * direction for the layout. That is, in an RTL layout, gets
+ * the widget in the left pane, and in an LTR layout, gets
+ * the widget in the right pane.
+ *
+ * @return the widget, <code>null</code> if there is not one.
+ */
+ public Widget getEndOfLineWidget() {
+ return getWidget(getEndOfLinePos());
+ }
+
+ /**
* Gets the widget in the left side of the panel.
*
* @return the widget, <code>null</code> if there is not one.
*/
- public final Widget getLeftWidget() {
+ public Widget getLeftWidget() {
return getWidget(LEFT);
}
@@ -290,34 +432,77 @@
*
* @return the widget, <code>null</code> if there is not one.
*/
- public final Widget getRightWidget() {
+ public Widget getRightWidget() {
return getWidget(RIGHT);
}
/**
+ * Gets the widget in the pane that is at the start of the line
+ * direction for the layout. That is, in an RTL environment, gets
+ * the widget in the right pane, and in an LTR environment, gets
+ * the widget in the left pane.
+ *
+ * @return the widget, <code>null</code> if there is not one.
+ */
+ public Widget getStartOfLineWidget() {
+ return getWidget(getStartOfLinePos());
+ }
+
+ /**
+ * Sets the widget in the pane that is at the end of the line direction
+ * for the layout. That is, in an RTL layout, sets the widget in
+ * the left pane, and in and RTL layout, sets the widget in the
+ * right pane.
+ *
+ * @param w the widget
+ */
+ public void setEndOfLineWidget(Widget w) {
+ setWidget(getEndOfLinePos(), w);
+ }
+
+ /**
* Sets the widget in the left side of the panel.
*
* @param w the widget
*/
- public final void setLeftWidget(Widget w) {
+ public void setLeftWidget(Widget w) {
setWidget(LEFT, w);
}
/**
- * Sets the widget in the right side of the panel.
+ * Sets the widget in the right side of the panel.
*
* @param w the widget
*/
- public final void setRightWidget(Widget w) {
+ public void setRightWidget(Widget w) {
setWidget(RIGHT, w);
}
-
+
+ /**
+ * Moves the position of the splitter.
+ *
+ * This method is not bidi-sensitive. The size specified is always
+ * the size of the left region, regardless of directionality.
+ *
+ * @param pos the new size of the left region in CSS units (e.g. "10px",
+ * "1em")
+ */
@Override
public final void setSplitPosition(String pos) {
lastSplitPosition = pos;
- final Element leftElem = getElement(LEFT);
- setWidth(leftElem, pos);
- impl.setSplitPosition(getOffsetWidth(leftElem));
+ impl.setSplitPosition(pos);
+ }
+
+ /**
+ * Sets the widget in the pane that is at the start of the line direction
+ * for the layout. That is, in an RTL layout, sets the widget in
+ * the right pane, and in and RTL layout, sets the widget in the
+ * left pane.
+ *
+ * @param w the widget
+ */
+ public void setStartOfLineWidget(Widget w) {
+ setWidget(getStartOfLinePos(), w);
}
/**
@@ -327,7 +512,7 @@
* <li>-right = the container on the right side of the splitter.</li>
* <li>-left = the container on the left side of the splitter.</li>
* </ul>
- *
+ *
* @see UIObject#onEnsureDebugId(String)
*/
@Override
@@ -395,4 +580,12 @@
addScrolling(leftDiv);
addScrolling(rightDiv);
}
+
+ private int getEndOfLinePos() {
+ return (LocaleInfo.getCurrentLocale().isRTL() ? LEFT : RIGHT);
+ }
+
+ private int getStartOfLinePos() {
+ return (LocaleInfo.getCurrentLocale().isRTL() ? RIGHT : LEFT);
+ }
}
diff --git a/user/src/com/google/gwt/user/client/ui/Label.java b/user/src/com/google/gwt/user/client/ui/Label.java
index 45eb7d8..386ab0a 100644
--- a/user/src/com/google/gwt/user/client/ui/Label.java
+++ b/user/src/com/google/gwt/user/client/ui/Label.java
@@ -18,6 +18,8 @@
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.i18n.client.HasDirection;
+import com.google.gwt.i18n.client.BidiUtils;
/**
* A widget that contains arbitrary text, <i>not</i> interpreted as HTML.
@@ -34,7 +36,7 @@
*/
public class Label extends Widget implements SourcesClickEvents,
SourcesMouseEvents, SourcesMouseWheelEvents, HasHorizontalAlignment,
- HasText, HasWordWrap {
+ HasText, HasWordWrap, HasDirection {
private ClickListenerCollection clickListeners;
private HorizontalAlignmentConstant horzAlign;
@@ -103,6 +105,10 @@
mouseWheelListeners.add(listener);
}
+ public Direction getDirection() {
+ return BidiUtils.getDirectionOnElement(getElement());
+ }
+
public HorizontalAlignmentConstant getHorizontalAlignment() {
return horzAlign;
}
@@ -159,7 +165,11 @@
mouseWheelListeners.remove(listener);
}
}
-
+
+ public void setDirection(Direction direction) {
+ BidiUtils.setDirectionOnElement(getElement(), direction);
+ }
+
public void setHorizontalAlignment(HorizontalAlignmentConstant align) {
horzAlign = align;
DOM.setStyleAttribute(getElement(), "textAlign", align.getTextAlignString());
diff --git a/user/src/com/google/gwt/user/client/ui/MenuBar.java b/user/src/com/google/gwt/user/client/ui/MenuBar.java
index be483f7..37aa280 100644
--- a/user/src/com/google/gwt/user/client/ui/MenuBar.java
+++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -21,6 +21,7 @@
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
+import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.user.client.ui.PopupPanel.AnimationType;
import java.util.ArrayList;
@@ -68,6 +69,26 @@
}
/**
+ * A bundle containing the RTL versions of the images for MenuBar.
+ *
+ * Notice that this interface is package protected. This interface need not be
+ * publicly exposed, as it is only used by the MenuBar class to provide RTL
+ * versions of the images in the case the the user does not pass in their own
+ * bundle. However, we cannot make this class private, because the generated
+ * class needs to be able to extend this class.
+ */
+ interface MenuBarImagesRTL extends MenuBarImages {
+ /**
+ * An image indicating a {@link MenuItem} has an associated submenu for
+ * a RTL context.
+ *
+ * @return a prototype of this image
+ */
+ @Resource("menuBarSubMenuIcon_rtl.gif")
+ AbstractImagePrototype menuBarSubMenuIcon();
+ }
+
+ /**
* List of all {@link MenuItem}s and {@link MenuItemSeparator}s.
*/
private ArrayList<UIObject> allItems = new ArrayList<UIObject>();
@@ -95,42 +116,41 @@
}
/**
+ * Creates an empty horizontal menu bar that uses the specified image bundle
+ * for menu images.
+ *
+ * @param images a bundle that provides images for this menu
+ */
+ public MenuBar(MenuBarImages images) {
+ this(false, images);
+ }
+
+ /**
* Creates an empty menu bar.
- *
+ *
* @param vertical <code>true</code> to orient the menu bar vertically
*/
public MenuBar(boolean vertical) {
super();
-
- Element table = DOM.createTable();
- body = DOM.createTBody();
- DOM.appendChild(table, body);
-
- if (!vertical) {
- Element tr = DOM.createTR();
- DOM.appendChild(body, tr);
- }
-
- this.vertical = vertical;
-
- Element outer = FocusPanel.impl.createFocusable();
- DOM.appendChild(outer, table);
- setElement(outer);
-
- Accessibility.setRole(getElement(), Accessibility.ROLE_MENUBAR);
-
- sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT
- | Event.ONFOCUS | Event.ONKEYDOWN);
-
- setStyleName("gwt-MenuBar");
- if (vertical) {
- addStyleDependentName("vertical");
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ init(vertical, GWT.<MenuBarImagesRTL>create(MenuBarImagesRTL.class));
} else {
- addStyleDependentName("horizontal");
+ init(vertical, GWT.<MenuBarImages>create(MenuBarImages.class));
}
}
/**
+ * Creates an empty menu bar that uses the specified image bundle
+ * for menu images.
+ *
+ * @param vertical <code>true</code> to orient the menu bar vertically
+ * @param images a bundle that provides images for this menu
+ */
+ public MenuBar(boolean vertical, MenuBarImages images) {
+ init(vertical, images);
+ }
+
+ /**
* Adds a menu item to the bar.
*
* @param item the item to be added
@@ -305,10 +325,18 @@
int keyCode = DOM.eventGetKeyCode(event);
switch (keyCode) {
case KeyboardListener.KEY_LEFT:
- moveLeft();
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ moveToNextItem();
+ } else {
+ moveToPrevItem();
+ }
break;
case KeyboardListener.KEY_RIGHT:
- moveRight();
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ moveToPrevItem();
+ } else {
+ moveToNextItem();
+ }
break;
case KeyboardListener.KEY_UP:
moveUp();
@@ -524,15 +552,6 @@
popup.setStyleName("gwt-MenuBarPopup");
popup.addPopupListener(this);
- if (vertical) {
- popup.setPopupPosition(
- this.getAbsoluteLeft() + this.getOffsetWidth() - 1,
- item.getAbsoluteTop());
- } else {
- popup.setPopupPosition(item.getAbsoluteLeft(), this.getAbsoluteTop()
- + this.getOffsetHeight() - 1);
- }
-
shownChildMenu = item.getSubMenu();
item.getSubMenu().parentMenu = this;
@@ -547,7 +566,32 @@
// Show the popup, ensuring that the menubar's event preview remains on top
// of the popup's.
- popup.show();
+ popup.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
+
+ public void setPosition(int offsetWidth, int offsetHeight) {
+
+ // depending on the bidi direction position a menu on the left or right
+ // of its base item
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ int popableWidth = item.getSubMenu().getOffsetWidth();
+ if (vertical) {
+ popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() - popableWidth + 1,
+ item.getAbsoluteTop());
+ } else {
+ popup.setPopupPosition(item.getAbsoluteLeft() + item.getOffsetWidth() - popableWidth,
+ MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight() - 1);
+ }
+ } else {
+ if (vertical) {
+ popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() + MenuBar.this.getOffsetWidth() - 1,
+ item.getAbsoluteTop());
+ } else {
+ popup.setPopupPosition(item.getAbsoluteLeft(),
+ MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight() - 1);
+ }
+ }
+ }
+ });
shownChildMenu.focus();
}
@@ -651,9 +695,6 @@
setItemColSpan(item, 2);
} else if (tdCount == 1) {
// Show the submenu indicator
- if (images == null) {
- images = GWT.create(MenuBarImages.class);
- }
setItemColSpan(item, 1);
Element td = DOM.createTD();
DOM.setElementProperty(td, "vAlign", "middle");
@@ -709,7 +750,38 @@
return DOM.getChild(body, 0);
}
}
+
+ private void init(boolean vertical, MenuBarImages images) {
+ this.images = images;
+
+ Element table = DOM.createTable();
+ body = DOM.createTBody();
+ DOM.appendChild(table, body);
+ if (!vertical) {
+ Element tr = DOM.createTR();
+ DOM.appendChild(body, tr);
+ }
+
+ this.vertical = vertical;
+
+ Element outer = FocusPanel.impl.createFocusable();
+ DOM.appendChild(outer, table);
+ setElement(outer);
+
+ Accessibility.setRole(getElement(), Accessibility.ROLE_MENUBAR);
+
+ sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT
+ | Event.ONFOCUS | Event.ONKEYDOWN);
+
+ setStyleName("gwt-MenuBar");
+ if (vertical) {
+ addStyleDependentName("vertical");
+ } else {
+ addStyleDependentName("horizontal");
+ }
+ }
+
private void moveDown() {
if (selectFirstItemIfNoneSelected()) {
return;
@@ -729,8 +801,28 @@
}
}
}
+
+ private void moveToNextItem() {
+ if (selectFirstItemIfNoneSelected()) {
+ return;
+ }
- private void moveLeft() {
+ if (!vertical) {
+ selectNextItem();
+ } else {
+ if ((shownChildMenu == null) && (selectedItem.getSubMenu() != null)) {
+ doItemAction(selectedItem, false);
+ } else if (parentMenu != null) {
+ if (!parentMenu.vertical) {
+ parentMenu.selectNextItem();
+ } else {
+ parentMenu.moveToNextItem();
+ }
+ }
+ }
+ }
+
+ private void moveToPrevItem() {
if (selectFirstItemIfNoneSelected()) {
return;
}
@@ -745,27 +837,7 @@
}
}
}
-
- private void moveRight() {
- if (selectFirstItemIfNoneSelected()) {
- return;
- }
-
- if (!vertical) {
- selectNextItem();
- } else {
- if ((shownChildMenu == null) && (selectedItem.getSubMenu() != null)) {
- doItemAction(selectedItem, false);
- } else if (parentMenu != null) {
- if (!parentMenu.vertical) {
- parentMenu.selectNextItem();
- } else {
- parentMenu.moveRight();
- }
- }
- }
- }
-
+
private void moveUp() {
if (selectFirstItemIfNoneSelected()) {
return;
diff --git a/user/src/com/google/gwt/user/client/ui/RootPanel.java b/user/src/com/google/gwt/user/client/ui/RootPanel.java
index c1f0738..8205251 100644
--- a/user/src/com/google/gwt/user/client/ui/RootPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/RootPanel.java
@@ -19,6 +19,9 @@
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowCloseListener;
+import com.google.gwt.i18n.client.LocaleInfo;
+import com.google.gwt.i18n.client.BidiUtils;
+import com.google.gwt.i18n.client.HasDirection;
import java.util.HashMap;
@@ -70,8 +73,19 @@
}
}
+ // Note that the code in this if block only happens once -
+ // on the first RootPanel.get(String) or RootPanel.get()
+ // call.
+
if (rootPanels.size() == 0) {
hookWindowClosing();
+
+ // If we're in a RTL locale, set the RTL directionality
+ // on the entire document.
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ BidiUtils.setDirectionOnElement(getRootElement(), HasDirection.Direction.RTL);
+ }
}
// Create the panel and put it in the map.
@@ -92,6 +106,16 @@
return $doc.body;
}-*/;
+ /**
+ * Convenience method for getting the document's root
+ * (<html>) element.
+ *
+ * @return the document's root element
+ */
+ private static native Element getRootElement() /*-{
+ return $doc;
+ }-*/;
+
private static void hookWindowClosing() {
// Catch the window closing event.
Window.addWindowCloseListener(new WindowCloseListener() {
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestBox.java b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
index 6cd541a..87cdbd4 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestBox.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
@@ -23,6 +23,7 @@
import com.google.gwt.user.client.ui.SuggestOracle.Request;
import com.google.gwt.user.client.ui.SuggestOracle.Response;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
+import com.google.gwt.i18n.client.LocaleInfo;
import java.util.ArrayList;
import java.util.Collection;
@@ -217,37 +218,88 @@
// Set the position of the popup right before it is shown.
setPopupPositionAndShow(new PositionCallback() {
public void setPosition(int offsetWidth, int offsetHeight) {
- // Calculate left position for the popup.
+
+ // Calculate left position for the popup. The computation for
+ // the left position is bidi-sensitive.
+
+ int textBoxOffsetWidth = box.getOffsetWidth();
+
+ // Compute the difference between the popup's width and the
+ // textbox's width
+ int offsetWidthDiff = offsetWidth - textBoxOffsetWidth;
+
+ int left;
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) { // RTL case
+
+ int textBoxAbsoluteLeft = box.getAbsoluteLeft();
+
+ // Right-align the popup. Note that this computation is
+ // valid in the case where offsetWidthDiff is negative.
+ left = textBoxAbsoluteLeft - offsetWidthDiff;
- int left = box.getAbsoluteLeft();
- int offsetWidthDiff = offsetWidth - box.getOffsetWidth();
+ // If the suggestion popup is not as wide as the text box, always align
+ // to the right edge of the text box. Otherwise, figure out whether to
+ // right-align or left-align the popup.
+ if (offsetWidthDiff > 0) {
+
+ // Make sure scrolling is taken into account, since box.getAbsoluteLeft()
+ // takes scrolling into account.
+ int windowRight = Window.getClientWidth() + Window.getScrollLeft();
+ int windowLeft = Window.getScrollLeft();
- // If the suggestion popup is not as wide as the text box, always align
- // to the left edge of the text box. Otherwise, figure out whether to
- // left-align or right-align the popup.
- if (offsetWidthDiff > 0) {
- // Make sure scrolling is taken into account, since box.getAbsoluteLeft()
- // takes scrolling into account.
- int windowRight = Window.getClientWidth() + Window.getScrollLeft();
- int windowLeft = Window.getScrollLeft();
+ // Compute the left value for the right edge of the textbox
+ int textBoxLeftValForRightEdge = textBoxAbsoluteLeft + textBoxOffsetWidth;
+
+ // Distance from the right edge of the text box to the right edge of the
+ // window
+ int distanceToWindowRight = windowRight - textBoxLeftValForRightEdge;
- // Distance from the left edge of the text box to the right edge of the
- // window
- int distanceToWindowRight = windowRight - left;
+ // Distance from the right edge of the text box to the left edge of the
+ // window
+ int distanceFromWindowLeft = textBoxLeftValForRightEdge - windowLeft;
- // Distance from the left edge of the text box to the left edge of the
- // window
- int distanceFromWindowLeft = left - windowLeft;
+ // If there is not enough space for the overflow of the popup's width to
+ // the right of the text box and there IS enough space for the overflow
+ // to the right of the text box, then left-align the popup. However, if
+ // there is not enough space on either side, stick with right-alignment.
+ if (distanceFromWindowLeft < offsetWidth &&
+ distanceToWindowRight >= offsetWidthDiff) {
+ // Align with the left edge of the text box.
+ left = textBoxAbsoluteLeft;
+ }
+ }
+ } else { // LTR case
+
+ // Left-align the popup.
+ left = box.getAbsoluteLeft();
- // If there is not enough space for the popup's width overflow to the
- // right of the text box and there IS enough space for the popup's
- // width overflow to the left of the text box, then right-align
- // the popup. However, if there is not enough space on either side,
- // then stick with left-alignment.
- if (distanceToWindowRight < offsetWidth &&
- distanceFromWindowLeft >= (offsetWidth - box.getOffsetWidth())) {
- // Align with the right edge of the text box.
- left -= offsetWidthDiff;
+ // If the suggestion popup is not as wide as the text box, always align
+ // to the left edge of the text box. Otherwise, figure out whether to
+ // left-align or right-align the popup.
+ if (offsetWidthDiff > 0) {
+ // Make sure scrolling is taken into account, since box.getAbsoluteLeft()
+ // takes scrolling into account.
+ int windowRight = Window.getClientWidth() + Window.getScrollLeft();
+ int windowLeft = Window.getScrollLeft();
+
+ // Distance from the left edge of the text box to the right edge of the
+ // window
+ int distanceToWindowRight = windowRight - left;
+
+ // Distance from the left edge of the text box to the left edge of the
+ // window
+ int distanceFromWindowLeft = left - windowLeft;
+
+ // If there is not enough space for the overflow of the popup's width to
+ // the right of hte text box, and there IS enough space for the overflow
+ // to the left of the text box, then right-align the popup. However, if
+ // there is not enough space on either side, then stick with left-alignment.
+ if (distanceToWindowRight < offsetWidth &&
+ distanceFromWindowLeft >= offsetWidthDiff) {
+ // Align with the right edge of the text box.
+ left -= offsetWidthDiff;
+ }
}
}
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 bad1c9e..90c0a01 100644
--- a/user/src/com/google/gwt/user/client/ui/TextArea.java
+++ b/user/src/com/google/gwt/user/client/ui/TextArea.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * 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
@@ -16,6 +16,8 @@
package com.google.gwt.user.client.ui;
import com.google.gwt.user.client.DOM;
+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.
@@ -34,7 +36,7 @@
* <h3>Example</h3> {@example com.google.gwt.examples.TextBoxExample}
* </p>
*/
-public class TextArea extends TextBoxBase {
+public class TextArea extends TextBoxBase implements HasDirection {
/**
* Creates an empty text area.
@@ -59,6 +61,10 @@
return getImpl().getTextAreaCursorPos(getElement());
}
+ public Direction getDirection() {
+ return BidiUtils.getDirectionOnElement(getElement());
+ }
+
@Override
public int getSelectionLength() {
return getImpl().getSelectionLength(getElement());
@@ -83,6 +89,10 @@
DOM.setElementPropertyInt(getElement(), "cols", width);
}
+ public void setDirection(Direction direction) {
+ BidiUtils.setDirectionOnElement(getElement(), direction);
+ }
+
/**
* Sets the number of text lines that are visible.
*
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 bc10ca8..1108fbf 100644
--- a/user/src/com/google/gwt/user/client/ui/TextBox.java
+++ b/user/src/com/google/gwt/user/client/ui/TextBox.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * 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
@@ -17,6 +17,8 @@
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
+import com.google.gwt.i18n.client.HasDirection;
+import com.google.gwt.i18n.client.BidiUtils;
/**
* A standard single-line text box.
@@ -36,7 +38,7 @@
* {@example com.google.gwt.examples.TextBoxExample}
* </p>
*/
-public class TextBox extends TextBoxBase {
+public class TextBox extends TextBoxBase implements HasDirection {
/**
* Creates an empty text box.
@@ -54,6 +56,10 @@
super(element);
}
+ public Direction getDirection() {
+ return BidiUtils.getDirectionOnElement(getElement());
+ }
+
/**
* Gets the maximum allowable length of the text box.
*
@@ -72,6 +78,10 @@
return DOM.getElementPropertyInt(getElement(), "size");
}
+ public void setDirection(Direction direction) {
+ BidiUtils.setDirectionOnElement(getElement(), direction);
+ }
+
/**
* Sets the maximum allowable length of the text box.
*
diff --git a/user/src/com/google/gwt/user/client/ui/Tree.java b/user/src/com/google/gwt/user/client/ui/Tree.java
index e7568fb..d0980fc 100644
--- a/user/src/com/google/gwt/user/client/ui/Tree.java
+++ b/user/src/com/google/gwt/user/client/ui/Tree.java
@@ -19,6 +19,7 @@
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.i18n.client.LocaleInfo;
import java.util.ArrayList;
import java.util.HashMap;
@@ -125,14 +126,14 @@
*/
private final Map<Widget, TreeItem> childWidgets = new HashMap<Widget, TreeItem>();
private TreeItem curSelection;
- private final Element focusable;
+ private Element focusable;
private FocusListenerCollection focusListeners;
private TreeImages images;
private boolean isAnimationEnabled = true;
private KeyboardListenerCollection keyboardListeners;
private TreeListenerCollection listeners;
private MouseListenerCollection mouseListeners = null;
- private final TreeItem root;
+ private TreeItem root;
/**
* Keeps track of the last event type seen. We do this to determine if we have
@@ -144,7 +145,11 @@
* Constructs an empty tree.
*/
public Tree() {
- this(GWT.<TreeImages>create(TreeImages.class));
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ init(GWT.<TreeImagesRTL>create(TreeImagesRTL.class));
+ } else {
+ init(GWT.<TreeImages>create(TreeImages.class));
+ }
}
/**
@@ -183,7 +188,11 @@
getChildren().add(item);
// Use no margin on top-most items.
- DOM.setIntStyleAttribute(item.getElement(), "marginLeft", 0);
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ DOM.setIntStyleAttribute(item.getElement(), "marginRight", 0);
+ } else {
+ DOM.setIntStyleAttribute(item.getElement(), "marginLeft", 0);
+ }
}
@Override
@@ -471,31 +480,24 @@
break;
}
case KeyboardListener.KEY_LEFT: {
- TreeItem topClosedParent = getTopClosedParent(curSelection);
- if (topClosedParent != null) {
- // Select the first visible parent if curSelection is hidden
- setSelectedItem(topClosedParent);
- } else if (curSelection.getState()) {
- curSelection.setState(false);
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ maybeExpandTreeItem();
} else {
- TreeItem parent = curSelection.getParentItem();
- if (parent != null) {
- setSelectedItem(parent);
- }
+ maybeCollapseTreeItem();
}
+
DOM.eventPreventDefault(event);
break;
}
case KeyboardListener.KEY_RIGHT: {
- TreeItem topClosedParent = getTopClosedParent(curSelection);
- if (topClosedParent != null) {
- // Select the first visible parent if curSelection is hidden
- setSelectedItem(topClosedParent);
- } else if (!curSelection.getState()) {
- curSelection.setState(true);
- } else if (curSelection.getChildCount() > 0) {
- setSelectedItem(curSelection.getChild(0));
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ maybeCollapseTreeItem();
+ } else {
+ maybeExpandTreeItem();
}
+
DOM.eventPreventDefault(event);
break;
}
@@ -803,7 +805,7 @@
/**
* Get the top parent above this {@link TreeItem} that is in closed state. In
* other words, get the parent that is guaranteed to be visible.
- *
+ *
* @param item
* @return the closed parent, or null if all parents are opened
*/
@@ -818,7 +820,96 @@
}
return topClosedParent;
}
+
+ private void init(TreeImages images) {
+ this.images = images;
+ setElement(DOM.createDiv());
+ DOM.setStyleAttribute(getElement(), "position", "relative");
+ focusable = FocusPanel.impl.createFocusable();
+ DOM.setStyleAttribute(focusable, "fontSize", "0");
+ DOM.setStyleAttribute(focusable, "position", "absolute");
+ DOM.setIntStyleAttribute(focusable, "zIndex", -1);
+ DOM.appendChild(getElement(), focusable);
+
+ sinkEvents(Event.MOUSEEVENTS | Event.ONCLICK | Event.KEYEVENTS);
+ DOM.sinkEvents(focusable, Event.FOCUSEVENTS);
+
+ // The 'root' item is invisible and serves only as a container
+ // for all top-level items.
+ root = new TreeItem() {
+ @Override
+ public void addItem(TreeItem item) {
+ // If this element already belongs to a tree or tree item, remove it.
+ if ((item.getParentItem() != null) || (item.getTree() != null)) {
+ item.remove();
+ }
+ DOM.appendChild(Tree.this.getElement(), item.getElement());
+
+ item.setTree(this.getTree());
+
+ // Explicitly set top-level items' parents to null.
+ item.setParentItem(null);
+ getChildren().add(item);
+
+ // Use no margin on top-most items.
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ DOM.setIntStyleAttribute(item.getElement(), "marginRight", 0);
+ } else {
+ DOM.setIntStyleAttribute(item.getElement(), "marginLeft", 0);
+ }
+ }
+
+ @Override
+ public void removeItem(TreeItem item) {
+ if (!getChildren().contains(item)) {
+ return;
+ }
+
+ // Update Item state.
+ item.setTree(null);
+ item.setParentItem(null);
+ getChildren().remove(item);
+
+ DOM.removeChild(Tree.this.getElement(), item.getElement());
+ }
+ };
+ root.setTree(this);
+ setStyleName("gwt-Tree");
+
+ // Add a11y role "tree"
+ Accessibility.setRole(getElement(), Accessibility.ROLE_TREE);
+ Accessibility.setRole(focusable, Accessibility.ROLE_TREEITEM);
+ }
+ private void maybeCollapseTreeItem() {
+
+ TreeItem topClosedParent = getTopClosedParent(curSelection);
+ if (topClosedParent != null) {
+ // Select the first visible parent if curSelection is hidden
+ setSelectedItem(topClosedParent);
+ } else if (curSelection.getState()) {
+ curSelection.setState(false);
+ } else {
+ TreeItem parent = curSelection.getParentItem();
+ if (parent != null) {
+ setSelectedItem(parent);
+ }
+ }
+ }
+
+ private void maybeExpandTreeItem() {
+
+ TreeItem topClosedParent = getTopClosedParent(curSelection);
+ if (topClosedParent != null) {
+ // Select the first visible parent if curSelection is hidden
+ setSelectedItem(topClosedParent);
+ } else if (!curSelection.getState()) {
+ curSelection.setState(true);
+ } else if (curSelection.getChildCount() > 0) {
+ setSelectedItem(curSelection.getChild(0));
+ }
+ }
+
/**
* Move the tree focus to the specified selected item.
*
diff --git a/user/src/com/google/gwt/user/client/ui/TreeImages.java b/user/src/com/google/gwt/user/client/ui/TreeImages.java
index 731295c..7769371 100644
--- a/user/src/com/google/gwt/user/client/ui/TreeImages.java
+++ b/user/src/com/google/gwt/user/client/ui/TreeImages.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * 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
@@ -46,3 +46,17 @@
*/
AbstractImagePrototype treeLeaf();
}
+
+/**
+ * A bundle containing the RTL versions of the images for Tree. Right now, there is no
+ * need to override any of the methods in TreeImages and specify a different image in
+ * the RTL context, because the images that we're currently using are direction-agnostic.
+ *
+ * Notice that this interface is package protected. This interface need not be
+ * publicly exposed, as it is only used by the Tree class to provide RTL
+ * versions of the images in the case the the user does not pass in their own
+ * bundle. However, we cannot make this class private, because the generated
+ * class needs to be able to extend this class.
+ */
+interface TreeImagesRTL extends TreeImages {
+}
diff --git a/user/src/com/google/gwt/user/client/ui/TreeItem.java b/user/src/com/google/gwt/user/client/ui/TreeItem.java
index 5a5a0ea..4d986c3 100644
--- a/user/src/com/google/gwt/user/client/ui/TreeItem.java
+++ b/user/src/com/google/gwt/user/client/ui/TreeItem.java
@@ -17,6 +17,7 @@
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
+import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.user.client.animation.WidgetAnimation;
import java.util.ArrayList;
@@ -223,7 +224,12 @@
children.add(item);
// Physical attach.
- DOM.setStyleAttribute(item.getElement(), "marginLeft", "16px");
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ DOM.setStyleAttribute(item.getElement(), "marginRight", "16px");
+ } else {
+ DOM.setStyleAttribute(item.getElement(), "marginLeft", "16px");
+ }
+
DOM.appendChild(childSpanElem, item.getElement());
// Adopt.
diff --git a/user/src/com/google/gwt/user/client/ui/VerticalPanel.java b/user/src/com/google/gwt/user/client/ui/VerticalPanel.java
index 2c640b3..877d0f8 100644
--- a/user/src/com/google/gwt/user/client/ui/VerticalPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/VerticalPanel.java
@@ -27,7 +27,7 @@
*/
public class VerticalPanel extends CellPanel implements HasAlignment {
- private HorizontalAlignmentConstant horzAlign = ALIGN_LEFT;
+ private HorizontalAlignmentConstant horzAlign = ALIGN_DEFAULT;
private VerticalAlignmentConstant vertAlign = ALIGN_TOP;
/**
diff --git a/user/src/com/google/gwt/user/client/ui/disclosurePanelClosed_rtl.png b/user/src/com/google/gwt/user/client/ui/disclosurePanelClosed_rtl.png
new file mode 100644
index 0000000..8450a2f
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ui/disclosurePanelClosed_rtl.png
Binary files differ
diff --git a/user/src/com/google/gwt/user/client/ui/menuBarSubMenuIcon_rtl.gif b/user/src/com/google/gwt/user/client/ui/menuBarSubMenuIcon_rtl.gif
new file mode 100644
index 0000000..4187c7b
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ui/menuBarSubMenuIcon_rtl.gif
Binary files differ
diff --git a/user/test/com/google/gwt/i18n/I18NSuite.java b/user/test/com/google/gwt/i18n/I18NSuite.java
index bcb8f23..dc2c553 100644
--- a/user/test/com/google/gwt/i18n/I18NSuite.java
+++ b/user/test/com/google/gwt/i18n/I18NSuite.java
@@ -22,7 +22,6 @@
import com.google.gwt.i18n.client.I18NTest;
import com.google.gwt.i18n.client.LocaleInfoTest;
import com.google.gwt.i18n.client.LocaleInfo_ar_Test;
-import com.google.gwt.i18n.client.LocaleInfo_none_Test;
import com.google.gwt.i18n.client.NumberFormat_en_Test;
import com.google.gwt.i18n.client.NumberFormat_fr_Test;
import com.google.gwt.i18n.client.NumberParse_en_Test;
@@ -47,8 +46,7 @@
suite.addTestSuite(DateTimeParse_zh_CN_Test.class);
suite.addTestSuite(I18NTest.class);
suite.addTestSuite(I18N2Test.class);
- suite.addTestSuite(LocaleInfo_ar_Test.class);
- suite.addTestSuite(LocaleInfo_none_Test.class);
+ suite.addTestSuite(LocaleInfo_ar_Test.class);
suite.addTestSuite(LocaleInfoTest.class);
suite.addTestSuite(NumberFormat_en_Test.class);
suite.addTestSuite(NumberFormat_fr_Test.class);
diff --git a/user/test/com/google/gwt/i18n/I18NTest_none.gwt.xml b/user/test/com/google/gwt/i18n/I18NTest_none.gwt.xml
deleted file mode 100644
index 4ccde67..0000000
--- a/user/test/com/google/gwt/i18n/I18NTest_none.gwt.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!-- -->
-<!-- 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 -->
-<!-- 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. License for the specific language governing permissions and -->
-<!-- limitations under the License. -->
-
-<module>
- <!-- Inherit the JUnit support -->
- <inherits name='com.google.gwt.junit.JUnit'/>
- <!-- Include client-side source for the test cases -->
- <source path="client"/>
-</module>
diff --git a/user/test/com/google/gwt/i18n/client/LocaleInfo_none_Test.java b/user/test/com/google/gwt/i18n/client/LocaleInfo_none_Test.java
deleted file mode 100644
index e505f28..0000000
--- a/user/test/com/google/gwt/i18n/client/LocaleInfo_none_Test.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.i18n.client;
-
-import com.google.gwt.junit.client.GWTTestCase;
-
-/**
- * Test that LocaleInfo works properly if i18n isn't imported.
- */
-public class LocaleInfo_none_Test extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.i18n.I18NTest_none";
- }
-
- public void testLocaleInfo() {
- LocaleInfo localeInfo = LocaleInfo.getCurrentLocale();
- assertFalse(localeInfo.isRTL());
- assertNull(localeInfo.getLocaleName());
- assertNull(LocaleInfo.getAvailableLocaleNames());
- }
-}