monaco-editor-core
Version:
A browser based code editor
93 lines (92 loc) • 3.89 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { isHTMLElement } from '../../../../base/browser/dom.js';
import { CancellationTokenSource } from '../../../../base/common/cancellation.js';
import { isMarkdownString } from '../../../../base/common/htmlContent.js';
import { isFunction, isString } from '../../../../base/common/types.js';
import { localize } from '../../../../nls.js';
export class ManagedHoverWidget {
constructor(hoverDelegate, target, fadeInAnimation) {
this.hoverDelegate = hoverDelegate;
this.target = target;
this.fadeInAnimation = fadeInAnimation;
}
async update(content, focus, options) {
if (this._cancellationTokenSource) {
// there's an computation ongoing, cancel it
this._cancellationTokenSource.dispose(true);
this._cancellationTokenSource = undefined;
}
if (this.isDisposed) {
return;
}
let resolvedContent;
if (content === undefined || isString(content) || isHTMLElement(content)) {
resolvedContent = content;
}
else if (!isFunction(content.markdown)) {
resolvedContent = content.markdown ?? content.markdownNotSupportedFallback;
}
else {
// compute the content, potentially long-running
// show 'Loading' if no hover is up yet
if (!this._hoverWidget) {
this.show(localize('iconLabel.loading', "Loading..."), focus, options);
}
// compute the content
this._cancellationTokenSource = new CancellationTokenSource();
const token = this._cancellationTokenSource.token;
resolvedContent = await content.markdown(token);
if (resolvedContent === undefined) {
resolvedContent = content.markdownNotSupportedFallback;
}
if (this.isDisposed || token.isCancellationRequested) {
// either the widget has been closed in the meantime
// or there has been a new call to `update`
return;
}
}
this.show(resolvedContent, focus, options);
}
show(content, focus, options) {
const oldHoverWidget = this._hoverWidget;
if (this.hasContent(content)) {
const hoverOptions = {
content,
target: this.target,
actions: options?.actions,
linkHandler: options?.linkHandler,
trapFocus: options?.trapFocus,
appearance: {
showPointer: this.hoverDelegate.placement === 'element',
skipFadeInAnimation: !this.fadeInAnimation || !!oldHoverWidget, // do not fade in if the hover is already showing
showHoverHint: options?.appearance?.showHoverHint,
},
position: {
hoverPosition: 2 /* HoverPosition.BELOW */,
},
};
this._hoverWidget = this.hoverDelegate.showHover(hoverOptions, focus);
}
oldHoverWidget?.dispose();
}
hasContent(content) {
if (!content) {
return false;
}
if (isMarkdownString(content)) {
return !!content.value;
}
return true;
}
get isDisposed() {
return this._hoverWidget?.isDisposed;
}
dispose() {
this._hoverWidget?.dispose();
this._cancellationTokenSource?.dispose(true);
this._cancellationTokenSource = undefined;
}
}