notebookEditor.ts 36.9 KB
Newer Older
P
Peng Lyu 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

B
Benjamin Pasero 已提交
6
import 'vs/css!./media/notebook';
R
rebornix 已提交
7
import { getZoomLevel } from 'vs/base/browser/browser';
P
Peng Lyu 已提交
8
import * as DOM from 'vs/base/browser/dom';
R
rebornix 已提交
9
import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
10 11 12
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Color, RGBA } from 'vs/base/common/color';
import { Emitter, Event } from 'vs/base/common/event';
R
rebornix 已提交
13
import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
14
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
15
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
R
rebornix 已提交
16
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
17 18 19
import { Range } from 'vs/editor/common/core/range';
import { ICompositeCodeEditor, IEditor } from 'vs/editor/common/editorCommon';
import * as nls from 'vs/nls';
20
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
R
Rob Lourens 已提交
21
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
22
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
R
rebornix 已提交
23 24 25
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
26
import { contrastBorder, editorBackground, focusBorder, foreground, registerColor, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground, textPreformatForeground } from 'vs/platform/theme/common/colorRegistry';
R
rebornix 已提交
27 28
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
29 30
import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
import { EditorOptions, IEditorCloseEvent, IEditorMemento } from 'vs/workbench/common/editor';
31
import { CELL_MARGIN, CELL_RUN_GUTTER, EDITOR_TOP_MARGIN, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
R
rebornix 已提交
32
import { FoldingController } from 'vs/workbench/contrib/notebook/browser/contrib/fold/folding';
33
import { NotebookFindWidget } from 'vs/workbench/contrib/notebook/browser/contrib/notebookFindWidget';
R
rebornix 已提交
34
import { CellEditState, CellFocusMode, ICellRange, ICellViewModel, INotebookCellList, INotebookEditor, INotebookEditorMouseEvent, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
R
rebornix 已提交
35
import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
R
rebornix 已提交
36
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
37
import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList';
R
rebornix 已提交
38 39
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
R
Rob Lourens 已提交
40
import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate, CellDragAndDropController } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
R
rebornix 已提交
41
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
R
rebornix 已提交
42
import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
43 44
import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind, CellUri, IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
R
rebornix 已提交
45
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
46 47
import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
P
Peng Lyu 已提交
48 49

const $ = DOM.$;
R
rebornix 已提交
50 51
const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState';

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
export class NotebookEditorOptions extends EditorOptions {

	readonly cellOptions?: IResourceEditorInput;

	constructor(options: Partial<NotebookEditorOptions>) {
		super();
		this.overwrite(options);
		this.cellOptions = options.cellOptions;
	}

	with(options: Partial<NotebookEditorOptions>): NotebookEditorOptions {
		return new NotebookEditorOptions({ ...this, ...options });
	}
}

R
rebornix 已提交
67
export class NotebookCodeEditors implements ICompositeCodeEditor {
68

69
	private readonly _disposables = new DisposableStore();
70 71 72 73
	private readonly _onDidChangeActiveEditor = new Emitter<this>();
	readonly onDidChangeActiveEditor: Event<this> = this._onDidChangeActiveEditor.event;

	constructor(
R
rebornix 已提交
74
		private _list: INotebookCellList,
R
rebornix 已提交
75
		private _renderedEditors: Map<ICellViewModel, ICodeEditor | undefined>
76
	) {
77
		_list.onDidChangeFocus(_e => this._onDidChangeActiveEditor.fire(this), undefined, this._disposables);
78 79 80 81 82 83
	}

	dispose(): void {
		this._onDidChangeActiveEditor.dispose();
		this._disposables.dispose();
	}
84 85 86

	get activeCodeEditor(): IEditor | undefined {
		const [focused] = this._list.getFocusedElements();
R
rebornix 已提交
87
		return this._renderedEditors.get(focused);
88 89 90
	}
}

R
rebornix 已提交
91
export class NotebookEditor extends BaseEditor implements INotebookEditor {
P
Peng Lyu 已提交
92 93 94
	static readonly ID: string = 'workbench.editor.notebook';
	private rootElement!: HTMLElement;
	private body!: HTMLElement;
P
Peng Lyu 已提交
95
	private webview: BackLayerWebView | null = null;
R
rebornix 已提交
96
	private webviewTransparentCover: HTMLElement | null = null;
R
rebornix 已提交
97
	private list: INotebookCellList | undefined;
98
	private control: ICompositeCodeEditor | undefined;
R
rebornix 已提交
99
	private renderedEditors: Map<ICellViewModel, ICodeEditor | undefined> = new Map();
R
rebornix 已提交
100
	private eventDispatcher: NotebookEventDispatcher | undefined;
R
rebornix 已提交
101
	private notebookViewModel: NotebookViewModel | undefined;
102
	private localStore: DisposableStore = this._register(new DisposableStore());
R
rebornix 已提交
103
	private editorMemento: IEditorMemento<INotebookEditorViewState>;
R
rebornix 已提交
104
	private readonly groupListener = this._register(new MutableDisposable());
105
	private fontInfo: BareFontInfo | undefined;
106
	private dimension: DOM.Dimension | null = null;
R
rebornix 已提交
107
	private editorFocus: IContextKey<boolean> | null = null;
R
rebornix 已提交
108
	private editorEditable: IContextKey<boolean> | null = null;
109
	private editorExecutingNotebook: IContextKey<boolean> | null = null;
R
rebornix 已提交
110
	private outputRenderer: OutputRenderer;
R
rebornix 已提交
111
	private findWidget: NotebookFindWidget;
P
Peng Lyu 已提交
112 113 114 115 116

	constructor(
		@ITelemetryService telemetryService: ITelemetryService,
		@IThemeService themeService: IThemeService,
		@IInstantiationService private readonly instantiationService: IInstantiationService,
P
Peng Lyu 已提交
117
		@IStorageService storageService: IStorageService,
R
rebornix 已提交
118
		@INotebookService private notebookService: INotebookService,
119
		@IEditorGroupsService editorGroupService: IEditorGroupsService,
R
rebornix 已提交
120
		@IConfigurationService private readonly configurationService: IConfigurationService,
R
rebornix 已提交
121
		@IContextKeyService private readonly contextKeyService: IContextKeyService,
122
		// @IEditorProgressService private readonly progressService: IEditorProgressService,
P
Peng Lyu 已提交
123 124
	) {
		super(NotebookEditor.ID, telemetryService, themeService, storageService);
R
rebornix 已提交
125 126

		this.editorMemento = this.getEditorMemento<INotebookEditorViewState>(editorGroupService, NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY);
R
rebornix 已提交
127
		this.outputRenderer = new OutputRenderer(this, this.instantiationService);
R
rebornix 已提交
128
		this.findWidget = this.instantiationService.createInstance(NotebookFindWidget, this);
129
		this.findWidget.updateTheme(this.themeService.getColorTheme());
R
rebornix 已提交
130 131
	}

R
rebornix 已提交
132 133 134 135
	get viewModel() {
		return this.notebookViewModel;
	}

P
Peng Lyu 已提交
136 137 138 139 140 141 142 143
	get minimumWidth(): number { return 375; }
	get maximumWidth(): number { return Number.POSITIVE_INFINITY; }

	// these setters need to exist because this extends from BaseEditor
	set minimumWidth(value: number) { /*noop*/ }
	set maximumWidth(value: number) { /*noop*/ }


R
rebornix 已提交
144
	//#region Editor Core
R
rebornix 已提交
145

R
rebornix 已提交
146 147 148 149 150

	public get isNotebookEditor() {
		return true;
	}

P
Peng Lyu 已提交
151 152 153
	protected createEditor(parent: HTMLElement): void {
		this.rootElement = DOM.append(parent, $('.notebook-editor'));
		this.createBody(this.rootElement);
154
		this.generateFontInfo();
R
rebornix 已提交
155
		this.editorFocus = NOTEBOOK_EDITOR_FOCUSED.bindTo(this.contextKeyService);
156
		this.editorFocus.set(true);
R
rebornix 已提交
157 158 159 160 161 162 163
		this._register(this.onDidFocus(() => {
			this.editorFocus?.set(true);
		}));

		this._register(this.onDidBlur(() => {
			this.editorFocus?.set(false);
		}));
R
rebornix 已提交
164 165 166

		this.editorEditable = NOTEBOOK_EDITOR_EDITABLE.bindTo(this.contextKeyService);
		this.editorEditable.set(true);
167
		this.editorExecutingNotebook = NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK.bindTo(this.contextKeyService);
168 169 170 171 172
	}

	private generateFontInfo(): void {
		const editorOptions = this.configurationService.getValue<IEditorOptions>('editor');
		this.fontInfo = BareFontInfo.createFromRawSettings(editorOptions, getZoomLevel());
P
Peng Lyu 已提交
173 174 175
	}

	private createBody(parent: HTMLElement): void {
P
Peng Lyu 已提交
176
		this.body = document.createElement('div');
P
Peng Lyu 已提交
177 178 179
		DOM.addClass(this.body, 'cell-list-container');
		this.createCellList();
		DOM.append(parent, this.body);
R
rebornix 已提交
180
		DOM.append(parent, this.findWidget.getDomNode());
P
Peng Lyu 已提交
181 182
	}

P
Peng Lyu 已提交
183 184
	private createCellList(): void {
		DOM.addClass(this.body, 'cell-list-container');
P
Peng Lyu 已提交
185

R
Rob Lourens 已提交
186
		const dndController = new CellDragAndDropController(this);
P
Peng Lyu 已提交
187
		const renders = [
R
Rob Lourens 已提交
188 189
			this.instantiationService.createInstance(CodeCellRenderer, this, this.contextKeyService, this.renderedEditors, dndController),
			this.instantiationService.createInstance(MarkdownCellRenderer, this.contextKeyService, this, dndController),
P
Peng Lyu 已提交
190 191
		];

J
João Moreno 已提交
192
		this.list = this.instantiationService.createInstance(
R
rebornix 已提交
193
			NotebookCellList,
P
Peng Lyu 已提交
194 195 196 197
			'NotebookCellList',
			this.body,
			this.instantiationService.createInstance(NotebookCellListDelegate),
			renders,
R
rebornix 已提交
198
			this.contextKeyService,
P
Peng Lyu 已提交
199 200
			{
				setRowLineHeight: false,
R
rebornix 已提交
201
				setRowHeight: false,
P
Peng Lyu 已提交
202 203 204
				supportDynamicHeights: true,
				horizontalScrolling: false,
				keyboardSupport: false,
R
rebornix 已提交
205
				mouseSupport: true,
P
Peng Lyu 已提交
206
				multipleSelectionSupport: false,
R
rebornix 已提交
207
				enableKeyboardNavigation: true,
208
				additionalScrollHeight: 0,
209
				styleController: (_suffix: string) => { return this.list!; },
P
Peng Lyu 已提交
210 211 212 213 214 215 216 217 218 219
				overrideStyles: {
					listBackground: editorBackground,
					listActiveSelectionBackground: editorBackground,
					listActiveSelectionForeground: foreground,
					listFocusAndSelectionBackground: editorBackground,
					listFocusAndSelectionForeground: foreground,
					listFocusBackground: editorBackground,
					listFocusForeground: foreground,
					listHoverForeground: foreground,
					listHoverBackground: editorBackground,
220 221
					listHoverOutline: focusBorder,
					listFocusOutline: focusBorder,
222 223 224 225
					listInactiveSelectionBackground: editorBackground,
					listInactiveSelectionForeground: foreground,
					listInactiveFocusBackground: editorBackground,
					listInactiveFocusOutline: editorBackground,
J
João Moreno 已提交
226 227 228
				},
				accessibilityProvider: {
					getAriaLabel() { return null; }
P
Peng Lyu 已提交
229
				}
R
rebornix 已提交
230
			},
P
Peng Lyu 已提交
231
		);
P
Peng Lyu 已提交
232

233
		this.control = new NotebookCodeEditors(this.list, this.renderedEditors);
234
		this.webview = this.instantiationService.createInstance(BackLayerWebView, this);
235 236 237 238 239
		this._register(this.webview.onMessage(message => {
			if (this.viewModel) {
				this.notebookService.onDidReceiveMessage(this.viewModel.viewType, this.viewModel.uri, message);
			}
		}));
R
rebornix 已提交
240
		this.list.rowsContainer.appendChild(this.webview.element);
R
rebornix 已提交
241

P
Peng Lyu 已提交
242
		this._register(this.list);
R
rebornix 已提交
243 244 245

		// transparent cover
		this.webviewTransparentCover = DOM.append(this.list.rowsContainer, $('.webview-cover'));
246
		this.webviewTransparentCover.style.display = 'none';
R
rebornix 已提交
247 248 249 250 251 252 253 254 255 256

		this._register(DOM.addStandardDisposableGenericMouseDownListner(this.rootElement, (e: StandardMouseEvent) => {
			if (DOM.hasClass(e.target, 'slider') && this.webviewTransparentCover) {
				this.webviewTransparentCover.style.display = 'block';
			}
		}));

		this._register(DOM.addStandardDisposableGenericMouseUpListner(this.rootElement, (e: StandardMouseEvent) => {
			if (this.webviewTransparentCover) {
				// no matter when
257
				this.webviewTransparentCover.style.display = 'none';
R
rebornix 已提交
258 259 260
			}
		}));

R
rebornix 已提交
261 262 263 264 265 266 267 268 269 270 271 272
		this._register(this.list.onMouseDown(e => {
			if (e.element) {
				this._onMouseDown.fire({ event: e.browserEvent, target: e.element });
			}
		}));

		this._register(this.list.onMouseUp(e => {
			if (e.element) {
				this._onMouseUp.fire({ event: e.browserEvent, target: e.element });
			}
		}));

P
Peng Lyu 已提交
273 274
	}

275 276 277 278
	getControl() {
		return this.control;
	}

R
rebornix 已提交
279 280 281 282
	getInnerWebview(): Webview | undefined {
		return this.webview?.webview;
	}

283 284 285 286 287
	onWillHide() {
		if (this.input && this.input instanceof NotebookEditorInput && !this.input.isDisposed()) {
			this.saveTextEditorViewState(this.input);
		}

R
rebornix 已提交
288
		this.editorFocus?.set(false);
289 290
		if (this.webview) {
			this.localStore.clear();
R
rebornix 已提交
291
			this.list?.rowsContainer.removeChild(this.webview?.element);
292 293 294 295
			this.webview?.dispose();
			this.webview = null;
		}

R
rebornix 已提交
296
		this.list?.clear();
297
		super.onHide();
P
Peng Lyu 已提交
298 299
	}

R
rebornix 已提交
300 301 302 303 304 305 306 307 308 309 310 311 312
	setEditorVisible(visible: boolean, group: IEditorGroup | undefined): void {
		super.setEditorVisible(visible, group);
		this.groupListener.value = ((group as IEditorGroupView).onWillCloseEditor(e => this.onWillCloseEditorInGroup(e)));
	}

	private onWillCloseEditorInGroup(e: IEditorCloseEvent): void {
		const editor = e.editor;
		if (!(editor instanceof NotebookEditorInput)) {
			return; // only handle files
		}

		if (editor === this.input) {
			this.saveTextEditorViewState(editor);
313 314 315
		}
	}

R
rebornix 已提交
316 317 318
	focus() {
		super.focus();
		this.editorFocus?.set(true);
319
		this.list?.domFocus();
R
rebornix 已提交
320 321
	}

R
rebornix 已提交
322
	async setInput(input: NotebookEditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
R
rebornix 已提交
323 324 325 326
		if (this.input instanceof NotebookEditorInput) {
			this.saveTextEditorViewState(this.input);
		}

R
rebornix 已提交
327 328
		await super.setInput(input, options, token);
		const model = await input.resolve();
P
Peng Lyu 已提交
329

330 331 332
		if (this.notebookViewModel === undefined || !this.notebookViewModel.equal(model) || this.webview === null) {
			this.detachModel();
			await this.attachModel(input, model);
R
rebornix 已提交
333
		}
P
Peng Lyu 已提交
334

335 336 337
		// reveal cell if editor options tell to do so
		if (options instanceof NotebookEditorOptions && options.cellOptions) {
			const cellOptions = options.cellOptions;
R
rebornix 已提交
338
			const cell = this.notebookViewModel!.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString());
339
			if (cell) {
340
				this.selectElement(cell);
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
				this.revealInCenterIfOutsideViewport(cell);
				const editor = this.renderedEditors.get(cell)!;
				if (editor) {
					if (cellOptions.options?.selection) {
						const { selection } = cellOptions.options;
						editor.setSelection({
							...selection,
							endLineNumber: selection.endLineNumber || selection.startLineNumber,
							endColumn: selection.endColumn || selection.startColumn
						});
					}
					if (!cellOptions.options?.preserveFocus) {
						editor.focus();
					}
				}
356 357
			}
		}
R
rebornix 已提交
358
	}
359

R
rebornix 已提交
360 361 362 363
	clearInput(): void {
		super.clearInput();
	}

R
rebornix 已提交
364 365
	private detachModel() {
		this.localStore.clear();
R
rebornix 已提交
366
		this.list?.detachViewModel();
R
rebornix 已提交
367 368 369 370
		this.notebookViewModel?.dispose();
		this.notebookViewModel = undefined;
		this.webview?.clearInsets();
		this.webview?.clearPreloadsCache();
371
		this.findWidget.clear();
R
rebornix 已提交
372
		this.list?.clear();
R
rebornix 已提交
373
	}
R
rebornix 已提交
374

R
rebornix 已提交
375 376
	private async attachModel(input: NotebookEditorInput, model: NotebookEditorModel) {
		if (!this.webview) {
377
			this.webview = this.instantiationService.createInstance(BackLayerWebView, this);
R
rebornix 已提交
378 379
			this.list?.rowsContainer.insertAdjacentElement('afterbegin', this.webview!.element);
		}
380

381 382
		await this.webview.waitForInitialization();

R
rebornix 已提交
383
		this.eventDispatcher = new NotebookEventDispatcher();
384
		this.notebookViewModel = this.instantiationService.createInstance(NotebookViewModel, input.viewType!, model, this.eventDispatcher, this.getLayoutInfo());
385
		this.editorEditable?.set(!!this.notebookViewModel.metadata?.editable);
R
rebornix 已提交
386
		this.eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
R
rebornix 已提交
387
		const viewState = this.loadTextEditorViewState(input);
R
rebornix 已提交
388
		this.notebookViewModel.restoreEditorViewState(viewState);
389

R
rebornix 已提交
390 391 392 393
		this.localStore.add(this.eventDispatcher.onDidChangeMetadata((e) => {
			this.editorEditable?.set(e.source.editable);
		}));

394 395
		this.localStore.add(this.instantiationService.createInstance(FoldingController, this));

R
rebornix 已提交
396 397 398 399
		this.webview?.updateRendererPreloads(this.notebookViewModel.renderers);

		this.localStore.add(this.list!.onWillScroll(e => {
			this.webview!.updateViewScrollTop(-e.scrollTop, []);
R
rebornix 已提交
400
			this.webviewTransparentCover!.style.top = `${e.scrollTop}px`;
R
rebornix 已提交
401 402 403 404 405 406
		}));

		this.localStore.add(this.list!.onDidChangeContentHeight(() => {
			const scrollTop = this.list?.scrollTop || 0;
			const scrollHeight = this.list?.scrollHeight || 0;
			this.webview!.element.style.height = `${scrollHeight}px`;
R
rebornix 已提交
407
			let updateItems: { cell: CodeCellViewModel, output: IOutput, cellTop: number }[] = [];
R
rebornix 已提交
408 409 410

			if (this.webview?.insetMapping) {
				this.webview?.insetMapping.forEach((value, key) => {
R
rebornix 已提交
411 412
					const cell = value.cell;
					const cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0;
R
rebornix 已提交
413 414 415 416 417 418
					if (this.webview!.shouldUpdateInset(cell, key, cellTop)) {
						updateItems.push({
							cell: cell,
							output: key,
							cellTop: cellTop
						});
R
rebornix 已提交
419
					}
R
rebornix 已提交
420
				});
421

R
rebornix 已提交
422 423 424 425 426 427
				if (updateItems.length) {
					this.webview?.updateViewScrollTop(-scrollTop, updateItems);
				}
			}
		}));

R
rebornix 已提交
428 429 430 431 432 433
		this.list!.attachViewModel(this.notebookViewModel);
		this.localStore.add(this.list!.onDidRemoveOutput(output => {
			this.removeInset(output);
		}));

		this.list!.layout();
R
rebornix 已提交
434

435 436 437 438
		this.restoreTextEditorViewState(viewState);
	}

	private restoreTextEditorViewState(viewState: INotebookEditorViewState | undefined): void {
R
rebornix 已提交
439 440 441 442 443 444 445
		if (viewState?.scrollPosition !== undefined) {
			this.list!.scrollTop = viewState!.scrollPosition.top;
			this.list!.scrollLeft = viewState!.scrollPosition.left;
		} else {
			this.list!.scrollTop = 0;
			this.list!.scrollLeft = 0;
		}
446

447 448 449 450 451 452 453 454 455 456
		const focusIdx = typeof viewState?.focus === 'number' ? viewState.focus : 0;
		this.list!.setFocus([focusIdx]);
		this.list!.setSelection([focusIdx]);

		if (viewState?.editorFocused) {
			this.list?.focusView();
			const cell = this.notebookViewModel?.viewCells[focusIdx];
			if (cell) {
				cell.focusMode = CellFocusMode.Editor;
			}
457
		}
P
Peng Lyu 已提交
458 459
	}

R
rebornix 已提交
460
	private saveTextEditorViewState(input: NotebookEditorInput): void {
R
npe  
rebornix 已提交
461
		if (this.group && this.notebookViewModel) {
R
rebornix 已提交
462
			const state = this.notebookViewModel.saveEditorViewState();
R
rebornix 已提交
463 464
			if (this.list) {
				state.scrollPosition = { left: this.list.scrollLeft, top: this.list.scrollTop };
465
				let cellHeights: { [key: number]: number } = {};
R
rebornix 已提交
466
				for (let i = 0; i < this.viewModel!.length; i++) {
R
rebornix 已提交
467
					const elm = this.viewModel!.viewCells[i] as CellViewModel;
468 469 470 471 472 473 474 475
					if (elm.cellKind === CellKind.Code) {
						cellHeights[i] = elm.layoutInfo.totalHeight;
					} else {
						cellHeights[i] = 0;
					}
				}

				state.cellTotalHeights = cellHeights;
476 477 478

				const focus = this.list.getFocus()[0];
				if (focus) {
479 480 481 482 483 484 485 486
					const element = this.notebookViewModel!.viewCells[focus];
					const itemDOM = this.list?.domElementOfElement(element!);
					let editorFocused = false;
					if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) {
						editorFocused = true;
					}

					state.editorFocused = editorFocused;
487 488
					state.focus = focus;
				}
R
rebornix 已提交
489 490
			}

R
rebornix 已提交
491
			this.editorMemento.saveEditorState(this.group, input.resource, state);
R
rebornix 已提交
492 493 494 495 496
		}
	}

	private loadTextEditorViewState(input: NotebookEditorInput): INotebookEditorViewState | undefined {
		if (this.group) {
R
rebornix 已提交
497
			return this.editorMemento.loadEditorState(this.group, input.resource);
R
rebornix 已提交
498 499 500 501 502 503 504 505 506 507
		}

		return;
	}

	layout(dimension: DOM.Dimension): void {
		this.dimension = new DOM.Dimension(dimension.width, dimension.height);
		DOM.toggleClass(this.rootElement, 'mid-width', dimension.width < 1000 && dimension.width >= 600);
		DOM.toggleClass(this.rootElement, 'narrow-width', dimension.width < 600);
		DOM.size(this.body, dimension.width, dimension.height);
508
		this.list?.updateOptions({ additionalScrollHeight: dimension.height });
R
rebornix 已提交
509
		this.list?.layout(dimension.height, dimension.width);
R
rebornix 已提交
510 511 512 513 514 515

		if (this.webviewTransparentCover) {
			this.webviewTransparentCover.style.height = `${dimension.height}px`;
			this.webviewTransparentCover.style.width = `${dimension.width}px`;
		}

R
rebornix 已提交
516
		this.eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
R
rebornix 已提交
517 518 519 520 521 522 523 524 525 526 527 528
	}

	protected saveState(): void {
		if (this.input instanceof NotebookEditorInput) {
			this.saveTextEditorViewState(this.input);
		}

		super.saveState();
	}

	//#endregion

