Skip to content

Commit 5d18ad4

Browse files
committed
editable metadata
1 parent a7e8704 commit 5d18ad4

9 files changed

Lines changed: 154 additions & 34 deletions

File tree

src/vs/vscode.proposed.d.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1635,13 +1635,22 @@ declare module 'vscode' {
16351635

16361636
export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput;
16371637

1638+
export interface NotebookCellMetadata {
1639+
editable: boolean;
1640+
}
1641+
16381642
export interface NotebookCell {
16391643
readonly uri: Uri;
16401644
handle: number;
16411645
language: string;
16421646
cellKind: CellKind;
16431647
outputs: CellOutput[];
16441648
getContent(): string;
1649+
metadata?: NotebookCellMetadata;
1650+
}
1651+
1652+
export interface NotebookDocumentMetadata {
1653+
editable: boolean;
16451654
}
16461655

16471656
export interface NotebookDocument {
@@ -1651,6 +1660,7 @@ declare module 'vscode' {
16511660
languages: string[];
16521661
cells: NotebookCell[];
16531662
displayOrder?: GlobPattern[];
1663+
metadata?: NotebookDocumentMetadata;
16541664
}
16551665

16561666
export interface NotebookEditor {
@@ -1672,7 +1682,7 @@ declare module 'vscode' {
16721682
/**
16731683
* Create a notebook cell. The cell is not inserted into current document when created. Extensions should insert the cell into the document by [TextDocument.cells](#TextDocument.cells)
16741684
*/
1675-
createCell(content: string, language: string, type: CellKind, outputs: CellOutput[]): NotebookCell;
1685+
createCell(content: string, language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata): NotebookCell;
16761686
}
16771687

16781688
export interface NotebookProvider {

src/vs/workbench/api/browser/mainThreadNotebook.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
88
import { Disposable } from 'vs/base/common/lifecycle';
99
import { URI, UriComponents } from 'vs/base/common/uri';
1010
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/browser/notebookService';
11-
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellsSplice, NotebookCellOutputsSplice, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
11+
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellsSplice, NotebookCellOutputsSplice, CellKind, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1212
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1313
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
1414
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
@@ -127,6 +127,14 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
127127
}
128128
}
129129

130+
async $updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata | undefined): Promise<void> {
131+
let controller = this._notebookProviders.get(viewType);
132+
133+
if (controller) {
134+
controller.updateNotebookMetadata(resource, metadata);
135+
}
136+
}
137+
130138
async resolveNotebook(viewType: string, uri: URI): Promise<number | undefined> {
131139
let handle = await this._proxy.$resolveNotebook(viewType, uri);
132140
return handle;
@@ -220,6 +228,11 @@ export class MainThreadNotebookController implements IMainNotebookController {
220228
document?.textModel.updateLanguages(languages);
221229
}
222230

231+
updateNotebookMetadata(resource: UriComponents, metadata: NotebookDocumentMetadata | undefined) {
232+
let document = this._mapping.get(URI.from(resource).toString());
233+
document?.textModel.updateNotebookMetadata(metadata);
234+
}
235+
223236
updateNotebookRenderers(resource: UriComponents, renderers: number[]): void {
224237
let document = this._mapping.get(URI.from(resource).toString());
225238
document?.textModel.updateRenderers(renderers);

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
5151
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
5252
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
5353
import { revive } from 'vs/base/common/marshalling';
54-
import { INotebookMimeTypeSelector, IOutput, INotebookDisplayOrder } from 'vs/workbench/contrib/notebook/common/notebookCommon';
54+
import { INotebookMimeTypeSelector, IOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
5555
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
5656
import { Dto } from 'vs/base/common/types';
5757

@@ -665,6 +665,7 @@ export interface ICellDto {
665665
language: string;
666666
cellKind: CellKind;
667667
outputs: IOutput[];
668+
metadata?: NotebookCellMetadata;
668669
}
669670

670671
export type NotebookCellsSplice = [
@@ -686,6 +687,7 @@ export interface MainThreadNotebookShape extends IDisposable {
686687
$unregisterNotebookRenderer(handle: number): Promise<void>;
687688
$createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void>;
688689
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
690+
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata | undefined): Promise<void>;
689691
$spliceNotebookCells(viewType: string, resource: UriComponents, splices: NotebookCellsSplice[], renderers: number[]): Promise<void>;
690692
$spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void>;
691693
$postMessage(handle: number, value: any): Promise<boolean>;

src/vs/workbench/api/common/extHostNotebook.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ export class ExtHostCell implements vscode.NotebookCell {
3232
private _content: string,
3333
public cellKind: CellKind,
3434
public language: string,
35-
outputs: any[]
35+
outputs: any[],
36+
public metadata: vscode.NotebookCellMetadata | undefined,
3637
) {
3738
this.source = this._content.split(/\r|\n|\r\n/g);
3839
this._outputs = outputs;
@@ -130,6 +131,17 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
130131
this._proxy.$updateNotebookLanguages(this.viewType, this.uri, this._languages);
131132
}
132133

134+
private _metadata: vscode.NotebookDocumentMetadata | undefined = undefined;
135+
136+
get metadata() {
137+
return this._metadata;
138+
}
139+
140+
set metadata(newMetadata: vscode.NotebookDocumentMetadata | undefined) {
141+
this._metadata = newMetadata;
142+
this._proxy.$updateNotebookMetadata(this.viewType, this.uri, this._metadata);
143+
}
144+
133145
private _displayOrder: string[] = [];
134146

135147
get displayOrder() {
@@ -366,10 +378,10 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
366378
}));
367379
}
368380

369-
createCell(content: string, language: string, type: CellKind, outputs: vscode.CellOutput[]): vscode.NotebookCell {
381+
createCell(content: string, language: string, type: CellKind, outputs: vscode.CellOutput[], metadata: vscode.NotebookCellMetadata | undefined): vscode.NotebookCell {
370382
const handle = ExtHostNotebookEditor._cellhandlePool++;
371383
const uri = CellUri.generate(this.document.uri, handle);
372-
const cell = new ExtHostCell(handle, uri, content, type, language, outputs);
384+
const cell = new ExtHostCell(handle, uri, content, type, language, outputs, metadata);
373385
return cell;
374386
}
375387

@@ -568,7 +580,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
568580
let editor = this._editors.get(URI.revive(uri).toString());
569581
let document = this._documents.get(URI.revive(uri).toString());
570582

571-
let rawCell = editor?.editor.createCell('', language, type, []) as ExtHostCell;
583+
let rawCell = editor?.editor.createCell('', language, type, [], undefined) as ExtHostCell;
572584
document?.insertCell(index, rawCell!);
573585

574586
let allDocuments = this._documentsAndEditors.allDocuments();
@@ -586,6 +598,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
586598
source: rawCell.source,
587599
language: rawCell.language,
588600
cellKind: rawCell.cellKind,
601+
metadata: rawCell.metadata,
589602
outputs: []
590603
};
591604
}

src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts

Lines changed: 86 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ abstract class AbstractCellRenderer {
119119
return menu;
120120
}
121121

122+
abstract getCellToolbarActions(element: CellViewModel): IAction[];
123+
122124
showContextMenu(listIndex: number | undefined, element: CellViewModel, x: number, y: number) {
123125
const actions: IAction[] = [
124126
this.instantiationService.createInstance(InsertCodeCellAboveAction),
@@ -215,21 +217,16 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
215217

216218
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
217219
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown');
218-
const menu = this.createMenu().getCellTitleActions(this.contextKeyService);
219-
const actions: IAction[] = [];
220-
for (let [, actions] of menu.getActions({ shouldForwardArgs: true })) {
221-
actions.push(...actions);
220+
const toolbarActions = this.getCellToolbarActions(element);
221+
templateData.toolbar!.setActions(toolbarActions)();
222+
223+
if (templateData.focusIndicator) {
224+
if (!toolbarActions.length) {
225+
templateData.focusIndicator.style.top = `8px`;
226+
} else {
227+
templateData.focusIndicator.style.top = `24px`;
228+
}
222229
}
223-
224-
templateData.toolbar!.setActions([
225-
...actions,
226-
this.instantiationService.createInstance(MoveCellUpAction),
227-
this.instantiationService.createInstance(MoveCellDownAction),
228-
this.instantiationService.createInstance(InsertCodeCellBelowAction),
229-
this.instantiationService.createInstance(EditCellAction),
230-
this.instantiationService.createInstance(SaveCellAction),
231-
this.instantiationService.createInstance(DeleteCellAction)
232-
])();
233230
}
234231

235232
templateData.toolbar!.context = <INotebookCellActionContext>{
@@ -239,6 +236,44 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
239236
};
240237
}
241238

239+
getCellToolbarActions(element: CellViewModel): IAction[] {
240+
const viewModel = this.notebookEditor.viewModel;
241+
242+
if (!viewModel) {
243+
return [];
244+
}
245+
246+
const menu = this.createMenu().getCellTitleActions(this.contextKeyService);
247+
const actions: IAction[] = [];
248+
for (let [, actions] of menu.getActions({ shouldForwardArgs: true })) {
249+
actions.push(...actions);
250+
}
251+
252+
const metadata = viewModel.metadata;
253+
254+
if (!metadata || metadata.editable) {
255+
actions.push(
256+
this.instantiationService.createInstance(MoveCellUpAction),
257+
this.instantiationService.createInstance(MoveCellDownAction),
258+
this.instantiationService.createInstance(InsertCodeCellBelowAction)
259+
);
260+
}
261+
262+
const cellMetadata = element.metadata;
263+
if (!cellMetadata || cellMetadata.editable) {
264+
actions.push(
265+
this.instantiationService.createInstance(EditCellAction),
266+
this.instantiationService.createInstance(SaveCellAction)
267+
);
268+
}
269+
270+
if (!metadata || metadata.editable) {
271+
this.instantiationService.createInstance(DeleteCellAction);
272+
}
273+
274+
return actions;
275+
}
276+
242277
getAdditionalContextMenuActions(): IAction[] {
243278
return [
244279
this.instantiationService.createInstance(EditCellAction),
@@ -363,24 +398,49 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
363398

364399
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
365400
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'code');
366-
const menu = this.createMenu().getCellTitleActions(contextKeyService);
401+
const toolbarActions = this.getCellToolbarActions(element);
402+
templateData.toolbar!.setActions(toolbarActions)();
403+
templateData.toolbar!.context = toolbarContext;
404+
templateData.runToolbar!.context = toolbarContext;
405+
406+
if (templateData.focusIndicator) {
407+
if (!toolbarActions.length) {
408+
templateData.focusIndicator.style.top = `8px`;
409+
} else {
410+
templateData.focusIndicator.style.top = `24px`;
411+
}
412+
}
413+
}
414+
415+
416+
getCellToolbarActions(element: CellViewModel): IAction[] {
417+
const viewModel = this.notebookEditor.viewModel;
418+
419+
if (!viewModel) {
420+
return [];
421+
}
422+
423+
const menu = this.createMenu().getCellTitleActions(this.contextKeyService);
367424
const actions: IAction[] = [];
368-
for (let [, items] of menu.getActions({ shouldForwardArgs: true })) {
369-
actions.push(...items);
425+
for (let [, actions] of menu.getActions({ shouldForwardArgs: true })) {
426+
actions.push(...actions);
370427
}
371428

372-
templateData.toolbar!.setActions([
373-
...actions,
374-
this.instantiationService.createInstance(MoveCellUpAction),
375-
this.instantiationService.createInstance(MoveCellDownAction),
376-
this.instantiationService.createInstance(InsertCodeCellBelowAction),
377-
this.instantiationService.createInstance(DeleteCellAction)
378-
])();
429+
const metadata = viewModel.metadata;
379430

380-
templateData.toolbar!.context = toolbarContext;
381-
templateData.runToolbar!.context = toolbarContext;
431+
if (!metadata || metadata.editable) {
432+
actions.push(
433+
this.instantiationService.createInstance(MoveCellUpAction),
434+
this.instantiationService.createInstance(MoveCellDownAction),
435+
this.instantiationService.createInstance(InsertCodeCellBelowAction),
436+
this.instantiationService.createInstance(DeleteCellAction)
437+
);
438+
}
439+
440+
return actions;
382441
}
383442

443+
384444
getAdditionalContextMenuActions(): IAction[] {
385445
return [];
386446
}

src/vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ export class CellViewModel extends Disposable implements ICellViewModel {
5555
return this.cell.outputs;
5656
}
5757

58+
get metadata() {
59+
return this.cell.metadata;
60+
}
61+
5862
private _state: CellState = CellState.Preview;
5963

6064
get state(): CellState {

src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ export class NotebookViewModel extends Disposable {
8181
return this._model.notebook.uri;
8282
}
8383

84+
get metadata() {
85+
return this._model.notebook.metadata;
86+
}
87+
8488
private readonly _onDidChangeViewCells = new Emitter<INotebookViewCellsUpdateEvent>();
8589
get onDidChangeViewCells(): Event<INotebookViewCellsUpdateEvent> { return this._onDidChangeViewCells.event; }
8690

src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Emitter, Event } from 'vs/base/common/event';
77
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
88
import { URI } from 'vs/base/common/uri';
99
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
10-
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon';
10+
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellsSplice, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1111

1212
export class NotebookTextModel extends Disposable implements INotebookTextModel {
1313
private readonly _onWillDispose: Emitter<void> = this._register(new Emitter<void>());
@@ -21,6 +21,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
2121
cells: NotebookCellTextModel[];
2222
activeCell: NotebookCellTextModel | undefined;
2323
languages: string[] = [];
24+
metadata: NotebookDocumentMetadata | undefined = undefined;
2425
renderers = new Set<number>();
2526

2627
constructor(
@@ -36,6 +37,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
3637
this.languages = languages;
3738
}
3839

40+
updateNotebookMetadata(metadata: NotebookDocumentMetadata | undefined) {
41+
this.metadata = metadata;
42+
}
43+
3944
updateRenderers(renderers: number[]) {
4045
renderers.forEach(render => {
4146
this.renderers.add(render);

src/vs/workbench/contrib/notebook/common/notebookCommon.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ export const NOTEBOOK_DISPLAY_ORDER = [
3636
'text/plain'
3737
];
3838

39+
export interface NotebookDocumentMetadata {
40+
editable: boolean;
41+
}
42+
43+
export interface NotebookCellMetadata {
44+
editable: boolean;
45+
}
46+
3947
export interface INotebookDisplayOrder {
4048
defaultOrder: string[];
4149
userOrder?: string[];
@@ -122,6 +130,7 @@ export interface ICell {
122130
language: string;
123131
cellKind: CellKind;
124132
outputs: IOutput[];
133+
metadata?: NotebookCellMetadata;
125134
onDidChangeOutputs?: Event<NotebookCellOutputsSplice[]>;
126135
resolveTextBufferFactory(): PieceTreeTextBufferFactory;
127136
// TODO@rebornix it should be later on replaced by moving textmodel resolution into CellTextModel

0 commit comments

Comments
 (0)