| // Copyright 2014 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| /** | |
| * @implements {SDK.SDKModelObserver<!SDK.DebuggerModel>} | |
| * @implements {UI.ListDelegate<!SDK.DebuggerModel>} | |
| */ | |
| Sources.ThreadsSidebarPane = class extends UI.VBox { | |
| constructor() { | |
| super(true); | |
| this.registerRequiredCSS('sources/threadsSidebarPane.css'); | |
| /** @type {!UI.ListModel<!SDK.DebuggerModel>} */ | |
| this._items = new UI.ListModel(); | |
| /** @type {!UI.ListControl<!SDK.DebuggerModel>} */ | |
| this._list = new UI.ListControl(this._items, this, UI.ListMode.NonViewport); | |
| const currentTarget = UI.context.flavor(SDK.Target); | |
| this._selectedModel = !!currentTarget ? currentTarget.model(SDK.DebuggerModel) : null; | |
| this.contentElement.appendChild(this._list.element); | |
| UI.context.addFlavorChangeListener(SDK.Target, this._targetFlavorChanged, this); | |
| SDK.targetManager.observeModels(SDK.DebuggerModel, this); | |
| } | |
| /** | |
| * @return {boolean} | |
| */ | |
| static shouldBeShown() { | |
| return SDK.targetManager.models(SDK.DebuggerModel).length >= 2; | |
| } | |
| /** | |
| * @override | |
| * @param {!SDK.DebuggerModel} debuggerModel | |
| * @return {!Element} | |
| */ | |
| createElementForItem(debuggerModel) { | |
| const element = createElementWithClass('div', 'thread-item'); | |
| const title = element.createChild('div', 'thread-item-title'); | |
| const pausedState = element.createChild('div', 'thread-item-paused-state'); | |
| element.appendChild(UI.Icon.create('smallicon-thick-right-arrow', 'selected-thread-icon')); | |
| element.tabIndex = -1; | |
| self.onInvokeElement(element, event => { | |
| UI.context.setFlavor(SDK.Target, debuggerModel.target()); | |
| event.consume(true); | |
| }); | |
| const isSelected = UI.context.flavor(SDK.Target) === debuggerModel.target(); | |
| element.classList.toggle('selected', isSelected); | |
| UI.ARIAUtils.setSelected(element, isSelected); | |
| function updateTitle() { | |
| const executionContext = debuggerModel.runtimeModel().defaultExecutionContext(); | |
| title.textContent = | |
| executionContext && executionContext.label() ? executionContext.label() : debuggerModel.target().name(); | |
| } | |
| function updatePausedState() { | |
| pausedState.textContent = debuggerModel.isPaused() ? ls`paused` : ''; | |
| } | |
| /** | |
| * @param {!Common.Event} event | |
| */ | |
| function targetNameChanged(event) { | |
| const target = /** @type {!SDK.Target} */ (event.data); | |
| if (target === debuggerModel.target()) { | |
| updateTitle(); | |
| } | |
| } | |
| debuggerModel.addEventListener(SDK.DebuggerModel.Events.DebuggerPaused, updatePausedState); | |
| debuggerModel.addEventListener(SDK.DebuggerModel.Events.DebuggerResumed, updatePausedState); | |
| debuggerModel.runtimeModel().addEventListener(SDK.RuntimeModel.Events.ExecutionContextChanged, updateTitle); | |
| SDK.targetManager.addEventListener(SDK.TargetManager.Events.NameChanged, targetNameChanged); | |
| updatePausedState(); | |
| updateTitle(); | |
| return element; | |
| } | |
| /** | |
| * @override | |
| * @param {!SDK.DebuggerModel} debuggerModel | |
| * @return {number} | |
| */ | |
| heightForItem(debuggerModel) { | |
| console.assert(false); // Should not be called. | |
| return 0; | |
| } | |
| /** | |
| * @override | |
| * @param {!SDK.DebuggerModel} debuggerModel | |
| * @return {boolean} | |
| */ | |
| isItemSelectable(debuggerModel) { | |
| return true; | |
| } | |
| /** | |
| * @override | |
| * @param {?SDK.DebuggerModel} from | |
| * @param {?SDK.DebuggerModel} to | |
| * @param {?Element} fromElement | |
| * @param {?Element} toElement | |
| */ | |
| selectedItemChanged(from, to, fromElement, toElement) { | |
| if (fromElement) { | |
| fromElement.tabIndex = -1; | |
| } | |
| if (toElement) { | |
| this.setDefaultFocusedElement(toElement); | |
| toElement.tabIndex = 0; | |
| if (this.hasFocus()) { | |
| toElement.focus(); | |
| } | |
| } | |
| } | |
| /** | |
| * @override | |
| * @param {?Element} fromElement | |
| * @param {?Element} toElement | |
| * @return {boolean} | |
| */ | |
| updateSelectedItemARIA(fromElement, toElement) { | |
| return false; | |
| } | |
| /** | |
| * @override | |
| * @param {!SDK.DebuggerModel} debuggerModel | |
| */ | |
| modelAdded(debuggerModel) { | |
| this._items.insert(this._items.length, debuggerModel); | |
| const currentTarget = UI.context.flavor(SDK.Target); | |
| if (currentTarget === debuggerModel.target()) { | |
| this._list.selectItem(debuggerModel); | |
| } | |
| } | |
| /** | |
| * @override | |
| * @param {!SDK.DebuggerModel} debuggerModel | |
| */ | |
| modelRemoved(debuggerModel) { | |
| this._items.remove(this._items.indexOf(debuggerModel)); | |
| } | |
| /** | |
| * @param {!Common.Event} event | |
| */ | |
| _targetFlavorChanged(event) { | |
| const hadFocus = this.hasFocus(); | |
| const target = /** @type {!SDK.Target} */ (event.data); | |
| const debuggerModel = target.model(SDK.DebuggerModel); | |
| if (debuggerModel) { | |
| this._list.refreshItem(debuggerModel); | |
| } | |
| if (!!this._selectedModel) { | |
| this._list.refreshItem(this._selectedModel); | |
| } | |
| this._selectedModel = debuggerModel; | |
| if (hadFocus) { | |
| this.focus(); | |
| } | |
| } | |
| }; |