diff --git a/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidget.ts b/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidget.ts index 9a19e5e5669..e2392cc8b4a 100644 --- a/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidget.ts +++ b/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidget.ts @@ -44,8 +44,8 @@ export class MultiDiffEditorWidget extends Disposable { this._register(recomputeInitiallyAndOnChange(this._widgetImpl)); } - public scrollTo(uri: URI): void { - this._widgetImpl.get().scrollTo(uri); + public reveal(resource: { original: URI } | { modified: URI }, lineNumber: number): void { + this._widgetImpl.get().reveal(resource, lineNumber); } public createViewModel(model: IMultiDiffEditorModel): MultiDiffEditorViewModel { diff --git a/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl.ts b/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl.ts index 5619b08b2cd..b8547c7d347 100644 --- a/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl.ts +++ b/src/vs/editor/browser/widget/multiDiffEditorWidget/multiDiffEditorWidgetImpl.ts @@ -25,6 +25,7 @@ import { ISelection, Selection } from 'vs/editor/common/core/selection'; import { URI } from 'vs/base/common/uri'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditor } from 'vs/editor/common/editorCommon'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export class MultiDiffEditorWidgetImpl extends Disposable { private readonly _elements = h('div.monaco-component.multiDiffEditor', [ @@ -104,6 +105,7 @@ export class MultiDiffEditorWidgetImpl extends Disposable { private readonly _workbenchUIElementFactory: IWorkbenchUIElementFactory, @IContextKeyService private readonly _parentContextKeyService: IContextKeyService, @IInstantiationService private readonly _parentInstantiationService: IInstantiationService, + @IConfigurationService private readonly _configurationService: IConfigurationService, ) { super(); @@ -186,10 +188,20 @@ export class MultiDiffEditorWidgetImpl extends Disposable { this._scrollableElement.setScrollPosition({ scrollLeft: scrollState.left, scrollTop: scrollState.top }); } - public scrollTo(originalUri: URI): void { + public reveal(resource: IMultiDiffResource, lineNumber: number): void { const viewItems = this._viewItems.get(); - const index = viewItems?.findIndex(item => item.viewModel.originalUri?.toString() === originalUri.toString()); - let scrollTop = 0; + let searchCallback: (item: VirtualizedViewItem) => boolean; + if (isMultiDiffOriginalResourceUri(resource)) { + searchCallback = (item) => item.viewModel.originalUri?.toString() === resource.original.toString(); + } else { + searchCallback = (item) => item.viewModel.modifiedUri?.toString() === resource.modified.toString(); + } + const index = viewItems.findIndex(searchCallback); + const scrollTopWithinItem = (lineNumber - 1) * this._configurationService.getValue('editor.lineHeight'); + // todo@aiday-mar: need to find the actual scroll top given the line number specific to the original or modified uri + // following does not neccessarily correspond to the appropriate scroll top within the editor + const maxScroll = viewItems[index].template.get()?.maxScroll.get().maxScroll; + let scrollTop = (maxScroll && scrollTopWithinItem < maxScroll) ? scrollTopWithinItem : 0; for (let i = 0; i < index; i++) { scrollTop += viewItems[i].contentHeight.get() + this._spaceBetweenPx; } @@ -289,6 +301,20 @@ interface IMultiDiffDocState { selections?: ISelection[]; } +interface IMultiDiffOriginalResource { + original: URI; +} + +interface IMultiDiffModifiedResource { + modified: URI; +} + +function isMultiDiffOriginalResourceUri(obj: any): obj is IMultiDiffOriginalResource { + return 'original' in obj && obj.original instanceof URI; +} + +type IMultiDiffResource = IMultiDiffOriginalResource | IMultiDiffModifiedResource; + class VirtualizedViewItem extends Disposable { private readonly _templateRef = this._register(disposableObservableValue | undefined>(this, undefined)); diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index bf6785d9675..322582ad33c 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -505,6 +505,11 @@ export interface IResourceMultiDiffEditorInput extends IBaseUntypedEditorInput { * If not set, the resources are dynamically derived from the {@link multiDiffSource}. */ readonly resources?: IResourceDiffEditorInput[]; + + /** + * Reveal the following resource on open + */ + readonly revealResource?: IResourceDiffEditorInput; } export type IResourceMergeEditorInputSide = (IResourceEditorInput | ITextResourceEditorInput) & { detail?: string }; diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts index 2d8031cbe77..ff0cc489d28 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts @@ -11,7 +11,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IThemeService } from 'vs/platform/theme/common/themeService'; import { localize } from 'vs/nls'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { BulkEditPreviewProvider, BulkFileOperations, BulkFileOperationType } from 'vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPreview'; +import { BulkEditPreviewProvider, BulkFileOperation, BulkFileOperations, BulkFileOperationType } from 'vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPreview'; import { ILabelService } from 'vs/platform/label/common/label'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { URI } from 'vs/base/common/uri'; @@ -36,8 +36,7 @@ import { ResourceEdit } from 'vs/editor/browser/services/bulkEditService'; import { ButtonBar } from 'vs/base/browser/ui/button/button'; import { defaultButtonStyles } from 'vs/platform/theme/browser/defaultStyles'; import { Mutable } from 'vs/base/common/types'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { MultiDiffEditor } from 'vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor'; +import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IResourceDiffEditorInput } from 'vs/workbench/common/editor'; const enum State { @@ -69,7 +68,8 @@ export class BulkEditPane extends ViewPane { private _currentResolve?: (edit?: ResourceEdit[]) => void; private _currentInput?: BulkFileOperations; private _currentProvider?: BulkEditPreviewProvider; - private _multiDiffEditor?: MultiDiffEditor; + private _fileOperations?: BulkFileOperation[]; + private _resources?: IResourceDiffEditorInput[]; constructor( options: IViewletViewOptions, @@ -98,11 +98,6 @@ export class BulkEditPane extends ViewPane { this._ctxHasCategories = BulkEditPane.ctxHasCategories.bindTo(contextKeyService); this._ctxGroupByFile = BulkEditPane.ctxGroupByFile.bindTo(contextKeyService); this._ctxHasCheckedChanges = BulkEditPane.ctxHasCheckedChanges.bindTo(contextKeyService); - this._disposables.add(this._editorService.onDidCloseEditor((e) => { - if (this._multiDiffEditor && e.editor === this._multiDiffEditor.input && e.groupId === this._multiDiffEditor.group?.id) { - this._multiDiffEditor = undefined; - } - })); } override dispose(): void { @@ -281,10 +276,6 @@ export class BulkEditPane extends ViewPane { this._currentInput = undefined; this._setState(State.Message); this._sessionDisposables.clear(); - if (this._multiDiffEditor && this._multiDiffEditor.input && this._multiDiffEditor.group) { - this._editorService.closeEditor({ editor: this._multiDiffEditor.input, groupId: this._multiDiffEditor.group.id }); - this._multiDiffEditor = undefined; - } } toggleChecked() { @@ -347,12 +338,26 @@ export class BulkEditPane extends ViewPane { return; } - if (this._multiDiffEditor) { - // Multi diff editor already visible - this._multiDiffEditor.scrollTo(fileElement.edit.uri); - return; + let resources: IResourceDiffEditorInput[]; + if (this._fileOperations === fileOperations && this._resources) { + resources = this._resources; + } else { + resources = await this._getResources(fileOperations); } + const revealResource = resources.find(r => r.original.resource!.toString() === fileElement.edit.uri.toString()); + const multiDiffSource = URI.from({ scheme: 'refactor-preview' }); + const label = 'Refactor Preview'; + this._editorService.openEditor({ + multiDiffSource, + revealResource, + resources, + label, + description: label, + options, + }, e.sideBySide ? SIDE_GROUP : ACTIVE_GROUP); + } + private async _getResources(fileOperations: BulkFileOperation[]): Promise { const resources: IResourceDiffEditorInput[] = []; for (const operation of fileOperations) { const operationUri = operation.uri; @@ -379,15 +384,7 @@ export class BulkEditPane extends ViewPane { }); } } - const multiDiffSource = URI.from({ scheme: 'refactor-preview' }); - const label = 'Refactor Preview'; - this._multiDiffEditor = await this._editorService.openEditor({ - multiDiffSource, - resources, - label, - description: label, - options, - }) as MultiDiffEditor; + return resources; } private _onContextMenu(e: ITreeContextMenuEvent): void { diff --git a/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor.ts b/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor.ts index 21b1d64a6fa..be2fab93175 100644 --- a/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor.ts +++ b/src/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor.ts @@ -72,8 +72,8 @@ export class MultiDiffEditor extends AbstractEditorWithViewState { diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 1be2060f98c..19b51a652c7 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -236,7 +236,6 @@ export interface IEditorService { * Open an editor in an editor group. * * @param editor the editor to open - * @param options the options to use for the editor * @param group the target group. If unspecified, the editor will open in the currently * active group. Use `SIDE_GROUP` to open the editor in a new editor group to the side * of the currently active group.