| /* |
| * 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; |
| |
| /** |
| * Abstract base class for all panels, which are widgets that can contain other |
| * widgets. |
| */ |
| public abstract class Panel extends Widget implements HasWidgets.ForIsWidget { |
| |
| /** |
| * Adds a child widget. |
| * |
| * <p> |
| * <b>How to Override this Method</b> |
| * </p> |
| * <p> |
| * There are several important things that must take place in the correct |
| * order to properly add or insert a Widget to a Panel. Not all of these steps |
| * will be relevant to every Panel, but all of the steps must be considered. |
| * <ol> |
| * <li><b>Validate:</b> Perform any sanity checks to ensure the Panel can |
| * accept a new Widget. Examples: checking for a valid index on insertion; |
| * checking that the Panel is not full if there is a max capacity.</li> |
| * <li><b>Adjust for Reinsertion:</b> Some Panels need to handle the case |
| * where the Widget is already a child of this Panel. Example: when performing |
| * a reinsert, the index might need to be adjusted to account for the Widget's |
| * removal. See {@link ComplexPanel#adjustIndex(Widget, int)}.</li> |
| * <li><b>Detach Child:</b> Remove the Widget from its existing parent, if |
| * any. Most Panels will simply call {@link Widget#removeFromParent()} on the |
| * Widget.</li> |
| * <li><b>Logical Attach:</b> Any state variables of the Panel should be |
| * updated to reflect the addition of the new Widget. Example: the Widget is |
| * added to the Panel's {@link WidgetCollection} at the appropriate index.</li> |
| * <li><b>Physical Attach:</b> The Widget's Element must be physically |
| * attached to the Panel's Element, either directly or indirectly.</li> |
| * <li><b>Adopt:</b> Call {@link #adopt(Widget)} to finalize the add as the |
| * very last step.</li> |
| * </ol> |
| * </p> |
| * |
| * @param child the widget to be added |
| * @throws UnsupportedOperationException if this method is not supported (most |
| * often this means that a specific overload must be called) |
| * @see HasWidgets#add(Widget) |
| */ |
| public void add(Widget child) { |
| throw new UnsupportedOperationException( |
| "This panel does not support no-arg add()"); |
| } |
| |
| public void add(IsWidget child) { |
| this.add(asWidgetOrNull(child)); |
| } |
| |
| public void clear() { |
| Iterator<Widget> it = iterator(); |
| while (it.hasNext()) { |
| it.next(); |
| it.remove(); |
| } |
| } |
| |
| /** |
| * Removes a child widget. |
| * |
| * <p> |
| * <b>How to Override this Method</b> |
| * </p> |
| * <p> |
| * There are several important things that must take place in the correct |
| * order to properly remove a Widget from a Panel. Not all of these steps will |
| * be relevant to every Panel, but all of the steps must be considered. |
| * <ol> |
| * <li><b>Validate:</b> Make sure this Panel is actually the parent of the |
| * child Widget; return <code>false</code> if it is not.</li> |
| * <li><b>Orphan:</b> Call {@link #orphan(Widget)} first while the child |
| * Widget is still attached.</li> |
| * <li><b>Physical Detach:</b> Adjust the DOM to account for the removal of |
| * the child Widget. The Widget's Element must be physically removed from the |
| * DOM.</li> |
| * <li><b>Logical Detach:</b> Update the Panel's state variables to reflect |
| * the removal of the child Widget. Example: the Widget is removed from the |
| * Panel's {@link WidgetCollection}.</li> |
| * </ol> |
| * </p> |
| * |
| * @param child the widget to be removed |
| * @return <code>true</code> if the child was present |
| */ |
| public abstract boolean remove(Widget child); |
| |
| public boolean remove(IsWidget child) { |
| return remove(asWidgetOrNull(child)); |
| } |
| |
| /** |
| * Finalize the attachment of a Widget to this Panel. This method is the |
| * <b>last</b> step in adding or inserting a Widget into a Panel, and should |
| * be called after physical attachment in the DOM is complete. This Panel |
| * becomes the parent of the child Widget, and the child will now fire its |
| * {@link Widget#onAttach()} event if this Panel is currently attached. |
| * |
| * @param child the widget to be adopted |
| * @see #add(Widget) |
| */ |
| protected final void adopt(Widget child) { |
| assert (child.getParent() == null); |
| child.setParent(this); |
| } |
| |
| @Override |
| protected void doAttachChildren() { |
| AttachDetachException.tryCommand(this, AttachDetachException.attachCommand); |
| } |
| |
| @Override |
| protected void doDetachChildren() { |
| AttachDetachException.tryCommand(this, AttachDetachException.detachCommand); |
| } |
| |
| /** |
| * <p> |
| * This method must be called as part of the remove method of any Panel. It |
| * ensures that the Widget's parent is cleared. This method should be called |
| * after verifying that the child Widget is an existing child of the Panel, |
| * but before physically removing the child Widget from the DOM. The child |
| * will now fire its {@link Widget#onDetach()} event if this Panel is |
| * currently attached. |
| * </p> |
| * <p> |
| * Calls to {@link #orphan(Widget)} should be wrapped in a try/finally block |
| * to ensure that the widget is physically detached even if orphan throws an |
| * exception. |
| * </p> |
| * |
| * @param child the widget to be disowned |
| * @see #add(Widget) |
| */ |
| protected final void orphan(Widget child) { |
| assert (child.getParent() == this); |
| child.setParent(null); |
| } |
| } |