Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/floatingMenu/browser/floatingMenu.ts
4779 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 { h } from '../../../../base/browser/dom.js';
7
import { Disposable } from '../../../../base/common/lifecycle.js';
8
import { autorun, constObservable, observableFromEvent } from '../../../../base/common/observable.js';
9
import { MenuEntryActionViewItem } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
10
import { HiddenItemStrategy, MenuWorkbenchToolBar } from '../../../../platform/actions/browser/toolbar.js';
11
import { IMenuService, MenuId, MenuItemAction } from '../../../../platform/actions/common/actions.js';
12
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
13
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
14
import { ICodeEditor, OverlayWidgetPositionPreference } from '../../../browser/editorBrowser.js';
15
import { observableCodeEditor } from '../../../browser/observableCodeEditor.js';
16
import { IEditorContribution } from '../../../common/editorCommon.js';
17
18
export class FloatingEditorToolbar extends Disposable implements IEditorContribution {
19
static readonly ID = 'editor.contrib.floatingToolbar';
20
21
constructor(
22
editor: ICodeEditor,
23
@IInstantiationService instantiationService: IInstantiationService,
24
@IKeybindingService keybindingService: IKeybindingService,
25
@IMenuService menuService: IMenuService
26
) {
27
super();
28
29
const editorObs = this._register(observableCodeEditor(editor));
30
31
const menu = this._register(menuService.createMenu(MenuId.EditorContent, editor.contextKeyService));
32
const menuIsEmptyObs = observableFromEvent(this, menu.onDidChange, () => menu.getActions().length === 0);
33
34
this._register(autorun(reader => {
35
const menuIsEmpty = menuIsEmptyObs.read(reader);
36
if (menuIsEmpty) {
37
return;
38
}
39
40
const container = h('div.floating-menu-overlay-widget');
41
42
// Set height explicitly to ensure that the floating menu element
43
// is rendered in the lower right corner at the correct position.
44
container.root.style.height = '28px';
45
46
// Toolbar
47
const toolbar = instantiationService.createInstance(MenuWorkbenchToolBar, container.root, MenuId.EditorContent, {
48
actionViewItemProvider: (action, options) => {
49
if (!(action instanceof MenuItemAction)) {
50
return undefined;
51
}
52
53
const keybinding = keybindingService.lookupKeybinding(action.id);
54
if (!keybinding) {
55
return undefined;
56
}
57
58
return instantiationService.createInstance(class extends MenuEntryActionViewItem {
59
protected override updateLabel(): void {
60
if (this.options.label && this.label) {
61
this.label.textContent = `${this._commandAction.label} (${keybinding.getLabel()})`;
62
}
63
}
64
}, action, { ...options, keybindingNotRenderedWithLabel: true });
65
},
66
hiddenItemStrategy: HiddenItemStrategy.Ignore,
67
menuOptions: {
68
shouldForwardArgs: true
69
},
70
telemetrySource: 'editor.overlayToolbar',
71
toolbarOptions: {
72
primaryGroup: () => true,
73
useSeparatorsInPrimaryActions: true
74
},
75
});
76
77
reader.store.add(toolbar);
78
reader.store.add(autorun(reader => {
79
const model = editorObs.model.read(reader);
80
toolbar.context = model?.uri;
81
}));
82
83
// Overlay widget
84
reader.store.add(editorObs.createOverlayWidget({
85
allowEditorOverflow: false,
86
domNode: container.root,
87
minContentWidthInPx: constObservable(0),
88
position: constObservable({
89
preference: OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER
90
})
91
}));
92
}));
93
}
94
}
95
96