notebookEditor.ts 22.1 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.
 *--------------------------------------------------------------------------------------------*/

R
rebornix 已提交
6
import { getZoomLevel } from 'vs/base/browser/browser';
P
Peng Lyu 已提交
7
import * as DOM from 'vs/base/browser/dom';
P
Peng Lyu 已提交
8
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
R
rebornix 已提交
9
import { CancellationToken } from 'vs/base/common/cancellation';
J
Johannes Rieken 已提交
10
import { DisposableStore } from 'vs/base/common/lifecycle';
R
rebornix 已提交
11
import 'vs/css!./notebook';
12
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
R
rebornix 已提交
13
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
14
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
R
rebornix 已提交
15
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
R
rebornix 已提交
16
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
R
rebornix 已提交
17 18 19 20 21 22
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { contrastBorder, editorBackground, focusBorder, foreground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground, textPreformatForeground } from 'vs/platform/theme/common/colorRegistry';
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
23
import { EditorOptions, IEditorMemento, ICompositeCodeEditor } from 'vs/workbench/common/editor';
24
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
R
rebornix 已提交
25
import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
R
rebornix 已提交
26
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
R
rebornix 已提交
27
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/output/outputRenderer';
R
rebornix 已提交
28 29 30
import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/renderers/backLayerWebView';
import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/renderers/cellRenderer';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/renderers/cellViewModel';
R
rebornix 已提交
31
import { CELL_MARGIN, INotebook, NotebookCellsSplice, IOutput, parseCellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
R
rebornix 已提交
32 33 34
import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
J
Johannes Rieken 已提交
35
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
36
import { IEditor } from 'vs/editor/common/editorCommon';
J
Johannes Rieken 已提交
37
import { IResourceInput } from 'vs/platform/editor/common/editor';
38
import { Emitter, Event } from 'vs/base/common/event';
R
rebornix 已提交
39
import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/notebookCellList';
P
Peng Lyu 已提交
40 41

const $ = DOM.$;
R
rebornix 已提交
42 43
const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState';

R
rebornix 已提交
44 45
export const NOTEBOOK_EDITOR_FOCUSED = new RawContextKey<boolean>('notebookEditorFocused', false);

R
rebornix 已提交
46 47 48
interface INotebookEditorViewState {
	editingCells: { [key: number]: boolean };
}
P
Peng Lyu 已提交
49

50 51
class NotebookCodeEditors implements ICompositeCodeEditor {

52
	private readonly _disposables = new DisposableStore();
53 54 55 56
	private readonly _onDidChangeActiveEditor = new Emitter<this>();
	readonly onDidChangeActiveEditor: Event<this> = this._onDidChangeActiveEditor.event;

	constructor(
R
rebornix 已提交
57
		private _list: NotebookCellList<CellViewModel>,
58
		private _renderedEditors: Map<CellViewModel, ICodeEditor | undefined>
59 60 61 62 63 64 65 66
	) {
		_list.onFocusChange(e => this._onDidChangeActiveEditor.fire(this), undefined, this._disposables);
	}

	dispose(): void {
		this._onDidChangeActiveEditor.dispose();
		this._disposables.dispose();
	}
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

	get activeCodeEditor(): IEditor | undefined {
		const [focused] = this._list.getFocusedElements();
		return focused instanceof CellViewModel
			? this._renderedEditors.get(focused)
			: undefined;
	}

	activate(input: IResourceInput): ICodeEditor | undefined {
		const data = parseCellUri(input.resource);
		if (!data) {
			return undefined;
		}
		// find the CellViewModel which represents the cell with the
		// given uri, scroll it into view so that the editor is alive,
		// and then set selection et al..
		for (let i = 0; i < this._list.length; i++) {
			const item = this._list.element(i);
			if (item.cell.uri.toString() === input.resource.toString()) {
				this._list.reveal(i, 0.2);
				this._list.setFocus([i]);
				const editor = this._renderedEditors.get(item);
				if (!editor) {
					break;
				}
				if (input.options?.selection) {
					const { selection } = input.options;
					editor.setSelection({
						...selection,
						endLineNumber: selection.endLineNumber || selection.startLineNumber,
						endColumn: selection.endColumn || selection.startColumn
					});
				}
				if (!input.options?.preserveFocus) {
					editor.focus();
				}
				return editor;
			}
		}
		return undefined;
	}
}

110
export class NotebookEditor extends BaseEditor implements INotebookEditor {
P
Peng Lyu 已提交
111 112 113
	static readonly ID: string = 'workbench.editor.notebook';
	private rootElement!: HTMLElement;
	private body!: HTMLElement;
P
Peng Lyu 已提交
114
	private contentWidgets!: HTMLElement;
P
Peng Lyu 已提交
115
	private webview: BackLayerWebView | null = null;
P
Peng Lyu 已提交
116

R
rebornix 已提交
117
	private list: NotebookCellList<CellViewModel> | undefined;
118
	private control: ICompositeCodeEditor | undefined;
J
Johannes Rieken 已提交
119
	private renderedEditors: Map<CellViewModel, ICodeEditor | undefined> = new Map();
P
Peng Lyu 已提交
120
	private model: NotebookEditorModel | undefined;
R
rebornix 已提交
121
	private notebook: INotebook | undefined;
R
rebornix 已提交
122
	viewType: string | undefined;
R
rebornix 已提交
123
	private viewCells: CellViewModel[] = [];
124
	private localStore: DisposableStore = new DisposableStore();
R
rebornix 已提交
125
	private editorMemento: IEditorMemento<INotebookEditorViewState>;
126
	private fontInfo: BareFontInfo | undefined;
127
	// private relayoutDisposable: IDisposable | null = null;
128
	private dimension: DOM.Dimension | null = null;
R
rebornix 已提交
129
	private editorFocus: IContextKey<boolean> | null = null;
R
rebornix 已提交
130
	private outputRenderer: OutputRenderer;
P
Peng Lyu 已提交
131 132 133 134 135

	constructor(
		@ITelemetryService telemetryService: ITelemetryService,
		@IThemeService themeService: IThemeService,
		@IInstantiationService private readonly instantiationService: IInstantiationService,
P
Peng Lyu 已提交
136
		@IStorageService storageService: IStorageService,
R
rebornix 已提交
137
		@IWebviewService private webviewService: IWebviewService,
R
rebornix 已提交
138
		@INotebookService private notebookService: INotebookService,
139
		@IEditorGroupsService editorGroupService: IEditorGroupsService,
R
rebornix 已提交
140
		@IConfigurationService private readonly configurationService: IConfigurationService,
R
rebornix 已提交
141
		@IEnvironmentService private readonly environmentSerice: IEnvironmentService,
R
rebornix 已提交
142
		@IContextKeyService private readonly contextKeyService: IContextKeyService,
P
Peng Lyu 已提交
143 144
	) {
		super(NotebookEditor.ID, telemetryService, themeService, storageService);
R
rebornix 已提交
145 146

		this.editorMemento = this.getEditorMemento<INotebookEditorViewState>(editorGroupService, NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY);
R
rebornix 已提交
147 148 149
		this.outputRenderer = new OutputRenderer(this, this.instantiationService);
	}

P
Peng Lyu 已提交
150

P
Peng Lyu 已提交
151 152 153 154 155 156 157 158
	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 已提交
159 160
	//#region Editor

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

		this._register(this.onDidBlur(() => {
			this.editorFocus?.set(false);
		}));
173 174 175 176 177
	}

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

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

		this.contentWidgets = document.createElement('div');
		DOM.addClass(this.contentWidgets, 'notebook-content-widgets');
		DOM.append(this.body, this.contentWidgets);
P
Peng Lyu 已提交
189 190
	}

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