R
rebornix 已提交
529 530
	//#region Editor Features

R
rebornix 已提交
531
	selectElement(cell: ICellViewModel) {
R
rebornix 已提交
532
		this.list?.selectElement(cell);
R
rebornix 已提交
533 534
	}

R
rebornix 已提交
535
	revealInView(cell: ICellViewModel) {
R
rebornix 已提交
536
		this.list?.revealElementInView(cell);
R
rebornix 已提交
537 538
	}

R
rebornix 已提交
539
	revealInCenterIfOutsideViewport(cell: ICellViewModel) {
R
rebornix 已提交
540
		this.list?.revealElementInCenterIfOutsideViewport(cell);
R
rebornix 已提交
541 542
	}

R
rebornix 已提交
543
	revealInCenter(cell: ICellViewModel) {
R
rebornix 已提交
544
		this.list?.revealElementInCenter(cell);
R
rebornix 已提交
545 546
	}

R
rebornix 已提交
547
	revealLineInView(cell: ICellViewModel, line: number): void {
R
rebornix 已提交
548
		this.list?.revealElementLineInView(cell, line);
R
rebornix 已提交
549
	}
R
rebornix 已提交
550

R
rebornix 已提交
551
	revealLineInCenter(cell: ICellViewModel, line: number) {
R
rebornix 已提交
552
		this.list?.revealElementLineInCenter(cell, line);
R
rebornix 已提交
553 554
	}

