notebookEditor.ts 36.4 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';
R
rebornix 已提交
31
import { CELL_MARGIN, CELL_RUN_GUTTER, EDITOR_TOP_MARGIN } 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';
R
Rob Lourens 已提交
48 49
import { domEvent } from 'vs/base/browser/event';
import { throttle } from 'vs/base/common/decorators';
P
Peng Lyu 已提交
50 51

const $ = DOM.$;
R
rebornix 已提交
52 53
const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState';

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
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 已提交
69
export class NotebookCodeEditors implements ICompositeCodeEditor {
70

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

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

	dispose(): void {
		this._onDidChangeActiveEditor.dispose();
		this._disposables.dispose();
	}
86 87 88

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

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

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

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

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

P
Peng Lyu 已提交
138 139 140 141 142 143 144 145
	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 已提交
146
	//#region Editor Core
R
rebornix 已提交
147

R
rebornix 已提交
148 149 150 151 152

	public get isNotebookEditor() {
		return true;
	}

R
Rob Lourens 已提交
153 154 155 156 157
	@throttle(500, (_, r) => r)
	private log(msg: string) {
		console.log(msg);
	}

P
Peng Lyu 已提交
158 159 160
	protected createEditor(parent: HTMLElement): void {
		this.rootElement = DOM.append(parent, $('.notebook-editor'));
		this.createBody(this.rootElement);
161
		this.generateFontInfo();
R
rebornix 已提交
162
		this.editorFocus = NOTEBOOK_EDITOR_FOCUSED.bindTo(this.contextKeyService);
163
		this.editorFocus.set(true);
R
rebornix 已提交
164 165 166 167 168 169 170
		this._register(this.onDidFocus(() => {
			this.editorFocus?.set(true);
		}));

		this._register(this.onDidBlur(() => {
			this.editorFocus?.set(false);
		}));
R
rebornix 已提交
171 172 173

		this.editorEditable = NOTEBOOK_EDITOR_EDITABLE.bindTo(this.contextKeyService);
		this.editorEditable.set(true);
174
		this.editorExecutingNotebook = NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK.bindTo(this.contextKeyService);
175 176 177 178 179
	}

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

	private createBody(parent: HTMLElement): void {
P
Peng Lyu 已提交
183
		this.body = document.createElement('div');
P
Peng Lyu 已提交
184 185 186
		DOM.addClass(this.body, 'cell-list-container');
		this.createCellList();
		DOM.append(parent, this.body);
R
rebornix 已提交
187
		DOM.append(parent, this.findWidget.getDomNode());
P
Peng Lyu 已提交
188 189
	}

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

R
Rob Lourens 已提交
193
		const dndController = new CellDragAndDropController(this);
P
Peng Lyu 已提交
194
		const renders = [
R
Rob Lourens 已提交
195 196
			this.instantiationService.createInstance(CodeCellRenderer, this, this.contextKeyService, this.renderedEditors, dndController),
			this.instantiationService.createInstance(MarkdownCellRenderer, this.contextKeyService, this, dndController),
P
Peng Lyu 已提交
197 198
		];

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

R
Rob Lourens 已提交
240 241 242 243 244 245 246 247
		domEvent(this.body, 'dragover')(e => {
			// this.log('list dragover');
		});

		domEvent(this.body, 'mousemove')(e => {
			// this.log('list mousemove');
		});

248
		this.control = new NotebookCodeEditors(this.list, this.renderedEditors);
249
		this.webview = this.instantiationService.createInstance(BackLayerWebView, this);
250 251 252 253 254
		this._register(this.webview.onMessage(message => {
			if (this.viewModel) {
				this.notebookService.onDidReceiveMessage(this.viewModel.viewType, this.viewModel.uri, message);
			}
		}));
R
rebornix 已提交
255
		this.list.rowsContainer.appendChild(this.webview.element);
R
Rob Lourens 已提交
256
		// document.body.querySelector('.monaco-workbench')!.appendChild(this.webview!.element);
R
rebornix 已提交
257

P
Peng Lyu 已提交
258
		this._register(this.list);
R
rebornix 已提交
259 260 261

