diff --git a/src/vs/editor/browser/widget/multiDiffEditorWidget/diffEditorItemTemplate.ts b/src/vs/editor/browser/widget/multiDiffEditorWidget/diffEditorItemTemplate.ts index aaa832d3804..7021e1a0147 100644 --- a/src/vs/editor/browser/widget/multiDiffEditorWidget/diffEditorItemTemplate.ts +++ b/src/vs/editor/browser/widget/multiDiffEditorWidget/diffEditorItemTemplate.ts @@ -5,22 +5,22 @@ import { h } from 'vs/base/browser/dom'; import { Button } from 'vs/base/browser/ui/button/button'; import { Codicon } from 'vs/base/common/codicons'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { autorun, derived } from 'vs/base/common/observable'; import { globalTransaction, observableValue } from 'vs/base/common/observableInternal/base'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditor/diffEditorWidget'; -import { IDiffEntry } from 'vs/editor/browser/widget/multiDiffEditorWidget/model'; +import { IDocumentDiffItem } from 'vs/editor/browser/widget/multiDiffEditorWidget/model'; import { IWorkbenchUIElementFactory } from 'vs/editor/browser/widget/multiDiffEditorWidget/workbenchUIElementFactory'; import { OffsetRange } from 'vs/editor/common/core/offsetRange'; import { IDiffEditorViewModel } from 'vs/editor/common/editorCommon'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IObjectData, IPooledObject } from './objectPool'; - +import { IDiffEditorOptions } from 'vs/editor/common/config/editorOptions'; export class TemplateData implements IObjectData { constructor( public readonly viewModel: IDiffEditorViewModel, - public readonly entry: IDiffEntry + public readonly entry: IDocumentDiffItem, ) { } @@ -86,17 +86,6 @@ export class DiffEditorItemTemplate extends Disposable implements IPooledObject< ]); private readonly _editor = this._register(this._instantiationService.createInstance(DiffEditorWidget, this._elements.editor, { - scrollBeyondLastLine: false, - hideUnchangedRegions: { - enabled: true, - }, - scrollbar: { - vertical: 'hidden', - horizontal: 'hidden', - handleMouseWheel: false, - }, - renderOverviewRuler: false, - fixedOverflowWidgets: true, overflowWidgetsDomNode: this._overflowWidgetsDomNode, }, {})); @@ -143,9 +132,7 @@ export class DiffEditorItemTemplate extends Disposable implements IPooledObject< }); })); - this._container.appendChild(this._elements.root); - this._outerEditorHeight = 38; } @@ -157,10 +144,37 @@ export class DiffEditorItemTemplate extends Disposable implements IPooledObject< } } - public setData(data: TemplateData) { + private readonly _dataStore = new DisposableStore(); + + public setData(data: TemplateData): void { this._resourceLabel?.setUri(data.viewModel.model.modified.uri); + this._dataStore.clear(); + + function updateOptions(options: IDiffEditorOptions): IDiffEditorOptions { + return { + ...options, + scrollBeyondLastLine: false, + hideUnchangedRegions: { + enabled: true, + }, + scrollbar: { + vertical: 'hidden', + horizontal: 'hidden', + handleMouseWheel: false, + }, + renderOverviewRuler: false, + fixedOverflowWidgets: true, + }; + } + + if (data.entry.onOptionsDidChange) { + this._dataStore.add(data.entry.onOptionsDidChange(() => { + this._editor.updateOptions(updateOptions(data.entry.options ?? {})); + })); + } globalTransaction(tx => { this._editor.setModel(data.viewModel, tx); + this._editor.updateOptions(updateOptions(data.entry.options ?? {})); }); } diff --git a/src/vs/editor/browser/widget/multiDiffEditorWidget/model.ts b/src/vs/editor/browser/widget/multiDiffEditorWidget/model.ts index 4de8c1a0280..376a4557308 100644 --- a/src/vs/editor/browser/widget/multiDiffEditorWidget/model.ts +++ b/src/vs/editor/browser/widget/multiDiffEditorWidget/model.ts @@ -4,10 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; +import { IDiffEditorOptions } from 'vs/editor/common/config/editorOptions'; import { ITextModel } from 'vs/editor/common/model'; -export interface IMultiDocumentDiffEditorModel { - readonly diffs: LazyPromise[]; +export interface IMultiDiffEditorModel { + readonly documents: LazyPromise[]; readonly onDidChange: Event; } @@ -33,8 +34,10 @@ export class ConstLazyPromise implements LazyPromise { } } -export interface IDiffEntry { +export interface IDocumentDiffItem { readonly title: string; readonly original: ITextModel | undefined; // undefined if the file was created. readonly modified: ITextModel | undefined; // undefined if the file was deleted. + readonly options?: IDiffEditorOptions; + readonly onOptionsDidChange?: Event; } diff --git a/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidget.ts b/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidget.ts index 07545691df9..b1918272211 100644 --- a/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidget.ts +++ b/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidget.ts @@ -7,7 +7,7 @@ import { Dimension } from 'vs/base/browser/dom'; import { Disposable } from 'vs/base/common/lifecycle'; import { derivedWithStore, observableValue, recomputeInitiallyAndOnChange } from 'vs/base/common/observable'; import { readHotReloadableExport } from 'vs/editor/browser/widget/diffEditor/utils'; -import { IMultiDocumentDiffEditorModel } from 'vs/editor/browser/widget/multiDiffEditorWidget/model'; +import { IMultiDiffEditorModel } from 'vs/editor/browser/widget/multiDiffEditorWidget/model'; import { MultiDiffEditorWidgetImpl } from 'vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import './colors'; @@ -16,7 +16,7 @@ import { IWorkbenchUIElementFactory } from 'vs/editor/browser/widget/multiDiffEd export class MultiDiffEditorWidget extends Disposable { private readonly _dimension = observableValue(this, undefined); - private readonly _model = observableValue(this, undefined); + private readonly _model = observableValue(this, undefined); private readonly widgetImpl = derivedWithStore(this, (reader, store) => { readHotReloadableExport(DiffEditorItemTemplate, reader); @@ -39,7 +39,7 @@ export class MultiDiffEditorWidget extends Disposable { this._register(recomputeInitiallyAndOnChange(this.widgetImpl)); } - public setModel(model: IMultiDocumentDiffEditorModel | undefined): void { + public setModel(model: IMultiDiffEditorModel | undefined): void { this._model.set(model, undefined); } diff --git a/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl.ts b/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl.ts index c8e0db5060e..7eddb9db7e1 100644 --- a/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl.ts +++ b/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl.ts @@ -11,7 +11,7 @@ import { Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable'; import 'vs/css!./style'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditor/diffEditorWidget'; import { ObservableElementSizeObserver } from 'vs/editor/browser/widget/diffEditor/utils'; -import { IDiffEntry, IMultiDocumentDiffEditorModel, LazyPromise } from 'vs/editor/browser/widget/multiDiffEditorWidget/model'; +import { IDocumentDiffItem, IMultiDiffEditorModel, LazyPromise } from 'vs/editor/browser/widget/multiDiffEditorWidget/model'; import { OffsetRange } from 'vs/editor/common/core/offsetRange'; import { IDiffEditorViewModel } from 'vs/editor/common/editorCommon'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -37,7 +37,7 @@ export class MultiDiffEditorWidgetImpl extends Disposable { ]); private readonly _sizeObserver = this._register(new ObservableElementSizeObserver(this._element, undefined)); - private readonly _documentsObs = this._model.map(this, m => !m ? constObservable([]) : observableFromEvent(m.onDidChange, /** @description Documents changed */() => m.diffs)); + private readonly _documentsObs = this._model.map(this, m => !m ? constObservable([]) : observableFromEvent(m.onDidChange, /** @description Documents changed */() => m.documents)); private readonly _documents = this._documentsObs.map(this, (m, reader) => m.read(reader)); private readonly _objectPool = this._register(new ObjectPool((data) => { @@ -84,7 +84,7 @@ export class MultiDiffEditorWidgetImpl extends Disposable { constructor( private readonly _element: HTMLElement, private readonly _dimension: IObservable, - private readonly _model: IObservable, + private readonly _model: IObservable, private readonly _workbenchUIElementFactory: IWorkbenchUIElementFactory, @IInstantiationService private readonly _instantiationService: IInstantiationService, ) { @@ -139,7 +139,7 @@ export class MultiDiffEditorWidgetImpl extends Disposable { let contentScrollOffsetToScrollOffset = 0; let itemHeightSumBefore = 0; let itemContentHeightSumBefore = 0; - const viewPortHeight = this._elements.root.clientHeight; + const viewPortHeight = this._sizeObserver.height.read(reader); const contentViewPort = OffsetRange.ofStartAndLength(scrollTop, viewPortHeight); const width = this._sizeObserver.width.read(reader); @@ -186,7 +186,7 @@ class DiffEditorItem extends Disposable { constructor( private readonly _objectPool: ObjectPool, - private readonly _entry: LazyPromise, + private readonly _entry: LazyPromise, baseDiffEditorWidget: DiffEditorWidget, private readonly _scrollLeft: IObservable, ) { diff --git a/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor.ts b/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor.ts index 303955802e4..d8ee0901199 100644 --- a/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor.ts +++ b/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor.ts @@ -27,7 +27,7 @@ export class MultiDiffEditor extends EditorPane { @IInstantiationService private readonly instantiationService: InstantiationService, @ITelemetryService telemetryService: ITelemetryService, @IThemeService themeService: IThemeService, - @IStorageService storageService: IStorageService + @IStorageService storageService: IStorageService, ) { super(MultiDiffEditor.ID, telemetryService, themeService, storageService); } diff --git a/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput.ts b/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput.ts index dd4365ba554..1102fa5d1e6 100644 --- a/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput.ts +++ b/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput.ts @@ -3,13 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { localize } from 'vs/nls'; +import { toDisposable } from 'vs/base/common/lifecycle'; +import { deepClone } from 'vs/base/common/objects'; +import { isObject } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; +import { ConstLazyPromise, IDocumentDiffItem, IMultiDiffEditorModel } from 'vs/editor/browser/widget/multiDiffEditorWidget/model'; +import { IDiffEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; +import { localize } from 'vs/nls'; +import { IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; import { DEFAULT_EDITOR_ASSOCIATION, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { ConstLazyPromise, IDiffEntry, IMultiDocumentDiffEditorModel } from 'vs/editor/browser/widget/multiDiffEditorWidget/model'; -import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { toDisposable } from 'vs/base/common/lifecycle'; export class MultiDiffEditorInput extends EditorInput { static readonly ID: string = 'workbench.input.multiDiffEditor'; @@ -34,41 +39,73 @@ export class MultiDiffEditorInput extends EditorInput { return DEFAULT_EDITOR_ASSOCIATION.id; } - private _viewModel: IMultiDocumentDiffEditorModel | undefined; + private _viewModel: IMultiDiffEditorModel | undefined; constructor( readonly label: string | undefined, readonly resources: readonly MultiDiffEditorInputData[], @ITextModelService private readonly _textModelService: ITextModelService, + @ITextResourceConfigurationService private readonly _textResourceConfigurationService: ITextResourceConfigurationService, ) { super(); } - async getViewModel(): Promise { + async getViewModel(): Promise { if (!this._viewModel) { this._viewModel = await this._createViewModel(); } return this._viewModel; } - private async _createViewModel(): Promise { + private async _createViewModel(): Promise { const rs = await Promise.all(this.resources.map(async r => ({ originalRef: await this._textModelService.createModelReference(r.original!), modifiedRef: await this._textModelService.createModelReference(r.modified!), title: r.resource.fsPath, }))); + const textResourceConfigurationService = this._textResourceConfigurationService; + return { onDidChange: () => toDisposable(() => { }), - diffs: rs.map(r => new ConstLazyPromise({ + documents: rs.map(r => new ConstLazyPromise({ original: r.originalRef.object.textEditorModel, modified: r.modifiedRef.object.textEditorModel, title: r.title, + get options() { + return computeOptions(textResourceConfigurationService.getValue(r.originalRef.object.textEditorModel.uri)); + }, + onOptionsDidChange: h => this._textResourceConfigurationService.onDidChangeConfiguration(e => { + const uri = r.modifiedRef.object.textEditorModel.uri; + if (e.affectsConfiguration(uri, 'editor') || e.affectsConfiguration(uri, 'diffEditor')) { + h(); + } + }), })), }; } } +function computeOptions(configuration: IEditorConfiguration): IDiffEditorOptions { + const editorConfiguration = deepClone(configuration.editor); + + // Handle diff editor specially by merging in diffEditor configuration + if (isObject(configuration.diffEditor)) { + const diffEditorConfiguration: IDiffEditorOptions = deepClone(configuration.diffEditor); + + // User settings defines `diffEditor.codeLens`, but here we rename that to `diffEditor.diffCodeLens` to avoid collisions with `editor.codeLens`. + diffEditorConfiguration.diffCodeLens = diffEditorConfiguration.codeLens; + delete diffEditorConfiguration.codeLens; + + // User settings defines `diffEditor.wordWrap`, but here we rename that to `diffEditor.diffWordWrap` to avoid collisions with `editor.wordWrap`. + diffEditorConfiguration.diffWordWrap = <'off' | 'on' | 'inherit' | undefined>diffEditorConfiguration.wordWrap; + delete diffEditorConfiguration.wordWrap; + + Object.assign(editorConfiguration, diffEditorConfiguration); + } + return editorConfiguration; +} + export class MultiDiffEditorInputData { constructor( readonly resource: URI,