R
rebornix 已提交
555
	revealLineInCenterIfOutsideViewport(cell: ICellViewModel, line: number) {
R
rebornix 已提交
556
		this.list?.revealElementLineInCenterIfOutsideViewport(cell, line);
R
rebornix 已提交
557 558
	}

R
rebornix 已提交
559
	revealRangeInView(cell: ICellViewModel, range: Range): void {
R
rebornix 已提交
560
		this.list?.revealElementRangeInView(cell, range);
R
rebornix 已提交
561 562
	}

R
rebornix 已提交
563
	revealRangeInCenter(cell: ICellViewModel, range: Range): void {
R
rebornix 已提交
564
		this.list?.revealElementRangeInCenter(cell, range);
R
rebornix 已提交
565 566
	}

R
rebornix 已提交
567
	revealRangeInCenterIfOutsideViewport(cell: ICellViewModel, range: Range): void {
R
rebornix 已提交
568
		this.list?.revealElementRangeInCenterIfOutsideViewport(cell, range);
R
rebornix 已提交
569 570
	}

R
rebornix 已提交
571
	setCellSelection(cell: ICellViewModel, range: Range): void {
R
rebornix 已提交
572
		this.list?.setCellSelection(cell, range);
R
rebornix 已提交
573 574
	}

R
rebornix 已提交
575 576 577 578
	changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any {
		return this.notebookViewModel?.changeDecorations(callback);
	}

