From 3d716c20e2c6bb95efab33406b68d8016e15711e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 12 Oct 2019 02:03:54 +0200 Subject: [PATCH] Fixes #45131: Render a floating click widget when the diff editor has whitespace only changes and whitespace is ignored --- src/vs/editor/browser/editorBrowser.ts | 7 ++ .../editor/browser/widget/diffEditorWidget.ts | 4 + .../browser/codeEditor.contribution.ts | 1 + .../codeEditor/browser/diffEditorHelper.ts | 91 +++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 3a05cd5c8f4..0253876b502 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -18,6 +18,7 @@ import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguag import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager'; import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IDiffComputationResult } from 'vs/editor/common/services/editorWorkerService'; /** * A view zone is a full horizontal rectangle that 'pushes' text down. @@ -906,6 +907,12 @@ export interface IDiffEditor extends editorCommon.IEditor { */ getLineChanges(): editorCommon.ILineChange[] | null; + /** + * Get the computed diff information. + * @internal + */ + getDiffComputationResult(): IDiffComputationResult | null; + /** * Get information based on computed diff about a line number from the original model. * If the diff computation is not finished or the model is missing, will return null. diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index fd79438a75d..1ac2ad30699 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -578,6 +578,10 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE return this._diffComputationResult.changes; } + public getDiffComputationResult(): IDiffComputationResult | null { + return this._diffComputationResult; + } + public getOriginalEditor(): editorBrowser.ICodeEditor { return this.originalEditor; } diff --git a/src/vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts b/src/vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts index 39a4d1afe66..dcc524d15e7 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts @@ -5,6 +5,7 @@ import './menuPreventer'; import './accessibility/accessibility'; +import './diffEditorHelper'; import './inspectKeybindings'; import './largeFileOptimizations'; import './selectionClipboard'; diff --git a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts new file mode 100644 index 00000000000..eed47f4fad8 --- /dev/null +++ b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts @@ -0,0 +1,91 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; +import { registerDiffEditorContribution } from 'vs/editor/browser/editorExtensions'; +import { IEditorContribution } from 'vs/editor/common/editorCommon'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { FloatingClickWidget } from 'vs/workbench/browser/parts/editor/editorWidgets'; +import { IDiffComputationResult } from 'vs/editor/common/services/editorWorkerService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; + +const enum WidgetState { + Hidden, + HintWhitespace +} + +class DiffEditorHelperContribution extends Disposable implements IEditorContribution { + + private _helperWidget: FloatingClickWidget | null; + private _helperWidgetListener: IDisposable | null; + private _state: WidgetState; + + constructor( + private readonly _diffEditor: IDiffEditor, + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IConfigurationService private readonly _configurationService: IConfigurationService, + ) { + super(); + this._helperWidget = null; + this._helperWidgetListener = null; + this._state = WidgetState.Hidden; + + + this._register(this._diffEditor.onDidUpdateDiff(() => { + this._setState(this._deduceState(this._diffEditor.getDiffComputationResult())); + })); + } + + private _deduceState(diffComputationResult: IDiffComputationResult | null): WidgetState { + if (!diffComputationResult) { + return WidgetState.Hidden; + } + if (this._diffEditor.ignoreTrimWhitespace && diffComputationResult.changes.length === 0 && !diffComputationResult.identical) { + return WidgetState.HintWhitespace; + } + return WidgetState.Hidden; + } + + private _setState(newState: WidgetState) { + if (this._state === newState) { + return; + } + + this._state = newState; + + if (this._helperWidgetListener) { + this._helperWidgetListener.dispose(); + this._helperWidgetListener = null; + } + if (this._helperWidget) { + this._helperWidget.dispose(); + this._helperWidget = null; + } + + if (this._state === WidgetState.HintWhitespace) { + this._helperWidget = this._instantiationService.createInstance(FloatingClickWidget, this._diffEditor.getModifiedEditor(), nls.localize('hintWhitespace', "Show Whitespace Differences"), null); + this._helperWidgetListener = this._helperWidget.onClick(() => this._onDidClickHelperWidget()); + this._helperWidget.render(); + } + } + + private _onDidClickHelperWidget(): void { + if (this._state === WidgetState.HintWhitespace) { + this._configurationService.updateValue('diffEditor.ignoreTrimWhitespace', false, ConfigurationTarget.USER); + } + } + + dispose(): void { + super.dispose(); + } + + getId(): string { + return 'editor.contrib.diffEditorHelper'; + } +} + +registerDiffEditorContribution(DiffEditorHelperContribution); -- GitLab