001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.client.ui;
017:
018: import com.google.gwt.user.client.Element;
019:
020: /**
021: * A type of widget that can wrap another widget, hiding the wrapped widget's
022: * methods. When added to a panel, a composite behaves exactly as if the widget
023: * it wraps had been added.
024: *
025: * <p>
026: * The composite is useful for creating a single widget out of an aggregate of
027: * multiple other widgets contained in a single panel.
028: * </p>
029: *
030: * <p>
031: * <h3>Example</h3>
032: * {@example com.google.gwt.examples.CompositeExample}
033: * </p>
034: */
035: public abstract class Composite extends Widget {
036:
037: private Widget widget;
038:
039: /**
040: * This override checks to ensure {@link #initWidget(Widget)} has been called.
041: */
042: @Override
043: public Element getElement() {
044: if (widget == null) {
045: throw new IllegalStateException(
046: "initWidget() was never called in "
047: + this .getClass().getName());
048: }
049: return super .getElement();
050: }
051:
052: @Override
053: public boolean isAttached() {
054: if (widget != null) {
055: return widget.isAttached();
056: }
057: return false;
058: }
059:
060: /**
061: * Provides subclasses access to the topmost widget that defines this
062: * composite.
063: *
064: * @return the widget
065: */
066: protected Widget getWidget() {
067: return widget;
068: }
069:
070: /**
071: * Sets the widget to be wrapped by the composite. The wrapped widget must be
072: * set before calling any {@link Widget} methods on this object, or adding it
073: * to a panel. This method may only be called once for a given composite.
074: *
075: * @param widget the widget to be wrapped
076: */
077: protected void initWidget(Widget widget) {
078: // Validate. Make sure the widget is not being set twice.
079: if (this .widget != null) {
080: throw new IllegalStateException(
081: "Composite.initWidget() may only be "
082: + "called once.");
083: }
084:
085: // Detach the new child.
086: widget.removeFromParent();
087:
088: // Use the contained widget's element as the composite's element,
089: // effectively merging them within the DOM.
090: setElement(widget.getElement());
091:
092: // Logical attach.
093: this .widget = widget;
094:
095: // Adopt.
096: widget.setParent(this );
097: }
098:
099: @Override
100: protected void onAttach() {
101: widget.onAttach();
102: onLoad();
103: }
104:
105: @Override
106: protected void onDetach() {
107: try {
108: onUnload();
109: } finally {
110: // We don't want an exception in user code to keep us from calling the
111: // super implementation (or event listeners won't get cleaned up and
112: // the attached flag will be wrong).
113: widget.onDetach();
114: }
115: }
116:
117: /**
118: * This method was for initializing the Widget to be wrapped by this
119: * Composite, but has been deprecated in favor of {@link #initWidget(Widget)}.
120: *
121: * @deprecated this method is deprecated, and will be removed (use
122: * {@link #initWidget(Widget)} instead)
123: */
124: @Deprecated
125: protected void setWidget(Widget widget) {
126: initWidget(widget);
127: }
128: }
|