R
rebornix 已提交
579 580 581 582
	setHiddenAreas(_ranges: ICellRange[]): boolean {
		return this.list!.setHiddenAreas(_ranges);
	}

R
rebornix 已提交
583 584
	//#endregion

R
rebornix 已提交
585 586 587 588 589 590 591 592
	//#region Find Delegate

	public showFind() {
		this.findWidget.reveal();
	}

	public hideFind() {
		this.findWidget.hide();
R
rebornix 已提交
593
		this.focus();
R
rebornix 已提交
594 595 596 597
	}

	//#endregion

R
rebornix 已提交
598 599 600 601 602 603 604 605 606
	//#region Mouse Events
	private readonly _onMouseUp: Emitter<INotebookEditorMouseEvent> = this._register(new Emitter<INotebookEditorMouseEvent>());
	public readonly onMouseUp: Event<INotebookEditorMouseEvent> = this._onMouseUp.event;

	private readonly _onMouseDown: Emitter<INotebookEditorMouseEvent> = this._register(new Emitter<INotebookEditorMouseEvent>());
	public readonly onMouseDown: Event<INotebookEditorMouseEvent> = this._onMouseDown.event;

	//#endregion

R
rebornix 已提交
607
	//#region Cell operations
608
	async layoutNotebookCell(cell: ICellViewModel, height: number): Promise<void> {
R
rebornix 已提交
609
		let relayout = (cell: ICellViewModel, height: number) => {
R
rebornix 已提交
610
			this.list?.updateElementHeight2(cell, height);
R
rebornix 已提交
611 612
		};

613
		let r: () => void;
R
rebornix 已提交
614
		DOM.scheduleAtNextAnimationFrame(() => {
R
rebornix 已提交
615
			relayout(cell, height);
616
			r();
R
rebornix 已提交
617
		});
618 619

		return new Promise(resolve => { r = resolve; });
620 621
	}