P
Peng Lyu 已提交
194
		const renders = [
195
			this.instantiationService.createInstance(CodeCellRenderer, this, this.renderedEditors),
P
Peng Lyu 已提交
196
			this.instantiationService.createInstance(MarkdownCellRenderer, this),
P
Peng Lyu 已提交
197 198
		];

R
rebornix 已提交
199 200
		this.list = <NotebookCellList<CellViewModel>>this.instantiationService.createInstance(
			NotebookCellList,
P
Peng Lyu 已提交
201 202 203 204 205 206
			'NotebookCellList',
			this.body,
			this.instantiationService.createInstance(NotebookCellListDelegate),
			renders,
			{
				setRowLineHeight: false,
R
rebornix 已提交
207
				setRowHeight: false,
P
Peng Lyu 已提交
208 209 210
				supportDynamicHeights: true,
				horizontalScrolling: false,
				keyboardSupport: false,
R
rebornix 已提交
211
				mouseSupport: true,
P
Peng Lyu 已提交
212
				multipleSelectionSupport: false,
R
rebornix 已提交
213
				enableKeyboardNavigation: true,
P
Peng Lyu 已提交
214 215 216 217 218 219 220 221 222 223
				overrideStyles: {
					listBackground: editorBackground,
					listActiveSelectionBackground: editorBackground,
					listActiveSelectionForeground: foreground,
					listFocusAndSelectionBackground: editorBackground,
					listFocusAndSelectionForeground: foreground,
					listFocusBackground: editorBackground,
					listFocusForeground: foreground,
					listHoverForeground: foreground,
					listHoverBackground: editorBackground,
224 225
					listHoverOutline: focusBorder,
					listFocusOutline: focusBorder,
226 227 228 229
					listInactiveSelectionBackground: editorBackground,
					listInactiveSelectionForeground: foreground,
					listInactiveFocusBackground: editorBackground,
					listInactiveFocusOutline: editorBackground,
P
Peng Lyu 已提交
230 231 232
				}
			}
		);
