# Source: ItemChooser.js

    /**
     * A dialog box letting the user select an item from a predefined list.
     * <p>Part of the XUI module which, for now, has an undocumented API.
     */
    export class ItemChooser extends Dialog {
        static showChooser(title, items, initialText=null, options=null,
                           reference=null) {
            return new Promise((resolve, reject) => {
                let dialog = new ItemChooser(title, items, initialText, options,
                                             resolve);
                dialog.open("center", reference);
            });
        }

        constructor(title, items, initialText, options, resolve) {
            super({ movable: true, resizable: true,
                    title: title, closeable: true,
                    template: ItemChooser.TEMPLATE });

            let pane = this.contentPane.firstElementChild;
            let fieldPane = pane.firstElementChild;

            let cancelButton = fieldPane.firstElementChild;
            cancelButton.setAttribute("title", "Cancel");
            cancelButton.textContent = StockIcon["cancel"];
            cancelButton.onclick = this.cancelAction.bind(this);

            let okButton = cancelButton.nextElementSibling;
            okButton.setAttribute("title", "OK");
            okButton.textContent = StockIcon["ok"];
            okButton.onclick = this.okAction.bind(this);

            this._field = fieldPane.lastElementChild;
            this._list = pane.lastElementChild;

            this._list.id = Util.uid();
            this._field.setAttribute("for", this._list.id);

            this._field.addEventListener("selectionaccepted",
                                         this.onSelectionAccepted.bind(this));

            // xui-autocomplete-field and xui-list cannot be configured until they
            // are "connected".

            this._items = items;
            this._initialText = initialText;
            this._options = options;
            this._resolve = resolve;
        }

        open(position="center", reference=null) {
            super.open(position, reference);

            // Now that xui-autocomplete-field and xui-list are "connected",
            // we can configure them.

            this._field.autofocus = true;

            if (this._options !== null) {
                for (let opt in this._options) {
                    let val = this._options[opt];

                    switch (opt.toLowerCase()) {
                    case "completionkey":
                        this._field.completionKey = val;
                        break;
                    case "acceptmode":
                        this._field.acceptMode =  val;
                        break;
                    case "singleclicktoaccept":
                        this._field.singleClickToAccept = val;
                        break;
                    case "lenienttextchecker":
                        this._field.lenientTextChecker = val;
                        break;
                    case "labelmaker":
                        this._list.labelMaker = val;
                        break;
                    case "htmlrenderer":
                        this._list.htmlRenderer = val;
                        break;
                    case "disabledchecker":
                        this._list.disabledChecker = val;
                        break;
                    case "columns":
                        {
                            let len = ItemChooser.countToLength(val);
                            if (len !== null) {
                                // Note that unlike the field width, the list
                                // width is "not flex".
                                this._field.style.width = len;
                            }
                        }
                        break;
                    case "rows":
                        {
                            let len = ItemChooser.countToLength(val);
                            if (len !== null) {
                                this._list.style.height = len;
                            }
                        }
                        break;
                    default:
                        console.warn(`ItemChooser: ignoring option "${opt}"`);
                        break;
                    }
                }
            }

            this._list.setAll(this._items);
            if (this._initialText !== null) {
                this._field.text = this._initialText;
            }
        }

        static countToLength(val, mult=1) {
            let num = Number.parseInt(val);
            if (Number.isNaN(num) || num <= 0) {
                return null;
            }

            return String(mult * num) + "em";
        }

        onSelectionAccepted(event) {
            this.close([ event.detail.acceptedText,
                         event.detail.selectedIndex, event.detail.selectedItem ]);
        }

        dialogClosed(result) {
            // Close button clicked ==> null result, which is just fine.
            this._resolve(result);
        }

        cancelAction() {
            this.close(null);
        }

        okAction() {
            this._field.acceptSelection();
        }
    }

    ItemChooser.TEMPLATE = document.createElement("template");
    ItemChooser.TEMPLATE.innerHTML = `
    <div class="xui-item-chooser-pane">
      <div class="xui-itmchsr-field-pane">
        <button type="button"
                class="xui-control xui-small-icon xui-itmchsr-cancel"></button>
        <button type="button"
                class="xui-control xui-small-icon xui-dlg-default-button
                       xui-itmchsr-ok"></button>
        <xui-autocomplete-field class="xui-itmchsr-field"></xui-autocomplete-field>
      </div>
      <xui-list class="xui-itmchsr-list"></xui-list>
    </div>
    `;