diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 026344c5e1b6166a46371ae679c6cd7262b5269c..339cc5af913df811f75ad80bb6fbfe28ecfd3c2e 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -1546,6 +1546,16 @@ export class List implements ISpliceable, IDisposable { return this.getFocus().map(i => this.view.element(i)); } + isElementVisible(index: number) { + const viewTop = this.view.getScrollTop(); + const viewBottom = this.view.renderHeight + viewTop; + + const elementTop = this.view.elementTop(index); + const elementBottom = this.view.elementHeight(index) + elementTop; + + return (elementTop >= viewTop && elementBottom <= viewBottom); + } + reveal(index: number, relativeTop?: number): void { if (index < 0 || index >= this.length) { throw new ListError(this.user, `Invalid index ${index}`); diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index 9e584efcc560d92f2879acee9db38df89a0aaad7..1032a5a723f7cf75c1d044582e544d03853cfe10 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -1589,6 +1589,19 @@ export abstract class AbstractTree implements IDisposable this.view.open(indexes, browserEvent); } + isElementVisible(location: TRef) { + const index = this.model.getListIndex(location); + + if (index === -1) { + return false; + } + + const parentNode = this.model.getNode(this.model.getParentNodeLocation(location)); + const parentCollapsed = !parentNode.visible || parentNode.collapsed; + + return this.view.isElementVisible(index) && !parentCollapsed; + } + reveal(location: TRef, relativeTop?: number): void { this.model.expandTo(location); diff --git a/src/vs/base/browser/ui/tree/asyncDataTree.ts b/src/vs/base/browser/ui/tree/asyncDataTree.ts index bbdc7bc605401038b2db1298163107734c84c0c3..7edd15a2f62bbd3cff231f8e85594758c98f428a 100644 --- a/src/vs/base/browser/ui/tree/asyncDataTree.ts +++ b/src/vs/base/browser/ui/tree/asyncDataTree.ts @@ -662,6 +662,10 @@ export class AsyncDataTree implements IDisposable this.tree.open(nodes, browserEvent); } + isElementVisible(element: T) { + return this.tree.isElementVisible(this.getDataNode(element)); + } + reveal(element: T, relativeTop?: number): void { this.tree.reveal(this.getDataNode(element), relativeTop); } diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index f75377476493d213f6976df61cb41c2ecb981977..cce6ba126a0a86c88e3d4608d2cbfe435e2b2d3c 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -675,7 +675,11 @@ export class ExplorerView extends ViewPane { if (item.isDisposed) { return this.onSelectResource(resource, reveal, retry + 1); } - this.tree.reveal(item, 0.5); + + // Don't scroll to the item if it's already visible + if (!this.tree.isElementVisible(item)) { + this.tree.reveal(item, 0.5); + } } this.tree.setFocus([item]);