"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
var algorithm_1 = require("@phosphor/algorithm");
var messaging_1 = require("@phosphor/messaging");
var layout_1 = require("./layout");
var widget_1 = require("./widget");
/**
 * A concrete layout implementation which holds a single widget.
 *
 * #### Notes
 * This class is useful for creating simple container widgets which
 * hold a single child. The child should be positioned with CSS.
 */
var SingletonLayout = /** @class */ (function (_super) {
    __extends(SingletonLayout, _super);
    function SingletonLayout() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this._widget = null;
        return _this;
    }
    /**
     * Dispose of the resources held by the layout.
     */
    SingletonLayout.prototype.dispose = function () {
        if (this._widget) {
            var widget = this._widget;
            this._widget = null;
            widget.dispose();
        }
        _super.prototype.dispose.call(this);
    };
    Object.defineProperty(SingletonLayout.prototype, "widget", {
        /**
         * Get the child widget for the layout.
         */
        get: function () {
            return this._widget;
        },
        /**
         * Set the child widget for the layout.
         *
         * #### Notes
         * Setting the child widget will cause the old child widget to be
         * automatically disposed. If that is not desired, set the parent
         * of the old child to `null` before assigning a new child.
         */
        set: function (widget) {
            // Remove the widget from its current parent. This is a no-op
            // if the widget's parent is already the layout parent widget.
            if (widget) {
                widget.parent = this.parent;
            }
            // Bail early if the widget does not change.
            if (this._widget === widget) {
                return;
            }
            // Dispose of the old child widget.
            if (this._widget) {
                this._widget.dispose();
            }
            // Update the internal widget.
            this._widget = widget;
            // Attach the new child widget if needed.
            if (this.parent && widget) {
                this.attachWidget(widget);
            }
        },
        enumerable: true,
        configurable: true
    });
    /**
     * Create an iterator over the widgets in the layout.
     *
     * @returns A new iterator over the widgets in the layout.
     */
    SingletonLayout.prototype.iter = function () {
        return this._widget ? algorithm_1.once(this._widget) : algorithm_1.empty();
    };
    /**
     * Remove a widget from the layout.
     *
     * @param widget - The widget to remove from the layout.
     *
     * #### Notes
     * A widget is automatically removed from the layout when its `parent`
     * is set to `null`. This method should only be invoked directly when
     * removing a widget from a layout which has yet to be installed on a
     * parent widget.
     *
     * This method does *not* modify the widget's `parent`.
     */
    SingletonLayout.prototype.removeWidget = function (widget) {
        // Bail early if the widget does not exist in the layout.
        if (this._widget !== widget) {
            return;
        }
        // Clear the internal widget.
        this._widget = null;
        // If the layout is parented, detach the widget from the DOM.
        if (this.parent) {
            this.detachWidget(widget);
        }
    };
    /**
     * Perform layout initialization which requires the parent widget.
     */
    SingletonLayout.prototype.init = function () {
        var _this = this;
        _super.prototype.init.call(this);
        algorithm_1.each(this, function (widget) { _this.attachWidget(widget); });
    };
    /**
     * Attach a widget to the parent's DOM node.
     *
     * @param index - The current index of the widget in the layout.
     *
     * @param widget - The widget to attach to the parent.
     *
     * #### Notes
     * This method is called automatically by the single layout at the
     * appropriate time. It should not be called directly by user code.
     *
     * The default implementation adds the widgets's node to the parent's
     * node at the proper location, and sends the appropriate attach
     * messages to the widget if the parent is attached to the DOM.
     *
     * Subclasses may reimplement this method to control how the widget's
     * node is added to the parent's node.
     */
    SingletonLayout.prototype.attachWidget = function (widget) {
        // Send a `'before-attach'` message if the parent is attached.
        if (this.parent.isAttached) {
            messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.BeforeAttach);
        }
        // Add the widget's node to the parent.
        this.parent.node.appendChild(widget.node);
        // Send an `'after-attach'` message if the parent is attached.
        if (this.parent.isAttached) {
            messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.AfterAttach);
        }
    };
    /**
     * Detach a widget from the parent's DOM node.
     *
     * @param widget - The widget to detach from the parent.
     *
     * #### Notes
     * This method is called automatically by the single layout at the
     * appropriate time. It should not be called directly by user code.
     *
     * The default implementation removes the widget's node from the
     * parent's node, and sends the appropriate detach messages to the
     * widget if the parent is attached to the DOM.
     *
     * Subclasses may reimplement this method to control how the widget's
     * node is removed from the parent's node.
     */
    SingletonLayout.prototype.detachWidget = function (widget) {
        // Send a `'before-detach'` message if the parent is attached.
        if (this.parent.isAttached) {
            messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.BeforeDetach);
        }
        // Remove the widget's node from the parent.
        this.parent.node.removeChild(widget.node);
        // Send an `'after-detach'` message if the parent is attached.
        if (this.parent.isAttached) {
            messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.AfterDetach);
        }
    };
    return SingletonLayout;
}(layout_1.Layout));
exports.SingletonLayout = SingletonLayout;