R
rebornix 已提交
622
	async insertNotebookCell(cell: ICellViewModel, type: CellKind, direction: 'above' | 'below', initialText: string = ''): Promise<void> {
R
rebornix 已提交
623 624
		const newLanguages = this.notebookViewModel!.languages;
		const language = newLanguages && newLanguages.length ? newLanguages[0] : 'markdown';
R
rebornix 已提交
625
		const index = this.notebookViewModel!.getCellIndex(cell);
P
Peng Lyu 已提交
626
		const insertIndex = direction === 'above' ? index : index + 1;
R
rebornix 已提交
627
		const newCell = this.notebookViewModel!.createCell(insertIndex, initialText.split(/\r?\n/g), language, type, true);
R
rebornix 已提交
628
		this.list?.focusElement(newCell);
P
Peng Lyu 已提交
629

R
rebornix 已提交
630
		if (type === CellKind.Markdown) {
631
			newCell.editState = CellEditState.Editing;
P
Peng Lyu 已提交
632
		}
R
rebornix 已提交
633

634
		let r: () => void;
R
rebornix 已提交
635
		DOM.scheduleAtNextAnimationFrame(() => {
R
rebornix 已提交
636
			this.list?.revealElementInCenterIfOutsideViewport(cell);
637
			r();
R
rebornix 已提交
638
		});
639 640

		return new Promise(resolve => { r = resolve; });
P
Peng Lyu 已提交
641 642
	}

