notebookBrowser.ts 13.7 KB
Newer Older
R
rebornix 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
R
rebornix 已提交
7 8
import { IListEvent, IListMouseEvent } from 'vs/base/browser/ui/list/list';
import { IListOptions, IListStyles } from 'vs/base/browser/ui/list/listWidget';
9
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
10
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
11
import { CancellationTokenSource } from 'vs/base/common/cancellation';
R
rebornix 已提交
12 13 14
import { Event } from 'vs/base/common/event';
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { ScrollEvent } from 'vs/base/common/scrollable';
R
rebornix 已提交
15
import { URI } from 'vs/base/common/uri';
16 17 18 19 20
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { Range } from 'vs/editor/common/core/range';
import { FindMatch } from 'vs/editor/common/model';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
21
import { NOTEBOOK_EDITABLE_CONTEXT_KEY, NOTEBOOK_EXECUTING_KEY } from 'vs/workbench/contrib/notebook/browser/constants';
22
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
23
import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
R
rebornix 已提交
24
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
R
rebornix 已提交
25
import { CellKind, IOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
R
rebornix 已提交
26
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
R
rebornix 已提交
27 28

export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey<boolean>('notebookFindWidgetFocused', false);
R
rebornix 已提交
29

30
export const NOTEBOOK_EDITOR_FOCUSED = new RawContextKey<boolean>('notebookEditorFocused', false);
R
rebornix 已提交
31
export const NOTEBOOK_EDITOR_EDITABLE = new RawContextKey<boolean>(NOTEBOOK_EDITABLE_CONTEXT_KEY, true);
32
export const NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK = new RawContextKey<boolean>(NOTEBOOK_EXECUTING_KEY, false);
33

R
rebornix 已提交
34 35 36 37 38 39
export interface NotebookLayoutInfo {
	width: number;
	height: number;
	fontInfo: BareFontInfo;
}

R
rebornix 已提交
40 41 42 43 44 45 46 47 48 49 50
export interface NotebookLayoutChangeEvent {
	width?: boolean;
	height?: boolean;
	fontInfo?: boolean;
}

export interface CodeCellLayoutInfo {
	readonly fontInfo: BareFontInfo | null;
	readonly editorHeight: number;
	readonly editorWidth: number;
	readonly totalHeight: number;
51
	readonly outputContainerOffset: number;
R
rebornix 已提交
52 53
	readonly outputTotalHeight: number;
	readonly indicatorHeight: number;
R
rebornix 已提交
54
	readonly bottomToolbarOffset: number;
R
rebornix 已提交
55 56 57 58 59 60
}

export interface CodeCellLayoutChangeEvent {
	editorHeight?: boolean;
	outputHeight?: boolean;
	totalHeight?: boolean;
R
rebornix 已提交
61 62
	outerWidth?: number;
	font?: BareFontInfo;
R
rebornix 已提交
63 64 65 66 67
}

export interface MarkdownCellLayoutInfo {
	readonly fontInfo: BareFontInfo | null;
	readonly editorWidth: number;
R
rebornix 已提交
68
	readonly bottomToolbarOffset: number;
R
rebornix 已提交
69
	readonly totalHeight: number;
R
rebornix 已提交
70 71 72
}

export interface MarkdownCellLayoutChangeEvent {
R
rebornix 已提交
73 74
	font?: BareFontInfo;
	outerWidth?: number;
R
rebornix 已提交
75
	totalHeight?: number;
R
rebornix 已提交
76 77
}

R
rebornix 已提交
78
export interface ICellViewModel {
R
rebornix 已提交
79
	readonly model: NotebookCellTextModel;
R
rebornix 已提交
80 81 82 83
	readonly id: string;
	handle: number;
	uri: URI;
	cellKind: CellKind;
84
	editState: CellEditState;
85 86
	readonly runState: CellRunState;
	currentTokenSource: CancellationTokenSource | undefined;
R
rebornix 已提交
87 88
	focusMode: CellFocusMode;
	getText(): string;
89
	metadata: NotebookCellMetadata | undefined;
R
rebornix 已提交
90
	getEvaluatedMetadata(documentMetadata: NotebookDocumentMetadata | undefined): NotebookCellMetadata;
R
rebornix 已提交
91 92
}

R
rebornix 已提交
93 94 95 96 97
export interface INotebookEditorMouseEvent {
	readonly event: MouseEvent;
	readonly target: CellViewModel;
}

98
export interface INotebookEditor {
R
rebornix 已提交
99 100 101 102

	/**
	 * Notebook view model attached to the current editor
	 */
R
rebornix 已提交
103
	viewModel: NotebookViewModel | undefined;
R
rebornix 已提交
104

105 106
	isNotebookEditor: boolean;

R
rebornix 已提交
107 108
	getInnerWebview(): Webview | undefined;

R
rebornix 已提交
109 110 111
	/**
	 * Focus the notebook editor cell list
	 */
R
rebornix 已提交
112
	focus(): void;
R
rebornix 已提交
113

R
rebornix 已提交
114 115 116
	/**
	 * Select & focus cell
	 */
R
rebornix 已提交
117
	selectElement(cell: ICellViewModel): void;
R
rebornix 已提交
118

R
rebornix 已提交
119 120 121
	/**
	 * Layout info for the notebook editor
	 */
R
rebornix 已提交
122
	getLayoutInfo(): NotebookLayoutInfo;
R
rebornix 已提交
123 124 125
	/**
	 * Fetch the output renderers for notebook outputs.
	 */
R
rebornix 已提交
126
	getOutputRenderer(): OutputRenderer;
R
rebornix 已提交
127 128 129 130

	/**
	 * Insert a new cell around `cell`
	 */
R
rebornix 已提交
131
	insertNotebookCell(cell: ICellViewModel, type: CellKind, direction: 'above' | 'below', initialText?: string): Promise<void>;
R
rebornix 已提交
132 133 134 135

	/**
	 * Delete a cell from the notebook
	 */
R
rebornix 已提交
136
	deleteNotebookCell(cell: ICellViewModel): void;
R
rebornix 已提交
137

138 139 140
	/**
	 * Move a cell up one spot
	 */
141
	moveCellUp(cell: ICellViewModel): void;
142 143 144 145

	/**
	 * Move a cell down one spot
	 */
146
	moveCellDown(cell: ICellViewModel): void;
147

R
rebornix 已提交
148 149 150 151 152 153
	/**
	 * Switch the cell into editing mode.
	 *
	 * For code cell, the monaco editor will be focused.
	 * For markdown cell, it will switch from preview mode to editing mode, which focuses the monaco editor.
	 */
R
rebornix 已提交
154
	editNotebookCell(cell: ICellViewModel): void;
R
rebornix 已提交
155 156 157 158

	/**
	 * Quit cell editing mode.
	 */
R
rebornix 已提交
159
	saveNotebookCell(cell: ICellViewModel): void;
R
rebornix 已提交
160 161 162 163

	/**
	 * Focus the container of a cell (the monaco editor inside is not focused).
	 */
R
rebornix 已提交
164
	focusNotebookCell(cell: ICellViewModel, focusEditor: boolean): void;
R
rebornix 已提交
165

166 167 168 169 170
	/**
	 * Execute the given notebook cell
	 */
	executeNotebookCell(cell: ICellViewModel): Promise<void>;

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
	/**
	 * Cancel the cell execution
	 */
	cancelNotebookCellExecution(cell: ICellViewModel): void;

	/**
	 * Executes all notebook cells in order
	 */
	executeNotebook(): Promise<void>;

	/**
	 * Cancel the notebook execution
	 */
	cancelNotebookExecution(): void;

R
rebornix 已提交
186 187 188
	/**
	 * Get current active cell
	 */
R
rebornix 已提交
189
	getActiveCell(): ICellViewModel | undefined;
R
rebornix 已提交
190 191 192 193

	/**
	 * Layout the cell with a new height
	 */
194
	layoutNotebookCell(cell: ICellViewModel, height: number): Promise<void>;
R
rebornix 已提交
195 196 197 198

	/**
	 * Render the output in webview layer
	 */
R
rebornix 已提交
199
	createInset(cell: ICellViewModel, output: IOutput, shadowContent: string, offset: number): void;
R
rebornix 已提交
200 201 202 203

	/**
	 * Remove the output from the webview layer
	 */
R
rebornix 已提交
204
	removeInset(output: IOutput): void;
R
rebornix 已提交
205

206 207 208 209 210
	/**
	 * Send message to the webview for outputs.
	 */
	postMessage(message: any): void;

R
rebornix 已提交
211 212 213
	/**
	 * Trigger the editor to scroll from scroll event programmatically
	 */
214
	triggerScroll(event: IMouseWheelEvent): void;
R
rebornix 已提交
215 216 217 218

	/**
	 * Reveal cell into viewport.
	 */
R
rebornix 已提交
219
	revealInView(cell: ICellViewModel): void;
R
rebornix 已提交
220 221 222 223

	/**
	 * Reveal cell into viewport center.
	 */
R
rebornix 已提交
224
	revealInCenter(cell: ICellViewModel): void;
R
rebornix 已提交
225 226 227 228

	/**
	 * Reveal cell into viewport center if cell is currently out of the viewport.
	 */
R
rebornix 已提交
229
	revealInCenterIfOutsideViewport(cell: ICellViewModel): void;
R
rebornix 已提交
230 231 232 233

	/**
	 * Reveal a line in notebook cell into viewport with minimal scrolling.
	 */
R
rebornix 已提交
234
	revealLineInView(cell: ICellViewModel, line: number): void;
R
rebornix 已提交
235

R
rebornix 已提交
236 237 238
	/**
	 * Reveal a line in notebook cell into viewport center.
	 */
R
rebornix 已提交
239
	revealLineInCenter(cell: ICellViewModel, line: number): void;
R
rebornix 已提交
240 241 242 243

	/**
	 * Reveal a line in notebook cell into viewport center.
	 */
R
rebornix 已提交
244
	revealLineInCenterIfOutsideViewport(cell: ICellViewModel, line: number): void;
R
rebornix 已提交
245

R
rebornix 已提交
246 247 248
	/**
	 * Reveal a range in notebook cell into viewport with minimal scrolling.
	 */
R
rebornix 已提交
249
	revealRangeInView(cell: ICellViewModel, range: Range): void;
R
rebornix 已提交
250 251 252 253

	/**
	 * Reveal a range in notebook cell into viewport center.
	 */
R
rebornix 已提交
254
	revealRangeInCenter(cell: ICellViewModel, range: Range): void;
R
rebornix 已提交
255 256 257 258

	/**
	 * Reveal a range in notebook cell into viewport center.
	 */
R
rebornix 已提交
259
	revealRangeInCenterIfOutsideViewport(cell: ICellViewModel, range: Range): void;
R
rebornix 已提交
260

R
rebornix 已提交
261 262 263 264 265
	/**
	 * Set hidden areas on cell text models.
	 */
	setHiddenAreas(_ranges: ICellRange[]): boolean;

R
rebornix 已提交
266
	setCellSelection(cell: ICellViewModel, selection: Range): void;
R
rebornix 已提交
267

R
rebornix 已提交
268 269 270 271
	/**
	 * Change the decorations on cells.
	 * The notebook is virtualized and this method should be called to create/delete editor decorations safely.
	 */
R
rebornix 已提交
272
	changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any;
R
rebornix 已提交
273 274 275 276 277 278

	/**
	 * Show Find Widget.
	 *
	 * Currently Find is still part of the NotebookEditor core
	 */
R
rebornix 已提交
279
	showFind(): void;
R
rebornix 已提交
280 281 282 283

	/**
	 * Hide Find Widget
	 */
R
rebornix 已提交
284
	hideFind(): void;
R
rebornix 已提交
285 286 287 288 289 290 291 292 293 294 295 296

	/**
	 * An event emitted on a "mouseup".
	 * @event
	 */
	onMouseUp(listener: (e: INotebookEditorMouseEvent) => void): IDisposable;

	/**
	 * An event emitted on a "mousedown".
	 * @event
	 */
	onMouseDown(listener: (e: INotebookEditorMouseEvent) => void): IDisposable;
R
rebornix 已提交
297 298
}

R
rebornix 已提交
299 300 301 302 303 304 305 306 307 308
export interface INotebookCellList {
	onWillScroll: Event<ScrollEvent>;
	onDidChangeFocus: Event<IListEvent<ICellViewModel>>;
	onDidChangeContentHeight: Event<number>;
	scrollTop: number;
	scrollHeight: number;
	scrollLeft: number;
	length: number;
	rowsContainer: HTMLElement;
	readonly onDidRemoveOutput: Event<IOutput>;
R
rebornix 已提交
309 310
	readonly onMouseUp: Event<IListMouseEvent<CellViewModel>>;
	readonly onMouseDown: Event<IListMouseEvent<CellViewModel>>;
R
rebornix 已提交
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
	detachViewModel(): void;
	attachViewModel(viewModel: NotebookViewModel): void;
	clear(): void;
	focusElement(element: ICellViewModel): void;
	selectElement(element: ICellViewModel): void;
	getFocusedElements(): ICellViewModel[];
	revealElementInView(element: ICellViewModel): void;
	revealElementInCenterIfOutsideViewport(element: ICellViewModel): void;
	revealElementInCenter(element: ICellViewModel): void;
	revealElementLineInView(element: ICellViewModel, line: number): void;
	revealElementLineInCenter(element: ICellViewModel, line: number): void;
	revealElementLineInCenterIfOutsideViewport(element: ICellViewModel, line: number): void;
	revealElementRangeInView(element: ICellViewModel, range: Range): void;
	revealElementRangeInCenter(element: ICellViewModel, range: Range): void;
	revealElementRangeInCenterIfOutsideViewport(element: ICellViewModel, range: Range): void;
R
rebornix 已提交
326
	setHiddenAreas(_ranges: ICellRange[]): boolean;
R
rebornix 已提交
327 328 329 330 331 332 333 334 335 336 337 338 339
	domElementOfElement(element: ICellViewModel): HTMLElement | null;
	focusView(): void;
	getAbsoluteTopOfElement(element: ICellViewModel): number;
	triggerScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent): void;
	updateElementHeight2(element: ICellViewModel, size: number): void;
	domFocus(): void;
	setCellSelection(element: ICellViewModel, range: Range): void;
	style(styles: IListStyles): void;
	updateOptions(options: IListOptions<ICellViewModel>): void;
	layout(height?: number, width?: number): void;
	dispose(): void;
}

