notebookBrowser.ts 14.0 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
Rob Lourens 已提交
148 149 150 151 152
	/**
	 * Move a cell above or below another cell
	 */
	moveCell(cell: ICellViewModel, relativeToCell: ICellViewModel, direction: 'above' | 'below'): Promise<void>;

R
rebornix 已提交
153 154 155 156 157 158
	/**
	 * 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 已提交
159
	editNotebookCell(cell: ICellViewModel): void;
R
rebornix 已提交
160 161 162 163

	/**
	 * Quit cell editing mode.
	 */
R
rebornix 已提交
164
	saveNotebookCell(cell: ICellViewModel): void;
R
rebornix 已提交
165 166 167 168

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

171 172 173 174 175
	/**
	 * Execute the given notebook cell
	 */
	executeNotebookCell(cell: ICellViewModel): Promise<void>;

176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
	/**
	 * 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 已提交
191 192 193
	/**
	 * Get current active cell
	 */
R
rebornix 已提交
194
	getActiveCell(): ICellViewModel | undefined;
R
rebornix 已提交
195 196 197 198

	/**
	 * Layout the cell with a new height
	 */
199
	layoutNotebookCell(cell: ICellViewModel, height: number): Promise<void>;
R
rebornix 已提交
200 201 202 203

	/**
	 * Render the output in webview layer
	 */
R
rebornix 已提交
204
	createInset(cell: ICellViewModel, output: IOutput, shadowContent: string, offset: number): void;
R
rebornix 已提交
205 206 207 208

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

211 212 213 214 215
	/**
	 * Send message to the webview for outputs.
	 */
	postMessage(message: any): void;

R
rebornix 已提交
216 217 218
	/**
	 * Trigger the editor to scroll from scroll event programmatically
	 */
219
	triggerScroll(event: IMouseWheelEvent): void;
R
rebornix 已提交
220 221 222 223

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

	/**
	 * Reveal cell into viewport center.
	 */
R
rebornix 已提交
229
	revealInCenter(cell: ICellViewModel): void;
R
rebornix 已提交
230 231 232 233

	/**
	 * Reveal cell into viewport center if cell is currently out of the viewport.
	 */
R
rebornix 已提交
234
	revealInCenterIfOutsideViewport(cell: ICellViewModel): void;
R
rebornix 已提交
235 236 237 238

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

R
rebornix 已提交
241 242 243
	/**
	 * Reveal a line in notebook cell into viewport center.
	 */
R
rebornix 已提交
244
	revealLineInCenter(cell: ICellViewModel, line: number): void;
R
rebornix 已提交
245 246 247 248

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

R
rebornix 已提交
251 252 253
	/**
	 * Reveal a range in notebook cell into viewport with minimal scrolling.
	 */
R
rebornix 已提交
254
	revealRangeInView(cell: ICellViewModel, range: Range): void;
R
rebornix 已提交
255 256 257 258

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

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

R
rebornix 已提交
266 267 268 269 270
	/**
	 * Set hidden areas on cell text models.
	 */
	setHiddenAreas(_ranges: ICellRange[]): boolean;

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

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

	/**
	 * Show Find Widget.
	 *
	 * Currently Find is still part of the NotebookEditor core
	 */
R
rebornix 已提交
284
	showFind(): void;
R
rebornix 已提交
285 286 287 288

	/**
	 * Hide Find Widget
	 */
R
rebornix 已提交
289
	hideFind(): void;
R
rebornix 已提交
290 291 292 293 294 295 296 297 298 299 300 301

	/**
	 * 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 已提交
302 303
}

R
rebornix 已提交
304 305 306 307 308 309 310 311 312 313
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 已提交
314 315
	readonly onMouseUp: Event<IListMouseEvent<CellViewModel>>;
	readonly onMouseDown: Event<IListMouseEvent<CellViewModel>>;
R
rebornix 已提交
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
	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 已提交
331
	setHiddenAreas(_ranges: ICellRange[]): boolean;
R
rebornix 已提交
332 333 334 335 336 337 338 339 340 341 342 343 344
	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;
}

345
export interface BaseCellRenderTemplate {
R
rebornix 已提交
346 347
	container: HTMLElement;
	cellContainer: HTMLElement;
R
Rob Lourens 已提交
348
	dragHandle: HTMLElement;
349
	toolbar: ToolBar;
350
	focusIndicator: HTMLElement;
R
Rob Lourens 已提交
351
	insertionIndicatorTop: HTMLElement;
352
	disposables: DisposableStore;
R
rebornix 已提交
353
	bottomCellContainer: HTMLElement;
R
Rob Lourens 已提交
354
	currentRenderedCell?: ICellViewModel;
R
rebornix 已提交
355
	toJSON: () => any;
356 357 358 359
}

export interface MarkdownCellRenderTemplate extends BaseCellRenderTemplate {
	editingContainer: HTMLElement;
R
rebornix 已提交
360
	foldingIndicator: HTMLElement;
361 362 363
}

export interface CodeCellRenderTemplate extends BaseCellRenderTemplate {
R
Rob Lourens 已提交
364 365 366 367
	statusBarContainer: HTMLElement;
	cellRunStatusContainer: HTMLElement;
	cellStatusMessageContainer: HTMLElement;
	cellStatusPlaceholderContainer: HTMLElement;
368 369 370 371 372 373
	runToolbar: ToolBar;
	runButtonContainer: HTMLElement;
	executionOrderLabel: HTMLElement;
	outputContainer: HTMLElement;
	editor: CodeEditorWidget;
	progressBar: ProgressBar;
R
rebornix 已提交
374
}
R
rebornix 已提交
375 376 377 378 379 380 381 382 383

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

	render(output: IOutput, container: HTMLElement, preferredMimeType: string | undefined): IRenderOutput;
}
R
rebornix 已提交
384 385 386 387 388 389

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

R
rebornix 已提交
390 391 392 393 394 395 396 397 398
export enum CellRevealType {
	Line,
	Range
}

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

400 401 402 403 404 405
export enum CellRunState {
	Idle,
	Running
}

export enum CellEditState {
R
rebornix 已提交
406 407 408 409 410
	/**
	 * Default state.
	 * For markdown cell, it's Markdown preview.
	 * For code cell, the browser focus should be on the container instead of the editor
	 */
411
	Preview,
R
rebornix 已提交
412 413 414 415 416 417 418


	/**
	 * Eding mode. Source for markdown or code is rendered in editors and the state will be persistent.
	 */
	Editing
}
R
rebornix 已提交
419 420 421 422 423 424 425 426 427 428 429 430

export enum CellFocusMode {
	Container,
	Editor
}

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

432 433 434 435 436 437 438
export interface CellViewModelStateChangeEvent {
	metadataChanged?: boolean;
	selectionChanged?: boolean;
	focusModeChanged?: boolean;
	runStateChanged?: boolean;
	editStateChanged?: boolean;
	languageChanged?: boolean;
R
rebornix 已提交
439 440
	foldingStateChanged?: boolean;
	contentChanged?: boolean;
441 442
}

R
rebornix 已提交
443
/**
R
rebornix 已提交
444
 * [start, start + length - 1]
R
rebornix 已提交
445 446
 */
export interface ICellRange {
R
rebornix 已提交
447 448 449
	/**
	 * zero based index
	 */
R
rebornix 已提交
450
	start: number;
R
rebornix 已提交
451 452 453
	/**
	 * One based, includes `start`
	 */
R
rebornix 已提交
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 501 502 503 504 505 506 507 508 509 510
	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;
}