Consider settings in multi diff editor

This commit is contained in:
Henning Dieterichs
2023-11-16 18:02:11 +01:00
committed by Henning Dieterichs
parent 70b6f9519a
commit 4e7a8779b9
6 changed files with 92 additions and 38 deletions
@@ -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 ?? {}));
});
}
@@ -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<IDiffEntry>[];
export interface IMultiDiffEditorModel {
readonly documents: LazyPromise<IDocumentDiffItem>[];
readonly onDidChange: Event<void>;
}
@@ -33,8 +34,10 @@ export class ConstLazyPromise<T> implements LazyPromise<T> {
}
}
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<void>;
}
@@ -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<Dimension | undefined>(this, undefined);
private readonly _model = observableValue<IMultiDocumentDiffEditorModel | undefined>(this, undefined);
private readonly _model = observableValue<IMultiDiffEditorModel | undefined>(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);
}
@@ -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<TemplateData, DiffEditorItemTemplate>((data) => {
@@ -84,7 +84,7 @@ export class MultiDiffEditorWidgetImpl extends Disposable {
constructor(
private readonly _element: HTMLElement,
private readonly _dimension: IObservable<Dimension | undefined>,
private readonly _model: IObservable<IMultiDocumentDiffEditorModel | undefined>,
private readonly _model: IObservable<IMultiDiffEditorModel | undefined>,
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<TemplateData, DiffEditorItemTemplate>,
private readonly _entry: LazyPromise<IDiffEntry>,
private readonly _entry: LazyPromise<IDocumentDiffItem>,
baseDiffEditorWidget: DiffEditorWidget,
private readonly _scrollLeft: IObservable<number>,
) {
@@ -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);
}
@@ -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<IMultiDocumentDiffEditorModel> {
async getViewModel(): Promise<IMultiDiffEditorModel> {
if (!this._viewModel) {
this._viewModel = await this._createViewModel();
}
return this._viewModel;
}
private async _createViewModel(): Promise<IMultiDocumentDiffEditorModel> {
private async _createViewModel(): Promise<IMultiDiffEditorModel> {
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<IDiffEntry>({
documents: rs.map(r => new ConstLazyPromise<IDocumentDiffItem>({
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,