P
Peng Lyu 已提交
233

234
		this.control = new NotebookCodeEditors(this.list, this.renderedEditors);
R
rebornix 已提交
235
		this.webview = new BackLayerWebView(this.webviewService, this.notebookService, this, this.environmentSerice);
R
rebornix 已提交
236
		this.list.rowsContainer.appendChild(this.webview.element);
P
Peng Lyu 已提交
237 238 239
		this._register(this.list);
	}

240 241 242 243
	getControl() {
		return this.control;
	}

P
Peng Lyu 已提交
244
	onHide() {
245 246 247

		if (this.webview) {
			this.localStore.clear();
R
rebornix 已提交
248
			this.list?.rowsContainer.removeChild(this.webview?.element);
249 250 251 252 253
			this.webview?.dispose();
			this.webview = null;
		}

		this.list?.splice(0, this.list?.length);
R
rebornix 已提交
254 255 256 257 258 259 260 261

		if (this.model && !this.model.isDirty()) {
			this.notebookService.destoryNotebookDocument(this.viewType!, this.notebook!);
			this.model = undefined;
			this.notebook = undefined;
			this.viewType = undefined;
		}

262
		super.onHide();
P
Peng Lyu 已提交
263 264
	}

265
	setVisible(visible: boolean, group?: IEditorGroup): void {
R
rebornix 已提交
266
		super.setVisible(visible, group);
267
		if (!visible) {
R
rebornix 已提交
268 269 270 271 272
			this.viewCells.forEach(cell => {
				if (cell.getText() !== '') {
					cell.isEditing = false;
				}
			});
273 274 275
		}
	}

