Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add contentWidth/onDidChangeContentWidth to ListView, adopt in debugHover #183479

Merged
merged 2 commits into from May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/vs/base/browser/ui/list/listView.ts
Expand Up @@ -219,7 +219,9 @@ export interface IListView<T> extends ISpliceable<T>, IDisposable {
readonly scrollableElementDomNode: HTMLElement;
readonly length: number;
readonly contentHeight: number;
readonly contentWidth: number;
readonly onDidChangeContentHeight: Event<number>;
readonly onDidChangeContentWidth: Event<number>;
readonly renderHeight: number;
readonly scrollHeight: number;
readonly firstVisibleIndex: number;
Expand Down Expand Up @@ -310,8 +312,11 @@ export class ListView<T> implements IListView<T> {
private readonly disposables: DisposableStore = new DisposableStore();

private readonly _onDidChangeContentHeight = new Emitter<number>();
private readonly _onDidChangeContentWidth = new Emitter<number>();
readonly onDidChangeContentHeight: Event<number> = Event.latch(this._onDidChangeContentHeight.event, undefined, this.disposables);
readonly onDidChangeContentWidth: Event<number> = Event.latch(this._onDidChangeContentWidth.event, undefined, this.disposables);
get contentHeight(): number { return this.rangeMap.size; }
get contentWidth(): number { return this.scrollWidth ?? 0; }

get onDidScroll(): Event<ScrollEvent> { return this.scrollableElement.onScroll; }
get onWillScroll(): Event<ScrollEvent> { return this.scrollableElement.onWillScroll; }
Expand Down Expand Up @@ -689,6 +694,7 @@ export class ListView<T> implements IListView<T> {

this.scrollWidth = scrollWidth;
this.scrollableElement.setScrollDimensions({ scrollWidth: scrollWidth === 0 ? 0 : (scrollWidth + 10) });
this._onDidChangeContentWidth.fire(this.scrollWidth);
}

updateWidth(index: number): void {
Expand All @@ -702,6 +708,7 @@ export class ListView<T> implements IListView<T> {
if (typeof item.width !== 'undefined' && item.width > this.scrollWidth) {
this.scrollWidth = item.width;
this.scrollableElement.setScrollDimensions({ scrollWidth: this.scrollWidth + 10 });
this._onDidChangeContentWidth.fire(this.scrollWidth);
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/vs/base/browser/ui/list/listWidget.ts
Expand Up @@ -1506,10 +1506,18 @@ export class List<T> implements ISpliceable<T>, IDisposable {
return this.view.contentHeight;
}

get contentWidth(): number {
return this.view.contentWidth;
}

get onDidChangeContentHeight(): Event<number> {
return this.view.onDidChangeContentHeight;
}

get onDidChangeContentWidth(): Event<number> {
return this.view.onDidChangeContentWidth;
}

get scrollTop(): number {
return this.view.getScrollTop();
}
Expand Down
8 changes: 8 additions & 0 deletions src/vs/base/browser/ui/tree/abstractTree.ts
Expand Up @@ -1706,10 +1706,18 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
return this.view.contentHeight;
}

get contentWidth(): number {
return this.view.contentWidth;
}

get onDidChangeContentHeight(): Event<number> {
return this.view.onDidChangeContentHeight;
}

get onDidChangeContentWidth(): Event<number> {
return this.view.onDidChangeContentWidth;
}

get scrollTop(): number {
return this.view.scrollTop;
}
Expand Down
8 changes: 8 additions & 0 deletions src/vs/base/browser/ui/tree/asyncDataTree.ts
Expand Up @@ -438,10 +438,18 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return this.tree.contentHeight;
}

get contentWidth(): number {
return this.tree.contentWidth;
}

get onDidChangeContentHeight(): Event<number> {
return this.tree.onDidChangeContentHeight;
}

get onDidChangeContentWidth(): Event<number> {
return this.tree.onDidChangeContentWidth;
}

get scrollTop(): number {
return this.tree.scrollTop;
}
Expand Down
24 changes: 8 additions & 16 deletions src/vs/workbench/contrib/debug/browser/debugHover.ts
Expand Up @@ -112,7 +112,6 @@ export class DebugHoverWidget implements IContentWidget {
private create(): void {
this.domNode = $('.debug-hover-widget');
this.complexValueContainer = dom.append(this.domNode, $('.complex-value'));
this.complexValueContainer.style.visibility = 'hidden';
this.complexValueTitle = dom.append(this.complexValueContainer, $('.title'));
this.treeContainer = dom.append(this.complexValueContainer, $('.debug-hover-tree'));
this.treeContainer.setAttribute('role', 'tree');
Expand Down Expand Up @@ -150,6 +149,12 @@ export class DebugHoverWidget implements IContentWidget {
this.layoutTreeAndContainer();
}
}));
this.toDispose.push(this.tree.onDidChangeContentWidth(() => {
if (!this.isUpdatingTree) {
// Don't do a layout in the middle of the async setInput
this.layoutTreeAndContainer();
}
}));

this.registerListeners();
this.editor.addContentWidget(this);
Expand Down Expand Up @@ -295,12 +300,7 @@ export class DebugHoverWidget implements IContentWidget {
const scrollBarHeight = 10;
const treeHeight = Math.min(Math.max(266, this.editor.getLayoutInfo().height * 0.55), this.tree.contentHeight + scrollBarHeight);

// Reset to a smaller width, if it was previously rendered wide
this.tree.layout(treeHeight, 400);

// const titleWidth = this.complexValueTitle.clientWidth;
const realTreeWidth = this.tree.getHTMLElement().offsetWidth;
// const contentWidth = Math.max(titleWidth, realTreeWidth);
const realTreeWidth = this.tree.contentWidth;
const treeWidth = clamp(realTreeWidth, 400, 550);
this.tree.layout(treeHeight, treeWidth);
this.treeContainer.style.height = `${treeHeight}px`;
Expand All @@ -315,14 +315,7 @@ export class DebugHoverWidget implements IContentWidget {

// Do this in beforeRender once the content widget is no longer display=none so that its elements' sizes will be measured correctly.
this.isUpdatingTree = true;
this.tree.setInput(expression).then(() => {
dom.scheduleAtNextAnimationFrame(() => {
// Wait for scrollWidth to update after a frame
this.layoutTree();
this.editor.layoutContentWidget(this);
this.complexValueContainer.style.visibility = '';
});
}).finally(() => {
this.tree.setInput(expression).finally(() => {
this.isUpdatingTree = false;
});
}
Expand All @@ -339,7 +332,6 @@ export class DebugHoverWidget implements IContentWidget {


hide(): void {
this.complexValueContainer.style.visibility = 'hidden';
if (this.showCancellationSource) {
this.showCancellationSource.cancel();
this.showCancellationSource = undefined;
Expand Down