R
rebornix 已提交
643
	async deleteNotebookCell(cell: ICellViewModel): Promise<void> {
644
		(cell as CellViewModel).save();
R
rebornix 已提交
645
		const index = this.notebookViewModel!.getCellIndex(cell);
R
rebornix 已提交
646
		this.notebookViewModel!.deleteCell(index, true);
R
rebornix 已提交
647 648
	}

649
	async moveCellDown(cell: ICellViewModel): Promise<void> {
R
rebornix 已提交
650
		const index = this.notebookViewModel!.getCellIndex(cell);
R
rebornix 已提交
651
		if (index === this.notebookViewModel!.length - 1) {
R
rebornix 已提交
652 653 654
			return;
		}

655
		const newIdx = index + 1;
656
		return this.moveCellToIndex(index, newIdx);
657 658
	}

659
	async moveCellUp(cell: ICellViewModel): Promise<void> {
R
rebornix 已提交
660
		const index = this.notebookViewModel!.getCellIndex(cell);
R
rebornix 已提交
661 662 663 664
		if (index === 0) {
			return;
		}

665
		const newIdx = index - 1;
666
		return this.moveCellToIndex(index, newIdx);
667 668
	}

R
Rob Lourens 已提交
669 670 671 672 673 674 675 676 677 678 679 680
	async moveCell(cell: ICellViewModel, relativeToCell: ICellViewModel, direction: 'above' | 'below'): Promise<void> {
		if (cell === relativeToCell) {
			return;
		}

		const originalIdx = this.notebookViewModel!.getCellIndex(cell);
		const relativeToIndex = this.notebookViewModel!.getCellIndex(relativeToCell);

		const newIdx = direction === 'above' ? relativeToIndex : relativeToIndex + 1;
		return this.moveCellToIndex(originalIdx, newIdx);
	}

681
	private async moveCellToIndex(index: number, newIdx: number): Promise<void> {
682 683 684 685 686
		if (index < newIdx) {
			// newIdx will be one less after index has been removed
			newIdx--;
		}

R
rebornix 已提交
687
		if (!this.notebookViewModel!.moveCellToIdx(index, newIdx, true)) {
688 689 690
			return;
		}

691
		let r: () => void;
692
		DOM.scheduleAtNextAnimationFrame(() => {
693
			this.list?.revealElementInView(this.notebookViewModel!.viewCells[newIdx]);
694
			r();
695
		});
696 697

		return new Promise(resolve => { r = resolve; });
698 699
	}

R
rebornix 已提交
700
	editNotebookCell(cell: CellViewModel): void {
701
		cell.editState = CellEditState.Editing;
R
rebornix 已提交
702 703

		this.renderedEditors.get(cell)?.focus();
P
Peng Lyu 已提交
704 705
	}

R
rebornix 已提交
706
	saveNotebookCell(cell: ICellViewModel): void {
707
		cell.editState = CellEditState.Preview;
P
Peng Lyu 已提交
708 709
	}

R
rebornix 已提交
710 711 712 713 714 715 716 717 718 719
	getActiveCell() {
		let elements = this.list?.getFocusedElements();

		if (elements && elements.length) {
			return elements[0];
		}

		return undefined;
	}

