com.google.gwt.user.client.ui.Composite.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.user.client.ui.Composite.java

Source

/*
 * Copyright 2008 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.dom.builder.shared.HtmlBuilderFactory;
import com.google.gwt.dom.builder.shared.HtmlSpanBuilder;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;

/**
 * A type of widget that can wrap another widget, hiding the wrapped widget's
 * methods. When added to a panel, a composite behaves exactly as if the widget
 * it wraps had been added.
 *
 * <p>
 * The composite is useful for creating a single widget out of an aggregate of
 * multiple other widgets contained in a single panel.
 * </p>
 *
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.CompositeExample}
 * </p>
 */
public abstract class Composite extends Widget implements IsRenderable {

    private Widget widget;

    private IsRenderable renderable;

    private Element elementToWrap;

    @Override
    public void claimElement(Element element) {
        if (renderable != null) {
            renderable.claimElement(element);
            setElement(widget.getElement());
        } else {
            this.elementToWrap = element;
        }
    }

    @Override
    public void initializeClaimedElement() {
        if (renderable != null) {
            renderable.initializeClaimedElement();
        } else {
            elementToWrap.getParentNode().replaceChild(widget.getElement(), elementToWrap);
        }
    }

    @Override
    public boolean isAttached() {
        if (widget != null) {
            return widget.isAttached();
        }
        return false;
    }

    @Override
    public void onBrowserEvent(Event event) {
        // Fire any handler added to the composite itself.
        super.onBrowserEvent(event);

        // Delegate events to the widget.
        widget.onBrowserEvent(event);
    }

    @Override
    public SafeHtml render(RenderableStamper stamper) {
        if (renderable != null) {
            return renderable.render(stamper);
        } else {
            HtmlSpanBuilder spanBuilder = HtmlBuilderFactory.get().createSpanBuilder();
            stamper.stamp(spanBuilder).end();
            return spanBuilder.asSafeHtml();
        }
    }

    @Override
    public void render(RenderableStamper stamper, SafeHtmlBuilder builder) {
        if (renderable != null) {
            renderable.render(stamper, builder);
        } else {
            builder.append(render(stamper));
        }
    }

    /**
     * Provides subclasses access to the topmost widget that defines this
     * composite.
     * 
     * @return the widget
     */
    protected Widget getWidget() {
        return widget;
    }

    /**
     * Sets the widget to be wrapped by the composite. The wrapped widget must be
     * set before calling any {@link Widget} methods on this object, or adding it
     * to a panel. This method may only be called once for a given composite.
     * 
     * @param widget the widget to be wrapped
     */
    protected void initWidget(Widget widget) {
        // Validate. Make sure the widget is not being set twice.
        if (this.widget != null) {
            throw new IllegalStateException("Composite.initWidget() may only be " + "called once.");
        }

        if (widget instanceof IsRenderable) {
            // In case the Widget being wrapped is an IsRenderable, we save that fact.
            this.renderable = (IsRenderable) widget;
        }

        // Detach the new child.
        widget.removeFromParent();

        // Use the contained widget's element as the composite's element,
        // effectively merging them within the DOM.
        Element elem = widget.getElement();
        setElement(elem);

        if (PotentialElement.isPotential(elem)) {
            PotentialElement.as(elem).setResolver(this);
        }

        // Logical attach.
        this.widget = widget;

        // Adopt.
        widget.setParent(this);
    }

    @Override
    protected void onAttach() {
        if (!isOrWasAttached()) {
            widget.sinkEvents(eventsToSink);
            eventsToSink = -1;
        }

        widget.onAttach();

        // Clobber the widget's call to setEventListener(), causing all events to
        // be routed to this composite, which will delegate back to the widget by
        // default (note: it's not necessary to clear this in onDetach(), because
        // the widget's onDetach will do so).
        DOM.setEventListener(getElement(), this);

        // Call onLoad() directly, because we're not calling super.onAttach().
        onLoad();
        AttachEvent.fire(this, true);
    }

    @Override
    protected void onDetach() {
        try {
            onUnload();
            AttachEvent.fire(this, false);
        } finally {
            // We don't want an exception in user code to keep us from calling the
            // super implementation (or event listeners won't get cleaned up and
            // the attached flag will be wrong).
            widget.onDetach();
        }
    }

    @Override
    protected Element resolvePotentialElement() {
        setElement(widget.resolvePotentialElement());
        return getElement();
    }

    /**
     * This method was for initializing the Widget to be wrapped by this
     * Composite, but has been deprecated in favor of {@link #initWidget(Widget)}.
     * 
     * @deprecated Use {@link #initWidget(Widget)} instead
     */
    @Deprecated
    protected void setWidget(Widget widget) {
        initWidget(widget);
    }
}