diff --git a/packages/notebook/src/browser/service/notebook-cell-editor-service.ts b/packages/notebook/src/browser/service/notebook-cell-editor-service.ts index e1d338a4b7602..53268eb62b4ec 100644 --- a/packages/notebook/src/browser/service/notebook-cell-editor-service.ts +++ b/packages/notebook/src/browser/service/notebook-cell-editor-service.ts @@ -15,12 +15,17 @@ // ***************************************************************************** import { Emitter, URI } from '@theia/core'; -import { injectable } from '@theia/core/shared/inversify'; +import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; import { SimpleMonacoEditor } from '@theia/monaco/lib/browser/simple-monaco-editor'; +import { NotebookEditorWidgetService } from './notebook-editor-widget-service'; +import { CellUri } from '../../common'; @injectable() export class NotebookCellEditorService { + @inject(NotebookEditorWidgetService) + protected readonly notebookEditorWidgetService: NotebookEditorWidgetService; + protected onDidChangeCellEditorsEmitter = new Emitter(); readonly onDidChangeCellEditors = this.onDidChangeCellEditorsEmitter.event; @@ -31,6 +36,17 @@ export class NotebookCellEditorService { protected currentCellEditors: Map = new Map(); + @postConstruct() + protected init(): void { + this.notebookEditorWidgetService.onDidChangeCurrentEditor(editor => { + // if defocus notebook editor or another notebook editor is focused, clear the active cell + if (!editor || (this.currentActiveCell && CellUri.parse(this.currentActiveCell.uri)?.notebook.toString() !== editor?.model?.uri.toString())) { + this.currentActiveCell = undefined; + this.onDidChangeFocusedCellEditorEmitter.fire(undefined); + } + }); + } + get allCellEditors(): SimpleMonacoEditor[] { return Array.from(this.currentCellEditors.values()); } @@ -46,8 +62,10 @@ export class NotebookCellEditorService { } editorFocusChanged(editor?: SimpleMonacoEditor): void { - this.currentActiveCell = editor; - this.onDidChangeFocusedCellEditorEmitter.fire(editor); + if (editor) { + this.currentActiveCell = editor; + this.onDidChangeFocusedCellEditorEmitter.fire(editor); + } } getActiveCell(): SimpleMonacoEditor | undefined { diff --git a/packages/notebook/src/browser/service/notebook-editor-widget-service.ts b/packages/notebook/src/browser/service/notebook-editor-widget-service.ts index b585834ce6013..c54faa00db166 100644 --- a/packages/notebook/src/browser/service/notebook-editor-widget-service.ts +++ b/packages/notebook/src/browser/service/notebook-editor-widget-service.ts @@ -45,13 +45,23 @@ export class NotebookEditorWidgetService { protected readonly onDidChangeFocusedEditorEmitter = new Emitter(); readonly onDidChangeFocusedEditor = this.onDidChangeFocusedEditorEmitter.event; + protected readonly onDidChangeCurrentEditorEmitter = new Emitter(); + readonly onDidChangeCurrentEditor = this.onDidChangeCurrentEditorEmitter.event; + focusedEditor?: NotebookEditorWidget = undefined; + currentEditor?: NotebookEditorWidget = undefined; + @postConstruct() protected init(): void { this.applicationShell.onDidChangeActiveWidget(event => { this.notebookEditorFocusChanged(event.newValue as NotebookEditorWidget, event.newValue instanceof NotebookEditorWidget); }); + this.applicationShell.onDidChangeCurrentWidget(event => { + if (event.newValue instanceof NotebookEditorWidget || event.oldValue instanceof NotebookEditorWidget) { + this.currentNotebookEditorChanged(event.newValue); + } + }); } // --- editor management @@ -98,4 +108,14 @@ export class NotebookEditorWidgetService { } } + currentNotebookEditorChanged(newEditor: unknown): void { + if (newEditor instanceof NotebookEditorWidget) { + this.currentEditor = newEditor; + this.onDidChangeCurrentEditorEmitter.fire(newEditor); + } else if (this.currentEditor?.isDisposed || !this.currentEditor?.isVisible) { + this.currentEditor = undefined; + this.onDidChangeCurrentEditorEmitter.fire(undefined); + } + } + } diff --git a/packages/plugin-ext/src/main/browser/editors-and-documents-main.ts b/packages/plugin-ext/src/main/browser/editors-and-documents-main.ts index f88d72dc27b0b..18af7ae744aed 100644 --- a/packages/plugin-ext/src/main/browser/editors-and-documents-main.ts +++ b/packages/plugin-ext/src/main/browser/editors-and-documents-main.ts @@ -250,7 +250,7 @@ class EditorAndDocumentStateComputer implements Disposable { this.toDispose.push(this.cellEditorService.onDidChangeCellEditors(() => this.update())); - this.toDispose.push(this.notebookWidgetService.onDidChangeFocusedEditor(() => { + this.toDispose.push(this.notebookWidgetService.onDidChangeCurrentEditor(() => { this.currentState = this.currentState && new EditorAndDocumentState( this.currentState.documents, this.currentState.editors, diff --git a/packages/plugin-ext/src/main/browser/notebooks/notebook-documents-and-editors-main.ts b/packages/plugin-ext/src/main/browser/notebooks/notebook-documents-and-editors-main.ts index 11285a9f55101..87efcbb53de12 100644 --- a/packages/plugin-ext/src/main/browser/notebooks/notebook-documents-and-editors-main.ts +++ b/packages/plugin-ext/src/main/browser/notebooks/notebook-documents-and-editors-main.ts @@ -55,7 +55,6 @@ class NotebookAndEditorState { const documentDelta = diffSets(before.documents, after.documents); const editorDelta = diffMaps(before.textEditors, after.textEditors); - const newActiveEditor = before.activeEditor !== after.activeEditor ? after.activeEditor : undefined; const visibleEditorDelta = diffMaps(before.visibleEditors, after.visibleEditors); return { @@ -63,7 +62,7 @@ class NotebookAndEditorState { removedDocuments: documentDelta.removed.map(e => e.uri.toComponents()), addedEditors: editorDelta.added, removedEditors: editorDelta.removed.map(removed => removed.id), - newActiveEditor: newActiveEditor, + newActiveEditor: after.activeEditor, visibleEditors: visibleEditorDelta.added.length === 0 && visibleEditorDelta.removed.length === 0 ? undefined : [...after.visibleEditors].map(editor => editor[0]) @@ -114,7 +113,7 @@ export class NotebooksAndEditorsMain implements NotebookDocumentsAndEditorsMain // this.WidgetManager.onActiveEditorChanged(() => this.updateState(), this, this.disposables); this.notebookEditorService.onDidAddNotebookEditor(async editor => this.handleEditorAdd(editor), this, this.disposables); this.notebookEditorService.onDidRemoveNotebookEditor(async editor => this.handleEditorRemove(editor), this, this.disposables); - this.notebookEditorService.onDidChangeFocusedEditor(async editor => this.updateState(editor), this, this.disposables); + this.notebookEditorService.onDidChangeCurrentEditor(async editor => this.updateState(editor), this, this.disposables); } dispose(): void { @@ -221,7 +220,7 @@ export class NotebooksAndEditorsMain implements NotebookDocumentsAndEditorsMain if (delta.visibleEditors?.length) { return false; } - if (delta.newActiveEditor) { + if (delta.newActiveEditor !== undefined) { return false; } return true; diff --git a/packages/plugin-ext/src/plugin/notebook/notebooks.ts b/packages/plugin-ext/src/plugin/notebook/notebooks.ts index 5470495d402ec..d31d9554ca2ac 100644 --- a/packages/plugin-ext/src/plugin/notebook/notebooks.ts +++ b/packages/plugin-ext/src/plugin/notebook/notebooks.ts @@ -341,7 +341,7 @@ export class NotebooksExtImpl implements NotebooksExt { }); } } - if (delta.newActiveEditor !== undefined) { + if (delta.newActiveEditor !== undefined && delta.newActiveEditor !== this.activeNotebookEditor?.id) { this.onDidChangeActiveNotebookEditorEmitter.fire(this.activeNotebookEditor?.apiEditor); } }