notebookEditor.ts 22.2 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 = this._register(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 315 316
					const viewCell = this.instantiationService.createInstance(CellViewModel, input.viewType!, this.notebook!.handle, cell, !!isEditing);
					this.localStore.add(viewCell);
					return viewCell;
317
				}));
318 319 320 321

				const updateScrollPosition = () => {
					let scrollTop = this.list?.scrollTop || 0;
					this.webview!.element.style.top = `${scrollTop}px`;
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
					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
								});
							}
						});
337 338 339 340 341

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

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

R
rebornix 已提交
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 397 398
	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
399
	layoutNotebookCell(cell: CellViewModel, height: number) {
R
rebornix 已提交
400
		let relayout = (cell: CellViewModel, height: number) => {
P
Peng Lyu 已提交
401
			let index = this.model!.getNotebook().cells.indexOf(cell.cell);
R
rebornix 已提交
402 403 404
			if (index >= 0) {
				this.list?.updateDynamicHeight(index, cell, height);
			}
R
rebornix 已提交
405 406
		};

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

421 422 423 424 425 426 427
	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 已提交
428
		if (this.list?.isRendering) {
429 430 431 432
			// if (this.relayoutDisposable) {
			// 	this.relayoutDisposable.dispose();
			// 	this.relayoutDisposable = null;
			// }
433

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

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

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

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

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

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

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

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

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

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

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

		return undefined;
	}

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

		if (focusEditor) {

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

			cell.isEditing = false;
R
rebornix 已提交
499 500 501
		}

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

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

R
rebornix 已提交
508 509
		// 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 已提交
510 511
		this.viewCells!.splice(index, 1);
		this.model!.deleteCell(cell.cell);
P
Peng Lyu 已提交
512 513 514
		this.list?.splice(index, 1);
	}

R
rebornix 已提交
515 516 517 518 519 520
	//#endregion

	//#region MISC

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

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

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

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

R
rebornix 已提交
536 537
		let preloads = this.notebook!.renderers;

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

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

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

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

		this.webview!.removeInset(output);
	}

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

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

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 已提交
572 573
		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 已提交
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 599 600
	}
	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}; }`);
	}
601 602 603 604 605 606

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

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

	// 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; }`);
610
	collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 8px ${CELL_MARGIN}px; }`);
P
Peng Lyu 已提交
611
});