Try to lay debug hover out correctly with scrollbar (#182817)

Fix #173980
This commit is contained in:
Rob Lourens
2023-05-17 16:51:12 -07:00
committed by GitHub
parent c54b191fce
commit 751fdcb904
@@ -14,10 +14,12 @@ import { coalesce } from 'vs/base/common/arrays';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { KeyCode } from 'vs/base/common/keyCodes';
import * as lifecycle from 'vs/base/common/lifecycle';
import { clamp } from 'vs/base/common/numbers';
import { isMacintosh } from 'vs/base/common/platform';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';
import { IDimension } from 'vs/editor/common/core/dimension';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
@@ -91,6 +93,9 @@ export class DebugHoverWidget implements IContentWidget {
private scrollbar!: DomScrollableElement;
private debugHoverComputer: DebugHoverComputer;
private expressionToRender: IExpression | undefined;
private isUpdatingTree = false;
constructor(
private editor: ICodeEditor,
@IDebugService private readonly debugService: IDebugService,
@@ -107,6 +112,7 @@ 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');
@@ -138,7 +144,12 @@ export class DebugHoverWidget implements IContentWidget {
this.domNode.style.border = `1px solid ${asCssVariable(editorHoverBorder)}`;
this.domNode.style.color = asCssVariable(editorHoverForeground);
this.toDispose.push(this.tree.onDidChangeContentHeight(() => this.layoutTreeAndContainer(false)));
this.toDispose.push(this.tree.onDidChangeContentHeight(() => {
if (!this.isUpdatingTree) {
// Don't do a layout in the middle of the async setInput
this.layoutTreeAndContainer();
}
}));
this.registerListeners();
this.editor.addContentWidget(this);
@@ -261,10 +272,10 @@ export class DebugHoverWidget implements IContentWidget {
this.valueContainer.hidden = true;
await this.tree.setInput(expression);
this.expressionToRender = expression;
this.complexValueTitle.textContent = expression.value;
this.complexValueTitle.title = expression.value;
this.layoutTreeAndContainer(true);
this.editor.layoutContentWidget(this);
this.tree.scrollTop = 0;
this.tree.scrollLeft = 0;
this.complexValueContainer.hidden = false;
@@ -275,15 +286,49 @@ export class DebugHoverWidget implements IContentWidget {
}
}
private layoutTreeAndContainer(initialLayout: boolean): void {
private layoutTreeAndContainer(): void {
this.layoutTree();
this.editor.layoutContentWidget(this);
}
private layoutTree(): void {
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 treeWidth = clamp(realTreeWidth, 400, 550);
this.tree.layout(treeHeight, treeWidth);
this.treeContainer.style.height = `${treeHeight}px`;
this.tree.layout(treeHeight, initialLayout ? 400 : undefined);
this.editor.layoutContentWidget(this);
this.scrollbar.scanDomNode();
}
beforeRender(): IDimension | null {
// beforeRender will be called each time the hover size changes, and the content widget is layed out again.
if (this.expressionToRender) {
const expression = this.expressionToRender;
this.expressionToRender = undefined;
// 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(() => {
this.isUpdatingTree = false;
dom.scheduleAtNextAnimationFrame(() => {
// Wait for scrollWidth to update after a frame
this.layoutTree();
this.editor.layoutContentWidget(this);
this.complexValueContainer.style.visibility = '';
});
});
}
return null;
}
afterRender(positionPreference: ContentWidgetPositionPreference | null) {
if (positionPreference) {
// Remember where the editor placed you to keep position stable #109226
@@ -293,6 +338,7 @@ export class DebugHoverWidget implements IContentWidget {
hide(): void {
this.complexValueContainer.style.visibility = 'hidden';
if (this.showCancellationSource) {
this.showCancellationSource.cancel();
this.showCancellationSource = undefined;