P
Peng Lyu 已提交
276
	setInput(input: NotebookEditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
R
rebornix 已提交
277 278 279 280
		if (this.input instanceof NotebookEditorInput) {
			this.saveTextEditorViewState(this.input);
		}

281 282 283 284
		return super.setInput(input, options, token)
			.then(() => {
				return input.resolve();
			})
285
			.then(async model => {
286
				if (this.model !== undefined && this.model === model && this.webview !== null) {
P
Peng Lyu 已提交
287 288 289
					return;
				}

290
				this.localStore.clear();
P
Peng Lyu 已提交
291 292 293 294
				this.viewCells.forEach(cell => {
					cell.save();
				});

295
				if (this.webview) {
R
rebornix 已提交
296
					this.webview?.clearInsets();
297
					this.webview?.clearPreloadsCache();
298
				} else {
R
rebornix 已提交
299
					this.webview = new BackLayerWebView(this.webviewService, this.notebookService, this, this.environmentSerice);
R
rebornix 已提交
300
					this.list?.rowsContainer.insertAdjacentElement('afterbegin', this.webview!.element);
301 302
				}

P
Peng Lyu 已提交
303
				this.model = model;
304 305
				this.localStore.add(this.model.onDidChangeCells((e) => {
					this.updateViewCells(e);
R
rebornix 已提交
306 307
				}));

R
rebornix 已提交
308
				let viewState = this.loadTextEditorViewState(input);
R
rebornix 已提交
309
				this.notebook = model.getNotebook();
310
				this.webview.updateRendererPreloads(this.notebook.renderers);
R
rebornix 已提交
311
				this.viewType = input.viewType;
312
				this.viewCells = await Promise.all(this.notebook!.cells.map(async cell => {
R
rebornix 已提交
313
					const isEditing = viewState && viewState.editingCells[cell.handle];
314
					return this.instantiationService.createInstance(CellViewModel, input.viewType!, this.notebook!.handle, cell, !!isEditing);
315
				}));
316 317 318 319

				const updateScrollPosition = () => {
					let scrollTop = this.list?.scrollTop || 0;
					this.webview!.element.style.top = `${scrollTop}px`;
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
					let updateItems: { cell: CellViewModel, output: IOutput, cellTop: number }[] = [];

					if (this.webview?.insetMapping) {
						this.webview?.insetMapping.forEach((value, key) => {
							let cell = value.cell;
							let index = this.model!.getNotebook().cells.indexOf(cell.cell);
							let cellTop = this.list?.getAbsoluteTop(index) || 0;
							if (this.webview!.shouldUpdateInset(cell, key, cellTop)) {
								updateItems.push({
									cell: cell,
									output: key,
									cellTop: cellTop
								});
							}
						});
335 336 337 338 339

						this.webview?.updateViewScrollTop(-scrollTop, updateItems);
					}
				};
				this.localStore.add(this.list!.onWillScroll(e => {
R
rebornix 已提交
340 341
					// const date = new Date();
					// console.log('----- will scroll ----  ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds());
342 343
					this.webview?.updateViewScrollTop(-e.scrollTop, []);
				}));
344 345 346
				this.localStore.add(this.list!.onDidScroll(() => {
					updateScrollPosition();
				}));
347
				this.localStore.add(this.list!.onDidChangeContentHeight(() => updateScrollPosition()));
R
rebornix 已提交
348 349
				this.localStore.add(this.list!.onFocusChange((e) => {
					if (e.elements.length > 0) {
J
Johannes Rieken 已提交
350
						this.notebookService.updateNotebookActiveCell(input.viewType!, input.resource!, e.elements[0].cell.handle);
R
rebornix 已提交
351 352
					}
				}));
353

354 355
				this.list?.splice(0, this.list?.length);
				this.list?.splice(0, 0, this.viewCells);
356 357
				this.list?.layout();
			});
P
Peng Lyu 已提交
358 359
	}

R
rebornix 已提交
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
	private saveTextEditorViewState(input: NotebookEditorInput): void {
		if (this.group) {
			let state: { [key: number]: boolean } = {};
			this.viewCells.filter(cell => cell.isEditing).forEach(cell => state[cell.cell.handle] = true);
			this.editorMemento.saveEditorState(this.group, input, {
				editingCells: state
			});
		}
	}

	private loadTextEditorViewState(input: NotebookEditorInput): INotebookEditorViewState | undefined {
		if (this.group) {
			return this.editorMemento.loadEditorState(this.group, input);
		}

		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);
		this.list?.layout(dimension.height, dimension.width);
	}

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

		super.saveState();
	}

	//#endregion

	//#region Cell operations
397
	layoutNotebookCell(cell: CellViewModel, height: number) {
R
rebornix 已提交
398
		let relayout = (cell: CellViewModel, height: number) => {
P
Peng Lyu 已提交
399
			let index = this.model!.getNotebook().cells.indexOf(cell.cell);
R
rebornix 已提交
400 401 402
			if (index >= 0) {
				this.list?.updateDynamicHeight(index, cell, height);
			}
R
rebornix 已提交
403 404
		};

R
rebornix 已提交
405
		if (this.list?.isRendering) {
406 407 408 409 410
			// if (this.relayoutDisposable) {
			// 	this.relayoutDisposable.dispose();
			// 	this.relayoutDisposable = null;
			// }
			DOM.scheduleAtNextAnimationFrame(() => {
R
rebornix 已提交
411
				relayout(cell, height);
412
				// this.relayoutDisposable = null;
R
rebornix 已提交
413 414 415 416
			});
		} else {
			relayout(cell, height);
		}
417 418
	}