340
export interface BaseCellRenderTemplate {
R
rebornix 已提交
341 342
	container: HTMLElement;
	cellContainer: HTMLElement;
343
	toolbar: ToolBar;
344
	focusIndicator: HTMLElement;
345
	disposables: DisposableStore;
R
rebornix 已提交
346
	bottomCellContainer: HTMLElement;
R
rebornix 已提交
347
	toJSON: () => any;
348 349 350 351
}

export interface MarkdownCellRenderTemplate extends BaseCellRenderTemplate {
	editingContainer: HTMLElement;
R
rebornix 已提交
352
	foldingIndicator: HTMLElement;
353 354 355
}

export interface CodeCellRenderTemplate extends BaseCellRenderTemplate {
R
Rob Lourens 已提交
356 357 358 359
	statusBarContainer: HTMLElement;
	cellRunStatusContainer: HTMLElement;
	cellStatusMessageContainer: HTMLElement;
	cellStatusPlaceholderContainer: HTMLElement;
360 361 362 363 364 365
	runToolbar: ToolBar;
	runButtonContainer: HTMLElement;
	executionOrderLabel: HTMLElement;
	outputContainer: HTMLElement;
	editor: CodeEditorWidget;
	progressBar: ProgressBar;
R
rebornix 已提交
366
}
R
rebornix 已提交
367 368 369 370 371 372 373 374 375

