Skip to content

Commit 62e2deb

Browse files
committed
common metadata editor.
1 parent e906097 commit 62e2deb

1 file changed

Lines changed: 138 additions & 117 deletions

File tree

src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts

Lines changed: 138 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,20 @@ abstract class AbstractCellRenderer extends Disposable {
8585
metadataStatusHeight: number;
8686
metadataHeight: number;
8787
};
88+
protected _foldingIndicator!: HTMLElement;
89+
protected _foldingState!: MetadataFoldingState;
90+
protected _metadataEditorContainer?: HTMLElement;
91+
protected _metadataEditorDisposeStore!: DisposableStore;
92+
protected _metadataEditor?: CodeEditorWidget;
8893

8994
constructor(
9095
readonly notebookEditor: INotebookTextDiffEditor,
9196
readonly cell: CellDiffViewModel,
9297
readonly templateData: CellDiffRenderTemplate,
9398
protected readonly instantiationService: IInstantiationService,
99+
protected readonly modeService: IModeService,
100+
protected readonly modelService: IModelService,
101+
94102
) {
95103
super();
96104
// init
@@ -100,6 +108,8 @@ abstract class AbstractCellRenderer extends Disposable {
100108
metadataHeight: 0,
101109
metadataStatusHeight: 24
102110
};
111+
this._metadataEditorDisposeStore = new DisposableStore();
112+
this._foldingState = MetadataFoldingState.Collapsed;
103113
this.initData();
104114
this.buildBody(templateData.container);
105115
this._register(cell.onDidLayoutChange(e => this.onDidLayoutChange(e)));
@@ -118,37 +128,124 @@ abstract class AbstractCellRenderer extends Disposable {
118128
this.buildMetadataBody(this._metadataInfoContainer);
119129
}
120130

131+
buildMetadataHeader(metadataHeaderContainer: HTMLElement): void {
132+
this._foldingIndicator = DOM.append(metadataHeaderContainer, DOM.$('.metadata-folding-indicator'));
133+
this._updateFoldingIcon();
134+
const metadataStatus = DOM.append(metadataHeaderContainer, DOM.$('div.metadata-status'));
135+
const metadataStatusSpan = DOM.append(metadataStatus, DOM.$('span'));
136+
metadataStatusSpan.textContent = 'Metadata unchanged';
137+
138+
this._register(this.notebookEditor.onMouseUp(e => {
139+
if (!e.event.target) {
140+
return;
141+
}
142+
143+
const target = e.event.target as HTMLElement;
144+
145+
if (DOM.hasClass(target, 'codicon-chevron-down') || DOM.hasClass(target, 'codicon-chevron-right')) {
146+
const parent = target.parentElement as HTMLElement;
147+
148+
if (parent && !DOM.hasClass(parent, 'metadata-folding-indicator')) {
149+
return;
150+
}
151+
152+
// folding icon
153+
154+
const cellViewModel = e.target;
155+
156+
if (cellViewModel === this.cell) {
157+
this._foldingState = this._foldingState === MetadataFoldingState.Expanded ? MetadataFoldingState.Collapsed : MetadataFoldingState.Expanded;
158+
this.updateMetadataRendering();
159+
}
160+
}
161+
162+
return;
163+
}));
164+
165+
this.updateMetadataRendering();
166+
}
167+
168+
updateMetadataRendering() {
169+
if (this._foldingState === MetadataFoldingState.Expanded) {
170+
// we should expand the metadata editor
171+
this._metadataInfoContainer.style.display = 'block';
172+
173+
if (!this._metadataEditorContainer || !this._metadataEditor) {
174+
// create editor
175+
this._metadataEditorContainer = DOM.append(this._metadataInfoContainer, DOM.$('.metadata-editor-container'));
176+
177+
this._metadataEditor = this.instantiationService.createInstance(CodeEditorWidget, this._metadataEditorContainer, {
178+
...fixedEditorOptions,
179+
dimension: {
180+
width: this.notebookEditor.getLayoutInfo().width - 20,
181+
height: 0
182+
}
183+
}, {});
184+
185+
const mode = this.modeService.create('json');
186+
const content = JSON.stringify(this.cell.original!.metadata);
187+
const edits = format(content, undefined, {});
188+
const metadataSource = applyEdits(content, edits);
189+
const metadataModel = this.modelService.createModel(metadataSource, mode, undefined, true);
190+
this._metadataEditor.setModel(metadataModel);
191+
192+
this._layoutInfo.metadataHeight = this._metadataEditor.getContentHeight();
193+
this.layout({ metadataEditor: true });
194+
195+
this._register(this._metadataEditor.onDidContentSizeChange((e) => {
196+
if (e.contentHeightChanged && this._foldingState === MetadataFoldingState.Expanded) {
197+
this._layoutInfo.metadataHeight = e.contentHeight;
198+
this.layout({ metadataEditor: true });
199+
}
200+
}));
201+
} else {
202+
this._layoutInfo.metadataHeight = this._metadataEditor.getContentHeight();
203+
this.layout({ metadataEditor: true });
204+
}
205+
} else {
206+
// we should collapse the metadata editor
207+
this._metadataInfoContainer.style.display = 'none';
208+
this._metadataEditorDisposeStore.clear();
209+
this._layoutInfo.metadataHeight = 0;
210+
this.layout({});
211+
}
212+
213+
this._updateFoldingIcon();
214+
215+
}
216+
217+
private _updateFoldingIcon() {
218+
if (this._foldingState === MetadataFoldingState.Collapsed) {
219+
this._foldingIndicator.innerHTML = renderCodicons('$(chevron-right)');
220+
} else {
221+
this._foldingIndicator.innerHTML = renderCodicons('$(chevron-down)');
222+
}
223+
}
224+
121225
abstract initData(): void;
122226
abstract styleContainer(container: HTMLElement): void;
123227
abstract buildSourceEditor(sourceContainer: HTMLElement): void;
124-
abstract buildMetadataHeader(metadataHeaderContainer: HTMLElement): void;
125228
abstract buildMetadataBody(metadataBodyContainer: HTMLElement): void;
126229

127230
abstract onDidLayoutChange(event: CellDiffViewModelLayoutChangeEvent): void;
231+
abstract layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean }): void;
128232
}
129233