419 420 421 422 423 424 425
	updateViewCells(splices: NotebookCellsSplice[]) {
		let update = () => splices.reverse().forEach((diff) => {
			this.list?.splice(diff[0], diff[1], diff[2].map(cell => {
				return this.instantiationService.createInstance(CellViewModel, this.viewType!, this.notebook!.handle, cell, false);
			}));
		});

R
rebornix 已提交
426
		if (this.list?.isRendering) {
427 428 429 430
			// if (this.relayoutDisposable) {
			// 	this.relayoutDisposable.dispose();
			// 	this.relayoutDisposable = null;
			// }
431

432
			DOM.scheduleAtNextAnimationFrame(() => {
433
				update();
434
				// this.relayoutDisposable = null;
R
rebornix 已提交
435 436
			});
		} else {
437
			update();
R
rebornix 已提交
438
		}
R
rebornix 已提交
439 440
	}

R
rebornix 已提交
441
	async insertEmptyNotebookCell(listIndex: number | undefined, cell: CellViewModel, type: 'code' | 'markdown', direction: 'above' | 'below'): Promise<void> {
R
rebornix 已提交
442 443 444 445 446
		let newLanguages = this.notebook!.languages;
		let language = 'markdown';
		if (newLanguages && newLanguages.length) {
			language = newLanguages[0];
		}
P
Peng Lyu 已提交
447

448
		let index = listIndex ? listIndex : this.model!.getNotebook().cells.indexOf(cell.cell);
P
Peng Lyu 已提交
449 450
		const insertIndex = direction === 'above' ? index : index + 1;

R
rebornix 已提交
451
		let newModeCell = await this.notebookService.createNotebookCell(this.viewType!, this.notebook!.uri, insertIndex, language, type);
452
		let newCell = this.instantiationService.createInstance(CellViewModel, this.viewType!, this.notebook!.handle, newModeCell!, false);
R
rebornix 已提交
453

P
Peng Lyu 已提交
454 455
		this.viewCells!.splice(insertIndex, 0, newCell);
		this.model!.insertCell(newCell.cell, insertIndex);
P
Peng Lyu 已提交
456
		this.list?.splice(insertIndex, 0, [newCell]);
P
Peng Lyu 已提交
457 458 459 460

		if (type === 'markdown') {
			newCell.isEditing = true;
		}
R
rebornix 已提交
461 462 463 464

		DOM.scheduleAtNextAnimationFrame(() => {
			this.list?.reveal(insertIndex, 0.33);
		});
P
Peng Lyu 已提交
465 466
	}

R
rebornix 已提交
467
	editNotebookCell(listIndex: number | undefined, cell: CellViewModel): void {
P
Peng Lyu 已提交
468 469 470
		cell.isEditing = true;
	}

R
rebornix 已提交
471
	saveNotebookCell(listIndex: number | undefined, cell: CellViewModel): void {
P
Peng Lyu 已提交
472
		cell.isEditing = false;
P
Peng Lyu 已提交
473 474
	}

R
rebornix 已提交
475 476 477 478 479 480 481 482 483 484
	getActiveCell() {
		let elements = this.list?.getFocusedElements();

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

		return undefined;
	}

R
rebornix 已提交
485
	focusNotebookCell(cell: CellViewModel, focusEditor: boolean) {
R
rebornix 已提交
486 487 488 489 490
		let index = this.model!.getNotebook().cells.indexOf(cell.cell);

		if (focusEditor) {

		} else {
R
rebornix 已提交
491
			let itemDOM = this.list?.domElementAtIndex(index);
R
rebornix 已提交
492 493 494
			if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) {
				(document.activeElement as HTMLElement).blur();
			}
495 496

			cell.isEditing = false;
R
rebornix 已提交
497 498 499
		}

		this.list?.setFocus([index]);
R
rebornix 已提交
500
		this.list?.focusView();