export interface IOutputTransformContribution {
	/**
	 * Dispose this contribution.
	 */
	dispose(): void;

	render(output: IOutput, container: HTMLElement, preferredMimeType: string | undefined): IRenderOutput;
}
R
rebornix 已提交
376 377 378 379 380 381

export interface CellFindMatch {
	cell: CellViewModel;
	matches: FindMatch[];
}

R
rebornix 已提交
382 383 384 385 386 387 388 389 390
export enum CellRevealType {
	Line,
	Range
}

export enum CellRevealPosition {
	Top,
	Center
}
R
rebornix 已提交
391

392 393 394 395 396 397
export enum CellRunState {
	Idle,
	Running
}

export enum CellEditState {
R
rebornix 已提交
398 399 400 401 402
	/**
	 * Default state.
	 * For markdown cell, it's Markdown preview.
	 * For code cell, the browser focus should be on the container instead of the editor
	 */
403
	Preview,
R
rebornix 已提交
404 405 406 407 408 409 410


	/**
	 * Eding mode. Source for markdown or code is rendered in editors and the state will be persistent.
	 */
	Editing
}
R
rebornix 已提交
411 412 413 414 415 416 417 418 419 420 421 422

export enum CellFocusMode {
	Container,
	Editor
}

export enum CursorAtBoundary {
	None,
	Top,
	Bottom,
	Both
}
R
rebornix 已提交
423

