提交 343fdecf 编写于 作者: R rebornix

notebook metadata sync between ext and main

上级 ebb2030e
......@@ -1666,6 +1666,9 @@ declare module 'vscode' {
export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput;
export interface NotebookCellMetadata {
/**
* Controls if the content of a cell is editable or not.
*/
editable: boolean;
}
......@@ -1680,7 +1683,14 @@ declare module 'vscode' {
}
export interface NotebookDocumentMetadata {
/**
* Controls if users can add or delete cells
*/
editable: boolean;
/**
* Default value for [cell editable metadata](#NotebookCellMetadata.editable).
*/
cellEditable: boolean;
}
export interface NotebookDocument {
......
......@@ -8,7 +8,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
import { Disposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellsSplice, NotebookCellOutputsSplice, CellKind, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellsSplice, NotebookCellOutputsSplice, CellKind, NotebookDocumentMetadata, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
......@@ -135,6 +135,14 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
}
}
async $updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata): Promise<void> {
let controller = this._notebookProviders.get(viewType);
if (controller) {
controller.updateNotebookCellMetadata(resource, handle, metadata);
}
}
async resolveNotebook(viewType: string, uri: URI): Promise<number | undefined> {
let handle = await this._proxy.$resolveNotebook(viewType, uri);
return handle;
......@@ -233,6 +241,11 @@ export class MainThreadNotebookController implements IMainNotebookController {
document?.textModel.updateNotebookMetadata(metadata);
}
updateNotebookCellMetadata(resource: UriComponents, handle: number, metadata: NotebookCellMetadata) {
let document = this._mapping.get(URI.from(resource).toString());
document?.textModel.updateNotebookCellMetadata(handle, metadata);
}
updateNotebookRenderers(resource: UriComponents, renderers: number[]): void {
let document = this._mapping.get(URI.from(resource).toString());
document?.textModel.updateRenderers(renderers);
......
......@@ -694,6 +694,7 @@ export interface MainThreadNotebookShape extends IDisposable {
$createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void>;
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata | undefined): Promise<void>;
$updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata): Promise<void>;
$spliceNotebookCells(viewType: string, resource: UriComponents, splices: NotebookCellsSplice[], renderers: number[]): Promise<void>;
$spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void>;
$postMessage(handle: number, value: any): Promise<boolean>;
......
......@@ -16,6 +16,15 @@ import { INotebookDisplayOrder, ITransformedDisplayOutputDto, IOrderedMimeType,
import { ISplice } from 'vs/base/common/sequence';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
const notebookDocumentMetadataDefaults: vscode.NotebookDocumentMetadata = {
editable: true,
cellEditable: true
};
const notebookCellMetadataDefaults: vscode.NotebookCellMetadata = {
editable: true
};
export class ExtHostCell implements vscode.NotebookCell {
public source: string[];
......@@ -27,13 +36,16 @@ export class ExtHostCell implements vscode.NotebookCell {
private _outputMapping = new Set<vscode.CellOutput>();
constructor(
private viewType: string,
private documentUri: URI,
readonly handle: number,
readonly uri: URI,
private _content: string,
public cellKind: CellKind,
public language: string,
outputs: any[],
public metadata: vscode.NotebookCellMetadata,
private _metadata: vscode.NotebookCellMetadata,
private _proxy: MainThreadNotebookShape
) {
this.source = this._content.split(/\r|\n|\r\n/g);
this._outputs = outputs;
......@@ -62,6 +74,20 @@ export class ExtHostCell implements vscode.NotebookCell {
this._onDidChangeOutputs.fire(diffs);
}
get metadata() {
return this._metadata;
}
set metadata(newMetadata: vscode.NotebookCellMetadata) {
let newMetadataWithDefaults = {
...notebookCellMetadataDefaults,
...(newMetadata || {})
};
this._metadata = newMetadataWithDefaults;
this._proxy.$updateNotebookCellMetadata(this.viewType, this.documentUri, this.handle, newMetadataWithDefaults);
}
getContent(): string {
if (this._textDocument && this._initalVersion !== this._textDocument?.version) {
return this._textDocument.getText();
......@@ -131,14 +157,19 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
this._proxy.$updateNotebookLanguages(this.viewType, this.uri, this._languages);
}
private _metadata: vscode.NotebookDocumentMetadata | undefined = undefined;
private _metadata: vscode.NotebookDocumentMetadata = notebookDocumentMetadataDefaults;
get metadata() {
return this._metadata;
}
set metadata(newMetadata: vscode.NotebookDocumentMetadata | undefined) {
this._metadata = newMetadata;
let newMetadataWithDefaults = {
...notebookDocumentMetadataDefaults,
...(newMetadata || {})
};
this._metadata = newMetadataWithDefaults;
this._proxy.$updateNotebookMetadata(this.viewType, this.uri, this._metadata);
}
......@@ -341,17 +372,13 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
}
}
const notebookCellMetadataDefaults: vscode.NotebookCellMetadata = {
editable: true
};
export class ExtHostNotebookEditor extends Disposable implements vscode.NotebookEditor {
private _viewColumn: vscode.ViewColumn | undefined;
private static _cellhandlePool: number = 0;
onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
constructor(
viewType: string,
private readonly viewType: string,
readonly id: string,
public uri: URI,
private _proxy: MainThreadNotebookShape,
......@@ -390,7 +417,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
...notebookCellMetadataDefaults,
...(metadata || {})
};
const cell = new ExtHostCell(handle, uri, content, type, language, outputs, metadata);
const cell = new ExtHostCell(this.viewType, this.uri, handle, uri, content, type, language, outputs, metadata, this._proxy);
return cell;
}
......
......@@ -255,6 +255,7 @@ export interface CellRenderTemplate {
editor?: CodeEditorWidget;
progressBar?: ProgressBar;
disposables: DisposableStore;
toJSON(): void;
}
export interface IOutputTransformContribution {
......
......@@ -192,7 +192,8 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
cellContainer: innerContent,
editingContainer: codeInnerContent,
disposables,
toolbar
toolbar,
toJSON: () => { return {}; }
};
}
......@@ -214,9 +215,14 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
elementDisposable.add(new StatefullMarkdownCell(this.notebookEditor, element, templateData, this.editorOptions, this.instantiationService));
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown');
contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, element.metadata.editable);
contextKeyService.createKey(NOTEBOOK_EDITABLE_CONTEXT_KEY, this.notebookEditor.viewModel?.metadata?.editable);
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown');
const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, element.metadata.editable);
elementDisposable.add(element.onDidChangeMetadata((e) => {
cellEditableKey.set(e.editable);
}));
const editModeKey = contextKeyService.createKey(NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, element.editState === CellEditState.Editing);
elementDisposable.add(element.onDidChangeCellEditState(() => {
editModeKey.set(element.editState === CellEditState.Editing);
......@@ -307,7 +313,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
runToolbar,
outputContainer,
editor,
disposables
disposables,
toJSON: () => { return {}; }
};
}
......@@ -350,9 +357,13 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
};
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'code');
contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, element.metadata.editable);
contextKeyService.createKey(NOTEBOOK_EDITABLE_CONTEXT_KEY, this.notebookEditor.viewModel?.metadata?.editable);
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'code');
const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, element.metadata.editable);
elementDisposable.add(element.onDidChangeMetadata((e) => {
cellEditableKey.set(e.editable);
}));
this.setupCellToolbarActions(contextKeyService, templateData, elementDisposable);
templateData.toolbar.context = toolbarContext;
......
......@@ -80,6 +80,11 @@ export class CodeCell extends Disposable {
}
}));
templateData.editor?.updateOptions({ readOnly: !viewCell.metadata.editable });
this._register(viewCell.onDidChangeMetadata((e) => {
templateData.editor?.updateOptions({ readOnly: !e.editable });
}));
let cellWidthResizeObserver = getResizesObserver(templateData.editorContainer!, {
width: width,
height: totalHeight
......
......@@ -9,7 +9,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as model from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';
import { ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ICell, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CursorAtBoundary, CellFocusMode, CellEditState, CellRunState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { EDITOR_TOP_PADDING, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants';
import { SearchParams } from 'vs/editor/common/model/textModelSearch';
......@@ -27,6 +27,8 @@ export abstract class BaseCellViewModel extends Disposable {
readonly onDidChangeEditorAttachState = this._onDidChangeEditorAttachState.event;
protected readonly _onDidChangeCursorSelection: Emitter<void> = this._register(new Emitter<void>());
public readonly onDidChangeCursorSelection: Event<void> = this._onDidChangeCursorSelection.event;
protected readonly _onDidChangeMetadata: Emitter<NotebookCellMetadata> = this._register(new Emitter<NotebookCellMetadata>());
public readonly onDidChangeMetadata: Event<NotebookCellMetadata> = this._onDidChangeMetadata.event;
get handle() {
return this.cell.handle;
}
......@@ -92,6 +94,10 @@ export abstract class BaseCellViewModel extends Disposable {
constructor(readonly viewType: string, readonly notebookHandle: number, readonly cell: ICell, public id: string) {
super();
this._register(cell.onDidChangeMetadata((e) => {
this._onDidChangeMetadata.fire(e);
}));
}
abstract hasDynamicHeight(): boolean;
......
......@@ -15,6 +15,9 @@ export class NotebookCellTextModel implements ICell {
private _onDidChangeContent = new Emitter<void>();
onDidChangeContent: Event<void> = this._onDidChangeContent.event;
private _onDidChangeMetadata = new Emitter<NotebookCellMetadata>();
onDidChangeMetadata: Event<NotebookCellMetadata> = this._onDidChangeMetadata.event;
private _outputs: IOutput[];
get outputs(): IOutput[] {
......@@ -30,6 +33,17 @@ export class NotebookCellTextModel implements ICell {
this._buffer = null;
}
private _metadata: NotebookCellMetadata;
get metadata() {
return this._metadata;
}
set metadata(newMetadata: NotebookCellMetadata) {
this._metadata = newMetadata;
this._onDidChangeMetadata.fire(this._metadata);
}
private _buffer: PieceTreeTextBufferFactory | null = null;
constructor(
......@@ -39,9 +53,10 @@ export class NotebookCellTextModel implements ICell {
public language: string,
public cellKind: CellKind,
outputs: IOutput[],
public readonly metadata: NotebookCellMetadata
metadata: NotebookCellMetadata
) {
this._outputs = outputs;
this._metadata = metadata;
}
contentChange() {
......
......@@ -7,7 +7,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellsSplice, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellsSplice, NotebookDocumentMetadata, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
export class NotebookTextModel extends Disposable implements INotebookTextModel {
private readonly _onWillDispose: Emitter<void> = this._register(new Emitter<void>());
......@@ -20,7 +20,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
private _cellListeners: Map<number, IDisposable> = new Map();
cells: NotebookCellTextModel[];
languages: string[] = [];
metadata: NotebookDocumentMetadata | undefined = undefined;
metadata: NotebookDocumentMetadata | undefined = { editable: true };
renderers = new Set<number>();
constructor(
......@@ -40,6 +40,14 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
this.metadata = metadata;
}
updateNotebookCellMetadata(handle: number, metadata: NotebookCellMetadata) {
const cell = this.cells.find(cell => cell.handle === handle);
if (cell) {
cell.metadata = metadata;
}
}
updateRenderers(renderers: number[]) {
renderers.forEach(render => {
this.renderers.add(render);
......
......@@ -132,6 +132,7 @@ export interface ICell {
outputs: IOutput[];
metadata: NotebookCellMetadata;
onDidChangeOutputs?: Event<NotebookCellOutputsSplice[]>;
onDidChangeMetadata: Event<NotebookCellMetadata>;
resolveTextBufferFactory(): PieceTreeTextBufferFactory;
// TODO@rebornix it should be later on replaced by moving textmodel resolution into CellTextModel
contentChange(): void;
......
......@@ -24,6 +24,8 @@ export class TestCell implements ICell {
uri: URI;
private _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>();
onDidChangeOutputs: Event<NotebookCellOutputsSplice[]> = this._onDidChangeOutputs.event;
private _onDidChangeMetadata = new Emitter<NotebookCellMetadata>();
onDidChangeMetadata: Event<NotebookCellMetadata> = this._onDidChangeMetadata.event;
private _isDirty: boolean = false;
private _outputs: IOutput[];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册