Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.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 { Emitter } from '../../../../../base/common/event.js';
7
import { Disposable } from '../../../../../base/common/lifecycle.js';
8
import { generateUuid } from '../../../../../base/common/uuid.js';
9
import { PrefixSumComputer } from '../../../../../editor/common/model/prefixSumComputer.js';
10
import { IDiffNestedCellViewModel } from './notebookDiffEditorBrowser.js';
11
import { ICellOutputViewModel, IGenericCellViewModel } from '../notebookBrowser.js';
12
import { CellViewModelStateChangeEvent } from '../notebookViewEvents.js';
13
import { CellOutputViewModel } from '../viewModel/cellOutputViewModel.js';
14
import { NotebookCellTextModel } from '../../common/model/notebookCellTextModel.js';
15
import { INotebookService } from '../../common/notebookService.js';
16
17
export class DiffNestedCellViewModel extends Disposable implements IDiffNestedCellViewModel, IGenericCellViewModel {
18
private _id: string;
19
get id() {
20
return this._id;
21
}
22
23
get outputs() {
24
return this.textModel.outputs;
25
}
26
27
get language() {
28
return this.textModel.language;
29
}
30
31
get metadata() {
32
return this.textModel.metadata;
33
}
34
35
get uri() {
36
return this.textModel.uri;
37
}
38
39
get handle() {
40
return this.textModel.handle;
41
}
42
43
protected readonly _onDidChangeState: Emitter<CellViewModelStateChangeEvent> = this._register(new Emitter<CellViewModelStateChangeEvent>());
44
45
private _hoveringOutput: boolean = false;
46
public get outputIsHovered(): boolean {
47
return this._hoveringOutput;
48
}
49
50
public set outputIsHovered(v: boolean) {
51
this._hoveringOutput = v;
52
this._onDidChangeState.fire({ outputIsHoveredChanged: true });
53
}
54
55
private _focusOnOutput: boolean = false;
56
public get outputIsFocused(): boolean {
57
return this._focusOnOutput;
58
}
59
60
public set outputIsFocused(v: boolean) {
61
this._focusOnOutput = v;
62
this._onDidChangeState.fire({ outputIsFocusedChanged: true });
63
}
64
65
private _focusInputInOutput: boolean = false;
66
public get inputInOutputIsFocused(): boolean {
67
return this._focusInputInOutput;
68
}
69
70
public set inputInOutputIsFocused(v: boolean) {
71
this._focusInputInOutput = v;
72
}
73
74
private _outputViewModels: ICellOutputViewModel[];
75
76
get outputsViewModels() {
77
return this._outputViewModels;
78
}
79
80
protected _outputCollection: number[] = [];
81
protected _outputsTop: PrefixSumComputer | null = null;
82
83
protected readonly _onDidChangeOutputLayout = this._register(new Emitter<void>());
84
readonly onDidChangeOutputLayout = this._onDidChangeOutputLayout.event;
85
86
constructor(
87
readonly textModel: NotebookCellTextModel,
88
@INotebookService private _notebookService: INotebookService
89
) {
90
super();
91
this._id = generateUuid();
92
93
this._outputViewModels = this.textModel.outputs.map(output => new CellOutputViewModel(this, output, this._notebookService));
94
this._register(this.textModel.onDidChangeOutputs((splice) => {
95
this._outputCollection.splice(splice.start, splice.deleteCount, ...splice.newOutputs.map(() => 0));
96
const removed = this._outputViewModels.splice(splice.start, splice.deleteCount, ...splice.newOutputs.map(output => new CellOutputViewModel(this, output, this._notebookService)));
97
removed.forEach(vm => vm.dispose());
98
99
this._outputsTop = null;
100
this._onDidChangeOutputLayout.fire();
101
}));
102
this._outputCollection = new Array(this.textModel.outputs.length);
103
}
104
105
private _ensureOutputsTop() {
106
if (!this._outputsTop) {
107
const values = new Uint32Array(this._outputCollection.length);
108
for (let i = 0; i < this._outputCollection.length; i++) {
109
values[i] = this._outputCollection[i];
110
}
111
112
this._outputsTop = new PrefixSumComputer(values);
113
}
114
}
115
116
getOutputOffset(index: number): number {
117
this._ensureOutputsTop();
118
119
if (index >= this._outputCollection.length) {
120
throw new Error('Output index out of range!');
121
}
122
123
return this._outputsTop!.getPrefixSum(index - 1);
124
}
125
126
updateOutputHeight(index: number, height: number): void {
127
if (index >= this._outputCollection.length) {
128
throw new Error('Output index out of range!');
129
}
130
131
this._ensureOutputsTop();
132
this._outputCollection[index] = height;
133
if (this._outputsTop!.setValue(index, height)) {
134
this._onDidChangeOutputLayout.fire();
135
}
136
}
137
138
getOutputTotalHeight() {
139
this._ensureOutputsTop();
140
141
return this._outputsTop?.getTotalSum() ?? 0;
142
}
143
144
public override dispose(): void {
145
super.dispose();
146
147
this._outputViewModels.forEach(output => {
148
output.dispose();
149
});
150
}
151
}
152
153