mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
Try to lay debug hover out correctly with scrollbar (#182817)
Fix #173980
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user