		// transparent cover
		this.webviewTransparentCover = DOM.append(this.list.rowsContainer, $('.webview-cover'));
R
Rob Lourens 已提交
262 263 264 265 266 267 268 269 270 271
		domEvent(this.webviewTransparentCover, 'dragover')(e => {
			this.log(`cover dragover`);
		});
		domEvent(this.webviewTransparentCover, 'dragover')(e => {
			this.log(`cover dragover`);
		});
		domEvent(this.webviewTransparentCover, 'mousemove')(e => {
			// this.log(`cover mousemove`);
		});
		// this.webviewTransparentCover.style.display = 'none';
R
rebornix 已提交
272 273 274 275 276 277 278 279 280 281

		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
R
Rob Lourens 已提交
282
				// this.webviewTransparentCover.style.display = 'none';
R
rebornix 已提交
283 284 285
			}
		}));

R
rebornix 已提交
286 287 288 289 290 291 292 293 294 295 296 297
		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 已提交
298 299
	}

300 301 302 303
	getControl() {
		return this.control;
	}

R
rebornix 已提交
304 305 306 307
	getInnerWebview(): Webview | undefined {
		return this.webview?.webview;
	}

P
Peng Lyu 已提交
308
	onHide() {
R
rebornix 已提交
309
		this.editorFocus?.set(false);
310 311
		if (this.webview) {
			this.localStore.clear();
R
rebornix 已提交
312
			this.list?.rowsContainer.removeChild(this.webview?.element);
313 314 315 316
			this.webview?.dispose();
			this.webview = null;
		}

R
rebornix 已提交
317
		this.list?.clear();
318
		super.onHide();
P
Peng Lyu 已提交
319 320
	}

R
rebornix 已提交
321 322 323 324 325 326 327 328 329 330 331 332 333
	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);
334 335 336
		}
	}

R
rebornix 已提交
337 338 339 340 341
	focus() {
		super.focus();
		this.editorFocus?.set(true);
	}

R
rebornix 已提交
342
	async setInput(input: NotebookEditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
R
rebornix 已提交
343 344 345 346
		if (this.input instanceof NotebookEditorInput) {
			this.saveTextEditorViewState(this.input);
		}

R
rebornix 已提交
347 348
		await super.setInput(input, options, token);
		const model = await input.resolve();
P
Peng Lyu 已提交
349

350 351 352
		if (this.notebookViewModel === undefined || !this.notebookViewModel.equal(model) || this.webview === null) {
			this.detachModel();
			await this.attachModel(input, model);
R
rebornix 已提交
353
		}
P
Peng Lyu 已提交
354

355 356 357
		// reveal cell if editor options tell to do so
		if (options instanceof NotebookEditorOptions && options.cellOptions) {
			const cellOptions = options.cellOptions;
R
rebornix 已提交
358
			const cell = this.notebookViewModel!.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString());
359
			if (cell) {
360
				this.selectElement(cell);
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
				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();
					}
				}
376 377
			}
		}
R
rebornix 已提交
378
	}
379

R
rebornix 已提交
380 381 382 383 384 385 386 387
	clearInput(): void {
		if (this.input && this.input instanceof NotebookEditorInput && !this.input.isDisposed()) {
			this.saveTextEditorViewState(this.input);
		}

		super.clearInput();
	}

R
rebornix 已提交
388 389
	private detachModel() {
		this.localStore.clear();
R
rebornix 已提交
390
		this.list?.detachViewModel();
R
rebornix 已提交
391 392 393 394
		this.notebookViewModel?.dispose();
		this.notebookViewModel = undefined;
		this.webview?.clearInsets();
		this.webview?.clearPreloadsCache();
395
		this.findWidget.clear();
R
rebornix 已提交
396
		this.list?.clear();
R
rebornix 已提交
397
	}
R
rebornix 已提交
398