R
rebornix 已提交
501 502
	}

R
rebornix 已提交
503
	async deleteNotebookCell(listIndex: number | undefined, cell: CellViewModel): Promise<void> {
P
Peng Lyu 已提交
504
		let index = this.model!.getNotebook().cells.indexOf(cell.cell);
P
Peng Lyu 已提交
505

R
rebornix 已提交
506 507
		// await this.notebookService.createNotebookCell(this.viewType!, this.notebook!.uri, insertIndex, language, type);
		await this.notebookService.deleteNotebookCell(this.viewType!, this.notebook!.uri, index);
P
Peng Lyu 已提交
508 509
		this.viewCells!.splice(index, 1);
		this.model!.deleteCell(cell.cell);
P
Peng Lyu 已提交
510 511 512
		this.list?.splice(index, 1);
	}

R
rebornix 已提交
513 514 515 516 517 518
	//#endregion

	//#region MISC

	getFontInfo(): BareFontInfo | undefined {
		return this.fontInfo;
P
Peng Lyu 已提交
519
	}
R
rebornix 已提交
520

R
rebornix 已提交
521 522 523
	getListDimension(): DOM.Dimension | null {
		return this.dimension;
	}
R
rebornix 已提交
524

R
rebornix 已提交
525 526
	triggerScroll(event: IMouseWheelEvent) {
		this.list?.triggerScrollFromMouseWheelEvent(event);
R
rebornix 已提交
527 528
	}

529
	createInset(cell: CellViewModel, output: IOutput, shadowContent: string, offset: number) {
R
rebornix 已提交
530 531
		if (!this.webview) {
			return;
R
rebornix 已提交
532 533
		}

R
rebornix 已提交
534 535
		let preloads = this.notebook!.renderers;

536
		if (!this.webview!.insetMapping.has(output)) {
R
rebornix 已提交
537
			let index = this.model!.getNotebook().cells.indexOf(cell.cell);
538 539 540
			let cellTop = this.list?.getAbsoluteTop(index) || 0;

			this.webview!.createInset(cell, output, cellTop, offset, shadowContent, preloads);
R
rebornix 已提交
541 542
		} else {
			let index = this.model!.getNotebook().cells.indexOf(cell.cell);
543
			let cellTop = this.list?.getAbsoluteTop(index) || 0;
R
rebornix 已提交
544 545
			let scrollTop = this.list?.scrollTop || 0;

546
			this.webview!.updateViewScrollTop(-scrollTop, [{ cell: cell, output: output, cellTop: cellTop }]);
R
rebornix 已提交
547
		}
R
rebornix 已提交
548
	}
R
rebornix 已提交
549

R
rebornix 已提交
550 551 552 553 554 555 556 557
	removeInset(output: IOutput) {
		if (!this.webview) {
			return;
		}

		this.webview!.removeInset(output);
	}

R
rebornix 已提交
558 559
	getOutputRenderer(): OutputRenderer {
		return this.outputRenderer;
R
rebornix 已提交
560
	}
561

R
rebornix 已提交
562
	//#endregion
P
Peng Lyu 已提交
563 564 565 566 567 568 569
}

const embeddedEditorBackground = 'walkThrough.embeddedEditorBackground';

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 已提交
570 571
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .monaco-editor-background,
			.monaco-workbench .part.editor > .content .notebook-editor .cell .margin-view-overlays { background: ${color}; }`);
P
Peng Lyu 已提交
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
	}
	const link = theme.getColor(textLinkForeground);
	if (link) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor a { color: ${link}; }`);
	}
	const activeLink = theme.getColor(textLinkActiveForeground);
	if (activeLink) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor a:hover,
			.monaco-workbench .part.editor > .content .notebook-editor a:active { color: ${activeLink}; }`);
	}
	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}; }`);
	}
599 600 601 602 603 604

	const inactiveListItem = theme.getColor('list.inactiveSelectionBackground');

	if (inactiveListItem) {
		collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { background-color: ${inactiveListItem}; }`);
	}
605 606 607

	// Cell Margin
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell { padding: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN}px; }`);
608
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 8px ${CELL_MARGIN}px; }`);
P
Peng Lyu 已提交
609
});