Revision: 10046
Author: [email protected]
Date: Wed Apr 20 14:52:56 2011
Log: Replace HeaderPanel's custom iterator with a new package
protected FiniteWidgetIterator that iterates over children in a
WidgetProvider. FiniteWidgetIterator is a generic iterator over a finite
set of child widgets (versus WidgetIterator, which iterators over panel of
arbitrary size). I intended to use FiniteWidgetIterator in another change
then ended up not needing it, but I'm sure it will come in handy for other
widgets.
Review at http://gwt-code-reviews.appspot.com/1420807
Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=10046
Added:
/trunk/user/src/com/google/gwt/user/client/ui/FiniteWidgetIterator.java
/trunk/user/test/com/google/gwt/user/client/ui/FiniteWidgetIteratorTest.java
Modified:
/trunk/user/src/com/google/gwt/user/client/ui/HeaderPanel.java
/trunk/user/test/com/google/gwt/user/UISuite.java
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/user/client/ui/FiniteWidgetIterator.java
Wed Apr 20 14:52:56 2011
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2011 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 java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Iterator over a finite number of widgets, which are stored in a delegate
+ * class (usually a widget panel).
+ *
+ * <p>
+ * In order to use this class, assign each widget in the panel an arbitrary
+ * index. For example, {@link HeaderPanel} defines the header as index 0,
the
+ * content as index 1, and the footer as index 2. Construct a new
+ * {@link FiniteWidgetIterator} with a {@link WidgetProvider} that
provides the
+ * child widgets.
+ */
+class FiniteWidgetIterator implements Iterator<Widget> {
+
+ /**
+ * Provides widgets to the iterator.
+ */
+ public static interface WidgetProvider {
+ IsWidget get(int index);
+ }
+
+ private int index = -1;
+ private final WidgetProvider provider;
+ private final int widgetCount;
+
+ /**
+ * Construct a new {@link FiniteWidgetIterator}.
+ *
+ * <p>
+ * The widget count is the number of child widgets that the panel
supports,
+ * regardless of whether or not they are set.
+ *
+ * @param provider the widget provider
+ * @param widgetCount the finite number of widgets that can be provided
+ */
+ public FiniteWidgetIterator(WidgetProvider provider, int widgetCount) {
+ this.provider = provider;
+ this.widgetCount = widgetCount;
+ }
+
+ public boolean hasNext() {
+ // Iterate over the remaining widgets until we find one.
+ for (int i = index + 1; i < widgetCount; i++) {
+ IsWidget w = provider.get(i);
+ if (w != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Widget next() {
+ // Iterate over the remaining widgets until we find one.
+ for (int i = index + 1; i < widgetCount; i++) {
+ index = i;
+ IsWidget w = provider.get(i);
+ if (w != null) {
+ return w.asWidget();
+ }
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ if (index < 0 || index >= widgetCount) {
+ throw new IllegalStateException();
+ }
+ IsWidget w = provider.get(index);
+ if (w == null) {
+ throw new IllegalStateException("Widget was already removed.");
+ }
+ w.asWidget().removeFromParent();
+ }
+}
=======================================
--- /dev/null
+++
/trunk/user/test/com/google/gwt/user/client/ui/FiniteWidgetIteratorTest.java
Wed Apr 20 11:47:50 2011
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2011 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.junit.client.GWTTestCase;
+import com.google.gwt.user.client.ui.FiniteWidgetIterator.WidgetProvider;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+/**
+ * Test cases for {@link FiniteWidgetIterator}.
+ */
+public class FiniteWidgetIteratorTest extends GWTTestCase {
+
+ /**
+ * Implementation of {@link WidgetProvider}.
+ */
+ private static class WidgetProviderImpl implements WidgetProvider {
+
+ private final Map<Integer, Widget> widgets = new HashMap<Integer,
Widget>();
+
+ /**
+ * Construct a new {@link WidgetProviderImpl} with the specified
widgets.
+ */
+ public WidgetProviderImpl(Widget... widgets) {
+ if (widgets != null) {
+ for (int i = 0; i < widgets.length; i++) {
+ setWidget(i, widgets[i]);
+ }
+ }
+ }
+
+ /**
+ * Set the widget at the specified index.
+ *
+ * @param index the index
+ * @param w the widget
+ */
+ public void setWidget(int index, Widget w) {
+ widgets.put(index, w);
+ }
+
+ public Widget get(int index) {
+ if (!widgets.containsKey(index)) {
+ fail("A widget was not specified for index: " + index);
+ }
+ return widgets.get(index);
+ }
+ }
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ public void testHasNextEmpty() {
+ FiniteWidgetIterator iterator = new FiniteWidgetIterator(new
WidgetProviderImpl(), 0);
+ assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ fail("Expected NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected.
+ }
+ }
+
+ public void testNext() {
+ Widget w0 = new Widget();
+ Widget w1 = new Widget();
+ Widget w2 = new Widget();
+ FiniteWidgetIterator iterator = new FiniteWidgetIterator(new
WidgetProviderImpl(w0, w1, w2), 3);
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w0, iterator.next());
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w1, iterator.next());
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w2, iterator.next());
+
+ assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ fail("Expected NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected.
+ }
+ }
+
+ /**
+ * Test that the iterator skips null widgets at the start of the list.
+ */
+ public void testNullWidgetStart() {
+ Widget w1 = new Widget();
+ Widget w2 = new Widget();
+ FiniteWidgetIterator iterator =
+ new FiniteWidgetIterator(new WidgetProviderImpl(null, w1, w2), 3);
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w1, iterator.next());
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w2, iterator.next());
+
+ assertFalse(iterator.hasNext());
+ }
+
+ /**
+ * Test that the iterator skips null widgets at the end of the list.
+ */
+ public void testNullWidgetEnd() {
+ Widget w0 = new Widget();
+ Widget w1 = new Widget();
+ FiniteWidgetIterator iterator =
+ new FiniteWidgetIterator(new WidgetProviderImpl(w0, w1, null), 3);
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w0, iterator.next());
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w1, iterator.next());
+
+ assertFalse(iterator.hasNext());
+ }
+
+ /**
+ * Test that the iterator skips null widgets in the middle of the list.
+ */
+ public void testNullWidgetMiddle() {
+ Widget w0 = new Widget();
+ Widget w2 = new Widget();
+ FiniteWidgetIterator iterator =
+ new FiniteWidgetIterator(new WidgetProviderImpl(w0, null, w2), 3);
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w0, iterator.next());
+
+ assertTrue(iterator.hasNext());
+ assertEquals(w2, iterator.next());
+
+ assertFalse(iterator.hasNext());
+ }
+
+ public void testRemove() {
+ Widget w0 = new Label();
+ Widget w1 = new Label();
+ Widget w2 = new Label();
+ WidgetProviderImpl provider = new WidgetProviderImpl(w0, w1, w2);
+ FiniteWidgetIterator iterator = new FiniteWidgetIterator(provider, 3);
+
+ // Add the widgets to a panel.
+ FlowPanel panel = new FlowPanel();
+ panel.add(w0);
+ panel.add(w1);
+ panel.add(w2);
+
+ // Remove before getting first widget.
+ try {
+ iterator.remove();
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected.
+ }
+
+ // Remove the widget.
+ assertEquals(w0, iterator.next());
+ assertEquals(panel, w0.getParent());
+ iterator.remove();
+ assertNull(w0.getParent());
+ provider.setWidget(0, null); // Update the provider.
+
+ // Try to remove again.
+ try {
+ iterator.remove();
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected.
+ }
+
+ // Get the next widget.
+ assertEquals(w1, iterator.next());
+ }
+}
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/HeaderPanel.java Thu Jan
20 06:21:05 2011
+++ /trunk/user/src/com/google/gwt/user/client/ui/HeaderPanel.java Wed Apr
20 11:47:50 2011
@@ -24,9 +24,9 @@
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.FiniteWidgetIterator.WidgetProvider;
import java.util.Iterator;
-import java.util.NoSuchElementException;
/**
* A panel that includes a header (top), footer (bottom), and content
(middle)
@@ -34,17 +34,41 @@
* allocated all of the remaining space between the header and footer area.
*/
public class HeaderPanel extends Panel implements RequiresResize {
+
+ /**
+ * The widget provider for this panel.
+ *
+ * <p>
+ * Widgets are returned in the following order:
+ * <ol>
+ * <li>Header widget</li>
+ * <li>Content widget</li>
+ * <li>Footer widget</li>
+ * </ol>
+ */
+ private class WidgetProviderImpl implements WidgetProvider {
+
+ public Widget get(int index) {
+ switch (index) {
+ case 0:
+ return header;
+ case 1:
+ return content;
+ case 2:
+ return footer;
+ }
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ }
private Widget content;
private final Element contentContainer;
private Widget footer;
private final Element footerContainer;
- private final ResizeLayoutPanel.Impl footerImpl =
- GWT.create(ResizeLayoutPanel.Impl.class);
+ private final ResizeLayoutPanel.Impl footerImpl =
GWT.create(ResizeLayoutPanel.Impl.class);
private Widget header;
private final Element headerContainer;
- private final ResizeLayoutPanel.Impl headerImpl =
- GWT.create(ResizeLayoutPanel.Impl.class);
+ private final ResizeLayoutPanel.Impl headerImpl =
GWT.create(ResizeLayoutPanel.Impl.class);
private final ScheduledCommand layoutCmd = new ScheduledCommand() {
public void execute() {
layoutScheduled = false;
@@ -135,73 +159,7 @@
}
public Iterator<Widget> iterator() {
- // Return a simple iterator that iterates over the header, content, and
- // footer in order.
- return new Iterator<Widget>() {
- private int index = -1;
-
- public boolean hasNext() {
- switch (index) {
- case -1:
- if (header != null) {
- return true;
- }
- case 0: // Intentional fallthrough.
- if (content != null) {
- return true;
- }
- case 1: // Intentional fallthrough.
- if (footer != null) {
- return true;
- }
- }
- return false;
- }
-
- public Widget next() {
- switch (index) {
- case -1:
- index++;
- if (header != null) {
- return header;
- }
- case 0: // Intentional fallthrough.
- index++;
- if (content != null) {
- return content;
- }
- case 1: // Intentional fallthrough.
- index++;
- if (footer != null) {
- return footer;
- }
- }
- throw new NoSuchElementException();
- }
-
- public void remove() {
- switch (index) {
- case 0:
- doRemove(header, "Header");
- break;
- case 1:
- doRemove(content, "Content");
- break;
- case 2:
- doRemove(footer, "Footer");
- break;
- default:
- throw new IllegalStateException();
- }
- }
-
- private void doRemove(Widget widget, String position) {
- if (widget == null) {
- throw new IllegalStateException(position + " was already
removed.");
- }
- HeaderPanel.this.remove(widget);
- }
- };
+ return new FiniteWidgetIterator(new WidgetProviderImpl(), 3);
}
@Override
=======================================
--- /trunk/user/test/com/google/gwt/user/UISuite.java Tue Apr 5 08:03:17
2011
+++ /trunk/user/test/com/google/gwt/user/UISuite.java Wed Apr 20 11:47:50
2011
@@ -57,6 +57,7 @@
import com.google.gwt.user.client.ui.ElementWrappingTest;
import com.google.gwt.user.client.ui.FastStringMapTest;
import com.google.gwt.user.client.ui.FileUploadTest;
+import com.google.gwt.user.client.ui.FiniteWidgetIteratorTest;
import com.google.gwt.user.client.ui.FlexTableTest;
import com.google.gwt.user.client.ui.FlowPanelTest;
import com.google.gwt.user.client.ui.FocusPanelTest;
@@ -169,6 +170,7 @@
suite.addTestSuite(EventTest.class);
suite.addTestSuite(FastStringMapTest.class);
suite.addTestSuite(FileUploadTest.class);
+ suite.addTestSuite(FiniteWidgetIteratorTest.class);
suite.addTestSuite(FlexTableTest.class);
suite.addTestSuite(FlowPanelTest.class);
suite.addTestSuite(FocusPanelTest.class);
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors