Skip to content

Commit 04fbbf2

Browse files
authored
Merge pull request microsoft#165743 from rebornix/rebornix/above-opossum
Introduce CellOverlayPart
2 parents 1d4beed + af05f17 commit 04fbbf2

22 files changed

+436
-248
lines changed

src/vs/workbench/contrib/notebook/browser/docs/viewport-rendering.drawio.svg

Lines changed: 147 additions & 147 deletions
Loading

src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,14 @@ const $ = DOM.$;
8989

9090
export function getDefaultNotebookCreationOptions(): INotebookEditorCreationOptions {
9191
// We inlined the id to avoid loading comment contrib in tests
92-
const skipContributions = ['editor.contrib.review', FloatingClickMenu.ID];
92+
const skipContributions = [
93+
'editor.contrib.review',
94+
FloatingClickMenu.ID,
95+
'editor.contrib.dirtydiff',
96+
'editor.contrib.testingOutputPeek',
97+
'editor.contrib.testingDecorations',
98+
'store.contrib.stickyScrollController'
99+
];
93100
const contributions = EditorExtensionsRegistry.getEditorContributions().filter(c => skipContributions.indexOf(c.id) === -1);
94101

95102
return {

src/vs/workbench/contrib/notebook/browser/view/cellPart.ts

Lines changed: 125 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,30 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
6+
import * as DOM from 'vs/base/browser/dom';
7+
import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
78
import { ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
89
import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
910
import { ICellExecutionStateChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
1011

11-
export abstract class CellPart extends Disposable {
12+
/**
13+
* A content part is a non-floating element that is rendered inside a cell.
14+
* The rendering of the content part is synchronous to avoid flickering.
15+
*/
16+
export abstract class CellContentPart extends Disposable {
1217
protected currentCell: ICellViewModel | undefined;
1318
protected cellDisposables = new DisposableStore();
1419

1520
constructor() {
1621
super();
1722
}
1823

24+
/**
25+
* Prepare model for cell part rendering
26+
* No DOM operations recommended within this operation
27+
*/
28+
prepareRenderCell(element: ICellViewModel): void { }
29+
1930
/**
2031
* Update the DOM for the cell `element`
2132
*/
@@ -57,49 +68,149 @@ export abstract class CellPart extends Disposable {
5768
updateForExecutionState(element: ICellViewModel, e: ICellExecutionStateChangedEvent): void { }
5869
}
5970

60-
export class CellPartsCollection {
71+
/**
72+
* An overlay part renders on top of other components.
73+
* The rendering of the overlay part might be postponed to the next animation frame to avoid forced reflow.
74+
*/
75+
export abstract class CellOverlayPart extends Disposable {
76+
protected currentCell: ICellViewModel | undefined;
77+
protected readonly cellDisposables = this._register(new DisposableStore());
78+
79+
constructor() {
80+
super();
81+
}
82+
83+
/**
84+
* Prepare model for cell part rendering
85+
* No DOM operations recommended within this operation
86+
*/
87+
prepareRenderCell(element: ICellViewModel): void { }
88+
89+
/**
90+
* Update the DOM for the cell `element`
91+
*/
92+
renderCell(element: ICellViewModel): void {
93+
this.currentCell = element;
94+
this.didRenderCell(element);
95+
}
96+
97+
protected didRenderCell(element: ICellViewModel): void { }
98+
99+
/**
100+
* Dispose any disposables generated from `didRenderCell`
101+
*/
102+
unrenderCell(element: ICellViewModel): void {
103+
this.currentCell = undefined;
104+
this.cellDisposables.clear();
105+
}
106+
107+
/**
108+
* Update internal DOM (top positions) per cell layout info change
109+
* Note that a cell part doesn't need to call `DOM.scheduleNextFrame`,
110+
* the list view will ensure that layout call is invoked in the right frame
111+
*/
112+
updateInternalLayoutNow(element: ICellViewModel): void { }
113+
114+
/**
115+
* Update per cell state change
116+
*/
117+
updateState(element: ICellViewModel, e: CellViewModelStateChangeEvent): void { }
118+
119+
/**
120+
* Update per execution state change.
121+
*/
122+
updateForExecutionState(element: ICellViewModel, e: ICellExecutionStateChangedEvent): void { }
123+
}
124+
125+
export class CellPartsCollection extends Disposable {
126+
private _scheduledOverlayRendering = this._register(new MutableDisposable());
127+
private _scheduledOverlayUpdateState = this._register(new MutableDisposable());
128+
private _scheduledOverlayUpdateExecutionState = this._register(new MutableDisposable());
61129

62130
constructor(
63-
private readonly parts: readonly CellPart[],
64-
) { }
131+
private readonly contentParts: readonly CellContentPart[],
132+
private readonly overlayParts: readonly CellOverlayPart[]
133+
) {
134+
super();
135+
}
65136

66-
concat(other: readonly CellPart[]): CellPartsCollection {
67-
return new CellPartsCollection(this.parts.concat(other));
137+
concatContentPart(other: readonly CellContentPart[]): CellPartsCollection {
138+
return new CellPartsCollection(this.contentParts.concat(other), this.overlayParts);
68139
}
69140

70-
renderCell(element: ICellViewModel): void {
71-
for (const part of this.parts) {
141+
concatOverlayPart(other: readonly CellOverlayPart[]): CellPartsCollection {
142+
return new CellPartsCollection(this.contentParts, this.overlayParts.concat(other));
143+
}
144+
145+
scheduleRenderCell(element: ICellViewModel): void {
146+
// prepare model
147+
for (const part of this.contentParts) {
148+
part.prepareRenderCell(element);
149+
}
150+
151+
for (const part of this.overlayParts) {
152+
part.prepareRenderCell(element);
153+
}
154+
155+
// render content parts
156+
for (const part of this.contentParts) {
72157
part.renderCell(element);
73158
}
159+
160+
this._scheduledOverlayRendering.value = DOM.modify(() => {
161+
for (const part of this.overlayParts) {
162+
part.renderCell(element);
163+
}
164+
});
74165
}
75166

76167
unrenderCell(element: ICellViewModel): void {
77-
for (const part of this.parts) {
168+
for (const part of this.contentParts) {
169+
part.unrenderCell(element);
170+
}
171+
172+
this._scheduledOverlayRendering.value = undefined;
173+
this._scheduledOverlayUpdateState.value = undefined;
174+
this._scheduledOverlayUpdateExecutionState.value = undefined;
175+
176+
for (const part of this.overlayParts) {
78177
part.unrenderCell(element);
79178
}
80179
}
81180

82181
updateInternalLayoutNow(viewCell: ICellViewModel) {
83-
for (const part of this.parts) {
182+
for (const part of this.contentParts) {
84183
part.updateInternalLayoutNow(viewCell);
85184
}
86185
}
87186

88187
prepareLayout() {
89-
for (const part of this.parts) {
188+
for (const part of this.contentParts) {
90189
part.prepareLayout();
91190
}
92191
}
93192

94193
updateState(viewCell: ICellViewModel, e: CellViewModelStateChangeEvent) {
95-
for (const part of this.parts) {
194+
for (const part of this.contentParts) {
96195
part.updateState(viewCell, e);
97196
}
197+
198+
this._scheduledOverlayUpdateState.value = DOM.modify(() => {
199+
for (const part of this.overlayParts) {
200+
part.updateState(viewCell, e);
201+
}
202+
});
98203
}
99204

100205
updateForExecutionState(viewCell: ICellViewModel, e: ICellExecutionStateChangedEvent) {
101-
for (const part of this.parts) {
206+
for (const part of this.contentParts) {
102207
part.updateForExecutionState(viewCell, e);
103208
}
209+
210+
this._scheduledOverlayUpdateExecutionState.value = DOM.modify(() => {
211+
for (const part of this.overlayParts) {
212+
part.updateForExecutionState(viewCell, e);
213+
}
214+
});
104215
}
105216
}

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellComments.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
1414
import { ICommentService } from 'vs/workbench/contrib/comments/browser/commentService';
1515
import { CommentThreadWidget } from 'vs/workbench/contrib/comments/browser/commentThreadWidget';
1616
import { ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
17-
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
17+
import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
1818
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
1919
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
2020
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
2121

22-
export class CellComments extends CellPart {
22+
export class CellComments extends CellContentPart {
2323
private _initialized: boolean = false;
2424
private _commentThreadWidget: CommentThreadWidget<ICellRange> | null = null;
2525
private currentElement: CodeCellViewModel | undefined;

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
88
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
99
import { CellEditState, CellFocusMode, ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
1010
import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
11-
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
11+
import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
1212
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
1313
import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel';
1414
import { NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1515
import { NotebookCellExecutionStateContext, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_RESOURCE, NOTEBOOK_CELL_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
1616
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
1717

18-
export class CellContextKeyPart extends CellPart {
18+
export class CellContextKeyPart extends CellContentPart {
1919
private cellContextKeyManager: CellContextKeyManager;
2020

2121
constructor(

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDecorations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
import * as DOM from 'vs/base/browser/dom';
77
import { ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
8-
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
8+
import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
99

10-
export class CellDecorations extends CellPart {
10+
export class CellDecorations extends CellContentPart {
1111
constructor(
1212
readonly rootContainer: HTMLElement,
1313
readonly decorationContainer: HTMLElement,

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
99
import * as platform from 'vs/base/common/platform';
1010
import { expandCellRangesWithHiddenCells, ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
1111
import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
12-
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
12+
import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
1313
import { BaseCellRenderTemplate, INotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookRenderingCommon';
1414
import { cloneNotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
1515
import { CellEditType, ICellMoveEdit, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
@@ -30,7 +30,7 @@ interface CellDragEvent {
3030
dragPosRatio: number;
3131
}
3232

33-
export class CellDragAndDropPart extends CellPart {
33+
export class CellDragAndDropPart extends CellContentPart {
3434
constructor(
3535
private readonly container: HTMLElement
3636
) {

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellEditorOptions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ import { ActiveEditorContext } from 'vs/workbench/common/contextkeys';
1717
import { INotebookCellToolbarActionContext, INotebookCommandContext, NotebookMultiCellAction, NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
1818
import { IBaseCellEditorOptions, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
1919
import { NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
20-
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
20+
import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
2121
import { NotebookCellInternalMetadata, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon';
2222
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
2323
import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
2424

25-
export class CellEditorOptions extends CellPart {
25+
export class CellEditorOptions extends CellContentPart {
2626
private _lineNumbers: 'on' | 'off' | 'inherit' = 'inherit';
2727
private readonly _onDidChange = this._register(new Emitter<void>());
2828
readonly onDidChange: Event<void> = this._onDidChange.event;

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import { disposableTimeout } from 'vs/base/common/async';
88
import { DisposableStore } from 'vs/base/common/lifecycle';
99
import { ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
1010
import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
11-
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
11+
import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
1212
import { NotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1313
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
1414

1515
const UPDATE_EXECUTION_ORDER_GRACE_PERIOD = 200;
1616

17-
export class CellExecutionPart extends CellPart {
17+
export class CellExecutionPart extends CellContentPart {
1818
private kernelDisposables = this._register(new DisposableStore());
1919

2020
constructor(

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellFocus.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
import * as DOM from 'vs/base/browser/dom';
77
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
8-
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
8+
import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
99
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
1010

11-
export class CellFocusPart extends CellPart {
11+
export class CellFocusPart extends CellContentPart {
1212
constructor(
1313
containerElement: HTMLElement,
1414
focusSinkElement: HTMLElement | undefined,

0 commit comments

Comments
 (0)