R
rebornix 已提交
399 400
	private async attachModel(input: NotebookEditorInput, model: NotebookEditorModel) {
		if (!this.webview) {
401
			this.webview = this.instantiationService.createInstance(BackLayerWebView, this);
R
rebornix 已提交
402 403
			this.list?.rowsContainer.insertAdjacentElement('afterbegin', this.webview!.element);
		}
404

R
rebornix 已提交
405
		this.eventDispatcher = new NotebookEventDispatcher();
406
		this.notebookViewModel = this.instantiationService.createInstance(NotebookViewModel, input.viewType!, model, this.eventDispatcher, this.getLayoutInfo());
407
		this.editorEditable?.set(!!this.notebookViewModel.metadata?.editable);
R
rebornix 已提交
408
		this.eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
R
rebornix 已提交
409
		const viewState = this.loadTextEditorViewState(input);
R
rebornix 已提交
410
		this.notebookViewModel.restoreEditorViewState(viewState);
411

R
rebornix 已提交
412 413 414 415
		this.localStore.add(this.eventDispatcher.onDidChangeMetadata((e) => {
			this.editorEditable?.set(e.source.editable);
		}));

416 417
		this.localStore.add(this.instantiationService.createInstance(FoldingController, this));

R
rebornix 已提交
418 419 420 421
		this.webview?.updateRendererPreloads(this.notebookViewModel.renderers);

		this.localStore.add(this.list!.onWillScroll(e => {
			this.webview!.updateViewScrollTop(-e.scrollTop, []);
R
rebornix 已提交
422
			this.webviewTransparentCover!.style.top = `${e.scrollTop}px`;
R
rebornix 已提交
423 424 425 426 427 428
		}));

		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 已提交
429
			let updateItems: { cell: CodeCellViewModel, output: IOutput, cellTop: number }[] = [];
R
rebornix 已提交
430 431 432

			if (this.webview?.insetMapping) {
				this.webview?.insetMapping.forEach((value, key) => {
R
rebornix 已提交
433 434
					const cell = value.cell;
					const cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0;
R
rebornix 已提交
435 436 437 438 439 440
					if (this.webview!.shouldUpdateInset(cell, key, cellTop)) {
						updateItems.push({
							cell: cell,
							output: key,
							cellTop: cellTop
						});
R
rebornix 已提交
441
					}
R
rebornix 已提交
442
				});
443

R
rebornix 已提交
444 445 446 447 448 449
				if (updateItems.length) {
					this.webview?.updateViewScrollTop(-scrollTop, updateItems);
				}
			}
		}));

R
rebornix 已提交
450 451 452 453 454 455
		this.list!.attachViewModel(this.notebookViewModel);
		this.localStore.add(this.list!.onDidRemoveOutput(output => {
			this.removeInset(output);
		}));

		this.list!.layout();
R
rebornix 已提交
456 457 458 459 460 461 462 463

		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;
		}
P
Peng Lyu 已提交
464 465
	}

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

				state.cellTotalHeights = cellHeights;
R
rebornix 已提交
482 483
			}

R
rebornix 已提交
484
			this.editorMemento.saveEditorState(this.group, input.resource, state);
R
rebornix 已提交
485 486 487 488 489
		}
	}

	private loadTextEditorViewState(input: NotebookEditorInput): INotebookEditorViewState | undefined {
		if (this.group) {
R
rebornix 已提交
490
			return this.editorMemento.loadEditorState(this.group, input.resource);
R
rebornix 已提交
491 492 493 494 495 496 497 498 499 500
		}

		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);
501
		this.list?.updateOptions({ additionalScrollHeight: dimension.height });
R
rebornix 已提交
502
		this.list?.layout(dimension.height, dimension.width);
R
rebornix 已提交
503 504 505 506 507 508

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

R
rebornix 已提交
509
		this.eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
R
rebornix 已提交
510 511 512 513 514 515 516 517 518 519 520 521
	}

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

		super.saveState();
	}

	//#endregion

R
rebornix 已提交
522 523
	//#region Editor Features

R
rebornix 已提交
524
	selectElement(cell: ICellViewModel) {
R
rebornix 已提交
525
		this.list?.selectElement(cell);
R
rebornix 已提交
526 527
	}

R
rebornix 已提交
528
	revealInView(cell: ICellViewModel) {
R
rebornix 已提交
529
		this.list?.revealElementInView(cell);
R
rebornix 已提交
530 531
	}

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

R
rebornix 已提交
536
	revealInCenter(cell: ICellViewModel) {
R
rebornix 已提交
537
		this.list?.revealElementInCenter(cell);
R
rebornix 已提交
538 539
	}

R
rebornix 已提交
540
	revealLineInView(cell: ICellViewModel, line: number): void {
R
rebornix 已提交
541
		this.list?.revealElementLineInView(cell, line);
R
rebornix 已提交
542
	}