720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
	cancelNotebookExecution(): void {
		if (!this.notebookViewModel!.currentTokenSource) {
			throw new Error('Notebook is not executing');
		}


		this.notebookViewModel!.currentTokenSource.cancel();
		this.notebookViewModel!.currentTokenSource = undefined;
	}

	async executeNotebook(): Promise<void> {
		// return this.progressService.showWhile(this._executeNotebook());
		return this._executeNotebook();
	}

	async _executeNotebook(): Promise<void> {
		if (this.notebookViewModel!.currentTokenSource) {
			return;
		}

		const tokenSource = new CancellationTokenSource();
		try {
			this.editorExecutingNotebook!.set(true);
			this.notebookViewModel!.currentTokenSource = tokenSource;

			for (let cell of this.notebookViewModel!.viewCells) {
				if (cell.cellKind === CellKind.Code) {
					await this._executeNotebookCell(cell, tokenSource);
				}
			}
		} finally {
			this.editorExecutingNotebook!.set(false);
			this.notebookViewModel!.currentTokenSource = undefined;
			tokenSource.dispose();
		}
	}

	cancelNotebookCellExecution(cell: ICellViewModel): void {
		if (!cell.currentTokenSource) {
			throw new Error('Cell is not executing');
		}

		cell.currentTokenSource.cancel();
		cell.currentTokenSource = undefined;
	}

766
	async executeNotebookCell(cell: ICellViewModel): Promise<void> {
767
		const tokenSource = new CancellationTokenSource();
768 769 770 771 772 773 774
		try {
			this._executeNotebookCell(cell, tokenSource);
		} finally {
			tokenSource.dispose();
		}
	}

R
Rob Lourens 已提交
775
	private async _executeNotebookCell(cell: ICellViewModel, tokenSource: CancellationTokenSource): Promise<void> {
776
		try {
777
			cell.currentTokenSource = tokenSource;
R
rebornix 已提交
778
			const provider = this.notebookService.getContributedNotebookProviders(this.viewModel!.uri)[0];
779 780 781 782
			if (provider) {
				const viewType = provider.id;
				const notebookUri = CellUri.parse(cell.uri)?.notebook;
				if (notebookUri) {
783
					return await this.notebookService.executeNotebookCell(viewType, notebookUri, cell.handle, tokenSource.token);
784 785 786
				}
			}
		} finally {
787
			cell.currentTokenSource = undefined;
788 789 790
		}
	}

R
rebornix 已提交
791
	focusNotebookCell(cell: ICellViewModel, focusEditor: boolean) {
R
rebornix 已提交
792
		if (focusEditor) {
R
rebornix 已提交
793
			this.selectElement(cell);
R
rebornix 已提交
794
			this.list?.focusView();
R
rebornix 已提交
795

796
			cell.editState = CellEditState.Editing;
R
rebornix 已提交
797
			cell.focusMode = CellFocusMode.Editor;
798
			this.revealInCenterIfOutsideViewport(cell);
R
rebornix 已提交
799
		} else {
R
rebornix 已提交
800
			let itemDOM = this.list?.domElementOfElement(cell);
R
rebornix 已提交
801 802 803
			if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) {
				(document.activeElement as HTMLElement).blur();
			}
804

805
			cell.editState = CellEditState.Preview;
806
			cell.focusMode = CellFocusMode.Editor;
R
rebornix 已提交
807

R
rebornix 已提交
808
			this.selectElement(cell);
809
			this.revealInCenterIfOutsideViewport(cell);
R
rebornix 已提交
810
			this.list?.focusView();
R
rebornix 已提交
811 812 813
		}
	}

R
rebornix 已提交
814 815 816 817
	//#endregion

	//#region MISC

R
rebornix 已提交
818 819 820 821 822 823 824 825 826 827 828
	getLayoutInfo(): NotebookLayoutInfo {
		if (!this.list) {
			throw new Error('Editor is not initalized successfully');
		}

		return {
			width: this.dimension!.width,
			height: this.dimension!.height,
			fontInfo: this.fontInfo!
		};
	}
R
rebornix 已提交
829

R
rebornix 已提交
830 831
	triggerScroll(event: IMouseWheelEvent) {
		this.list?.triggerScrollFromMouseWheelEvent(event);
R
rebornix 已提交
832 833
	}

R
rebornix 已提交
834
	createInset(cell: CodeCellViewModel, output: IOutput, shadowContent: string, offset: number) {
R
rebornix 已提交
835 836
		if (!this.webview) {
			return;
R
rebornix 已提交
837 838
		}

R
rebornix 已提交
839
		let preloads = this.notebookViewModel!.renderers;
R
rebornix 已提交
840

841
		if (!this.webview!.insetMapping.has(output)) {
R
rebornix 已提交
842
			let cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0;
843
			this.webview!.createInset(cell, output, cellTop, offset, shadowContent, preloads);
R
rebornix 已提交
844
		} else {
R
rebornix 已提交
845
			let cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0;
R
rebornix 已提交
846 847
			let scrollTop = this.list?.scrollTop || 0;

848
			this.webview!.updateViewScrollTop(-scrollTop, [{ cell: cell, output: output, cellTop: cellTop }]);
R
rebornix 已提交
849
		}
R
rebornix 已提交
850
	}
R
rebornix 已提交
851

R
rebornix 已提交
852 853 854 855 856 857 858 859
	removeInset(output: IOutput) {
		if (!this.webview) {
			return;
		}

		this.webview!.removeInset(output);
	}

R
rebornix 已提交
860 861
	getOutputRenderer(): OutputRenderer {
		return this.outputRenderer;
R
rebornix 已提交
862
	}
863

864 865 866 867
	postMessage(message: any) {
		this.webview?.webview.sendMessage(message);
	}

R
rebornix 已提交
868
	//#endregion
869 870 871 872 873 874

	toJSON(): any {
		return {
			notebookHandle: this.viewModel?.handle
		};
	}
P
Peng Lyu 已提交
875 876 877 878
}

const embeddedEditorBackground = 'walkThrough.embeddedEditorBackground';

879 880 881 882 883 884
export const focusedCellIndicator = registerColor('notebook.focusedCellIndicator', {
	light: new Color(new RGBA(102, 175, 224)),
	dark: new Color(new RGBA(12, 125, 157)),
	hc: new Color(new RGBA(0, 73, 122))
}, nls.localize('notebook.focusedCellIndicator', "The color of the focused notebook cell indicator."));

