define(["require", "exports", "rxjs"], function (require, exports, rxjs_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    /**
     * A simple button that can be clicked.
     */
    class Button {
        /**
         * @param desc The full description of what the button does. This will be used
         * in the button's tooltip.
         *
         * @param abbreviatedDesc An abbreviated description. This may be used as text
         * inside the button.
         *
         * @param icon An optional icon for the button.
         *
         * @param extraClass Extra classes to add to ``className``.
         */
        constructor(desc, abbreviatedDesc, icon = "", extraClass = "") {
            this.desc = desc;
            this.abbreviatedDesc = abbreviatedDesc;
            this.icon = icon;
            this.extraClass = extraClass;
            /**
             * The object on which this class and subclasses may push new events.
             */
            this._events = new rxjs_1.Subject();
            /**
             * The observable on which clients can listen for events.
             */
            this.events = this._events.asObservable();
        }
        /** The class name that [[makeButton]] must use. */
        get buttonClassName() {
            let extraClass = this.extraClass;
            if (extraClass !== "") {
                extraClass = ` ${extraClass}`;
            }
            return `btn btn-default${extraClass}`;
        }
        /**
         * The text that goes inside a button. This is the abbreviated description, or
         * if unavailable, the long description.
         */
        get buttonText() {
            // If we don't have an abbreviation, we get the regular description.
            return this.abbreviatedDesc === undefined ?
                this.desc : this.abbreviatedDesc;
        }
        /**
         * Render the button.
         *
         * @param parent On first render, this parameter must contain the parent DOM
         * element of the button. On later renders, this parameter is ignored.
         *
         */
        render(parent) {
            let position = null;
            if (this.el !== undefined) {
                position = this.el.nextSibling;
                parent = this.el.parentNode;
                const $el = $(this.el);
                $el.tooltip("destroy");
                $el.remove();
            }
            if (parent == null) {
                throw new Error("called first render without a parent");
            }
            const button = this.makeButton(parent.ownerDocument);
            this.el = button;
            parent.insertBefore(button, position);
        }
        /**
         * Create a button, fill its contents, set its tooltip and add the event
         * handlers.
         *
         * @param doc The document in which we are creating the element.
         *
         * @returns The new button.
         */
        makeButton(doc) {
            const button = doc.createElement("button");
            button.className = this.buttonClassName;
            const $button = $(button);
            this.setButtonContent(button);
            this.setButtonTooltip($button);
            this.setButtonEventHandlers($button);
            return button;
        }
        /**
         * Fill the content of the button.
         *
         * @param button The button to fill.
         */
        setButtonContent(button) {
            const icon = this.icon;
            if (icon !== "") {
                // tslint:disable-next-line:no-inner-html
                button.innerHTML = icon;
            }
            else {
                button.textContent = this.buttonText;
            }
        }
        /**
         * Make a tooltip for the button.
         *
         * @param $button The button for which to make a tooltip.
         */
        setButtonTooltip($button) {
            const desc = this.desc;
            if (this.icon !== "" || this.buttonText !== desc) {
                $button[0].setAttribute("title", desc);
                $button.tooltip({ title: desc,
                    container: "body",
                    placement: "auto",
                    trigger: "hover" });
            }
        }
        /**
         * Set event handlers on the button.
         */
        setButtonEventHandlers($button) {
            $button.click(() => {
                this._events.next({ name: "Click", button: this });
                return false;
            });
            // Prevents acquiring the focus.
            $button.mousedown(false);
        }
    }
    exports.Button = Button;
    /**
     * A button that represents an on/off state.
     */
    class ToggleButton extends Button {
        /**
         * @param initialyPressed Whether the button is initially pressed.
         *
         * @param desc See [[Button]].
         *
         * @param abbreviatedDesc See [[Button]].
         *
         * @param icon See [[Button]].
         *
         * @param extraClass See [[Button]].
         */
        constructor(initialyPressed, desc, abbreviatedDesc, icon = "", extraClass = "") {
            super(desc, abbreviatedDesc, icon, extraClass);
            this.desc = desc;
            this.abbreviatedDesc = abbreviatedDesc;
            this.icon = icon;
            this.extraClass = extraClass;
            this._pressed = initialyPressed;
            this.events.subscribe((event) => {
                if (event.name !== "Click" || this.el === undefined) {
                    return;
                }
                this._pressed = !this._pressed;
                this.render();
            });
        }
        /**
         * Whether the button is in the pressed state.
         */
        get pressed() {
            return this._pressed;
        }
        set pressed(value) {
            if (this._pressed === value) {
                return;
            }
            this._pressed = value;
            if (this.el !== undefined) {
                this.render();
            }
        }
        get buttonClassName() {
            let extraClass = this.extraClass;
            if (extraClass !== "") {
                extraClass = ` ${extraClass}`;
            }
            return `btn btn-default${extraClass}${this._pressed ? " active" : ""}`;
        }
    }
    exports.ToggleButton = ToggleButton;
});
//# sourceMappingURL=button.js.map