Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/browser/ui/hover/hoverWidget.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as dom from '../../dom.js';
7
import { StandardKeyboardEvent } from '../../keyboardEvent.js';
8
import { DomScrollableElement } from '../scrollbar/scrollableElement.js';
9
import { KeyCode } from '../../../common/keyCodes.js';
10
import { Disposable } from '../../../common/lifecycle.js';
11
import './hoverWidget.css';
12
import { localize } from '../../../../nls.js';
13
14
const $ = dom.$;
15
16
export const enum HoverPosition {
17
LEFT,
18
RIGHT,
19
BELOW,
20
ABOVE,
21
}
22
23
export class HoverWidget extends Disposable {
24
25
public readonly containerDomNode: HTMLElement;
26
public readonly contentsDomNode: HTMLElement;
27
public readonly scrollbar: DomScrollableElement;
28
29
constructor(fadeIn: boolean) {
30
super();
31
32
this.containerDomNode = document.createElement('div');
33
this.containerDomNode.className = 'monaco-hover';
34
this.containerDomNode.classList.toggle('fade-in', !!fadeIn);
35
this.containerDomNode.tabIndex = 0;
36
this.containerDomNode.setAttribute('role', 'tooltip');
37
38
this.contentsDomNode = document.createElement('div');
39
this.contentsDomNode.className = 'monaco-hover-content';
40
41
this.scrollbar = this._register(new DomScrollableElement(this.contentsDomNode, {
42
consumeMouseWheelIfScrollbarIsNeeded: true
43
}));
44
this.containerDomNode.appendChild(this.scrollbar.getDomNode());
45
}
46
47
public onContentsChanged(): void {
48
this.scrollbar.scanDomNode();
49
}
50
}
51
52
export class HoverAction extends Disposable {
53
public static render(parent: HTMLElement, actionOptions: { label: string; iconClass?: string; run: (target: HTMLElement) => void; commandId: string }, keybindingLabel: string | null) {
54
return new HoverAction(parent, actionOptions, keybindingLabel);
55
}
56
57
public readonly actionLabel: string;
58
public readonly actionKeybindingLabel: string | null;
59
60
public readonly actionRenderedLabel: string;
61
public readonly actionContainer: HTMLElement;
62
63
private readonly action: HTMLElement;
64
65
private constructor(parent: HTMLElement, actionOptions: { label: string; iconClass?: string; run: (target: HTMLElement) => void; commandId: string }, keybindingLabel: string | null) {
66
super();
67
68
this.actionLabel = actionOptions.label;
69
this.actionKeybindingLabel = keybindingLabel;
70
71
this.actionContainer = dom.append(parent, $('div.action-container'));
72
this.actionContainer.setAttribute('tabindex', '0');
73
74
this.action = dom.append(this.actionContainer, $('a.action'));
75
this.action.setAttribute('role', 'button');
76
if (actionOptions.iconClass) {
77
const iconElement = dom.append(this.action, $(`span.icon`));
78
iconElement.classList.add(...actionOptions.iconClass.split(' '));
79
}
80
this.actionRenderedLabel = keybindingLabel ? `${actionOptions.label} (${keybindingLabel})` : actionOptions.label;
81
const label = dom.append(this.action, $('span'));
82
label.textContent = this.actionRenderedLabel;
83
84
this._store.add(new ClickAction(this.actionContainer, actionOptions.run));
85
this._store.add(new KeyDownAction(this.actionContainer, actionOptions.run, [KeyCode.Enter, KeyCode.Space]));
86
this.setEnabled(true);
87
}
88
89
public setEnabled(enabled: boolean): void {
90
if (enabled) {
91
this.actionContainer.classList.remove('disabled');
92
this.actionContainer.removeAttribute('aria-disabled');
93
} else {
94
this.actionContainer.classList.add('disabled');
95
this.actionContainer.setAttribute('aria-disabled', 'true');
96
}
97
}
98
}
99
100
export function getHoverAccessibleViewHint(shouldHaveHint?: boolean, keybinding?: string | null): string | undefined {
101
return shouldHaveHint && keybinding ? localize('acessibleViewHint', "Inspect this in the accessible view with {0}.", keybinding) : shouldHaveHint ? localize('acessibleViewHintNoKbOpen', "Inspect this in the accessible view via the command Open Accessible View which is currently not triggerable via keybinding.") : '';
102
}
103
104
export class ClickAction extends Disposable {
105
constructor(container: HTMLElement, run: (container: HTMLElement) => void) {
106
super();
107
this._register(dom.addDisposableListener(container, dom.EventType.CLICK, e => {
108
e.stopPropagation();
109
e.preventDefault();
110
run(container);
111
}));
112
}
113
}
114
115
export class KeyDownAction extends Disposable {
116
constructor(container: HTMLElement, run: (container: HTMLElement) => void, keyCodes: KeyCode[]) {
117
super();
118
this._register(dom.addDisposableListener(container, dom.EventType.KEY_DOWN, e => {
119
const event = new StandardKeyboardEvent(e);
120
if (keyCodes.some(keyCode => event.equals(keyCode))) {
121
e.stopPropagation();
122
e.preventDefault();
123
run(container);
124
}
125
}));
126
}
127
}
128
129