44 *--------------------------------------------------------------------------------------------*/
55
66import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers' ;
7- import { MainContext , MainThreadNotebookShape , NotebookExtensionDescription , IExtHostContext , ExtHostNotebookShape , ExtHostContext } from '../common/extHost.protocol' ;
8- import { Disposable } from 'vs/base/common/lifecycle' ;
7+ import { MainContext , MainThreadNotebookShape , NotebookExtensionDescription , IExtHostContext , ExtHostNotebookShape , ExtHostContext , INotebookDocumentsAndEditorsDelta } from '../common/extHost.protocol' ;
8+ import { Disposable , IDisposable , combinedDisposable } from 'vs/base/common/lifecycle' ;
99import { URI , UriComponents } from 'vs/base/common/uri' ;
1010import { INotebookService , IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService' ;
11- import { INotebookTextModel , INotebookMimeTypeSelector , NOTEBOOK_DISPLAY_ORDER , NotebookCellOutputsSplice , NotebookDocumentMetadata , NotebookCellMetadata , ICellEditOperation , ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER , CellEditType , CellKind , INotebookKernelInfo , INotebookKernelInfoDto , INotebookTextModelBackup } from 'vs/workbench/contrib/notebook/common/notebookCommon' ;
11+ import { INotebookTextModel , INotebookMimeTypeSelector , NOTEBOOK_DISPLAY_ORDER , NotebookCellOutputsSplice , NotebookDocumentMetadata , NotebookCellMetadata , ICellEditOperation , ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER , CellEditType , CellKind , INotebookKernelInfo , INotebookKernelInfoDto , INotebookTextModelBackup , IEditor } from 'vs/workbench/contrib/notebook/common/notebookCommon' ;
1212import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
1313import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel' ;
1414import { IEditorService } from 'vs/workbench/services/editor/common/editorService' ;
@@ -58,11 +58,77 @@ export class MainThreadNotebookDocument extends Disposable {
5858 }
5959}
6060
61+ class DocumentAndEditorState {
62+ static ofMaps < K , V > ( before : Map < K , V > , after : Map < K , V > ) : { removed : V [ ] , added : V [ ] } {
63+ const removed : V [ ] = [ ] ;
64+ const added : V [ ] = [ ] ;
65+ before . forEach ( ( value , index ) => {
66+ if ( ! after . has ( index ) ) {
67+ removed . push ( value ) ;
68+ }
69+ } ) ;
70+ after . forEach ( ( value , index ) => {
71+ if ( ! before . has ( index ) ) {
72+ added . push ( value ) ;
73+ }
74+ } ) ;
75+ return { removed, added } ;
76+ }
77+
78+ static compute ( before : DocumentAndEditorState | undefined , after : DocumentAndEditorState ) : INotebookDocumentsAndEditorsDelta {
79+ if ( ! before ) {
80+ const apiEditors = [ ] ;
81+ for ( let id in after . textEditors ) {
82+ const editor = after . textEditors . get ( id ) ! ;
83+ apiEditors . push ( { id, documentUri : editor . uri ! , selections : editor ! . textModel ! . selections } ) ;
84+ }
85+
86+ return {
87+ addedDocuments : [ ] ,
88+ addedEditors : apiEditors
89+ } ;
90+ }
91+ // const documentDelta = delta.ofSets(before.documents, after.documents);
92+ const editorDelta = DocumentAndEditorState . ofMaps ( before . textEditors , after . textEditors ) ;
93+ const addedAPIEditors = editorDelta . added . map ( add => ( {
94+ id : add . getId ( ) ,
95+ documentUri : add . uri ! ,
96+ selections : add . textModel ! . selections
97+ } ) ) ;
98+
99+ const removedAPIEditors = editorDelta . removed . map ( removed => removed . getId ( ) ) ;
100+
101+ // const oldActiveEditor = before.activeEditor !== after.activeEditor ? before.activeEditor : undefined;
102+ const newActiveEditor = before . activeEditor !== after . activeEditor ? after . activeEditor : undefined ;
103+
104+ // return new DocumentAndEditorStateDelta(
105+ // documentDelta.removed, documentDelta.added,
106+ // editorDelta.removed, editorDelta.added,
107+ // oldActiveEditor, newActiveEditor
108+ // );
109+ return {
110+ addedEditors : addedAPIEditors ,
111+ removedEditors : removedAPIEditors ,
112+ newActiveEditor : newActiveEditor
113+ } ;
114+ }
115+
116+ constructor (
117+ readonly documents : Set < URI > ,
118+ readonly textEditors : Map < string , IEditor > ,
119+ readonly activeEditor : string | null | undefined ,
120+ ) {
121+ //
122+ }
123+ }
124+
61125@extHostNamedCustomer ( MainContext . MainThreadNotebook )
62126export class MainThreadNotebooks extends Disposable implements MainThreadNotebookShape {
63127 private readonly _notebookProviders = new Map < string , MainThreadNotebookController > ( ) ;
64128 private readonly _notebookKernels = new Map < string , MainThreadNotebookKernel > ( ) ;
65129 private readonly _proxy : ExtHostNotebookShape ;
130+ private _toDisposeOnEditorRemove = new Map < string , IDisposable > ( ) ;
131+ private _currentState ?: DocumentAndEditorState ;
66132
67133 constructor (
68134 extHostContext : IExtHostContext ,
@@ -90,10 +156,18 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
90156 registerListeners ( ) {
91157 this . _register ( this . _notebookService . onDidChangeActiveEditor ( e => {
92158 this . _proxy . $acceptDocumentAndEditorsDelta ( {
93- newActiveEditor : e . uri
159+ newActiveEditor : e
94160 } ) ;
95161 } ) ) ;
96162
163+ this . _register ( this . _notebookService . onNotebookEditorAdd ( editor => {
164+ this . _addNotebookEditor ( editor ) ;
165+ } ) ) ;
166+
167+ this . _register ( this . _notebookService . onNotebookEditorRemove ( editor => {
168+ this . _removeNotebookEditor ( editor ) ;
169+ } ) ) ;
170+
97171 const updateOrder = ( ) => {
98172 let userOrder = this . configurationService . getValue < string [ ] > ( 'notebook.displayOrder' ) ;
99173 this . _proxy . $acceptDisplayOrder ( {
@@ -115,6 +189,57 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
115189 } ) ) ;
116190 }
117191
192+ private _addNotebookEditor ( e : IEditor ) {
193+ this . _toDisposeOnEditorRemove . set ( e . getId ( ) , combinedDisposable (
194+ e . onDidChangeModel ( ( ) => this . _updateState ( ) ) ,
195+ e . onDidFocusEditorWidget ( ( ) => this . _updateState ( e ) ) ,
196+ ) ) ;
197+
198+ this . _updateState ( ) ;
199+ }
200+
201+ private _removeNotebookEditor ( e : IEditor ) {
202+ const sub = this . _toDisposeOnEditorRemove . get ( e . getId ( ) ) ;
203+ if ( sub ) {
204+ this . _toDisposeOnEditorRemove . delete ( e . getId ( ) ) ;
205+ sub . dispose ( ) ;
206+ this . _updateState ( ) ;
207+ }
208+ }
209+
210+ private async _updateState ( focusedNotebookEditor ?: IEditor ) {
211+ const documents = new Set < URI > ( ) ;
212+ this . _notebookService . listNotebookDocuments ( ) . forEach ( document => {
213+ documents . add ( document . uri ) ;
214+ } ) ;
215+
216+ const editors = new Map < string , IEditor > ( ) ;
217+ let activeEditor : string | null = null ;
218+
219+ for ( const editor of this . _notebookService . listNotebookEditors ( ) ) {
220+ if ( editor . hasModel ( ) ) {
221+ editors . set ( editor . getId ( ) , editor ) ;
222+ if ( editor . hasFocus ( ) ) {
223+ activeEditor = editor . getId ( ) ;
224+ }
225+ }
226+ }
227+
228+ // editors always have view model attached, which means there is already a document in exthost.
229+ const newState = new DocumentAndEditorState ( documents , editors , activeEditor ) ;
230+ const delta = DocumentAndEditorState . compute ( this . _currentState , newState ) ;
231+ // const isEmptyChange = (!delta.addedDocuments || delta.addedDocuments.length === 0)
232+ // && (!delta.removedDocuments || delta.removedDocuments.length === 0)
233+ // && (!delta.addedEditors || delta.addedEditors.length === 0)
234+ // && (!delta.removedEditors || delta.removedEditors.length === 0)
235+ // && (delta.newActiveEditor === undefined)
236+
237+ // if (!isEmptyChange) {
238+ this . _currentState = newState ;
239+ await this . _proxy . $acceptDocumentAndEditorsDelta ( delta ) ;
240+ // }
241+ }
242+
118243 async $registerNotebookRenderer ( extension : NotebookExtensionDescription , type : string , selectors : INotebookMimeTypeSelector , handle : number , preloads : UriComponents [ ] ) : Promise < void > {
119244 this . _notebookService . registerNotebookRenderer ( handle , extension , type , selectors , preloads . map ( uri => URI . revive ( uri ) ) ) ;
120245 }
0 commit comments