diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index f98ed6bb833..61521a984a2 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -420,9 +420,9 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo const editors = new Map(); this._notebookService.listNotebookEditors().forEach(editor => { - if (editor.hasModel()) { + if (editor.textModel) { editors.set(editor.getId(), editor); - documentEditorsMap.set(editor.textModel!.uri.toString(), editor); + documentEditorsMap.set(editor.textModel.uri.toString(), editor); } }); @@ -441,7 +441,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo documents.add(document); }); - if (!activeEditor && focusedNotebookEditor && focusedNotebookEditor.hasModel()) { + if (!activeEditor && focusedNotebookEditor && focusedNotebookEditor.textModel) { activeEditor = focusedNotebookEditor.getId(); } @@ -666,8 +666,11 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo const editor = this._notebookService.listNotebookEditors().find(editor => editor.getId() === id); if (editor && editor.isNotebookEditor) { const notebookEditor = editor as INotebookEditor; + if (!notebookEditor.hasModel()) { + return; + } const viewModel = notebookEditor.viewModel; - const cell = viewModel?.viewCells[range.start]; + const cell = viewModel.viewCells[range.start]; if (!cell) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index ca084aea984..aaf6e480c55 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -22,7 +22,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { CATEGORIES } from 'vs/workbench/common/actions'; -import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, IActiveNotebookEditor, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -103,7 +103,7 @@ const enum CellOverflowToolbarGroups { export interface INotebookActionContext { readonly cellTemplate?: BaseCellRenderTemplate; readonly cell?: ICellViewModel; - readonly notebookEditor: INotebookEditor; + readonly notebookEditor: INotebookEditor & IActiveNotebookEditor; readonly ui?: boolean; } @@ -162,6 +162,10 @@ abstract class NotebookAction extends Action2 { return; } + if (!editor.hasModel()) { + return; + } + const activeCell = editor.getActiveCell(); return { cell: activeCell, @@ -385,7 +389,7 @@ registerAction2(class extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - const idx = context.notebookEditor.viewModel?.getCellIndex(context.cell); + const idx = context.notebookEditor.viewModel.getCellIndex(context.cell); if (typeof idx !== 'number') { return; } @@ -393,7 +397,7 @@ registerAction2(class extends NotebookCellAction { const executionP = runCell(accessor, context); // Try to select below, fall back on inserting - const nextCell = context.notebookEditor.viewModel?.viewCells[idx + 1]; + const nextCell = context.notebookEditor.viewModel.viewCells[idx + 1]; if (nextCell) { context.notebookEditor.focusNotebookCell(nextCell, 'container'); } else { @@ -471,7 +475,7 @@ registerAction2(class extends NotebookAction { }); function renderAllMarkdownCells(context: INotebookActionContext): void { - context.notebookEditor.viewModel!.viewCells.forEach(cell => { + context.notebookEditor.viewModel.viewCells.forEach(cell => { if (cell.cellKind === CellKind.Markdown) { cell.editState = CellEditState.Preview; } @@ -907,14 +911,14 @@ registerAction2(class extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext) { - const index = context.notebookEditor.viewModel!.getCellIndex(context.cell); + const index = context.notebookEditor.viewModel.getCellIndex(context.cell); const result = await context.notebookEditor.deleteNotebookCell(context.cell); if (result) { // deletion succeeds, move focus to the next cell - const nextCellIdx = index < context.notebookEditor.viewModel!.length ? index : context.notebookEditor.viewModel!.length - 1; + const nextCellIdx = index < context.notebookEditor.viewModel.length ? index : context.notebookEditor.viewModel.length - 1; if (nextCellIdx >= 0) { - context.notebookEditor.focusNotebookCell(context.notebookEditor.viewModel!.viewCells[nextCellIdx], 'container'); + context.notebookEditor.focusNotebookCell(context.notebookEditor.viewModel.viewCells[nextCellIdx], 'container'); } } } @@ -1141,7 +1145,7 @@ registerAction2(class extends NotebookCellAction { return; } - const currCellIndex = viewModel.getCellIndex(context!.cell); + const currCellIndex = viewModel.getCellIndex(context.cell); let topPastedCell: CellViewModel | undefined = undefined; pasteCells.items.reverse().map(cell => { @@ -1239,12 +1243,12 @@ registerAction2(class extends NotebookCellAction { const editor = context.notebookEditor; const activeCell = context.cell; - const idx = editor.viewModel?.getCellIndex(activeCell); + const idx = editor.viewModel.getCellIndex(activeCell); if (typeof idx !== 'number') { return; } - const newCell = editor.viewModel?.viewCells[idx + 1]; + const newCell = editor.viewModel.viewCells[idx + 1]; if (!newCell) { return; @@ -1278,7 +1282,7 @@ registerAction2(class extends NotebookCellAction { const editor = context.notebookEditor; const activeCell = context.cell; - const idx = editor.viewModel?.getCellIndex(activeCell); + const idx = editor.viewModel.getCellIndex(activeCell); if (typeof idx !== 'number') { return; } @@ -1288,7 +1292,7 @@ registerAction2(class extends NotebookCellAction { return; } - const newCell = editor.viewModel?.viewCells[idx - 1]; + const newCell = editor.viewModel.viewCells[idx - 1]; if (!newCell) { return; @@ -1429,7 +1433,7 @@ registerAction2(class extends NotebookCellAction { editor.viewModel.notebookDocument.applyEdits(editor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Output, index, outputs: [] }], true, undefined, () => undefined, undefined); if (context.cell.metadata && context.cell.metadata?.runState !== NotebookCellRunState.Running) { - context.notebookEditor.viewModel!.notebookDocument.applyEdits(context.notebookEditor.viewModel!.notebookDocument.versionId, [{ + context.notebookEditor.viewModel.notebookDocument.applyEdits(context.notebookEditor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Metadata, index, metadata: { ...context.cell.metadata, runState: NotebookCellRunState.Idle, @@ -1468,7 +1472,7 @@ export class ChangeCellLanguageAction extends NotebookCellAction { const modelService = accessor.get(IModelService); const quickInputService = accessor.get(IQuickInputService); - const providerLanguages = [...context.notebookEditor.viewModel!.notebookDocument.resolvedLanguages, 'markdown']; + const providerLanguages = [...context.notebookEditor.viewModel.notebookDocument.resolvedLanguages, 'markdown']; providerLanguages.forEach(languageId => { let description: string; if (context.cell.cellKind === CellKind.Markdown ? (languageId === 'markdown') : (languageId === context.cell.language)) { @@ -1517,9 +1521,9 @@ export class ChangeCellLanguageAction extends NotebookCellAction { } else if (selection.languageId !== 'markdown' && context.cell?.cellKind === CellKind.Markdown) { await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor }, selection.languageId); } else { - const index = context.notebookEditor.viewModel!.notebookDocument.cells.indexOf(context.cell.model); - context.notebookEditor.viewModel!.notebookDocument.applyEdits( - context.notebookEditor.viewModel!.notebookDocument.versionId, + const index = context.notebookEditor.viewModel.notebookDocument.cells.indexOf(context.cell.model); + context.notebookEditor.viewModel.notebookDocument.applyEdits( + context.notebookEditor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.CellLanguage, index, language: selection.languageId }], true, undefined, () => undefined, undefined ); @@ -1591,7 +1595,7 @@ registerAction2(class extends NotebookAction { } }).filter(edit => !!edit) as ICellEditOperation[]; if (clearExecutionMetadataEdits.length) { - context.notebookEditor.viewModel!.notebookDocument.applyEdits(context.notebookEditor.viewModel!.notebookDocument.versionId, clearExecutionMetadataEdits, true, undefined, () => undefined, undefined); + context.notebookEditor.viewModel.notebookDocument.applyEdits(context.notebookEditor.viewModel.notebookDocument.versionId, clearExecutionMetadataEdits, true, undefined, () => undefined, undefined); } } }); @@ -1715,7 +1719,7 @@ registerAction2(class extends NotebookCellAction { abstract class ChangeNotebookCellMetadataAction extends NotebookCellAction { async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { const cell = context.cell; - const textModel = context.notebookEditor.viewModel?.notebookDocument; + const textModel = context.notebookEditor.viewModel.notebookDocument; if (!textModel) { return; } @@ -1842,6 +1846,10 @@ registerAction2(class extends Action2 { return; } + if (!editor.hasModel()) { + return; + } + const activeCell = editor.getActiveCell(); return { cell: activeCell, @@ -1853,7 +1861,7 @@ registerAction2(class extends Action2 { const activeEditorContext = this.getActiveEditorContext(accessor); if (activeEditorContext) { - const viewModel = activeEditorContext.notebookEditor.viewModel!; + const viewModel = activeEditorContext.notebookEditor.viewModel; console.log('--- notebook ---'); console.log(viewModel.layoutInfo); console.log('--- cells ---'); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 0a135c6fed9..7e79b196107 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -207,6 +207,11 @@ export interface INotebookEditorCreationOptions { readonly contributions?: INotebookEditorContributionDescription[]; } +export interface IActiveNotebookEditor { + viewModel: NotebookViewModel; + uri: URI; +} + export interface INotebookEditor extends IEditor { isEmbedded: boolean; @@ -216,6 +221,7 @@ export interface INotebookEditor extends IEditor { * Notebook view model attached to the current editor */ viewModel: NotebookViewModel | undefined; + hasModel(): this is IActiveNotebookEditor; /** * An event emitted when the model of this editor has changed. diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 32961c25b84..b6dd38b2980 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -42,7 +42,7 @@ import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellEditState, CellFocusMode, ICellViewModel, INotebookCellList, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellViewModel, INotebookCellList, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; import { NotebookKernelProviderAssociation, NotebookKernelProviderAssociations, notebookKernelProviderAssociationsSettingId } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation'; import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList'; @@ -288,7 +288,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return this.viewModel?.selectionHandles || []; } - hasModel() { + hasModel(): this is IActiveNotebookEditor { return !!this._notebookViewModel; } @@ -337,7 +337,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor // a descendent of the notebook editor root. const focused = DOM.isAncestor(document.activeElement, this._overlayContainer); this._editorFocus?.set(focused); - this._notebookViewModel?.setFocus(focused); + this.viewModel?.setFocus(focused); } hasFocus() { @@ -624,8 +624,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webview?.focusWebview(); } else { const focus = this._list?.getFocus()[0]; - if (typeof focus === 'number' && this._notebookViewModel) { - const element = this._notebookViewModel.viewCells[focus]; + if (typeof focus === 'number' && this.viewModel) { + const element = this.viewModel.viewCells[focus]; if (element.focusMode === CellFocusMode.Editor) { element.editState = CellEditState.Editing; @@ -646,7 +646,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async setModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined): Promise { - if (this._notebookViewModel === undefined || !this._notebookViewModel.equal(textModel)) { + if (this.viewModel === undefined || !this.viewModel.equal(textModel)) { this._detachModel(); await this._attachModel(textModel, viewState); } else { @@ -685,9 +685,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor async setOptions(options: NotebookEditorOptions | undefined) { // reveal cell if editor options tell to do so - if (options?.cellOptions && this._notebookViewModel) { + if (options?.cellOptions && this.viewModel) { const cellOptions = options.cellOptions; - const cell = this._notebookViewModel.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); + const cell = this.viewModel.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); if (cell) { this.selectElement(cell); await this.revealInCenterIfOutsideViewportAsync(cell); @@ -719,7 +719,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._list?.detachViewModel(); this.viewModel?.dispose(); // avoid event - this._notebookViewModel = undefined; + this.viewModel = undefined; // this.webview?.clearInsets(); // this.webview?.clearPreloadsCache(); this._webview?.dispose(); @@ -1068,7 +1068,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } if (viewState?.editorFocused) { - const cell = this._notebookViewModel?.viewCells[focusIdx]; + const cell = this.viewModel?.viewCells[focusIdx]; if (cell) { cell.focusMode = CellFocusMode.Editor; } @@ -1076,7 +1076,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } getEditorViewState(): INotebookEditorViewState { - const state = this._notebookViewModel?.getEditorViewState(); + const state = this.viewModel?.getEditorViewState(); if (!state) { return { editingCells: {}, @@ -1099,8 +1099,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor state.cellTotalHeights = cellHeights; const focus = this._list.getFocus()[0]; - if (typeof focus === 'number' && this._notebookViewModel) { - const element = this._notebookViewModel.viewCells[focus]; + if (typeof focus === 'number' && this.viewModel) { + const element = this.viewModel.viewCells[focus]; if (element) { const itemDOM = this._list?.domElementOfElement(element); const editorFocused = !!(document.activeElement && itemDOM && itemDOM.contains(document.activeElement)); @@ -1237,7 +1237,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } changeModelDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T | null { - return this._notebookViewModel?.changeModelDecorations(callback) || null; + return this.viewModel?.changeModelDecorations(callback) || null; } setHiddenAreas(_ranges: ICellRange[]): boolean { @@ -1355,15 +1355,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } private _nearestCodeCellIndex(index: number /* exclusive */, direction: 'above' | 'below') { - if (!this._notebookViewModel) { + if (!this.viewModel) { return -1; } - const nearest = this._notebookViewModel.viewCells.slice(0, index).reverse().findIndex(cell => cell.cellKind === CellKind.Code); + const nearest = this.viewModel.viewCells.slice(0, index).reverse().findIndex(cell => cell.cellKind === CellKind.Code); if (nearest > -1) { return index - nearest - 1; } else { - const nearestCellTheOtherDirection = this._notebookViewModel.viewCells.slice(index + 1).findIndex(cell => cell.cellKind === CellKind.Code); + const nearestCellTheOtherDirection = this.viewModel.viewCells.slice(index + 1).findIndex(cell => cell.cellKind === CellKind.Code); if (nearestCellTheOtherDirection > -1) { return index + nearestCellTheOtherDirection; } @@ -1372,16 +1372,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } insertNotebookCell(cell: ICellViewModel | undefined, type: CellKind, direction: 'above' | 'below' = 'above', initialText: string = '', ui: boolean = false): CellViewModel | null { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = cell ? this._notebookViewModel.getCellIndex(cell) : 0; - const nextIndex = ui ? this._notebookViewModel.getNextVisibleCellIndex(index) : index + 1; + const index = cell ? this.viewModel.getCellIndex(cell) : 0; + const nextIndex = ui ? this.viewModel.getNextVisibleCellIndex(index) : index + 1; let language; if (type === CellKind.Code) { if (cell?.cellKind === CellKind.Code) { @@ -1389,16 +1389,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } else if (cell?.cellKind === CellKind.Markdown) { const nearestCodeCellIndex = this._nearestCodeCellIndex(index, direction); if (nearestCodeCellIndex > -1) { - language = this._notebookViewModel.viewCells[nearestCodeCellIndex].language; + language = this.viewModel.viewCells[nearestCodeCellIndex].language; } else { - language = this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; + language = this.viewModel.resolvedLanguages[0] || 'plaintext'; } } else { if (cell === undefined && direction === 'above') { // insert cell at the very top - language = this._notebookViewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; + language = this.viewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || this.viewModel.resolvedLanguages[0] || 'plaintext'; } else { - language = this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; + language = this.viewModel.resolvedLanguages[0] || 'plaintext'; } } } else { @@ -1409,35 +1409,35 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor (direction === 'above' ? index : nextIndex) : index; const focused = this._list?.getFocusedElements(); - const newCell = this._notebookViewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); + const newCell = this.viewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); return newCell as CellViewModel; } async splitNotebookCell(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = this._notebookViewModel.getCellIndex(cell); + const index = this.viewModel.getCellIndex(cell); - return this._notebookViewModel.splitNotebookCell(index); + return this.viewModel.splitNotebookCell(index); } async joinNotebookCells(cell: ICellViewModel, direction: 'above' | 'below', constraint?: CellKind): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = this._notebookViewModel.getCellIndex(cell); - const ret = await this._notebookViewModel.joinNotebookCells(index, direction, constraint); + const index = this.viewModel.getCellIndex(cell); + const ret = await this.viewModel.joinNotebookCells(index, direction, constraint); if (ret) { ret.deletedCells.forEach(cell => { @@ -1453,11 +1453,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async deleteNotebookCell(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return false; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return false; } @@ -1465,22 +1465,22 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.pendingLayouts.get(cell)!.dispose(); } - const index = this._notebookViewModel.getCellIndex(cell); - this._notebookViewModel.deleteCell(index, true); + const index = this.viewModel.getCellIndex(cell); + this.viewModel.deleteCell(index, true); return true; } async moveCellDown(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = this._notebookViewModel.getCellIndex(cell); - if (index === this._notebookViewModel.length - 1) { + const index = this.viewModel.getCellIndex(cell); + if (index === this.viewModel.length - 1) { return null; } @@ -1489,15 +1489,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async moveCellUp(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = this._notebookViewModel.getCellIndex(cell); + const index = this.viewModel.getCellIndex(cell); if (index === 0) { return null; } @@ -1507,11 +1507,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async moveCell(cell: ICellViewModel, relativeToCell: ICellViewModel, direction: 'above' | 'below'): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } @@ -1519,19 +1519,19 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return null; } - const originalIdx = this._notebookViewModel.getCellIndex(cell); - const relativeToIndex = this._notebookViewModel.getCellIndex(relativeToCell); + const originalIdx = this.viewModel.getCellIndex(cell); + const relativeToIndex = this.viewModel.getCellIndex(relativeToCell); const newIdx = direction === 'above' ? relativeToIndex : relativeToIndex + 1; return this._moveCellToIndex(originalIdx, 1, newIdx); } async moveCellsToIdx(index: number, length: number, toIdx: number): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } @@ -1544,7 +1544,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor * @example to move the cell from index 0 down one spot, call with (0, 2) */ private async _moveCellToIndex(index: number, length: number, desiredIndex: number): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } @@ -1557,7 +1557,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return null; } - if (!this._notebookViewModel.moveCellToIdx(index, length, desiredIndex, true)) { + if (!this.viewModel.moveCellToIdx(index, length, desiredIndex, true)) { throw new Error('Notebook Editor move cell, index out of range'); } @@ -1568,12 +1568,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - if (!this._notebookViewModel) { + if (!this.viewModel) { r(null); return; } - const viewCell = this._notebookViewModel.viewCells[desiredIndex]; + const viewCell = this.viewModel.viewCells[desiredIndex]; this._list?.revealElementInView(viewCell); r(viewCell); }); @@ -1582,11 +1582,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } editNotebookCell(cell: CellViewModel): void { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } - if (!cell.getEvaluatedMetadata(this._notebookViewModel.metadata).editable) { + if (!cell.getEvaluatedMetadata(this.viewModel.metadata).editable) { return; } @@ -1694,33 +1694,33 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async cancelNotebookExecution(): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } - if (this._notebookViewModel.metadata.runState !== NotebookRunState.Running) { + if (this.viewModel.metadata.runState !== NotebookRunState.Running) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel.uri, undefined); + await this._activeKernel?.cancelNotebookCell!(this.viewModel.uri, undefined); } async executeNotebook(): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } - if (!this._notebookViewModel.runnable) { + if (!this.viewModel.runnable) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.executeNotebookCell!(this._notebookViewModel.uri, undefined); + await this._activeKernel?.executeNotebookCell!(this.viewModel.uri, undefined); } async cancelNotebookCellExecution(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } @@ -1728,7 +1728,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - const metadata = cell.getEvaluatedMetadata(this._notebookViewModel.metadata); + const metadata = cell.getEvaluatedMetadata(this.viewModel.metadata); if (!metadata.runnable) { return; } @@ -1738,11 +1738,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } await this._ensureActiveKernel(); - await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel.uri, cell.handle); + await this._activeKernel?.cancelNotebookCell!(this.viewModel.uri, cell.handle); } async executeNotebookCell(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } @@ -1751,12 +1751,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - if (!cell.getEvaluatedMetadata(this._notebookViewModel.metadata).runnable) { + if (!cell.getEvaluatedMetadata(this.viewModel.metadata).runnable) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.executeNotebookCell!(this._notebookViewModel.uri, cell.handle); + await this._activeKernel?.executeNotebookCell!(this.viewModel.uri, cell.handle); } focusNotebookCell(cell: ICellViewModel, focusItem: 'editor' | 'container' | 'output') { @@ -1803,7 +1803,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor //#region MISC deltaCellDecorations(oldDecorations: string[], newDecorations: INotebookDeltaDecoration[]): string[] { - return this._notebookViewModel?.deltaCellDecorations(oldDecorations, newDecorations) || []; + return this.viewModel?.deltaCellDecorations(oldDecorations, newDecorations) || []; } deltaCellOutputContainerClassNames(cellId: string, added: string[], removed: string[]) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index b8c2a1172b9..5560bbeb119 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -252,7 +252,10 @@ export class CellLanguageStatusBarItem extends Disposable { private run() { this.instantiationService.invokeFunction(accessor => { - new ChangeCellLanguageAction().run(accessor, { notebookEditor: this.editor!, cell: this.cell! }); + if (!this.editor || !this.editor.hasModel() || !this.cell) { + return; + } + new ChangeCellLanguageAction().run(accessor, { notebookEditor: this.editor, cell: this.cell }); }); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 0760fbf4d82..bbc8ee2374c 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -86,7 +86,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod this._layoutInfo = { fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorHeight: 0, - editorWidth: initialNotebookLayoutInfo ? this.computeEditorWidth(initialNotebookLayoutInfo!.width) : 0, + editorWidth: initialNotebookLayoutInfo ? this.computeEditorWidth(initialNotebookLayoutInfo.width) : 0, outputContainerOffset: 0, outputTotalHeight: 0, outputShowMoreContainerHeight: 0, diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 0a9b17b2139..941f4a479c4 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -748,7 +748,6 @@ export interface IEditor extends editorCommon.ICompositeCodeEditor { textModel?: NotebookTextModel; getId(): string; hasFocus(): boolean; - hasModel(): boolean; } export enum NotebookEditorPriority {