R
rebornix 已提交
543

R
rebornix 已提交
544
	revealLineInCenter(cell: ICellViewModel, line: number) {
R
rebornix 已提交
545
		this.list?.revealElementLineInCenter(cell, line);
R
rebornix 已提交
546 547
	}

R
rebornix 已提交
548
	revealLineInCenterIfOutsideViewport(cell: ICellViewModel, line: number) {
R
rebornix 已提交
549
		this.list?.revealElementLineInCenterIfOutsideViewport(cell, line);
R
rebornix 已提交
550 551
	}

R
rebornix 已提交
552
	revealRangeInView(cell: ICellViewModel, range: Range): void {
R
rebornix 已提交
553
		this.list?.revealElementRangeInView(cell, range);
R
rebornix 已提交
554 555
	}

R
rebornix 已提交
556
	revealRangeInCenter(cell: ICellViewModel, range: Range): void {
R
rebornix 已提交
557
		this.list?.revealElementRangeInCenter(cell, range);
R
rebornix 已提交
558 559
	}

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

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

R
rebornix 已提交
568 569 570 571
	changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any {
		return this.notebookViewModel?.changeDecorations(callback);
	}

R
rebornix 已提交
572 573 574 575
	setHiddenAreas(_ranges: ICellRange[]): boolean {
		return this.list!.setHiddenAreas(_ranges);
	}

R
rebornix 已提交
576 577
	//#endregion

R
rebornix 已提交
578 579 580 581 582 583 584 585
	//#region Find Delegate

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

	public hideFind() {
		this.findWidget.hide();
R
rebornix 已提交
586
		this.focus();
R
rebornix 已提交
587 588 589 590
	}

	//#endregion

R
rebornix 已提交
591 592 593 594 595 596 597 598 599
	//#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 已提交
600
	//#region Cell operations
601
	async layoutNotebookCell(cell: ICellViewModel, height: number): Promise<void> {
R
rebornix 已提交
602
		let relayout = (cell: ICellViewModel, height: number) => {
R
rebornix 已提交
603
			this.list?.updateElementHeight2(cell, height);
R
rebornix 已提交
604 605
		};

606
		let r: () => void;
R
rebornix 已提交
607
		DOM.scheduleAtNextAnimationFrame(() => {
R
rebornix 已提交
608
			relayout(cell, height);
609
			r();
R
rebornix 已提交
610
		});
611 612

		return new Promise(resolve => { r = resolve; });
613 614
	}

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

R
rebornix 已提交
623
		if (type === CellKind.Markdown) {
624
			newCell.editState = CellEditState.Editing;
P
Peng Lyu 已提交
625
		}
R
rebornix 已提交
626

627
		let r: () => void;
R
rebornix 已提交
628
		DOM.scheduleAtNextAnimationFrame(() => {
R
rebornix 已提交
629
			this.list?.revealElementInCenterIfOutsideViewport(cell);
630
			r();
R
rebornix 已提交
631
		});
632 633

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

R
rebornix 已提交
636
	async deleteNotebookCell(cell: ICellViewModel): Promise<void> {
637
		(cell as CellViewModel).save();
R
rebornix 已提交
638
		const index = this.notebookViewModel!.getCellIndex(cell);
R
rebornix 已提交
639
		this.notebookViewModel!.deleteCell(index, true);
R
rebornix 已提交
640 641
	}

642
	async moveCellDown(cell: ICellViewModel): Promise<void> {
R
rebornix 已提交
643
		const index = this.notebookViewModel!.getCellIndex(cell);
R
rebornix 已提交
644 645 646 647
		if (index === this.notebookViewModel!.viewCells.length - 1) {
			return;
		}

648
		const newIdx = index + 1;
649
		return this.moveCellToIndex(index, newIdx);
650 651
	}

652
	async moveCellUp(cell: ICellViewModel): Promise<void> {
R
rebornix 已提交
653
		const index = this.notebookViewModel!.getCellIndex(cell);
R
rebornix 已提交
654 655 656 657
		if (index === 0) {
			return;
		}

658
		const newIdx = index - 1;
659
		return this.moveCellToIndex(index, newIdx);
660 661
	}

