blob: d1459aceac3a02a702037583a233a307fa00bf9e [file] [log] [blame]
/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* 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;
/**
* A simple collection of widgets to be used by
* {@link com.google.gwt.user.client.ui.Panel panels} and
* {@link com.google.gwt.user.client.ui.Composite composites}.
*
* <p>
* The main purpose of this specialized collection is to implement
* {@link java.util.Iterator#remove()} in a way that delegates removal to its
* panel. This makes it much easier for the panel to implement an
* {@link com.google.gwt.user.client.ui.HasWidgets#iterator() iterator} that
* supports removal of widgets.
* </p>
*/
public class WidgetCollection implements Iterable<Widget> {
private class WidgetIterator implements Iterator<Widget> {
private int index = -1;
public boolean hasNext() {
return index < (size - 1);
}
public Widget next() {
if (index >= size) {
throw new NoSuchElementException();
}
return array[++index];
}
public void remove() {
if ((index < 0) || (index >= size)) {
throw new IllegalStateException();
}
parent.remove(array[index--]);
}
}
private static final int INITIAL_SIZE = 4;
private Widget[] array;
private HasWidgets parent;
private int size;
/**
* Constructs a new widget collection.
*
* @param parent the container whose {@link HasWidgets#remove(Widget)} will be
* delegated to by the iterator's {@link Iterator#remove()} method.
*/
public WidgetCollection(HasWidgets parent) {
this.parent = parent;
array = new Widget[INITIAL_SIZE];
}
/**
* Adds a widget to the end of this collection.
*
* @param w the widget to be added
*/
public void add(Widget w) {
insert(w, size);
}
/**
* Determines whether a given widget is contained in this collection.
*
* @param w the widget to be searched for
* @return <code>true</code> if the widget is present
*/
public boolean contains(Widget w) {
return (indexOf(w) != -1);
}
/**
* Gets the widget at the given index.
*
* @param index the index to be retrieved
* @return the widget at the specified index
* @throws IndexOutOfBoundsException if the index is out of range
*/
public Widget get(int index) {
if ((index < 0) || (index >= size)) {
throw new IndexOutOfBoundsException();
}
return array[index];
}
/**
* Gets the index of the specified index.
*
* @param w the widget to be found
* @return the index of the specified widget, or <code>-1</code> if it is
* not found
*/
public int indexOf(Widget w) {
for (int i = 0; i < size; ++i) {
if (array[i] == w) {
return i;
}
}
return -1;
}
/**
* Inserts a widget before the specified index.
*
* @param w the widget to be inserted
* @param beforeIndex the index before which the widget will be inserted
* @throws IndexOutOfBoundsException if <code>beforeIndex</code> is out of
* range
*/
public void insert(Widget w, int beforeIndex) {
if ((beforeIndex < 0) || (beforeIndex > size)) {
throw new IndexOutOfBoundsException();
}
// Realloc array if necessary (doubling).
if (size == array.length) {
Widget[] newArray = new Widget[array.length * 2];
for (int i = 0; i < array.length; ++i) {
newArray[i] = array[i];
}
array = newArray;
}
++size;
// Move all widgets after 'beforeIndex' back a slot.
for (int i = size - 1; i > beforeIndex; --i) {
array[i] = array[i - 1];
}
array[beforeIndex] = w;
}
/**
* Gets an iterator on this widget collection. This iterator is guaranteed to
* implement remove() in terms of its containing {@link HasWidgets}.
*
* @return an iterator
*/
public Iterator<Widget> iterator() {
return new WidgetIterator();
}
/**
* Removes the widget at the specified index.
*
* @param index the index of the widget to be removed
* @throws IndexOutOfBoundsException if <code>index</code> is out of range
*/
public void remove(int index) {
if ((index < 0) || (index >= size)) {
throw new IndexOutOfBoundsException();
}
--size;
for (int i = index; i < size; ++i) {
array[i] = array[i + 1];
}
array[size] = null;
}
/**
* Removes the specified widget.
*
* @param w the widget to be removed
* @throws NoSuchElementException if the widget is not present
*/
public void remove(Widget w) {
int index = indexOf(w);
if (index == -1) {
throw new NoSuchElementException();
}
remove(index);
}
/**
* Gets the number of widgets in this collection.
*
* @return the number of widgets
*/
public int size() {
return size;
}
}