424 425 426 427 428 429 430 431 432
export interface CellViewModelStateChangeEvent {
	metadataChanged?: boolean;
	selectionChanged?: boolean;
	focusModeChanged?: boolean;
	runStateChanged?: boolean;
	editStateChanged?: boolean;
	languageChanged?: boolean;
}

R
rebornix 已提交
433
/**
R
rebornix 已提交
434
 * [start, start + length - 1]
R
rebornix 已提交
435 436
 */
export interface ICellRange {
R
rebornix 已提交
437 438 439
	/**
	 * zero based index
	 */
R
rebornix 已提交
440
	start: number;
R
rebornix 已提交
441 442 443
	/**
	 * One based, includes `start`
	 */
R
rebornix 已提交
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
	length: number;
}


/**
 * @param _ranges
 */
export function reduceCellRanges(_ranges: ICellRange[]): ICellRange[] {
	if (!_ranges.length) {
		return [];
	}

	let ranges = _ranges.sort((a, b) => a.start - b.start);
	let result: ICellRange[] = [];
	let currentRangeStart = ranges[0].start;
	let currentRangeEnd = ranges[0].start + ranges[0].length;

	for (let i = 0, len = ranges.length; i < len; i++) {
		let range = ranges[i];

		if (range.start > currentRangeEnd) {
			result.push({ start: currentRangeStart, length: currentRangeEnd - currentRangeStart });
			currentRangeStart = range.start;
			currentRangeEnd = range.start + range.length;
		} else if (range.start + range.length > currentRangeEnd) {
			currentRangeEnd = range.start + range.length;
		}
	}

	result.push({ start: currentRangeStart, length: currentRangeEnd - currentRangeStart });
	return result;
}

export function getVisibleCells(cells: CellViewModel[], hiddenRanges: ICellRange[]) {
	if (!hiddenRanges.length) {
		return cells;
	}

	let start = 0;
	let hiddenRangeIndex = 0;
	let result: any[] = [];

	while (start < cells.length && hiddenRangeIndex < hiddenRanges.length) {
		if (start < hiddenRanges[hiddenRangeIndex].start) {
			result.push(...cells.slice(start, hiddenRanges[hiddenRangeIndex].start));
		}

		start = hiddenRanges[hiddenRangeIndex].start + hiddenRanges[hiddenRangeIndex].length;
		hiddenRangeIndex++;
	}

	if (start < cells.length) {
		result.push(...cells.slice(start));
	}

	return result;
}