Skip to content

Commit 28e972e

Browse files
Yoyokrazyrebornix
andauthored
initial stickyScroll support for notebooks (microsoft#188323)
* stickyscrool wip. dom node + filler static content * headers rendering. todo: too early, multiple headers * css file movement + outline rework * kernel css move * pop-in fixed // css cleaned // setting added * fix override * low hanging fixes * refactor to remove unnecessary layer * section transition logic cleanup + other misc fixes * whoops changed a little too much. todo: linesToRender thinking * finalized logic * nits * def false * Update zindex * Fix font size --------- Co-authored-by: Peng Lyu <[email protected]>
1 parent 2ba9f17 commit 28e972e

17 files changed

+839
-391
lines changed

build/lib/stylelint/vscode-known-variables.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@
755755
"--z-index-notebook-progress-bar",
756756
"--z-index-notebook-scrollbar",
757757
"--z-index-run-button-container",
758+
"--z-index-notebook-sticky-scroll",
758759
"--zoom-factor"
759760
]
760761
}

src/vs/workbench/contrib/interactive/browser/interactiveEditor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export class InteractiveEditor extends EditorPane {
159159
this._editorOptions = this._computeEditorOptions();
160160
}
161161
}));
162-
this._notebookOptions = new NotebookOptions(configurationService, notebookExecutionStateService, true, { cellToolbarInteraction: 'hover', globalToolbar: true, dragAndDropEnabled: false });
162+
this._notebookOptions = new NotebookOptions(configurationService, notebookExecutionStateService, true, { cellToolbarInteraction: 'hover', globalToolbar: true, stickyScroll: false, dragAndDropEnabled: false });
163163
this._editorMemento = this.getEditorMemento<InteractiveEditorViewState>(editorGroupService, textResourceConfigurationService, INTERACTIVE_EDITOR_VIEW_STATE_PREFERENCE_KEY);
164164

165165
codeEditorService.registerDecorationType('interactive-decoration', DECORATION_KEY, {});

src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts

