Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/browser/viewParts/notebookCellOverlays.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { createFastDomNode, FastDomNode } from '../../../../../base/browser/fastDomNode.js';
7
import { Disposable } from '../../../../../base/common/lifecycle.js';
8
import { INotebookCellOverlay, INotebookCellOverlayChangeAccessor, INotebookViewCellsUpdateEvent } from '../notebookBrowser.js';
9
import { NotebookCellListView } from '../view/notebookCellListView.js';
10
import { CellViewModel } from '../viewModel/notebookViewModelImpl.js';
11
12
interface INotebookCellOverlayWidget {
13
overlayId: string;
14
overlay: INotebookCellOverlay;
15
domNode: FastDomNode<HTMLElement>;
16
}
17
18
export class NotebookCellOverlays extends Disposable {
19
private _lastOverlayId = 0;
20
public domNode: FastDomNode<HTMLElement>;
21
private _overlays: { [key: string]: INotebookCellOverlayWidget } = Object.create(null);
22
23
constructor(
24
private readonly listView: NotebookCellListView<CellViewModel>
25
) {
26
super();
27
this.domNode = createFastDomNode(document.createElement('div'));
28
this.domNode.setClassName('cell-overlays');
29
this.domNode.setPosition('absolute');
30
this.domNode.setAttribute('role', 'presentation');
31
this.domNode.setAttribute('aria-hidden', 'true');
32
this.domNode.setWidth('100%');
33
34
this.listView.containerDomNode.appendChild(this.domNode.domNode);
35
}
36
37
changeCellOverlays(callback: (changeAccessor: INotebookCellOverlayChangeAccessor) => void): boolean {
38
let overlaysHaveChanged = false;
39
const changeAccessor: INotebookCellOverlayChangeAccessor = {
40
addOverlay: (overlay: INotebookCellOverlay): string => {
41
overlaysHaveChanged = true;
42
return this._addOverlay(overlay);
43
},
44
removeOverlay: (id: string): void => {
45
overlaysHaveChanged = true;
46
this._removeOverlay(id);
47
},
48
layoutOverlay: (id: string): void => {
49
overlaysHaveChanged = true;
50
this._layoutOverlay(id);
51
}
52
};
53
54
callback(changeAccessor);
55
56
return overlaysHaveChanged;
57
}
58
59
onCellsChanged(e: INotebookViewCellsUpdateEvent): void {
60
this.layout();
61
}
62
63
onHiddenRangesChange() {
64
this.layout();
65
}
66
67
layout() {
68
for (const id in this._overlays) {
69
this._layoutOverlay(id);
70
}
71
}
72
73
private _addOverlay(overlay: INotebookCellOverlay): string {
74
const overlayId = `${++this._lastOverlayId}`;
75
76
const overlayWidget = {
77
overlayId,
78
overlay,
79
domNode: createFastDomNode(overlay.domNode)
80
};
81
82
this._overlays[overlayId] = overlayWidget;
83
overlayWidget.domNode.setClassName('cell-overlay');
84
overlayWidget.domNode.setPosition('absolute');
85
this.domNode.appendChild(overlayWidget.domNode);
86
87
return overlayId;
88
}
89
90
private _removeOverlay(id: string): void {
91
const overlay = this._overlays[id];
92
if (overlay) {
93
// overlay.overlay.dispose();
94
try {
95
this.domNode.removeChild(overlay.domNode);
96
} catch {
97
// no op
98
}
99
100
delete this._overlays[id];
101
}
102
}
103
104
private _layoutOverlay(id: string): void {
105
const overlay = this._overlays[id];
106
if (!overlay) {
107
return;
108
}
109
110
const isInHiddenRanges = this._isInHiddenRanges(overlay);
111
if (isInHiddenRanges) {
112
overlay.domNode.setDisplay('none');
113
return;
114
}
115
116
overlay.domNode.setDisplay('block');
117
const index = this.listView.indexOf(overlay.overlay.cell as CellViewModel);
118
if (index === -1) {
119
// should not happen
120
return;
121
}
122
123
const top = this.listView.elementTop(index);
124
overlay.domNode.setTop(top);
125
}
126
127
private _isInHiddenRanges(zone: INotebookCellOverlayWidget) {
128
const index = this.listView.indexOf(zone.overlay.cell as CellViewModel);
129
if (index === -1) {
130
return true;
131
}
132
133
return false;
134
}
135
}
136
137
138
139