885 886 887 888 889 890 891
export const notebookOutputContainerColor = registerColor('notebook.outputContainerBackgroundColor', {
	dark: new Color(new RGBA(255, 255, 255, 0.06)),
	light: new Color(new RGBA(228, 230, 241)),
	hc: null
}
	, nls.localize('notebook.outputContainerBackgroundColor', "The Color of the notebook output container background."));

R
Rob Lourens 已提交
892
// TODO currently also used for toolbar border, if we keep all of this, pick a generic name
R
rebornix 已提交
893 894 895 896 897 898
export const CELL_TOOLBAR_SEPERATOR = registerColor('notebook.cellToolbarSeperator', {
	dark: Color.fromHex('#808080').transparent(0.35),
	light: Color.fromHex('#808080').transparent(0.35),
	hc: contrastBorder
}, nls.localize('cellToolbarSeperator', "The color of seperator in Cell bottom toolbar"));

899

P
Peng Lyu 已提交
900 901 902
registerThemingParticipant((theme, collector) => {
	const color = getExtraColor(theme, embeddedEditorBackground, { dark: 'rgba(0, 0, 0, .4)', extra_dark: 'rgba(200, 235, 255, .064)', light: '#f4f4f4', hc: null });
	if (color) {
R
rebornix 已提交
903
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .monaco-editor-background,
R
Rob Lourens 已提交
904 905
			.monaco-workbench .part.editor > .content .notebook-editor .cell .margin-view-overlays,
			.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-statusbar-container { background: ${color}; }`);
906
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-drag-image .cell-editor-container > div { background: ${color} !important; }`);
P
Peng Lyu 已提交
907 908 909
	}
	const link = theme.getColor(textLinkForeground);
	if (link) {
R
Rob Lourens 已提交
910
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .output a { color: ${link}; }`);
P
Peng Lyu 已提交
911 912 913
	}
	const activeLink = theme.getColor(textLinkActiveForeground);
	if (activeLink) {
R
Rob Lourens 已提交
914 915
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .output a:hover,
			.monaco-workbench .part.editor > .content .notebook-editor .cell .output a:active { color: ${activeLink}; }`);
P
Peng Lyu 已提交
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
	}
	const shortcut = theme.getColor(textPreformatForeground);
	if (shortcut) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor code,
			.monaco-workbench .part.editor > .content .notebook-editor .shortcut { color: ${shortcut}; }`);
	}
	const border = theme.getColor(contrastBorder);
	if (border) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-editor { border-color: ${border}; }`);
	}
	const quoteBackground = theme.getColor(textBlockQuoteBackground);
	if (quoteBackground) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor blockquote { background: ${quoteBackground}; }`);
	}
	const quoteBorder = theme.getColor(textBlockQuoteBorder);
	if (quoteBorder) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor blockquote { border-color: ${quoteBorder}; }`);
	}
934

935 936 937
	const containerBackground = theme.getColor(notebookOutputContainerColor);
	if (containerBackground) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { background-color: ${containerBackground}; }`);
938
	}
939

R
Rob Lourens 已提交
940 941 942
	const editorBackgroundColor = theme.getColor(editorBackground);
	if (editorBackgroundColor) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-statusbar-container { border-top: solid 1px ${editorBackgroundColor}; }`);
R
Rob Lourens 已提交
943
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > .monaco-toolbar { background-color: ${editorBackgroundColor}; }`);
R
Rob Lourens 已提交
944
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row.cell-drag-image { background-color: ${editorBackgroundColor}; }`);
945 946
	}

R
rebornix 已提交
947 948 949 950
	const cellToolbarSeperator = theme.getColor(CELL_TOOLBAR_SEPERATOR);
	if (cellToolbarSeperator) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-bottom-toolbar-container .seperator { background-color: ${cellToolbarSeperator} }`);
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-bottom-toolbar-container .seperator-short { background-color: ${cellToolbarSeperator} }`);
R
Rob Lourens 已提交
951
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > .monaco-toolbar { border: solid 1px ${cellToolbarSeperator}; }`);
R
Rob Lourens 已提交
952 953 954 955 956 957
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:hover .notebook-cell-focus-indicator { border-color: ${cellToolbarSeperator}; }`);
	}

	const focusedCellIndicatorColor = theme.getColor(focusedCellIndicator);
	if (focusedCellIndicatorColor) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row.focused .notebook-cell-focus-indicator { border-color: ${focusedCellIndicatorColor}; }`);
958
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .notebook-cell-focus-indicator { border-color: ${focusedCellIndicatorColor}; }`);
R
Rob Lourens 已提交
959
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .notebook-cell-insertion-indicator-top { background-color: ${focusedCellIndicatorColor}; }`);
R
rebornix 已提交
960 961
	}

962
	// Cell Margin
R
rebornix 已提交
963 964
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row  > div.cell { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN}px; }`);
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row { padding-top: ${EDITOR_TOP_MARGIN}px; }`);
965
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`);
R
rebornix 已提交
966
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-bottom-toolbar-container { width: calc(100% - ${CELL_MARGIN * 2 + CELL_RUN_GUTTER}px); margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`);
R
Rob Lourens 已提交
967

968
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .markdown-editor-container { margin-left: ${CELL_RUN_GUTTER}px; }`);
R
rebornix 已提交
969
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row  > div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`);
R
Rob Lourens 已提交
970
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .run-button-container { width: ${CELL_RUN_GUTTER}px; }`);
R
Rob Lourens 已提交
971
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list .monaco-list-row .notebook-cell-insertion-indicator-top { left: ${CELL_MARGIN + CELL_RUN_GUTTER}px; right: ${CELL_MARGIN}px; }`);
972
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-drag-image .cell-editor-container > div { padding: ${EDITOR_TOP_PADDING}px 16px ${EDITOR_BOTTOM_PADDING}px 16px; }`);
P
Peng Lyu 已提交
973
});