Lines changed: 54 additions & 385 deletions
Large diffs are not rendered by default.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
.monaco-workbench .notebookOverlay .notebook-sticky-scroll-container {
7+
display: none;
8+
position: absolute;
9+
background-color: var(--vscode-notebook-editorBackground);
10+
border-bottom: solid 1px var(--vscode-notebook-cellToolbarSeparator);
11+
box-sizing: border-box;
12+
z-index: var(--z-index-notebook-sticky-scroll);
13+
width: 100%;
14+
padding-left: 12px;
15+
font-family: var(--notebook-cell-input-preview-font-family);
16+
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,12 @@ configurationRegistry.registerConfiguration({
862862
default: true,
863863
tags: ['notebookLayout']
864864
},
865+
[NotebookSetting.stickyScroll]: {
866+
description: nls.localize('notebook.stickyScroll.description', "Experimental. Control whether to render notebook Sticky Scroll headers in the notebook editor."),
867+
type: 'boolean',
868+
default: false,
869+
tags: ['notebookLayout']
870+
},
865871
[NotebookSetting.consolidatedOutputButton]: {
866872
description: nls.localize('notebook.consolidatedOutputButton.description', "Control whether outputs action should be rendered in the output toolbar."),
867873
type: 'boolean',

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import 'vs/css!./media/notebookToolbar';
1212
import 'vs/css!./media/notebookDnd';
1313
import 'vs/css!./media/notebookFolding';
1414
import 'vs/css!./media/notebookCellOutput';
15+
import 'vs/css!./media/notebookEditorStickyScroll';
16+
import 'vs/css!./media/notebookKernelActionViewItem';
17+
import 'vs/css!./media/notebookOutline';
18+
1519
import { PixelRatio } from 'vs/base/browser/browser';
1620
import * as DOM from 'vs/base/browser/dom';
1721
import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
@@ -90,8 +94,11 @@ import { INotebookLoggingService } from 'vs/workbench/contrib/notebook/common/no
9094
import { Schemas } from 'vs/base/common/network';
9195
import { DropIntoEditorController } from 'vs/editor/contrib/dropOrPasteInto/browser/dropIntoEditorController';
9296
import { CopyPasteController } from 'vs/editor/contrib/dropOrPasteInto/browser/copyPasteController';
97+
import { NotebookEditorStickyScroll } from 'vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll';
98+
import { NotebookCellOutlineProvider } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider';
9399
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution';
94100
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
101+
import { OutlineTarget } from 'vs/workbench/services/outline/browser/outline';
95102

96103
const $ = DOM.$;
97104

@@ -171,6 +178,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
171178
private _overlayContainer!: HTMLElement;
172179
private _notebookTopToolbarContainer!: HTMLElement;
173180
private _notebookTopToolbar!: NotebookEditorWorkbenchToolbar;
181+
private _notebookStickyScrollContainer!: HTMLElement;
174182
private _notebookOverviewRulerContainer!: HTMLElement;
175183
private _notebookOverviewRuler!: NotebookOverviewRuler;
176184
private _body!: HTMLElement;
@@ -261,6 +269,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
261269
public readonly scopedContextKeyService: IContextKeyService;
262270
private readonly instantiationService: IInstantiationService;
263271
private readonly _notebookOptions: NotebookOptions;
272+
public readonly _notebookOutline: NotebookCellOutlineProvider;
264273

265274
private _currentProgress: IProgressRunner | undefined;
266275

@@ -315,6 +324,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
315324

316325
this._register(this.instantiationService.createInstance(NotebookEditorContextKeys, this));
317326

327+
this._notebookOutline = this.instantiationService.createInstance(NotebookCellOutlineProvider, this, OutlineTarget.QuickPick);
328+
318329
this._register(notebookKernelService.onDidChangeSelectedNotebooks(e => {
319330
if (isEqual(e.notebook, this.viewModel?.uri)) {
320331
this._loadKernelPreloads();
@@ -565,6 +576,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
565576
this._notebookTopToolbarContainer.classList.add('notebook-toolbar-container');
566577
this._notebookTopToolbarContainer.style.display = 'none';
567578
DOM.append(parent, this._notebookTopToolbarContainer);
579+
580+
this._notebookStickyScrollContainer = document.createElement('div');
581+
this._notebookStickyScrollContainer.classList.add('notebook-sticky-scroll-container');
582+
DOM.append(parent, this._notebookStickyScrollContainer);
583+
568584
this._body = document.createElement('div');
569585
DOM.append(parent, this._body);
570586

@@ -999,6 +1015,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
9991015
}));
10001016

10011017
this._registerNotebookActionsToolbar();
1018+
this._registerNotebookStickyScroll();
10021019

10031020
this._register(this.configurationService.onDidChangeConfiguration(e => {
10041021
if (e.affectsConfiguration(AccessibilityVerbositySettingId.Notebook)) {
@@ -1028,6 +1045,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
10281045
}));
10291046
}
10301047

1048+
private _registerNotebookStickyScroll() {
1049+
this._register(this.instantiationService.createInstance(NotebookEditorStickyScroll, this._notebookStickyScrollContainer, this, this._notebookOutline, this._list));
1050+
}
1051+
10311052
private _updateOutputRenderers() {
10321053
if (!this.viewModel || !this._webview) {
10331054
return;
@@ -3089,6 +3110,7 @@ registerZIndex(ZIndex.Base, 28, 'notebook-cell-bottom-toolbar-container');
30893110
registerZIndex(ZIndex.Base, 29, 'notebook-run-button-container');
30903111
registerZIndex(ZIndex.Base, 29, 'notebook-input-collapse-condicon');
30913112
registerZIndex(ZIndex.Base, 30, 'notebook-cell-output-toolbar');
3113+
registerZIndex(ZIndex.Base, 31, 'notebook-sticky-scroll');
30923114
registerZIndex(ZIndex.Sash, 1, 'notebook-cell-expand-part-button');
30933115
registerZIndex(ZIndex.Sash, 2, 'notebook-cell-toolbar');
30943116
registerZIndex(ZIndex.Sash, 3, 'notebook-cell-toolbar-dropdown-active');

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export interface NotebookLayoutConfiguration {
6161
insertToolbarPosition: 'betweenCells' | 'notebookToolbar' | 'both' | 'hidden';
6262
insertToolbarAlignment: 'left' | 'center';
6363
globalToolbar: boolean;
64+
stickyScroll: boolean;
6465
consolidatedOutputButton: boolean;
6566
consolidatedRunButton: boolean;
6667
showFoldingControls: 'always' | 'never' | 'mouseover';
@@ -89,6 +90,7 @@ export interface NotebookOptionsChangeEvent {
8990
readonly insertToolbarPosition?: boolean;
9091
readonly insertToolbarAlignment?: boolean;
9192
readonly globalToolbar?: boolean;
93+
readonly stickyScroll?: boolean;
9294
readonly showFoldingControls?: boolean;
9395
readonly consolidatedOutputButton?: boolean;
9496
readonly consolidatedRunButton?: boolean;
@@ -134,11 +136,12 @@ export class NotebookOptions extends Disposable {
134136
private readonly configurationService: IConfigurationService,
135137
private readonly notebookExecutionStateService: INotebookExecutionStateService,
136138
private isReadonly: boolean,
137-
private readonly overrides?: { cellToolbarInteraction: string; globalToolbar: boolean; dragAndDropEnabled: boolean }
139+
private readonly overrides?: { cellToolbarInteraction: string; globalToolbar: boolean; stickyScroll: boolean; dragAndDropEnabled: boolean }
138140
) {
139141
super();
140142
const showCellStatusBar = this.configurationService.getValue<ShowCellStatusBarType>(NotebookSetting.showCellStatusBar);
141143
const globalToolbar = overrides?.globalToolbar ?? this.configurationService.getValue<boolean | undefined>(NotebookSetting.globalToolbar) ?? true;
144+
const stickyScroll = overrides?.stickyScroll ?? this.configurationService.getValue<boolean | undefined>(NotebookSetting.stickyScroll) ?? false;
142145
const consolidatedOutputButton = this.configurationService.getValue<boolean | undefined>(NotebookSetting.consolidatedOutputButton) ?? true;
143146
const consolidatedRunButton = this.configurationService.getValue<boolean | undefined>(NotebookSetting.consolidatedRunButton) ?? false;
144147
const dragAndDropEnabled = overrides?.dragAndDropEnabled ?? this.configurationService.getValue<boolean | undefined>(NotebookSetting.dragAndDropEnabled) ?? true;
@@ -213,6 +216,7 @@ export class NotebookOptions extends Disposable {
213216
collapsedIndicatorHeight: 28,
214217
showCellStatusBar,
215218
globalToolbar,
219+
stickyScroll,
216220
consolidatedOutputButton,
217221
consolidatedRunButton,
218222
dragAndDropEnabled,
@@ -335,6 +339,7 @@ export class NotebookOptions extends Disposable {
335339
const insertToolbarPosition = e.affectsConfiguration(NotebookSetting.insertToolbarLocation);
336340
const insertToolbarAlignment = e.affectsConfiguration(NotebookSetting.experimentalInsertToolbarAlignment);
337341
const globalToolbar = e.affectsConfiguration(NotebookSetting.globalToolbar);
342+
const stickyScroll = e.affectsConfiguration(NotebookSetting.stickyScroll);
338343
const consolidatedOutputButton = e.affectsConfiguration(NotebookSetting.consolidatedOutputButton);
339344
const consolidatedRunButton = e.affectsConfiguration(NotebookSetting.consolidatedRunButton);
340345
const showFoldingControls = e.affectsConfiguration(NotebookSetting.showFoldingControls);
@@ -359,6 +364,7 @@ export class NotebookOptions extends Disposable {
359364
&& !insertToolbarPosition
360365
&& !insertToolbarAlignment
361366
&& !globalToolbar
367+
&& !stickyScroll
362368
&& !consolidatedOutputButton
363369
&& !consolidatedRunButton
364370
&& !showFoldingControls
@@ -414,6 +420,10 @@ export class NotebookOptions extends Disposable {
414420
configuration.globalToolbar = this.configurationService.getValue<boolean>(NotebookSetting.globalToolbar) ?? true;
415421
}
416422

423+
if (stickyScroll && this.overrides?.stickyScroll === undefined) {
424+
configuration.stickyScroll = this.configurationService.getValue<boolean>(NotebookSetting.stickyScroll) ?? false;
425+
}
426+
417427
if (consolidatedOutputButton) {
418428
configuration.consolidatedOutputButton = this.configurationService.getValue<boolean>(NotebookSetting.consolidatedOutputButton) ?? true;
419429
}
@@ -479,6 +489,7 @@ export class NotebookOptions extends Disposable {
479489
insertToolbarPosition,
480490
insertToolbarAlignment,
481491
globalToolbar,
492+
stickyScroll,
482493
showFoldingControls,
483494
consolidatedOutputButton,
484495
consolidatedRunButton,

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,26 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
686686
this.setSelection(indices);
687687
}
688688

689+
getCellViewScrollTop(cell: ICellViewModel) {
690+
const index = this._getViewIndexUpperBound(cell);
691+
if (index === undefined || index < 0 || index >= this.length) {
692+
throw new ListError(this.listUser, `Invalid index ${index}`);
693+
}
694+
695+
return this.view.elementTop(index);
696+
}
697+
698+
getCellViewScrollBottom(cell: ICellViewModel) {
699+
const index = this._getViewIndexUpperBound(cell);
700+
if (index === undefined || index < 0 || index >= this.length) {
701+
throw new ListError(this.listUser, `Invalid index ${index}`);
702+
}
703+
704+
const top = this.view.elementTop(index);
705+
const height = this.view.elementHeight(index);
706+
return top + height;
707+
}
708+
689709
override setFocus(indexes: number[], browserEvent?: UIEvent, ignoreTextModelUpdate?: boolean): void {
690710
if (ignoreTextModelUpdate) {
691711
super.setFocus(indexes, browserEvent);

0 commit comments

Comments
 (0)