R
Rob Lourens 已提交
662 663 664 665 666 667 668 669 670 671 672 673
	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);
	}

674
	private async moveCellToIndex(index: number, newIdx: number): Promise<void> {
R
Rob Lourens 已提交
675
		console.log(`Move ${index} to ${newIdx}`);
R
rebornix 已提交
676
		if (!this.notebookViewModel!.moveCellToIdx(index, newIdx, true)) {
677 678 679
			return;
		}

680
		let r: () => void;
681
		DOM.scheduleAtNextAnimationFrame(() => {
R
rebornix 已提交
682
			this.list?.revealElementInCenterIfOutsideViewport(this.notebookViewModel!.viewCells[index + 1]);
683
			r();
684
		});
685 686

		return new Promise(resolve => { r = resolve; });
687 688
	}

R
rebornix 已提交
689
	editNotebookCell(cell: CellViewModel): void {
690
		cell.editState = CellEditState.Editing;
R
rebornix 已提交
691 692

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

R
rebornix 已提交
695
	saveNotebookCell(cell: ICellViewModel): void {
696
		cell.editState = CellEditState.Preview;
P
Peng Lyu 已提交
697 698
	}

R
rebornix 已提交
699 700 701 702 703 704 705 706 707 708
	getActiveCell() {
		let elements = this.list?.getFocusedElements();

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

		return undefined;
	}

709 710 711 712 713 714 715 716 717 718 719 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
	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;
	}

755
	async executeNotebookCell(cell: ICellViewModel): Promise<void> {
756
		const tokenSource = new CancellationTokenSource();
757 758 759 760 761 762 763
		try {
			this._executeNotebookCell(cell, tokenSource);
		} finally {
			tokenSource.dispose();
		}
	}

R
Rob Lourens 已提交
764
	private async _executeNotebookCell(cell: ICellViewModel, tokenSource: CancellationTokenSource): Promise<void> {
765
		try {
766
			cell.currentTokenSource = tokenSource;
R
rebornix 已提交
767
			const provider = this.notebookService.getContributedNotebookProviders(this.viewModel!.uri)[0];
768 769 770 771
			if (provider) {
				const viewType = provider.id;
				const notebookUri = CellUri.parse(cell.uri)?.notebook;
				if (notebookUri) {
772
					return await this.notebookService.executeNotebookCell(viewType, notebookUri, cell.handle, tokenSource.token);
773 774 775
				}
			}
		} finally {
776
			cell.currentTokenSource = undefined;
777 778 779
		}
	}

R
rebornix 已提交
780
	focusNotebookCell(cell: ICellViewModel, focusEditor: boolean) {
R
rebornix 已提交
781
		if (focusEditor) {
R
rebornix 已提交
782
			this.selectElement(cell);
R
rebornix 已提交
783
			this.list?.focusView();
R
rebornix 已提交
784

785
			cell.editState = CellEditState.Editing;
R
rebornix 已提交
786
			cell.focusMode = CellFocusMode.Editor;
787
			this.revealInCenterIfOutsideViewport(cell);
R
rebornix 已提交
788
		} else {
R
rebornix 已提交
789
			let itemDOM = this.list?.domElementOfElement(cell);
R
rebornix 已提交
790 791 792
			if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) {
				(document.activeElement as HTMLElement).blur();
			}
793

794
			cell.editState = CellEditState.Preview;
795
			cell.focusMode = CellFocusMode.Editor;
R
rebornix 已提交
796

R
rebornix 已提交
797
			this.selectElement(cell);
798
			this.revealInCenterIfOutsideViewport(cell);
R
rebornix 已提交
799
			this.list?.focusView();
R
rebornix 已提交
800 801 802
		}
	}

R
rebornix 已提交
803 804 805 806
	//#endregion

	//#region MISC

R
rebornix 已提交
807 808 809 810 811 812 813 814 815 816 817
	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 已提交
818

R
rebornix 已提交
819 820
	triggerScroll(event: IMouseWheelEvent) {
		this.list?.triggerScrollFromMouseWheelEvent(event);
R
rebornix 已提交
821 822
	}

