notebookEditor.ts 22.5 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 23
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { WorkbenchList } from 'vs/platform/list/browser/listService';
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';
24
import { EditorOptions, IEditorMemento, ICompositeCodeEditor } from 'vs/workbench/common/editor';
25
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
R
rebornix 已提交
26
import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
27
import { INotebookService, parseCellUri } from 'vs/workbench/contrib/notebook/browser/notebookService';
R
rebornix 已提交
28
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/output/outputRenderer';
R
rebornix 已提交
29 30 31
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';
32
import { CELL_MARGIN, INotebook, NotebookCellsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon';
R
rebornix 已提交
33 34 35
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 已提交
36
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
37
import { IEditor } from 'vs/editor/common/editorCommon';
J
Johannes Rieken 已提交
38
import { IResourceInput } from 'vs/platform/editor/common/editor';
39
import { Emitter, Event } from 'vs/base/common/event';
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 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
class NotebookCodeEditors implements ICompositeCodeEditor {

	private readonly _onDidChangeActiveEditor = new Emitter<this>();
	readonly onDidChangeActiveEditor: Event<this> = this._onDidChangeActiveEditor.event;

	constructor(
		private _list: WorkbenchList<CellViewModel>,
		private _renderedEditors: Map<CellViewModel, ICodeEditor | undefined>
	) { }

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

	activate(input: IResourceInput): ICodeEditor | undefined {
		const result = this._doActivate(input);
		this._onDidChangeActiveEditor.fire(this);
		return result;
	}

	private _doActivate(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;
	}
}

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

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

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

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

P
Peng Lyu 已提交
148

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

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

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

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

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

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

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

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

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

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

238 239 240 241
	getControl() {
		return this.control;
	}

P
Peng Lyu 已提交
242
	onHide() {
R
rebornix 已提交
243 244 245 246 247
		this.viewCells.forEach(cell => {
			if (cell.getText() !== '') {
				cell.isEditing = false;
			}
		});
248 249 250 251 252 253 254 255 256

		if (this.webview) {
			this.localStore.clear();
			this.list?.view.rowsContainer.removeChild(this.webview?.element);
			this.webview?.dispose();
			this.webview = null;
		}

		this.list?.splice(0, this.list?.length);
R
rebornix 已提交
257 258 259 260 261 262 263 264

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

265
		super.onHide();
P
Peng Lyu 已提交
266 267
	}

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

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

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

293
				this.localStore.clear();
P
Peng Lyu 已提交
294 295 296 297
				this.viewCells.forEach(cell => {
					cell.save();
				});

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

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

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

				const updateScrollPosition = () => {
					let scrollTop = this.list?.scrollTop || 0;
					this.webview!.element.style.top = `${scrollTop}px`;
					let updateItems: { top: number, id: string }[] = [];

R
rebornix 已提交
325
					// const date = new Date();
326 327
					this.webview?.mapping.forEach((item) => {
						let index = this.model!.getNotebook().cells.indexOf(item.cell.cell);
R
rebornix 已提交
328
						let top = this.list?.getAbsoluteTop(index) || 0;
R
rebornix 已提交
329
						let newTop = this.webview!.shouldRenderInset(item.cell.id, top);
330 331 332 333 334 335 336 337 338 339

						if (newTop !== undefined) {
							updateItems.push({
								top: newTop,
								id: item.cell.id
							});
						}
					});

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		return undefined;
	}

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

		if (focusEditor) {

		} else {
			let itemDOM = this.list?.view.domElement(index);
			if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) {
				(document.activeElement as HTMLElement).blur();
			}
498 499

			cell.isEditing = false;
R
rebornix 已提交
500 501 502 503 504 505
		}

		this.list?.setFocus([index]);
		this.list?.view.domNode.focus();
	}

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

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

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

	//#region MISC

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

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

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

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

R
rebornix 已提交
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
		let preloads = this.notebook!.renderers;

		if (!this.webview!.mapping.has(cell.id)) {
			let index = this.model!.getNotebook().cells.indexOf(cell.cell);
			let top = this.list?.getAbsoluteTop(index) || 0;
			this.webview!.createInset(cell, offset, shadowContent, top + offset, preloads);
			this.webview!.outputMapping.set(cell.id + `-${outputIndex}`, true);
		} else if (!this.webview!.outputMapping.has(cell.id + `-${outputIndex}`)) {
			let index = this.model!.getNotebook().cells.indexOf(cell.cell);
			let top = this.list?.getAbsoluteTop(index) || 0;
			this.webview!.outputMapping.set(cell.id + `-${outputIndex}`, true);
			this.webview!.createInset(cell, offset, shadowContent, top + offset, preloads);
		} else {
			let index = this.model!.getNotebook().cells.indexOf(cell.cell);
			let top = this.list?.getAbsoluteTop(index) || 0;
			let scrollTop = this.list?.scrollTop || 0;

			this.webview!.updateViewScrollTop(-scrollTop, [{ id: cell.id, top: top + offset }]);
R
rebornix 已提交
555
		}
R
rebornix 已提交
556
	}
R
rebornix 已提交
557

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
});