UNPKG

@dcloudio/uni-debugger

Version:

uni-app debugger

1,109 lines (983 loc) 29.7 kB
/* * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @unrestricted */ UI.Toolbar = class { /** * @param {string} className * @param {!Element=} parentElement */ constructor(className, parentElement) { /** @type {!Array.<!UI.ToolbarItem>} */ this._items = []; this.element = parentElement ? parentElement.createChild('div') : createElement('div'); this.element.className = className; this.element.classList.add('toolbar'); this._enabled = true; this._shadowRoot = UI.createShadowRootWithCoreStyles(this.element, 'ui/toolbar.css'); this._contentElement = this._shadowRoot.createChild('div', 'toolbar-shadow'); this._insertionPoint = this._contentElement.createChild('slot'); } /** * @param {!UI.Action} action * @param {!Array<!UI.ToolbarButton>=} toggledOptions * @param {!Array<!UI.ToolbarButton>=} untoggledOptions * @return {!UI.ToolbarToggle} */ static createActionButton(action, toggledOptions, untoggledOptions) { const button = new UI.ToolbarToggle(action.title(), action.icon(), action.toggledIcon()); button.setToggleWithRedColor(action.toggleWithRedColor()); button.addEventListener(UI.ToolbarButton.Events.Click, action.execute, action); action.addEventListener(UI.Action.Events.Enabled, enabledChanged); action.addEventListener(UI.Action.Events.Toggled, toggled); /** @type {?UI.LongClickController} */ let longClickController = null; /** @type {?Array<!UI.ToolbarButton>} */ let longClickButtons = null; /** @type {?Element} */ let longClickGlyph = null; toggled(); button.setEnabled(action.enabled()); return button; /** * @param {!Common.Event} event */ function enabledChanged(event) { button.setEnabled(/** @type {boolean} */ (event.data)); } function toggled() { button.setToggled(action.toggled()); if (action.title()) UI.Tooltip.install(button.element, action.title(), action.id()); updateOptions(); } function updateOptions() { const buttons = action.toggled() ? (toggledOptions || null) : (untoggledOptions || null); if (buttons && buttons.length) { if (!longClickController) { longClickController = new UI.LongClickController(button.element, showOptions); longClickGlyph = UI.Icon.create('largeicon-longclick-triangle', 'long-click-glyph'); button.element.appendChild(longClickGlyph); longClickButtons = buttons; } } else { if (longClickController) { longClickController.dispose(); longClickController = null; longClickGlyph.remove(); longClickGlyph = null; longClickButtons = null; } } } function showOptions() { let buttons = longClickButtons.slice(); const mainButtonClone = new UI.ToolbarToggle(action.title(), action.icon(), action.toggledIcon()); mainButtonClone.addEventListener(UI.ToolbarButton.Events.Click, clicked); /** * @param {!Common.Event} event */ function clicked(event) { button._clicked(/** @type {!Event} */ (event.data)); } mainButtonClone.setToggled(action.toggled()); buttons.push(mainButtonClone); const document = button.element.ownerDocument; document.documentElement.addEventListener('mouseup', mouseUp, false); const optionsGlassPane = new UI.GlassPane(); optionsGlassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane); optionsGlassPane.show(document); const optionsBar = new UI.Toolbar('fill', optionsGlassPane.contentElement); optionsBar._contentElement.classList.add('floating'); const buttonHeight = 26; const hostButtonPosition = button.element.boxInWindow().relativeToElement(UI.GlassPane.container(document)); const topNotBottom = hostButtonPosition.y + buttonHeight * buttons.length < document.documentElement.offsetHeight; if (topNotBottom) buttons = buttons.reverse(); optionsBar.element.style.height = (buttonHeight * buttons.length) + 'px'; if (topNotBottom) optionsBar.element.style.top = (hostButtonPosition.y - 5) + 'px'; else optionsBar.element.style.top = (hostButtonPosition.y - (buttonHeight * (buttons.length - 1)) - 6) + 'px'; optionsBar.element.style.left = (hostButtonPosition.x - 5) + 'px'; for (let i = 0; i < buttons.length; ++i) { buttons[i].element.addEventListener('mousemove', mouseOver, false); buttons[i].element.addEventListener('mouseout', mouseOut, false); optionsBar.appendToolbarItem(buttons[i]); } const hostButtonIndex = topNotBottom ? 0 : buttons.length - 1; buttons[hostButtonIndex].element.classList.add('emulate-active'); function mouseOver(e) { if (e.which !== 1) return; const buttonElement = e.target.enclosingNodeOrSelfWithClass('toolbar-item'); buttonElement.classList.add('emulate-active'); } function mouseOut(e) { if (e.which !== 1) return; const buttonElement = e.target.enclosingNodeOrSelfWithClass('toolbar-item'); buttonElement.classList.remove('emulate-active'); } function mouseUp(e) { if (e.which !== 1) return; optionsGlassPane.hide(); document.documentElement.removeEventListener('mouseup', mouseUp, false); for (let i = 0; i < buttons.length; ++i) { if (buttons[i].element.classList.contains('emulate-active')) { buttons[i].element.classList.remove('emulate-active'); buttons[i]._clicked(e); break; } } } } } /** * @param {string} actionId * @return {!UI.ToolbarToggle} */ static createActionButtonForId(actionId) { const action = UI.actionRegistry.action(actionId); return UI.Toolbar.createActionButton(/** @type {!UI.Action} */ (action)); } /** * @return {!Element} */ gripElementForResize() { return this._contentElement; } /** * @param {boolean=} growVertically */ makeWrappable(growVertically) { this._contentElement.classList.add('wrappable'); if (growVertically) this._contentElement.classList.add('toolbar-grow-vertical'); } makeVertical() { this._contentElement.classList.add('vertical'); } makeBlueOnHover() { this._contentElement.classList.add('toolbar-blue-on-hover'); } makeToggledGray() { this._contentElement.classList.add('toolbar-toggled-gray'); } renderAsLinks() { this._contentElement.classList.add('toolbar-render-as-links'); } /** * @param {boolean} enabled */ setEnabled(enabled) { this._enabled = enabled; for (const item of this._items) item._applyEnabledState(this._enabled && item._enabled); } /** * @param {!UI.ToolbarItem} item */ appendToolbarItem(item) { this._items.push(item); item._toolbar = this; if (!this._enabled) item._applyEnabledState(false); this._contentElement.insertBefore(item.element, this._insertionPoint); this._hideSeparatorDupes(); } appendSeparator() { this.appendToolbarItem(new UI.ToolbarSeparator()); } appendSpacer() { this.appendToolbarItem(new UI.ToolbarSeparator(true)); } /** * @param {string} text */ appendText(text) { this.appendToolbarItem(new UI.ToolbarText(text)); } removeToolbarItems() { for (const item of this._items) delete item._toolbar; this._items = []; this._contentElement.removeChildren(); this._insertionPoint = this._contentElement.createChild('slot'); } /** * @param {string} color */ setColor(color) { const style = createElement('style'); style.textContent = '.toolbar-glyph { background-color: ' + color + ' !important }'; this._shadowRoot.appendChild(style); } /** * @param {string} color */ setToggledColor(color) { const style = createElement('style'); style.textContent = '.toolbar-button.toolbar-state-on .toolbar-glyph { background-color: ' + color + ' !important }'; this._shadowRoot.appendChild(style); } _hideSeparatorDupes() { if (!this._items.length) return; // Don't hide first and last separators if they were added explicitly. let previousIsSeparator = false; let lastSeparator; let nonSeparatorVisible = false; for (let i = 0; i < this._items.length; ++i) { if (this._items[i] instanceof UI.ToolbarSeparator) { this._items[i].setVisible(!previousIsSeparator); previousIsSeparator = true; lastSeparator = this._items[i]; continue; } if (this._items[i].visible()) { previousIsSeparator = false; lastSeparator = null; nonSeparatorVisible = true; } } if (lastSeparator && lastSeparator !== this._items.peekLast()) lastSeparator.setVisible(false); this.element.classList.toggle('hidden', !!lastSeparator && lastSeparator.visible() && !nonSeparatorVisible); } /** * @param {string} location */ appendLocationItems(location) { const extensions = self.runtime.extensions(UI.ToolbarItem.Provider); const promises = []; for (let i = 0; i < extensions.length; ++i) { if (extensions[i].descriptor()['location'] === location) promises.push(resolveItem(extensions[i])); } Promise.all(promises).then(appendItemsInOrder.bind(this)); /** * @param {!Runtime.Extension} extension * @return {!Promise<?UI.ToolbarItem>} */ function resolveItem(extension) { const descriptor = extension.descriptor(); if (descriptor['separator']) return Promise.resolve(/** @type {?UI.ToolbarItem} */ (new UI.ToolbarSeparator())); if (descriptor['actionId']) { return Promise.resolve( /** @type {?UI.ToolbarItem} */ (UI.Toolbar.createActionButtonForId(descriptor['actionId']))); } return extension.instance().then(fetchItemFromProvider); /** * @param {!Object} provider * @return {?UI.ToolbarItem} */ function fetchItemFromProvider(provider) { return /** @type {!UI.ToolbarItem.Provider} */ (provider).item(); } } /** * @param {!Array.<?UI.ToolbarItem>} items * @this {UI.Toolbar} */ function appendItemsInOrder(items) { for (let i = 0; i < items.length; ++i) { const item = items[i]; if (item) this.appendToolbarItem(item); } } } }; /** * @unrestricted */ UI.ToolbarItem = class extends Common.Object { /** * @param {!Element} element */ constructor(element) { super(); this.element = element; this.element.classList.add('toolbar-item'); this._visible = true; this._enabled = true; } /** * @param {string} title */ setTitle(title) { if (this._title === title) return; this._title = title; UI.ARIAUtils.setAccessibleName(this.element, title); UI.Tooltip.install(this.element, title); } /** * @param {boolean} value */ setEnabled(value) { if (this._enabled === value) return; this._enabled = value; this._applyEnabledState(this._enabled && (!this._toolbar || this._toolbar._enabled)); } /** * @param {boolean} enabled */ _applyEnabledState(enabled) { this.element.disabled = !enabled; } /** * @return {boolean} x */ visible() { return this._visible; } /** * @param {boolean} x */ setVisible(x) { if (this._visible === x) return; this.element.classList.toggle('hidden', !x); this._visible = x; if (this._toolbar && !(this instanceof UI.ToolbarSeparator)) this._toolbar._hideSeparatorDupes(); } setRightAligned(alignRight) { this.element.classList.toggle('toolbar-item-right-aligned', alignRight); } }; /** * @unrestricted */ UI.ToolbarText = class extends UI.ToolbarItem { /** * @param {string=} text */ constructor(text) { super(createElementWithClass('div', 'toolbar-text')); this.element.classList.add('toolbar-text'); this.setText(text || ''); } /** * @return {string} */ text() { return this.element.textContent; } /** * @param {string} text */ setText(text) { this.element.textContent = text; } }; /** * @unrestricted */ UI.ToolbarButton = class extends UI.ToolbarItem { /** * @param {string} title * @param {string=} glyph * @param {string=} text */ constructor(title, glyph, text) { super(createElementWithClass('button', 'toolbar-button')); this.element.addEventListener('click', this._clicked.bind(this), false); this.element.addEventListener('mousedown', this._mouseDown.bind(this), false); this.element.addEventListener('mouseup', this._mouseUp.bind(this), false); this._glyphElement = UI.Icon.create('', 'toolbar-glyph hidden'); this.element.appendChild(this._glyphElement); this._textElement = this.element.createChild('div', 'toolbar-text hidden'); this.setTitle(title); if (glyph) this.setGlyph(glyph); this.setText(text || ''); this._title = ''; } /** * @param {string} text */ setText(text) { if (this._text === text) return; this._textElement.textContent = text; this._textElement.classList.toggle('hidden', !text); this._text = text; } /** * @param {string} glyph */ setGlyph(glyph) { if (this._glyph === glyph) return; this._glyphElement.setIconType(glyph); this._glyphElement.classList.toggle('hidden', !glyph); this.element.classList.toggle('toolbar-has-glyph', !!glyph); this._glyph = glyph; } /** * @param {string} iconURL */ setBackgroundImage(iconURL) { this.element.style.backgroundImage = 'url(' + iconURL + ')'; } setDarkText() { this.element.classList.add('dark-text'); } /** * @param {number=} width */ turnIntoSelect(width) { this.element.classList.add('toolbar-has-dropdown'); const dropdownArrowIcon = UI.Icon.create('smallicon-triangle-down', 'toolbar-dropdown-arrow'); this.element.appendChild(dropdownArrowIcon); if (width) this.element.style.width = width + 'px'; } /** * @param {!Event} event */ _clicked(event) { if (!this._enabled) return; this.dispatchEventToListeners(UI.ToolbarButton.Events.Click, event); event.consume(); } /** * @param {!Event} event */ _mouseDown(event) { if (!this._enabled) return; this.dispatchEventToListeners(UI.ToolbarButton.Events.MouseDown, event); } /** * @param {!Event} event */ _mouseUp(event) { if (!this._enabled) return; this.dispatchEventToListeners(UI.ToolbarButton.Events.MouseUp, event); } }; UI.ToolbarButton.Events = { Click: Symbol('Click'), MouseDown: Symbol('MouseDown'), MouseUp: Symbol('MouseUp') }; UI.ToolbarInput = class extends UI.ToolbarItem { /** * @param {string} placeholder * @param {number=} growFactor * @param {number=} shrinkFactor * @param {string=} tooltip * @param {(function(string, string, boolean=):!Promise<!UI.SuggestBox.Suggestions>)=} completions */ constructor(placeholder, growFactor, shrinkFactor, tooltip, completions) { super(createElementWithClass('div', 'toolbar-input')); const internalPromptElement = this.element.createChild('div', 'toolbar-input-prompt'); internalPromptElement.addEventListener('focus', () => this.element.classList.add('focused')); internalPromptElement.addEventListener('blur', () => this.element.classList.remove('focused')); this._prompt = new UI.TextPrompt(); this._proxyElement = this._prompt.attach(internalPromptElement); this._proxyElement.classList.add('toolbar-prompt-proxy'); this._proxyElement.addEventListener('keydown', event => this._onKeydownCallback(event)); this._prompt.initialize(completions || (() => Promise.resolve([])), ' '); if (tooltip) this._prompt.setTitle(tooltip); this._prompt.setPlaceholder(placeholder); this._prompt.addEventListener(UI.TextPrompt.Events.TextChanged, this._onChangeCallback.bind(this)); if (growFactor) this.element.style.flexGrow = growFactor; if (shrinkFactor) this.element.style.flexShrink = shrinkFactor; const clearButton = this.element.createChild('div', 'toolbar-input-clear-button'); clearButton.appendChild(UI.Icon.create('mediumicon-gray-cross-hover', 'search-cancel-button')); clearButton.addEventListener('click', () => { this._internalSetValue('', true); this._prompt.focus(); }); this._updateEmptyStyles(); } /** * @override * @param {boolean} enabled */ _applyEnabledState(enabled) { this._prompt.setEnabled(enabled); } /** * @param {string} value */ setValue(value) { this._internalSetValue(value, false); } /** * @param {string} value * @param {boolean} notify */ _internalSetValue(value, notify) { this._prompt.setText(value); if (notify) this._onChangeCallback(); this._updateEmptyStyles(); } /** * @return {string} */ value() { return this._prompt.textWithCurrentSuggestion(); } /** * @param {!Event} event */ _onKeydownCallback(event) { if (!isEscKey(event) || !this._prompt.text()) return; this._internalSetValue('', true); event.consume(true); } _onChangeCallback() { this._updateEmptyStyles(); this.dispatchEventToListeners(UI.ToolbarInput.Event.TextChanged, this._prompt.text()); } _updateEmptyStyles() { this.element.classList.toggle('toolbar-input-empty', !this._prompt.text()); } }; UI.ToolbarInput.Event = { TextChanged: Symbol('TextChanged') }; /** * @unrestricted */ UI.ToolbarToggle = class extends UI.ToolbarButton { /** * @param {string} title * @param {string=} glyph * @param {string=} toggledGlyph */ constructor(title, glyph, toggledGlyph) { super(title, glyph, ''); this._toggled = false; this._untoggledGlyph = glyph; this._toggledGlyph = toggledGlyph; this.element.classList.add('toolbar-state-off'); UI.ARIAUtils.setPressed(this.element, false); } /** * @return {boolean} */ toggled() { return this._toggled; } /** * @param {boolean} toggled */ setToggled(toggled) { if (this._toggled === toggled) return; this._toggled = toggled; this.element.classList.toggle('toolbar-state-on', toggled); this.element.classList.toggle('toolbar-state-off', !toggled); UI.ARIAUtils.setPressed(this.element, toggled); if (this._toggledGlyph && this._untoggledGlyph) this.setGlyph(toggled ? this._toggledGlyph : this._untoggledGlyph); } /** * @param {boolean} withRedColor */ setDefaultWithRedColor(withRedColor) { this.element.classList.toggle('toolbar-default-with-red-color', withRedColor); } /** * @param {boolean} toggleWithRedColor */ setToggleWithRedColor(toggleWithRedColor) { this.element.classList.toggle('toolbar-toggle-with-red-color', toggleWithRedColor); } }; /** * @unrestricted */ UI.ToolbarMenuButton = class extends UI.ToolbarButton { /** * @param {function(!UI.ContextMenu)} contextMenuHandler * @param {boolean=} useSoftMenu */ constructor(contextMenuHandler, useSoftMenu) { super('', 'largeicon-menu'); this._contextMenuHandler = contextMenuHandler; this._useSoftMenu = !!useSoftMenu; } /** * @override * @param {!Event} event */ _mouseDown(event) { if (event.buttons !== 1) { super._mouseDown(event); return; } if (!this._triggerTimeout) this._triggerTimeout = setTimeout(this._trigger.bind(this, event), 200); } /** * @param {!Event} event */ _trigger(event) { delete this._triggerTimeout; // Throttling avoids entering a bad state on Macs when rapidly triggering context menus just // after the window gains focus. See crbug.com/655556 if (this._lastTriggerTime && Date.now() - this._lastTriggerTime < 300) return; const contextMenu = new UI.ContextMenu( event, this._useSoftMenu, this.element.totalOffsetLeft(), this.element.totalOffsetTop() + this.element.offsetHeight); this._contextMenuHandler(contextMenu); contextMenu.show(); this._lastTriggerTime = Date.now(); } /** * @override * @param {!Event} event */ _clicked(event) { if (this._triggerTimeout) clearTimeout(this._triggerTimeout); this._trigger(event); } }; /** * @unrestricted */ UI.ToolbarSettingToggle = class extends UI.ToolbarToggle { /** * @param {!Common.Setting} setting * @param {string} glyph * @param {string} title * @param {string=} toggledTitle */ constructor(setting, glyph, title, toggledTitle) { super(title, glyph); this._defaultTitle = title; this._toggledTitle = toggledTitle || title; this._setting = setting; this._settingChanged(); this._setting.addChangeListener(this._settingChanged, this); } _settingChanged() { const toggled = this._setting.get(); this.setToggled(toggled); this.setTitle(toggled ? this._toggledTitle : this._defaultTitle); } /** * @override * @param {!Event} event */ _clicked(event) { this._setting.set(!this.toggled()); super._clicked(event); } }; /** * @unrestricted */ UI.ToolbarSeparator = class extends UI.ToolbarItem { /** * @param {boolean=} spacer */ constructor(spacer) { super(createElementWithClass('div', spacer ? 'toolbar-spacer' : 'toolbar-divider')); } }; /** * @interface */ UI.ToolbarItem.Provider = function() {}; UI.ToolbarItem.Provider.prototype = { /** * @return {?UI.ToolbarItem} */ item() {} }; /** * @interface */ UI.ToolbarItem.ItemsProvider = function() {}; UI.ToolbarItem.ItemsProvider.prototype = { /** * @return {!Array<!UI.ToolbarItem>} */ toolbarItems() {} }; /** * @unrestricted */ UI.ToolbarComboBox = class extends UI.ToolbarItem { /** * @param {?function(!Event)} changeHandler * @param {string=} className */ constructor(changeHandler, className) { super(createElementWithClass('span', 'toolbar-select-container')); this._selectElement = this.element.createChild('select', 'toolbar-item'); const dropdownArrowIcon = UI.Icon.create('smallicon-triangle-down', 'toolbar-dropdown-arrow'); this.element.appendChild(dropdownArrowIcon); if (changeHandler) this._selectElement.addEventListener('change', changeHandler, false); if (className) this._selectElement.classList.add(className); } /** * @override * @param {string} title */ setTitle(title) { UI.ARIAUtils.setAccessibleName(this._selectElement, title); super.setTitle(title); } /** * @return {!HTMLSelectElement} */ selectElement() { return /** @type {!HTMLSelectElement} */ (this._selectElement); } /** * @return {number} */ size() { return this._selectElement.childElementCount; } /** * @return {!Array.<!Element>} */ options() { return Array.prototype.slice.call(this._selectElement.children, 0); } /** * @param {!Element} option */ addOption(option) { this._selectElement.appendChild(option); } /** * @param {string} label * @param {string=} title * @param {string=} value * @return {!Element} */ createOption(label, title, value) { const option = this._selectElement.createChild('option'); option.text = label; if (title) option.title = title; if (typeof value !== 'undefined') option.value = value; return option; } /** * @override * @param {boolean} enabled */ _applyEnabledState(enabled) { super._applyEnabledState(enabled); this._selectElement.disabled = !enabled; } /** * @param {!Element} option */ removeOption(option) { this._selectElement.removeChild(option); } removeOptions() { this._selectElement.removeChildren(); } /** * @return {?Element} */ selectedOption() { if (this._selectElement.selectedIndex >= 0) return this._selectElement[this._selectElement.selectedIndex]; return null; } /** * @param {!Element} option */ select(option) { this._selectElement.selectedIndex = Array.prototype.indexOf.call(/** @type {?} */ (this._selectElement), option); } /** * @param {number} index */ setSelectedIndex(index) { this._selectElement.selectedIndex = index; } /** * @return {number} */ selectedIndex() { return this._selectElement.selectedIndex; } /** * @param {number} width */ setMaxWidth(width) { this._selectElement.style.maxWidth = width + 'px'; } /** * @param {number} width */ setMinWidth(width) { this._selectElement.style.minWidth = width + 'px'; } }; /** * @unrestricted */ UI.ToolbarSettingComboBox = class extends UI.ToolbarComboBox { /** * @param {!Array<!{value: string, label: string, title: string}>} options * @param {!Common.Setting} setting * @param {string=} optGroup */ constructor(options, setting, optGroup) { super(null); this._setting = setting; this._options = options; this._selectElement.addEventListener('change', this._valueChanged.bind(this), false); if (optGroup) { const optGroupElement = this._selectElement.createChild('optgroup'); optGroupElement.label = optGroup; this._optionContainer = optGroupElement; } else { this._optionContainer = this._selectElement; } this.setOptions(options); setting.addChangeListener(this._settingChanged, this); } /** * @param {!Array<!{value: string, label: string, title: string}>} options */ setOptions(options) { this._options = options; this._optionContainer.removeChildren(); for (let i = 0; i < options.length; ++i) { const dataOption = options[i]; const option = this.createOption(dataOption.label, dataOption.title, dataOption.value); this._optionContainer.appendChild(option); if (this._setting.get() === dataOption.value) this.setSelectedIndex(i); } } /** * @return {string} */ value() { return this._options[this.selectedIndex()].value; } _settingChanged() { if (this._muteSettingListener) return; const value = this._setting.get(); for (let i = 0; i < this._options.length; ++i) { if (value === this._options[i].value) { this.setSelectedIndex(i); break; } } } /** * @param {!Event} event */ _valueChanged(event) { const option = this._options[this.selectedIndex()]; this._muteSettingListener = true; this._setting.set(option.value); this._muteSettingListener = false; } }; /** * @unrestricted */ UI.ToolbarCheckbox = class extends UI.ToolbarItem { /** * @param {string} text * @param {string=} tooltip * @param {function()=} listener */ constructor(text, tooltip, listener) { super(UI.CheckboxLabel.create(text)); this.element.classList.add('checkbox'); this.inputElement = this.element.checkboxElement; if (tooltip) this.element.title = tooltip; if (listener) this.inputElement.addEventListener('click', listener, false); } /** * @return {boolean} */ checked() { return this.inputElement.checked; } /** * @param {boolean} value */ setChecked(value) { this.inputElement.checked = value; } /** * @override * @param {boolean} enabled */ _applyEnabledState(enabled) { super._applyEnabledState(enabled); this.inputElement.disabled = !enabled; } }; UI.ToolbarSettingCheckbox = class extends UI.ToolbarCheckbox { /** * @param {!Common.Setting} setting * @param {string=} tooltip * @param {string=} alternateTitle */ constructor(setting, tooltip, alternateTitle) { super(alternateTitle || setting.title() || '', tooltip); UI.SettingsUI.bindCheckbox(this.inputElement, setting); } };