Path: blob/main/src/vs/workbench/contrib/notebook/browser/viewParts/notebookCellOverlays.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { createFastDomNode, FastDomNode } from '../../../../../base/browser/fastDomNode.js';6import { Disposable } from '../../../../../base/common/lifecycle.js';7import { INotebookCellOverlay, INotebookCellOverlayChangeAccessor, INotebookViewCellsUpdateEvent } from '../notebookBrowser.js';8import { NotebookCellListView } from '../view/notebookCellListView.js';9import { CellViewModel } from '../viewModel/notebookViewModelImpl.js';1011interface INotebookCellOverlayWidget {12overlayId: string;13overlay: INotebookCellOverlay;14domNode: FastDomNode<HTMLElement>;15}1617export class NotebookCellOverlays extends Disposable {18private _lastOverlayId = 0;19public domNode: FastDomNode<HTMLElement>;20private _overlays: { [key: string]: INotebookCellOverlayWidget } = Object.create(null);2122constructor(23private readonly listView: NotebookCellListView<CellViewModel>24) {25super();26this.domNode = createFastDomNode(document.createElement('div'));27this.domNode.setClassName('cell-overlays');28this.domNode.setPosition('absolute');29this.domNode.setAttribute('role', 'presentation');30this.domNode.setAttribute('aria-hidden', 'true');31this.domNode.setWidth('100%');3233this.listView.containerDomNode.appendChild(this.domNode.domNode);34}3536changeCellOverlays(callback: (changeAccessor: INotebookCellOverlayChangeAccessor) => void): boolean {37let overlaysHaveChanged = false;38const changeAccessor: INotebookCellOverlayChangeAccessor = {39addOverlay: (overlay: INotebookCellOverlay): string => {40overlaysHaveChanged = true;41return this._addOverlay(overlay);42},43removeOverlay: (id: string): void => {44overlaysHaveChanged = true;45this._removeOverlay(id);46},47layoutOverlay: (id: string): void => {48overlaysHaveChanged = true;49this._layoutOverlay(id);50}51};5253callback(changeAccessor);5455return overlaysHaveChanged;56}5758onCellsChanged(e: INotebookViewCellsUpdateEvent): void {59this.layout();60}6162onHiddenRangesChange() {63this.layout();64}6566layout() {67for (const id in this._overlays) {68this._layoutOverlay(id);69}70}7172private _addOverlay(overlay: INotebookCellOverlay): string {73const overlayId = `${++this._lastOverlayId}`;7475const overlayWidget = {76overlayId,77overlay,78domNode: createFastDomNode(overlay.domNode)79};8081this._overlays[overlayId] = overlayWidget;82overlayWidget.domNode.setClassName('cell-overlay');83overlayWidget.domNode.setPosition('absolute');84this.domNode.appendChild(overlayWidget.domNode);8586return overlayId;87}8889private _removeOverlay(id: string): void {90const overlay = this._overlays[id];91if (overlay) {92// overlay.overlay.dispose();93try {94this.domNode.removeChild(overlay.domNode);95} catch {96// no op97}9899delete this._overlays[id];100}101}102103private _layoutOverlay(id: string): void {104const overlay = this._overlays[id];105if (!overlay) {106return;107}108109const isInHiddenRanges = this._isInHiddenRanges(overlay);110if (isInHiddenRanges) {111overlay.domNode.setDisplay('none');112return;113}114115overlay.domNode.setDisplay('block');116const index = this.listView.indexOf(overlay.overlay.cell as CellViewModel);117if (index === -1) {118// should not happen119return;120}121122const top = this.listView.elementTop(index);123overlay.domNode.setTop(top);124}125126private _isInHiddenRanges(zone: INotebookCellOverlayWidget) {127const index = this.listView.indexOf(zone.overlay.cell as CellViewModel);128if (index === -1) {129return true;130}131132return false;133}134}135136137138139