Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 121 additions & 9 deletions src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import * as DOM from 'vs/base/browser/dom';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { DiffElementViewModelBase, getFormattedMetadataJSON, getFormattedOutputJSON, OutputComparison, outputEqual, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor, NOTEBOOK_DIFF_CELL_INPUT, NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser';
import { DiffElementCellViewModelBase, getFormattedMetadataJSON, getFormattedOutputJSON, OutputComparison, outputEqual, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel, DiffElementPlaceholderViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor, NOTEBOOK_DIFF_CELL_INPUT, NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED, CellDiffPlaceholderRenderTemplate, IDiffCellMarginOverlay } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser';
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditor/codeEditorWidget';
import { IModelService } from 'vs/editor/common/services/model';
import { ILanguageService } from 'vs/editor/common/languages/language';
Expand All @@ -31,7 +31,7 @@ import { SuggestController } from 'vs/editor/contrib/suggest/browser/suggestCont
import { MenuPreventer } from 'vs/workbench/contrib/codeEditor/browser/menuPreventer';
import { SelectionClipboardContributionID } from 'vs/workbench/contrib/codeEditor/browser/selectionClipboard';
import { TabCompletionController } from 'vs/workbench/contrib/snippets/browser/tabCompletion';
import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels';
import { renderIcon, renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
Expand All @@ -44,6 +44,8 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditor/diffEditorWidget';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel';
import { localize } from 'vs/nls';
import { Emitter } from 'vs/base/common/event';

export function getOptimizedNestedCodeEditorWidgetOptions(): ICodeEditorWidgetOptions {
return {
Expand All @@ -59,6 +61,29 @@ export function getOptimizedNestedCodeEditorWidgetOptions(): ICodeEditorWidgetOp
};
}

export class CellDiffPlaceholderElement extends Disposable {
Comment thread
DonJayamanne marked this conversation as resolved.
constructor(
placeholder: DiffElementPlaceholderViewModel,
templateData: CellDiffPlaceholderRenderTemplate,
) {
super();
templateData.body.classList.remove('left', 'right', 'full');
const text = (placeholder.hiddenCells.length === 1) ?
localize('hiddenCell', '{0} hidden cell', placeholder.hiddenCells.length) :
localize('hiddenCells', '{0} hidden cells', placeholder.hiddenCells.length);
templateData.placeholder.innerText = text;

this._register(DOM.addDisposableListener(templateData.placeholder, 'dblclick', (e: MouseEvent) => {
if (e.button !== 0) {
return;
}
e.preventDefault();
placeholder.showHiddenCells();
}));
this._register(templateData.marginOverlay.onAction(() => placeholder.showHiddenCells()));
templateData.marginOverlay.show();
}
}

class PropertyHeader extends Disposable {
protected _foldingIndicator!: HTMLElement;
Expand All @@ -69,14 +94,14 @@ class PropertyHeader extends Disposable {
protected _propertyExpanded?: IContextKey<boolean>;

constructor(
readonly cell: DiffElementViewModelBase,
readonly cell: DiffElementCellViewModelBase,
readonly propertyHeaderContainer: HTMLElement,
readonly notebookEditor: INotebookTextDiffEditor,
readonly accessor: {
updateInfoRendering: (renderOutput: boolean) => void;
checkIfModified: (cell: DiffElementViewModelBase) => false | { reason: string | undefined };
getFoldingState: (cell: DiffElementViewModelBase) => PropertyFoldingState;
updateFoldingState: (cell: DiffElementViewModelBase, newState: PropertyFoldingState) => void;
checkIfModified: (cell: DiffElementCellViewModelBase) => false | { reason: string | undefined };
getFoldingState: (cell: DiffElementCellViewModelBase) => PropertyFoldingState;
updateFoldingState: (cell: DiffElementCellViewModelBase, newState: PropertyFoldingState) => void;
unChangedLabel: string;
changedLabel: string;
prefix: string;
Expand Down Expand Up @@ -271,7 +296,7 @@ abstract class AbstractElementRenderer extends Disposable {

constructor(
readonly notebookEditor: INotebookTextDiffEditor,
readonly cell: DiffElementViewModelBase,
readonly cell: DiffElementCellViewModelBase,
readonly templateData: CellDiffSingleSideRenderTemplate | CellDiffSideBySideRenderTemplate,
readonly style: 'left' | 'right' | 'full',
protected readonly instantiationService: IInstantiationService,
Expand Down Expand Up @@ -1363,6 +1388,15 @@ export class ModifiedElement extends AbstractElementRenderer {
container.classList.remove('inserted', 'removed');
}

override buildBody(): void {
super.buildBody();
if (this.cell.displayIconToHideUnmodifiedCells) {
this._register(this.templateData.marginOverlay.onAction(() => this.cell.hideUnchangedCells()));
this.templateData.marginOverlay.show();
} else {
this.templateData.marginOverlay.hide();
}
}
_disposeMetadata() {
this.cell.metadataStatusHeight = 0;
this.cell.metadataHeight = 0;
Expand Down Expand Up @@ -1760,7 +1794,10 @@ export class ModifiedElement extends AbstractElementRenderer {
if (state.metadataHeight || state.outerWidth) {
if (this._metadataEditorContainer) {
this._metadataEditorContainer.style.height = `${this.cell.layoutInfo.metadataHeight}px`;
this._metadataEditor?.layout();
this._metadataEditor?.layout({
width: this._editor?.getViewWidth() || this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true),
height: this.cell.layoutInfo.metadataHeight
});
}
}

Expand Down Expand Up @@ -1789,3 +1826,78 @@ export class ModifiedElement extends AbstractElementRenderer {
super.dispose();
}
}


export class CollapsedCellOverlayWidget extends Disposable implements IDiffCellMarginOverlay {
private readonly _nodes = DOM.h('div.diff-hidden-cells', [
DOM.h('div.center@content', { style: { display: 'flex' } }, [
DOM.$('a', {
title: localize('showUnchangedCells', 'Show Unchanged Cells'),
role: 'button',
onclick: () => { this._action.fire(); }
},
...renderLabelWithIcons('$(unfold)'))]
),
]);

private readonly _action = this._register(new Emitter<void>());
public readonly onAction = this._action.event;
constructor(
private readonly container: HTMLElement
) {
super();

this._nodes.root.style.display = 'none';
container.appendChild(this._nodes.root);
}
Comment thread
DonJayamanne marked this conversation as resolved.
public show() {
this._nodes.root.style.display = 'block';
}
public hide() {
this._nodes.root.style.display = 'none';
}
public override dispose() {
this.hide();
this.container.removeChild(this._nodes.root);
DOM.reset(this._nodes.root);
super.dispose();
}
}

export class UnchangedCellOverlayWidget extends Disposable implements IDiffCellMarginOverlay {
private readonly _nodes = DOM.h('div.diff-hidden-cells', [
DOM.h('div.center@content', { style: { display: 'flex' } }, [
DOM.$('a', {
title: localize('hideUnchangedCells', 'Hide Unchanged Cells'),
role: 'button',
onclick: () => { this._action.fire(); }
},
...renderLabelWithIcons('$(fold)')
),
]
),
]);

private readonly _action = this._register(new Emitter<void>());
public readonly onAction = this._action.event;
constructor(
private readonly container: HTMLElement
) {
super();

this._nodes.root.style.display = 'none';
container.appendChild(this._nodes.root);
}
public show() {
this._nodes.root.style.display = 'block';
}
public hide() {
this._nodes.root.style.display = 'none';
}
public override dispose() {
this.hide();
this.container.removeChild(this._nodes.root);
DOM.reset(this._nodes.root);
super.dispose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import * as DOM from 'vs/base/browser/dom';
import * as nls from 'vs/nls';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { DiffElementViewModelBase, SideBySideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { DiffElementCellViewModelBase, SideBySideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { DiffSide, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser';
import { ICellOutputViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
Expand All @@ -33,7 +33,7 @@ export class OutputElement extends Disposable {
private _notebookTextModel: NotebookTextModel,
private _notebookService: INotebookService,
private _quickInputService: IQuickInputService,
private _diffElementViewModel: DiffElementViewModelBase,
private _diffElementViewModel: DiffElementCellViewModelBase,
private _diffSide: DiffSide,
private _nestedCell: DiffNestedCellViewModel,
private _outputContainer: HTMLElement,
Expand Down Expand Up @@ -228,7 +228,7 @@ export class OutputContainer extends Disposable {
constructor(
private _editor: INotebookTextDiffEditor,
private _notebookTextModel: NotebookTextModel,
private _diffElementViewModel: DiffElementViewModelBase,
private _diffElementViewModel: DiffElementCellViewModelBase,
private _nestedCellViewModel: DiffNestedCellViewModel,
private _diffSide: DiffSide,
private _outputContainer: HTMLElement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,77 @@ interface ILayoutInfoDelta extends ILayoutInfoDelta0 {
recomputeOutput?: boolean;
}

export type IDiffElementViewModelBase = DiffElementCellViewModelBase | DiffElementPlaceholderViewModel;

export abstract class DiffElementViewModelBase extends Disposable {
protected _layoutInfoEmitter = this._register(new Emitter<CellDiffViewModelLayoutChangeEvent>());
onDidLayoutChange = this._layoutInfoEmitter.event;
constructor(
public readonly mainDocumentTextModel: INotebookTextModel,
public readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher,
public readonly initData: {
metadataStatusHeight: number;
outputStatusHeight: number;
fontInfo: FontInfo | undefined;
}
) {
super();

this._register(this.editorEventDispatcher.onDidChangeLayout(e => this._layoutInfoEmitter.fire({ outerWidth: true })));
}

abstract layoutChange(): void;
abstract getHeight(lineHeight: number): number;
abstract get totalHeight(): number;
}

export class DiffElementPlaceholderViewModel extends DiffElementViewModelBase {
readonly type: 'placeholder' = 'placeholder';
public hiddenCells: DiffElementCellViewModelBase[] = [];
protected _unfoldHiddenCells = this._register(new Emitter<void>());
onUnfoldHiddenCells = this._unfoldHiddenCells.event;

constructor(
mainDocumentTextModel: INotebookTextModel,
editorEventDispatcher: NotebookDiffEditorEventDispatcher,
initData: {
metadataStatusHeight: number;
outputStatusHeight: number;
fontInfo: FontInfo | undefined;
}
) {
super(mainDocumentTextModel, editorEventDispatcher, initData);

}
get totalHeight() {
return 24 + (2 * DIFF_CELL_MARGIN);
}
getHeight(_: number): number {
return this.totalHeight;
}
override layoutChange(): void {
//
}
showHiddenCells() {
this._unfoldHiddenCells.fire();
}
}

export abstract class DiffElementCellViewModelBase extends DiffElementViewModelBase {
public cellFoldingState: PropertyFoldingState;
public metadataFoldingState: PropertyFoldingState;
public outputFoldingState: PropertyFoldingState;
protected _layoutInfoEmitter = this._register(new Emitter<CellDiffViewModelLayoutChangeEvent>());
onDidLayoutChange = this._layoutInfoEmitter.event;
protected _stateChangeEmitter = this._register(new Emitter<{ renderOutput: boolean }>());
onDidStateChange = this._stateChangeEmitter.event;
protected _layoutInfo!: IDiffElementLayoutInfo;

public displayIconToHideUnmodifiedCells?: boolean;
private _hideUnchangedCells = this._register(new Emitter<void>());
public onHideUnchangedCells = this._hideUnchangedCells.event;

hideUnchangedCells() {
this._hideUnchangedCells.fire();
}
set rawOutputHeight(height: number) {
this._layout({ rawOutputHeight: Math.min(OUTPUT_EDITOR_HEIGHT_MAGIC, height) });
}
Expand Down Expand Up @@ -115,23 +176,27 @@ export abstract class DiffElementViewModelBase extends Disposable {
return this._layoutInfo;
}

get totalHeight() {
return this.layoutInfo.totalHeight;
}

private _sourceEditorViewState: editorCommon.ICodeEditorViewState | editorCommon.IDiffEditorViewState | null = null;
private _outputEditorViewState: editorCommon.ICodeEditorViewState | editorCommon.IDiffEditorViewState | null = null;
private _metadataEditorViewState: editorCommon.ICodeEditorViewState | editorCommon.IDiffEditorViewState | null = null;

constructor(
readonly mainDocumentTextModel: INotebookTextModel,
mainDocumentTextModel: INotebookTextModel,
readonly original: DiffNestedCellViewModel | undefined,
readonly modified: DiffNestedCellViewModel | undefined,
readonly type: 'unchanged' | 'insert' | 'delete' | 'modified',
readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher,
readonly initData: {
editorEventDispatcher: NotebookDiffEditorEventDispatcher,
initData: {
metadataStatusHeight: number;
outputStatusHeight: number;
fontInfo: FontInfo | undefined;
}
) {
super();
super(mainDocumentTextModel, editorEventDispatcher, initData);
const editorHeight = this._estimateEditorHeight(initData.fontInfo);
const cellStatusHeight = 25;
this._layoutInfo = {
Expand All @@ -154,9 +219,7 @@ export abstract class DiffElementViewModelBase extends Disposable {
this.metadataFoldingState = PropertyFoldingState.Collapsed;
this.outputFoldingState = PropertyFoldingState.Collapsed;

this._register(this.editorEventDispatcher.onDidChangeLayout(e => {
this._layoutInfoEmitter.fire({ outerWidth: true });
}));
this._register(this.editorEventDispatcher.onDidChangeLayout(e => this._layoutInfoEmitter.fire({ outerWidth: true })));
}

layoutChange() {
Expand Down Expand Up @@ -385,7 +448,7 @@ export abstract class DiffElementViewModelBase extends Disposable {
}
}

export class SideBySideDiffElementViewModel extends DiffElementViewModelBase {
export class SideBySideDiffElementViewModel extends DiffElementCellViewModelBase {
get originalDocument() {
return this.otherDocumentTextModel;
}
Expand Down Expand Up @@ -543,7 +606,7 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase {
}
}

export class SingleSideDiffElementViewModel extends DiffElementViewModelBase {
export class SingleSideDiffElementViewModel extends DiffElementCellViewModelBase {
get cellViewModel() {
return this.type === 'insert' ? this.modified! : this.original!;
}
Expand Down
Loading