UNPKG

chrome-devtools-frontend

Version:
106 lines (95 loc) 4.59 kB
// Copyright 2022 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. import * as i18n from '../../core/i18n/i18n.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as IconButton from '../../ui/components/icon_button/icon_button.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as ElementsComponents from './components/components.js'; import * as ElementsTreeOutline from './ElementsTreeOutline.js'; import type {ElementsTreeElement} from './ElementsTreeElement.js'; const UIStrings = { /** * @description Top layer is rendered closest to the user within a viewport, therefore its elements always appear on top of all other content */ topLayer: 'top-layer', }; const str_ = i18n.i18n.registerUIStrings('panels/elements/TopLayerContainer.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class TopLayerContainer extends UI.TreeOutline.TreeElement { treeOutline: ElementsTreeOutline.ElementsTreeOutline|null; domModel: SDK.DOMModel.DOMModel; currentTopLayerElements: Set<ElementsTreeElement>; bodyElement: ElementsTreeElement; constructor(bodyElement: ElementsTreeElement) { super('#top-layer'); this.bodyElement = bodyElement; this.domModel = bodyElement.node().domModel(); this.treeOutline = null; this.currentTopLayerElements = new Set(); } updateBody(bodyElement: ElementsTreeElement): void { this.bodyElement = bodyElement; } async addTopLayerElementsAsChildren(): Promise<boolean> { this.removeCurrentTopLayerElementsAdorners(); this.currentTopLayerElements = new Set(); const newTopLayerElementsIDs = await this.domModel.getTopLayerElements(); if (newTopLayerElementsIDs === null) { return false; } let topLayerElementIndex = 0; if (newTopLayerElementsIDs) { for (const elementID of newTopLayerElementsIDs) { const topLayerDOMNode = this.domModel.idToDOMNode.get(elementID); // Will need to add support for backdrop in the future. if (topLayerDOMNode && topLayerDOMNode.nodeName() !== '::backdrop') { topLayerElementIndex++; const topLayerElementShortcut = new SDK.DOMModel.DOMNodeShortcut( this.domModel.target(), topLayerDOMNode.backendNodeId(), 0, topLayerDOMNode.nodeName()); const topLayerTreeElement = this.treeOutline?.treeElementByNode.get(topLayerDOMNode); const topLayerElementRepresentation = new ElementsTreeOutline.ShortcutTreeElement(topLayerElementShortcut); if (topLayerTreeElement && !this.currentTopLayerElements.has(topLayerTreeElement)) { this.appendChild(topLayerElementRepresentation); this.addTopLayerAdorner(topLayerTreeElement, topLayerElementRepresentation, topLayerElementIndex); this.currentTopLayerElements.add(topLayerTreeElement); } } } } return topLayerElementIndex > 0; } private removeCurrentTopLayerElementsAdorners(): void { for (const topLayerElement of this.currentTopLayerElements) { topLayerElement.removeAllAdorners(); } } private addTopLayerAdorner( element: ElementsTreeElement, topLayerElementRepresentation: ElementsTreeOutline.ShortcutTreeElement, topLayerElementIndex: number): void { const config = ElementsComponents.AdornerManager.getRegisteredAdorner( ElementsComponents.AdornerManager.RegisteredAdorners.TOP_LAYER); const adornerContent = document.createElement('span'); adornerContent.classList.add('adorner-with-icon'); const linkIcon = new IconButton.Icon.Icon(); linkIcon .data = {iconName: 'ic_show_node_16x16', color: 'var(--color-text-disabled)', width: '12px', height: '12px'}; const adornerText = document.createElement('span'); adornerText.textContent = ` top-layer (${topLayerElementIndex}) `; adornerContent.append(linkIcon); adornerContent.append(adornerText); const adorner = element?.adorn(config, adornerContent); if (adorner) { const onClick = (((): void => { topLayerElementRepresentation.revealAndSelect(); }) as EventListener); adorner.addInteraction(onClick, { isToggle: false, shouldPropagateOnKeydown: false, ariaLabelDefault: i18nString(UIStrings.topLayer), ariaLabelActive: i18nString(UIStrings.topLayer), }); adorner.addEventListener('mousedown', e => e.consume(), false); } } }