R
rebornix 已提交
823
	createInset(cell: CodeCellViewModel, output: IOutput, shadowContent: string, offset: number) {
R
rebornix 已提交
824 825
		if (!this.webview) {
			return;
R
rebornix 已提交
826 827
		}

R
rebornix 已提交
828
		let preloads = this.notebookViewModel!.renderers;
R
rebornix 已提交
829

830
		if (!this.webview!.insetMapping.has(output)) {
R
rebornix 已提交
831
			let cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0;
832
			this.webview!.createInset(cell, output, cellTop, offset, shadowContent, preloads);
R
rebornix 已提交
833
		} else {
R
rebornix 已提交
834
			let cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0;
R
rebornix 已提交
835 836
			let scrollTop = this.list?.scrollTop || 0;

837
			this.webview!.updateViewScrollTop(-scrollTop, [{ cell: cell, output: output, cellTop: cellTop }]);
R
rebornix 已提交
838
		}
R
rebornix 已提交
839
	}
R
rebornix 已提交
840

R
rebornix 已提交
841 842 843 844 845 846 847 848
	removeInset(output: IOutput) {
		if (!this.webview) {
			return;
		}

		this.webview!.removeInset(output);
	}

R
rebornix 已提交
849 850
	getOutputRenderer(): OutputRenderer {
		return this.outputRenderer;
R
rebornix 已提交
851
	}
852

853 854 855 856
	postMessage(message: any) {
		this.webview?.webview.sendMessage(message);
	}

R
rebornix 已提交
857
	//#endregion
858 859 860 861 862 863

	toJSON(): any {
		return {
			notebookHandle: this.viewModel?.handle
		};
	}
P
Peng Lyu 已提交
864 865 866 867
}

const embeddedEditorBackground = 'walkThrough.embeddedEditorBackground';

868 869 870 871 872 873
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."));

874 875 876 877 878 879 880
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 已提交
881
// TODO currently also used for toolbar border, if we keep all of this, pick a generic name
R
rebornix 已提交
882 883 884 885 886 887
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"));

888

P
Peng Lyu 已提交
889 890 891
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 已提交
892
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .monaco-editor-background,
R
Rob Lourens 已提交
893 894
			.monaco-workbench .part.editor > .content .notebook-editor .cell .margin-view-overlays,
			.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-statusbar-container { background: ${color}; }`);
P
Peng Lyu 已提交
895 896 897
	}
	const link = theme.getColor(textLinkForeground);
	if (link) {
R
Rob Lourens 已提交
898
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .output a { color: ${link}; }`);
P
Peng Lyu 已提交
899 900 901
	}
	const activeLink = theme.getColor(textLinkActiveForeground);
	if (activeLink) {
R
Rob Lourens 已提交
902 903
		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 已提交
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
	}
	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}; }`);
	}
922

923 924 925
	const containerBackground = theme.getColor(notebookOutputContainerColor);
	if (containerBackground) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { background-color: ${containerBackground}; }`);
926
	}
927

R
Rob Lourens 已提交
928 929 930
	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 已提交
931
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > .monaco-toolbar { background-color: ${editorBackgroundColor}; }`);
R
Rob Lourens 已提交
932
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row.cell-drag-image { background-color: ${editorBackgroundColor}; }`);
933 934
	}

R
rebornix 已提交
935 936 937 938
	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 已提交
939
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > .monaco-toolbar { border: solid 1px ${cellToolbarSeperator}; }`);
R
Rob Lourens 已提交
940 941 942 943 944 945 946 947
		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}; }`);
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row.selected .notebook-cell-focus-indicator { border-color: ${focusedCellIndicatorColor}; }`);
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .notebook-cell-insertion-indicator-top { background-color: ${focusedCellIndicatorColor}; }`);
R
rebornix 已提交
948 949
	}

950
	// Cell Margin
R
rebornix 已提交
951 952
	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; }`);
953
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`);
R
rebornix 已提交
954
	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 已提交
955

R
Rob Lourens 已提交
956
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-editor-container { width: calc(100% - ${CELL_RUN_GUTTER}px); }`);
957
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .markdown-editor-container { margin-left: ${CELL_RUN_GUTTER}px; }`);
R
rebornix 已提交
958
	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 已提交
959
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .run-button-container { width: ${CELL_RUN_GUTTER}px; }`);
R
Rob Lourens 已提交
960
	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; }`);
P
Peng Lyu 已提交
961
});