Fixes a bug in SplitLayoutPanel where calling setWidgetMinSize() on the center widget, the last widget, or a widget that is not a child results in an NPE or IndexOutOfBoundsException. The occured because getAssocatedSplitter() had an off by one bug and didn't check for an idx of -1. This patch asserts that the widget is a child, which is typical of other methods in DockLayoutPanel.
In addition, this patch fixes a bug where remove(myWidget) would always remove widget 0 instead of the splitter associated with myWidget because we were getting the idx of myWidget after it was removed, at which point it was -1. We now get the idx before removing the widget.
Review at http://gwt-code-reviews.appspot.com/378802
Review by: jgw@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7965 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/DockLayoutPanel.java b/user/src/com/google/gwt/user/client/ui/DockLayoutPanel.java
index c026d10..dfac34a 100644
--- a/user/src/com/google/gwt/user/client/ui/DockLayoutPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DockLayoutPanel.java
@@ -373,7 +373,7 @@
layout.onDetach();
}
- private void assertIsChild(Widget widget) {
+ void assertIsChild(Widget widget) {
assert (widget == null) || (widget.getParent() == this) : "The specified widget is not a child of this panel";
}
diff --git a/user/src/com/google/gwt/user/client/ui/SplitLayoutPanel.java b/user/src/com/google/gwt/user/client/ui/SplitLayoutPanel.java
index f1e6880..b7277d7 100644
--- a/user/src/com/google/gwt/user/client/ui/SplitLayoutPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/SplitLayoutPanel.java
@@ -222,12 +222,13 @@
public boolean remove(Widget child) {
assert !(child instanceof Splitter) : "Splitters may not be directly removed";
+ int idx = getWidgetIndex(child);
if (super.remove(child)) {
// Remove the associated splitter, if any.
- int idx = getWidgetIndex(child);
- if (idx < getWidgetCount() - 1) {
+ // Now that the widget is removed, idx is the index of the splitter.
+ if (idx < getWidgetCount()) {
// Call super.remove(), or we'll end up recursing.
- super.remove(getWidget(idx + 1));
+ super.remove(getWidget(idx));
}
return true;
}
@@ -238,7 +239,7 @@
* Sets the minimum allowable size for the given widget.
*
* <p>
- * Its assocated splitter cannot be dragged to a position that would make it
+ * Its associated splitter cannot be dragged to a position that would make it
* smaller than this size. This method has no effect for the
* {@link DockLayoutPanel.Direction#CENTER} widget.
* </p>
@@ -247,8 +248,12 @@
* @param minSize the minimum size for this widget
*/
public void setWidgetMinSize(Widget child, int minSize) {
+ assertIsChild(child);
Splitter splitter = getAssociatedSplitter(child);
- splitter.setMinSize(minSize);
+ // The splitter is null for the center element.
+ if (splitter != null) {
+ splitter.setMinSize(minSize);
+ }
}
private Splitter getAssociatedSplitter(Widget child) {
@@ -256,7 +261,7 @@
// widget that *isn't* followed by a splitter must be the CENTER, which has
// no associated splitter.
int idx = getWidgetIndex(child);
- if (idx < getWidgetCount() - 2) {
+ if (idx > -1 && idx < getWidgetCount() - 1) {
Widget splitter = getWidget(idx + 1);
assert splitter instanceof Splitter : "Expected child widget to be splitter";
return (Splitter) splitter;
diff --git a/user/test/com/google/gwt/user/client/ui/SplitLayoutPanelTest.java b/user/test/com/google/gwt/user/client/ui/SplitLayoutPanelTest.java
index 0f59fdd..391ca0a 100644
--- a/user/test/com/google/gwt/user/client/ui/SplitLayoutPanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/SplitLayoutPanelTest.java
@@ -47,6 +47,18 @@
assertEquals(l2, p.getCenter());
}
+ public void testSetWidgetMinSizeCenter() {
+ SplitLayoutPanel p = new SplitLayoutPanel();
+ Label west = new Label("west");
+ Label center = new Label("center");
+
+ p.addWest(west, 100);
+ p.add(center);
+
+ // Should be ignored gracefully.
+ p.setWidgetMinSize(center, 10);
+ }
+
public void testSplitterOrder() {
SplitLayoutPanel p = new SplitLayoutPanel();
WidgetCollection children = p.getChildren();
@@ -97,4 +109,27 @@
assertEquals(SplitLayoutPanel.HSplitter.class, children.get(1).getClass());
assertEquals(l1, children.get(2));
}
+
+ public void testRemoveOutOfOrder() {
+ SplitLayoutPanel p = new SplitLayoutPanel();
+ WidgetCollection children = p.getChildren();
+
+ Label l0 = new Label("foo");
+ Label l1 = new Label("bar");
+
+ p.addWest(l0, 64);
+ p.addWest(l1, 64);
+ assertEquals(l0, children.get(0));
+ assertEquals(SplitLayoutPanel.HSplitter.class, children.get(1).getClass());
+ assertEquals(l1, children.get(2));
+ assertEquals(SplitLayoutPanel.HSplitter.class, children.get(3).getClass());
+
+ SplitLayoutPanel.HSplitter splitter0 = (SplitLayoutPanel.HSplitter) children.get(1);
+
+ // Remove the second element and make sure the correct splitter is removed.
+ p.remove(l1);
+ assertEquals(2, children.size());
+ assertEquals(l0, children.get(0));
+ assertEquals(splitter0, children.get(1));
+ }
}