130234
export class UnchangedCell extends AbstractCellRenderer {
131235
private _editor!: CodeEditorWidget;
132-
private _metadataEditor?: CodeEditorWidget;
133-
private _foldingState!: MetadataFoldingState;
134-
private _metadataEditorContainer?: HTMLElement;
135-
private _foldingIndicator!: HTMLElement;
136-
private _metadataEditorDisposeStore!: DisposableStore;
137236

138237
constructor(
139238
readonly notebookEditor: INotebookTextDiffEditor,
140239
readonly cell: CellDiffViewModel,
141240
readonly templateData: CellDiffRenderTemplate,
142-
@IModeService private readonly modeService: IModeService,
241+
@IModeService readonly modeService: IModeService,
143242
@IModelService protected modelService: IModelService,
144243
@IInstantiationService protected readonly instantiationService: IInstantiationService,
145244
) {
146-
super(notebookEditor, cell, templateData, instantiationService);
245+
super(notebookEditor, cell, templateData, instantiationService, modeService, modelService);
147246
}
148247

149248
initData() {
150-
this._foldingState = MetadataFoldingState.Collapsed;
151-
this._metadataEditorDisposeStore = new DisposableStore();
152249
}
153250

154251
styleContainer(container: HTMLElement) {
@@ -187,42 +284,6 @@ export class UnchangedCell extends AbstractCellRenderer {
187284
});
188285
}
189286

190-
buildMetadataHeader(metadataHeaderContainer: HTMLElement): void {
191-
this._foldingIndicator = DOM.append(metadataHeaderContainer, DOM.$('.metadata-folding-indicator'));
192-
this._updateFoldingIcon();
193-
const metadataStatus = DOM.append(metadataHeaderContainer, DOM.$('div.metadata-status'));
194-
const metadataStatusSpan = DOM.append(metadataStatus, DOM.$('span'));
195-
metadataStatusSpan.textContent = 'Metadata unchanged';
196-
197-
this._register(this.notebookEditor.onMouseUp(e => {
198-
if (!e.event.target) {
199-
return;
200-
}
201-
202-
const target = e.event.target as HTMLElement;
203-
204-
if (DOM.hasClass(target, 'codicon-chevron-down') || DOM.hasClass(target, 'codicon-chevron-right')) {
205-
const parent = target.parentElement as HTMLElement;
206-
207-
if (parent && !DOM.hasClass(parent, 'metadata-folding-indicator')) {
208-
return;
209-
}
210-
211-
// folding icon
212-
213-
const cellViewModel = e.target;
214-
215-
if (cellViewModel === this.cell) {
216-
this._foldingState = this._foldingState === MetadataFoldingState.Expanded ? MetadataFoldingState.Collapsed : MetadataFoldingState.Expanded;
217-
this.updateMetadataRendering();
218-
}
219-
}
220-
221-
return;
222-
}));
223-
224-
this.updateMetadataRendering();
225-
}
226287
buildMetadataBody(metadataBodyContainer: HTMLElement): void {
227288

228289
}
@@ -247,69 +308,10 @@ export class UnchangedCell extends AbstractCellRenderer {
247308
height: this._layoutInfo.metadataHeight
248309
});
249310
}
311+
250312
this.notebookEditor.layoutNotebookCell(this.cell,
251313
this._layoutInfo.editorHeight + this._layoutInfo.editorMargin + this._layoutInfo.metadataHeight + this._layoutInfo.metadataStatusHeight);
252314
}
253-
254-
private _updateFoldingIcon() {
255-
if (this._foldingState === MetadataFoldingState.Collapsed) {
256-
this._foldingIndicator.innerHTML = renderCodicons('$(chevron-right)');
257-
} else {
258-
this._foldingIndicator.innerHTML = renderCodicons('$(chevron-down)');
259-
}
260-
}
261-
262-
buildMetadata(diffEditorContainer: HTMLElement) {
263-
}
264-
265-
updateMetadataRendering() {
266-
if (this._foldingState === MetadataFoldingState.Expanded) {
267-
// we should expand the metadata editor
268-
this._metadataInfoContainer.style.display = 'block';
269-
270-
if (!this._metadataEditorContainer || !this._metadataEditor) {
271-
// create editor
272-
this._metadataEditorContainer = DOM.append(this._metadataInfoContainer, DOM.$('.metadata-editor-container'));
273-
274-
this._metadataEditor = this.instantiationService.createInstance(CodeEditorWidget, this._metadataEditorContainer, {
275-
...fixedEditorOptions,
276-
dimension: {
277-
width: this.notebookEditor.getLayoutInfo().width - 20,
278-
height: 0
279-
}
280-
}, {});
281-
282-
const mode = this.modeService.create('json');
283-
const content = JSON.stringify(this.cell.original!.metadata);
284-
const edits = format(content, undefined, {});
285-
const metadataSource = applyEdits(content, edits);
286-
const metadataModel = this.modelService.createModel(metadataSource, mode, undefined, true);
287-
this._metadataEditor.setModel(metadataModel);
288-
289-
this._layoutInfo.metadataHeight = this._metadataEditor.getContentHeight();
290-
this.layout({ metadataEditor: true });
291-
292-
this._register(this._metadataEditor.onDidContentSizeChange((e) => {
293-
if (e.contentHeightChanged && this._foldingState === MetadataFoldingState.Expanded) {
294-
this._layoutInfo.metadataHeight = e.contentHeight;
295-
this.layout({ metadataEditor: true });
296-
}
297-
}));
298-
} else {
299-
this._layoutInfo.metadataHeight = this._metadataEditor.getContentHeight();
300-
this.layout({ metadataEditor: true });
301-
}
302-
} else {
303-
// we should collapse the metadata editor
304-
this._metadataInfoContainer.style.display = 'none';
305-
this._metadataEditorDisposeStore.clear();
306-
this._layoutInfo.metadataHeight = 0;
307-
this.layout({});
308-
}
309-
310-
this._updateFoldingIcon();
311-
312-
}
313315
}
314316

315317
export class DeletedCell extends AbstractCellRenderer {
@@ -319,9 +321,11 @@ export class DeletedCell extends AbstractCellRenderer {
319321
readonly notebookEditor: INotebookTextDiffEditor,
320322
readonly cell: CellDiffViewModel,
321323
readonly templateData: CellDiffRenderTemplate,
324+
@IModeService readonly modeService: IModeService,
325+
@IModelService readonly modelService: IModelService,
322326
@IInstantiationService protected readonly instantiationService: IInstantiationService,
323327
) {
324-
super(notebookEditor, cell, templateData, instantiationService);
328+
super(notebookEditor, cell, templateData, instantiationService, modeService, modelService);
325329
}
326330

327331
initData(): void {
@@ -367,8 +371,6 @@ export class DeletedCell extends AbstractCellRenderer {
367371
});
368372

369373
}
370-
buildMetadataHeader(metadataHeaderContainer: HTMLElement): void {
371-
}
372374

373375
buildMetadataBody(metadataBodyContainer: HTMLElement): void {
374376
}
@@ -386,6 +388,13 @@ export class DeletedCell extends AbstractCellRenderer {
386388
});
387389
}
388390

391+
if (state.metadataEditor || state.outerWidth) {
392+
this._metadataEditor?.layout({
393+
width: this.notebookEditor.getLayoutInfo().width - 20,
394+
height: this._layoutInfo.metadataHeight
395+
});
396+
}
397+
389398
this._diagonalFill.style.height = `${this._layoutInfo.editorHeight}px`;
390399

391400
this.notebookEditor.layoutNotebookCell(this.cell,
@@ -401,8 +410,10 @@ export class InsertCell extends AbstractCellRenderer {
401410
readonly cell: CellDiffViewModel,
402411
readonly templateData: CellDiffRenderTemplate,
403412
@IInstantiationService protected readonly instantiationService: IInstantiationService,
413+
@IModeService readonly modeService: IModeService,
414+
@IModelService readonly modelService: IModelService,
404415
) {
405-
super(notebookEditor, cell, templateData, instantiationService);
416+
super(notebookEditor, cell, templateData, instantiationService, modeService, modelService);
406417
}
407418

408419
initData(): void {
@@ -447,9 +458,6 @@ export class InsertCell extends AbstractCellRenderer {
447458
});
448459
}
449460

450-
buildMetadataHeader(metadataHeaderContainer: HTMLElement): void {
451-
}
452-
453461
buildMetadataBody(metadataBodyContainer: HTMLElement): void {
454462
}
455463

@@ -467,6 +475,13 @@ export class InsertCell extends AbstractCellRenderer {
467475
});
468476
}
469477

478+
if (state.metadataEditor || state.outerWidth) {
479+
this._metadataEditor?.layout({
480+
width: this.notebookEditor.getLayoutInfo().width - 20,
481+
height: this._layoutInfo.metadataHeight
482+
});
483+
}
484+
470485
this._diagonalFill.style.height = `${this._layoutInfo.editorHeight}px`;
471486

472487
this.notebookEditor.layoutNotebookCell(this.cell,
@@ -482,8 +497,10 @@ export class ModifiedCell extends AbstractCellRenderer {
482497
readonly cell: CellDiffViewModel,
483498
readonly templateData: CellDiffRenderTemplate,
484499
@IInstantiationService protected readonly instantiationService: IInstantiationService,
500+
@IModeService readonly modeService: IModeService,
501+
@IModelService readonly modelService: IModelService,
485502
) {
486-
super(notebookEditor, cell, templateData, instantiationService);
503+
super(notebookEditor, cell, templateData, instantiationService, modeService, modelService);
487504
}
488505

489506
initData(): void {
@@ -542,9 +559,6 @@ export class ModifiedCell extends AbstractCellRenderer {
542559

543560
}
544561

545-
buildMetadataHeader(metadataHeaderContainer: HTMLElement): void {
546-
}
547-
548562
buildMetadataBody(metadataBodyContainer: HTMLElement): void {
549563
}
550564

@@ -560,6 +574,13 @@ export class ModifiedCell extends AbstractCellRenderer {
560574
this._editor!.layout();
561575
}
562576

577+
if (state.metadataEditor || state.outerWidth) {
578+
this._metadataEditor?.layout({
579+
width: this.notebookEditor.getLayoutInfo().width - 20,
580+
height: this._layoutInfo.metadataHeight
581+
});
582+
}
583+
563584
this.notebookEditor.layoutNotebookCell(this.cell,
564585
this._layoutInfo.editorHeight + this._layoutInfo.editorMargin + this._layoutInfo.metadataHeight + this._layoutInfo.metadataStatusHeight);
565586

0 commit comments

Comments
 (0)