Skip to content

Commit

Permalink
re #102503. visible range change events.
Browse files Browse the repository at this point in the history
  • Loading branch information
rebornix committed Aug 28, 2020
1 parent fdf2910 commit 637d782
Show file tree
Hide file tree
Showing 17 changed files with 315 additions and 63 deletions.
17 changes: 17 additions & 0 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,11 @@ declare module 'vscode' {
delete(index: number): void;
}

export interface NotebookCellRange {
readonly start: number;
readonly end: number;
}

export interface NotebookEditor {
/**
* The document associated with this notebook editor.
Expand All @@ -1374,6 +1379,12 @@ declare module 'vscode' {
*/
readonly selection?: NotebookCell;


/**
* The current visible ranges in the editor (vertically).
*/
readonly visibleRanges: NotebookCellRange[];

/**
* The column in which this editor shows.
*/
Expand Down Expand Up @@ -1485,6 +1496,11 @@ declare module 'vscode' {
readonly selection?: NotebookCell;
}

export interface NotebookEditorVisibleRangesChangeEvent {
readonly notebookEditor: NotebookEditor;
readonly visibleRanges: ReadonlyArray<NotebookCellRange>;
}

export interface NotebookCellData {
readonly cellKind: CellKind;
readonly source: string;
Expand Down Expand Up @@ -1707,6 +1723,7 @@ declare module 'vscode' {
export const activeNotebookEditor: NotebookEditor | undefined;
export const onDidChangeActiveNotebookEditor: Event<NotebookEditor | undefined>;
export const onDidChangeNotebookEditorSelection: Event<NotebookEditorSelectionChangeEvent>;
export const onDidChangeNotebookEditorVisibleRanges: Event<NotebookEditorVisibleRangesChangeEvent>;
export const onDidChangeNotebookCells: Event<NotebookCellsChangeEvent>;
export const onDidChangeCellOutputs: Event<NotebookCellOutputsChangeEvent>;
export const onDidChangeCellLanguage: Event<NotebookCellLanguageChangeEvent>;
Expand Down
73 changes: 52 additions & 21 deletions src/vs/workbench/api/browser/mainThreadNotebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class DocumentAndEditorState {
const apiEditors = [];
for (let id in after.textEditors) {
const editor = after.textEditors.get(id)!;
apiEditors.push({ id, documentUri: editor.uri!, selections: editor!.textModel!.selections });
apiEditors.push({ id, documentUri: editor.uri!, selections: editor!.textModel!.selections, visibleRanges: editor.visibleRanges });
}

return {
Expand All @@ -74,7 +74,8 @@ class DocumentAndEditorState {
const addedAPIEditors = editorDelta.added.map(add => ({
id: add.getId(),
documentUri: add.uri!,
selections: add.textModel!.selections || []
selections: add.textModel!.selections || [],
visibleRanges: add.visibleRanges
}));

const removedAPIEditors = editorDelta.removed.map(removed => removed.getId());
Expand Down Expand Up @@ -137,6 +138,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
private _toDisposeOnEditorRemove = new Map<string, IDisposable>();
private _currentState?: DocumentAndEditorState;
private _editorEventListenersMapping: Map<string, DisposableStore> = new Map();
private _documentEventListenersMapping: Map<string, DisposableStore> = new Map();
private readonly _cellStatusBarEntries: Map<number, IDisposable> = new Map();

constructor(
Expand Down Expand Up @@ -166,9 +168,9 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
async removeNotebookTextModel(uri: URI): Promise<void> {
// TODO@rebornix, remove cell should use emitDelta as well to ensure document/editor events are sent together
this._proxy.$acceptDocumentAndEditorsDelta({ removedDocuments: [uri] });
let textModelDisposableStore = this._editorEventListenersMapping.get(uri.toString());
let textModelDisposableStore = this._documentEventListenersMapping.get(uri.toString());
textModelDisposableStore?.dispose();
this._editorEventListenersMapping.delete(URI.from(uri).toString());
this._documentEventListenersMapping.delete(URI.from(uri).toString());
}

private _isDeltaEmpty(delta: INotebookDocumentsAndEditorsDelta) {
Expand Down Expand Up @@ -228,38 +230,67 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
}
}));

const notebookEditorAddedHandler = (editor: IEditor) => {
if (!this._editorEventListenersMapping.has(editor.getId())) {
const disposableStore = new DisposableStore();
disposableStore.add(editor.onDidChangeVisibleRanges(() => {
this._proxy.$acceptEditorPropertiesChanged(editor.getId(), { visibleRanges: { ranges: editor.visibleRanges } });
}));

this._editorEventListenersMapping.set(editor.getId(), disposableStore);
}
};

this._register(this._notebookService.onNotebookEditorAdd(editor => {
notebookEditorAddedHandler(editor);
this._addNotebookEditor(editor);
}));

this._register(this._notebookService.onNotebookEditorsRemove(editors => {
this._removeNotebookEditor(editors);

editors.forEach(editor => {
this._editorEventListenersMapping.get(editor.getId())?.dispose();
this._editorEventListenersMapping.delete(editor.getId());
});
}));

this._notebookService.listNotebookEditors().forEach(editor => {
notebookEditorAddedHandler(editor);
});

const notebookDocumentAddedHandler = (doc: URI) => {
if (!this._editorEventListenersMapping.has(doc.toString())) {
const disposableStore = new DisposableStore();
const textModel = this._notebookService.getNotebookTextModel(doc);
disposableStore.add(textModel!.onDidModelChangeProxy(e => {
this._proxy.$acceptModelChanged(textModel!.uri, e, textModel!.isDirty);
this._proxy.$acceptDocumentPropertiesChanged(doc, { selections: { selections: textModel!.selections }, metadata: null });
}));
disposableStore.add(textModel!.onDidSelectionChange(e => {
const selectionsChange = e ? { selections: e } : null;
this._proxy.$acceptDocumentPropertiesChanged(doc, { selections: selectionsChange, metadata: null });
}));

this._editorEventListenersMapping.set(textModel!.uri.toString(), disposableStore);
}
};

this._register(this._notebookService.onNotebookDocumentAdd((documents) => {
documents.forEach(doc => {
if (!this._editorEventListenersMapping.has(doc.toString())) {
const disposableStore = new DisposableStore();
const textModel = this._notebookService.getNotebookTextModel(doc);
disposableStore.add(textModel!.onDidModelChangeProxy(e => {
this._proxy.$acceptModelChanged(textModel!.uri, e, textModel!.isDirty);
this._proxy.$acceptEditorPropertiesChanged(doc, { selections: { selections: textModel!.selections }, metadata: null });
}));
disposableStore.add(textModel!.onDidSelectionChange(e => {
const selectionsChange = e ? { selections: e } : null;
this._proxy.$acceptEditorPropertiesChanged(doc, { selections: selectionsChange, metadata: null });
}));

this._editorEventListenersMapping.set(textModel!.uri.toString(), disposableStore);
}
notebookDocumentAddedHandler(doc);
});
this._updateState();
}));

this._notebookService.listNotebookDocuments().forEach((doc) => {
notebookDocumentAddedHandler(doc.uri);
});

this._register(this._notebookService.onNotebookDocumentRemove((documents) => {
documents.forEach(doc => {
this._editorEventListenersMapping.get(doc.toString())?.dispose();
this._editorEventListenersMapping.delete(doc.toString());
this._documentEventListenersMapping.get(doc.toString())?.dispose();
this._documentEventListenersMapping.delete(doc.toString());
});

this._updateState();
Expand Down Expand Up @@ -420,7 +451,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
textModel.insertTemplateCell(mainCell);
}

this._proxy.$acceptEditorPropertiesChanged(textModel.uri, { selections: null, metadata: textModel.metadata });
this._proxy.$acceptDocumentPropertiesChanged(textModel.uri, { selections: null, metadata: textModel.metadata });
return;
},
resolveNotebookEditor: async (viewType: string, uri: URI, editorId: string) => {
Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeNotebookEditorSelection(listener, thisArgs, disposables);
},
onDidChangeNotebookEditorVisibleRanges(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeNotebookEditorVisibleRanges(listener, thisArgs, disposables);
},
onDidChangeCellOutputs(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeCellOutputs(listener, thisArgs, disposables);
Expand Down
23 changes: 19 additions & 4 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { revive } from 'vs/base/common/marshalling';
import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { Dto } from 'vs/base/common/types';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
Expand Down Expand Up @@ -1624,9 +1624,22 @@ export interface INotebookSelectionChangeEvent {
selections: number[];
}

export interface INotebookCellVisibleRange {
start: number;
end: number;
}

export interface INotebookVisibleRangesEvent {
ranges: INotebookCellVisibleRange[];
}

export interface INotebookEditorPropertiesChangeData {
selections: INotebookSelectionChangeEvent | null;
visibleRanges: INotebookVisibleRangesEvent | null;
}

export interface INotebookDocumentPropertiesChangeData {
metadata: NotebookDocumentMetadata | null;
selections: INotebookSelectionChangeEvent | null;
}

export interface INotebookModelAddedData {
Expand All @@ -1636,13 +1649,14 @@ export interface INotebookModelAddedData {
cells: IMainCellDto[],
viewType: string;
metadata?: NotebookDocumentMetadata;
attachedEditor?: { id: string; selections: number[]; }
attachedEditor?: { id: string; selections: number[]; visibleRanges: ICellRange[] }
}

export interface INotebookEditorAddData {
id: string;
documentUri: UriComponents;
selections: number[];
visibleRanges: ICellRange[];
}

export interface INotebookDocumentsAndEditorsDelta {
Expand Down Expand Up @@ -1670,7 +1684,8 @@ export interface ExtHostNotebookShape {
$onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void;
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent, isDirty: boolean): void;
$acceptModelSaved(uriComponents: UriComponents): void;
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void;
$acceptEditorPropertiesChanged(id: string, data: INotebookEditorPropertiesChangeData): void;
$acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void;
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): void;
$undoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise<void>;
$redoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise<void>;
Expand Down
54 changes: 48 additions & 6 deletions src/vs/workbench/api/common/extHostNotebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ISplice } from 'vs/base/common/sequence';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as UUID from 'vs/base/common/uuid';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { CellKind, ExtHostNotebookShape, ICommandDto, IMainContext, IModelAddedData, INotebookDocumentsAndEditorsDelta, INotebookEditorPropertiesChangeData, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice } from 'vs/workbench/api/common/extHost.protocol';
import { CellKind, ExtHostNotebookShape, ICommandDto, IMainContext, IModelAddedData, INotebookDocumentPropertiesChangeData, INotebookDocumentsAndEditorsDelta, INotebookEditorPropertiesChangeData, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice } from 'vs/workbench/api/common/extHost.protocol';
import { ILogService } from 'vs/platform/log/common/log';
import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
Expand Down Expand Up @@ -633,6 +633,20 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook

selection?: vscode.NotebookCell;

private _visibleRanges: vscode.NotebookCellRange[] = [];

get visibleRanges() {
return this._visibleRanges;
}

set visibleRanges(_range: vscode.NotebookCellRange[]) {
throw readonly('visibleRanges');
}

_acceptVisibleRanges(value: vscode.NotebookCellRange[]): void {
this._visibleRanges = value;
}

private _active: boolean = false;
get active(): boolean {
return this._active;
Expand Down Expand Up @@ -886,6 +900,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
private readonly _commandsConverter: CommandsConverter;
private readonly _onDidChangeNotebookEditorSelection = new Emitter<vscode.NotebookEditorSelectionChangeEvent>();
readonly onDidChangeNotebookEditorSelection = this._onDidChangeNotebookEditorSelection.event;
private readonly _onDidChangeNotebookEditorVisibleRanges = new Emitter<vscode.NotebookEditorVisibleRangesChangeEvent>();
readonly onDidChangeNotebookEditorVisibleRanges = this._onDidChangeNotebookEditorVisibleRanges.event;
private readonly _onDidChangeNotebookCells = new Emitter<vscode.NotebookCellsChangeEvent>();
readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
private readonly _onDidChangeCellOutputs = new Emitter<vscode.NotebookCellOutputsChangeEvent>();
Expand Down Expand Up @@ -1284,8 +1300,31 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
}

$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void {
this.logService.debug('ExtHostNotebook#$acceptEditorPropertiesChanged', uriComponents.path, data);
$acceptEditorPropertiesChanged(id: string, data: INotebookEditorPropertiesChangeData): void {
this.logService.debug('ExtHostNotebook#$acceptEditorPropertiesChanged', id, data);

let editor: { editor: ExtHostNotebookEditor; } | undefined;
this._editors.forEach(e => {
if (e.editor.id === id) {
editor = e;
}
});

if (!editor) {
return;
}

if (data.visibleRanges) {
editor.editor._acceptVisibleRanges(data.visibleRanges.ranges);
this._onDidChangeNotebookEditorVisibleRanges.fire({
notebookEditor: editor.editor,
visibleRanges: editor.editor.visibleRanges
});
}
}

$acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void {
this.logService.debug('ExtHostNotebook#$acceptDocumentPropertiesChanged', uriComponents.path, data);
const editor = this._getEditorFromURI(uriComponents);

if (!editor) {
Expand All @@ -1306,6 +1345,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
});
}


if (data.metadata) {
editor.editor.notebookData.notebookDocument.metadata = {
...notebookDocumentMetadataDefaults,
Expand All @@ -1314,7 +1354,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
}

private _createExtHostEditor(document: ExtHostNotebookDocument, editorId: string, selections: number[]) {
private _createExtHostEditor(document: ExtHostNotebookDocument, editorId: string, selections: number[], visibleRanges: vscode.NotebookCellRange[]) {
const revivedUri = document.uri;
let webComm = this._webviewComm.get(editorId);

Expand All @@ -1339,6 +1379,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
editor.selection = undefined;
}

editor._acceptVisibleRanges(visibleRanges);

this._editors.get(editorId)?.editor.dispose();
this._editors.set(editorId, { editor });
}
Expand Down Expand Up @@ -1423,7 +1465,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN

// create editor if populated
if (modelData.attachedEditor) {
this._createExtHostEditor(document, modelData.attachedEditor.id, modelData.attachedEditor.selections);
this._createExtHostEditor(document, modelData.attachedEditor.id, modelData.attachedEditor.selections, modelData.attachedEditor.visibleRanges);
editorChanged = true;
}
}
Expand All @@ -1445,7 +1487,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
const document = this._documents.get(revivedUri);

if (document) {
this._createExtHostEditor(document, editorModelData.id, editorModelData.selections);
this._createExtHostEditor(document, editorModelData.id, editorModelData.selections, editorModelData.visibleRanges);
editorChanged = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/

import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { INotebookEditor, INotebookEditorMouseEvent, ICellRange, INotebookEditorContribution, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { INotebookEditor, INotebookEditorMouseEvent, INotebookEditorContribution, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import * as DOM from 'vs/base/browser/dom';
import { CellFoldingState, FoldingModel } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel';
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions';
import { registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { TrackedRangeStickiness } from 'vs/editor/common/model';
import { FoldingRegion, FoldingRegions } from 'vs/editor/contrib/folding/foldingRanges';
import { IFoldingRangeData, sanitizeRanges } from 'vs/editor/contrib/folding/syntaxRangeProvider';
import { ICellRange } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon';

type RegionFilter = (r: FoldingRegion) => boolean;
type RegionFilterWithLevel = (r: FoldingRegion, level: number) => boolean;
Expand Down
Loading

0 comments on commit 637d782

Please sign in to comment.