@theia/plugin-ext 1.28.0-next.7 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/plugin-api-rpc-model.d.ts +1 -0
- package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc-model.js.map +1 -1
- package/lib/common/plugin-api-rpc.d.ts +3 -0
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/common/plugin-protocol.d.ts +4 -0
- package/lib/common/plugin-protocol.d.ts.map +1 -1
- package/lib/common/plugin-protocol.js.map +1 -1
- package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
- package/lib/hosted/browser/hosted-plugin.js +4 -2
- package/lib/hosted/browser/hosted-plugin.js.map +1 -1
- package/lib/hosted/browser/worker/worker-env-ext.d.ts +1 -0
- package/lib/hosted/browser/worker/worker-env-ext.d.ts.map +1 -1
- package/lib/hosted/browser/worker/worker-env-ext.js +3 -0
- package/lib/hosted/browser/worker/worker-env-ext.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.d.ts +5 -1
- package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.js +22 -15
- package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
- package/lib/main/browser/comments/comment-thread-widget.js +5 -5
- package/lib/main/browser/comments/comment-thread-widget.js.map +1 -1
- package/lib/main/browser/debug/debug-main.d.ts +1 -0
- package/lib/main/browser/debug/debug-main.d.ts.map +1 -1
- package/lib/main/browser/debug/debug-main.js +10 -0
- package/lib/main/browser/debug/debug-main.js.map +1 -1
- package/lib/main/browser/languages-main.d.ts.map +1 -1
- package/lib/main/browser/languages-main.js.map +1 -1
- package/lib/main/browser/menus/menus-contribution-handler.d.ts +24 -88
- package/lib/main/browser/menus/menus-contribution-handler.d.ts.map +1 -1
- package/lib/main/browser/menus/menus-contribution-handler.js +108 -518
- package/lib/main/browser/menus/menus-contribution-handler.js.map +1 -1
- package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts +44 -0
- package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts.map +1 -0
- package/lib/main/browser/menus/plugin-menu-command-adapter.js +274 -0
- package/lib/main/browser/menus/plugin-menu-command-adapter.js.map +1 -0
- package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts +18 -0
- package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts.map +1 -0
- package/lib/main/browser/menus/vscode-theia-menu-mappings.js +88 -0
- package/lib/main/browser/menus/vscode-theia-menu-mappings.js.map +1 -0
- package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.js +9 -4
- package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.js +4 -3
- package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
- package/lib/main/browser/plugin-frontend-contribution.d.ts +0 -2
- package/lib/main/browser/plugin-frontend-contribution.d.ts.map +1 -1
- package/lib/main/browser/plugin-frontend-contribution.js +0 -8
- package/lib/main/browser/plugin-frontend-contribution.js.map +1 -1
- package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
- package/lib/main/browser/plugin-shared-style.js +0 -1
- package/lib/main/browser/plugin-shared-style.js.map +1 -1
- package/lib/main/browser/scm-main.d.ts +1 -0
- package/lib/main/browser/scm-main.d.ts.map +1 -1
- package/lib/main/browser/scm-main.js +7 -0
- package/lib/main/browser/scm-main.js.map +1 -1
- package/lib/main/browser/view/tree-view-widget.js +2 -2
- package/lib/main/browser/view/tree-view-widget.js.map +1 -1
- package/lib/main/node/handlers/plugin-theia-file-handler.d.ts +0 -4
- package/lib/main/node/handlers/plugin-theia-file-handler.d.ts.map +1 -1
- package/lib/main/node/handlers/plugin-theia-file-handler.js +0 -26
- package/lib/main/node/handlers/plugin-theia-file-handler.js.map +1 -1
- package/lib/main/node/plugin-ext-backend-module.d.ts.map +1 -1
- package/lib/main/node/plugin-ext-backend-module.js +0 -2
- package/lib/main/node/plugin-ext-backend-module.js.map +1 -1
- package/lib/main/node/resolvers/local-plugin-deployer-resolver.d.ts.map +1 -1
- package/lib/main/node/resolvers/local-plugin-deployer-resolver.js.map +1 -1
- package/lib/plugin/debug/debug-ext.d.ts +3 -1
- package/lib/plugin/debug/debug-ext.d.ts.map +1 -1
- package/lib/plugin/debug/debug-ext.js +26 -4
- package/lib/plugin/debug/debug-ext.js.map +1 -1
- package/lib/plugin/debug/plugin-debug-adapter-session.d.ts +1 -0
- package/lib/plugin/debug/plugin-debug-adapter-session.d.ts.map +1 -1
- package/lib/plugin/debug/plugin-debug-adapter-session.js +3 -0
- package/lib/plugin/debug/plugin-debug-adapter-session.js.map +1 -1
- package/lib/plugin/env.d.ts +11 -0
- package/lib/plugin/env.d.ts.map +1 -1
- package/lib/plugin/env.js +20 -0
- package/lib/plugin/env.js.map +1 -1
- package/lib/plugin/languages/signature.d.ts.map +1 -1
- package/lib/plugin/languages/signature.js +5 -1
- package/lib/plugin/languages/signature.js.map +1 -1
- package/lib/plugin/node/debug/debug.spec.d.ts +2 -0
- package/lib/plugin/node/debug/debug.spec.d.ts.map +1 -0
- package/lib/plugin/node/debug/debug.spec.js +68 -0
- package/lib/plugin/node/debug/debug.spec.js.map +1 -0
- package/lib/plugin/node/env-node-ext.d.ts +3 -0
- package/lib/plugin/node/env-node-ext.d.ts.map +1 -1
- package/lib/plugin/node/env-node-ext.js +11 -0
- package/lib/plugin/node/env-node-ext.js.map +1 -1
- package/lib/plugin/plugin-context.d.ts.map +1 -1
- package/lib/plugin/plugin-context.js +10 -0
- package/lib/plugin/plugin-context.js.map +1 -1
- package/lib/plugin/plugin-manager.d.ts.map +1 -1
- package/lib/plugin/plugin-manager.js +1 -0
- package/lib/plugin/plugin-manager.js.map +1 -1
- package/lib/plugin/quick-open.d.ts.map +1 -1
- package/lib/plugin/quick-open.js +1 -0
- package/lib/plugin/quick-open.js.map +1 -1
- package/lib/plugin/scm.d.ts +3 -0
- package/lib/plugin/scm.d.ts.map +1 -1
- package/lib/plugin/scm.js +8 -0
- package/lib/plugin/scm.js.map +1 -1
- package/lib/plugin/type-converters.d.ts.map +1 -1
- package/lib/plugin/type-converters.js +4 -2
- package/lib/plugin/type-converters.js.map +1 -1
- package/lib/plugin/types-impl.d.ts +4 -3
- package/lib/plugin/types-impl.d.ts.map +1 -1
- package/lib/plugin/types-impl.js +9 -8
- package/lib/plugin/types-impl.js.map +1 -1
- package/package.json +27 -27
- package/src/common/plugin-api-rpc-model.ts +1 -0
- package/src/common/plugin-api-rpc.ts +3 -0
- package/src/common/plugin-protocol.ts +4 -0
- package/src/hosted/browser/hosted-plugin.ts +4 -2
- package/src/hosted/browser/worker/worker-env-ext.ts +4 -0
- package/src/hosted/node/scanners/scanner-theia.ts +21 -15
- package/src/main/browser/comments/comment-thread-widget.tsx +5 -5
- package/src/main/browser/debug/debug-main.ts +9 -0
- package/src/main/browser/languages-main.ts +5 -0
- package/src/main/browser/menus/menus-contribution-handler.ts +104 -578
- package/src/main/browser/menus/plugin-menu-command-adapter.ts +259 -0
- package/src/main/browser/menus/vscode-theia-menu-mappings.ts +85 -0
- package/src/main/browser/plugin-contribution-handler.ts +3 -1
- package/src/main/browser/plugin-ext-frontend-module.ts +4 -3
- package/src/main/browser/plugin-frontend-contribution.ts +0 -9
- package/src/main/browser/plugin-shared-style.ts +0 -1
- package/src/main/browser/scm-main.ts +10 -0
- package/src/main/browser/view/tree-view-widget.tsx +2 -2
- package/src/main/node/handlers/plugin-theia-file-handler.ts +0 -26
- package/src/main/node/plugin-ext-backend-module.ts +0 -2
- package/src/main/node/resolvers/local-plugin-deployer-resolver.ts +4 -8
- package/src/plugin/debug/debug-ext.ts +30 -5
- package/src/plugin/debug/plugin-debug-adapter-session.ts +4 -0
- package/src/plugin/env.ts +30 -0
- package/src/plugin/languages/signature.ts +3 -1
- package/src/plugin/node/debug/debug.spec.ts +94 -0
- package/src/plugin/node/env-node-ext.ts +13 -1
- package/src/plugin/plugin-context.ts +10 -0
- package/src/plugin/plugin-manager.ts +1 -0
- package/src/plugin/quick-open.ts +1 -0
- package/src/plugin/scm.ts +11 -0
- package/src/plugin/type-converters.ts +4 -2
- package/src/plugin/types-impl.ts +7 -5
- package/lib/main/browser/plugin-ext-deploy-command.d.ts +0 -10
- package/lib/main/browser/plugin-ext-deploy-command.d.ts.map +0 -1
- package/lib/main/browser/plugin-ext-deploy-command.js +0 -64
- package/lib/main/browser/plugin-ext-deploy-command.js.map +0 -1
- package/lib/main/node/resolvers/local-file-plugin-deployer-resolver.d.ts +0 -8
- package/lib/main/node/resolvers/local-file-plugin-deployer-resolver.d.ts.map +0 -1
- package/lib/main/node/resolvers/local-file-plugin-deployer-resolver.js +0 -43
- package/lib/main/node/resolvers/local-file-plugin-deployer-resolver.js.map +0 -1
- package/src/main/browser/plugin-ext-deploy-command.ts +0 -50
- package/src/main/node/resolvers/local-file-plugin-deployer-resolver.ts +0 -34
|
@@ -16,623 +16,149 @@
|
|
|
16
16
|
|
|
17
17
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { MenuPath, ILogger, CommandRegistry, Command, Mutable, MenuAction, SelectionService, CommandHandler, Disposable, DisposableCollection } from '@theia/core';
|
|
22
|
-
import { EDITOR_CONTEXT_MENU, EditorWidget } from '@theia/editor/lib/browser';
|
|
19
|
+
import { inject, injectable, optional } from '@theia/core/shared/inversify';
|
|
20
|
+
import { MenuPath, CommandRegistry, Disposable, DisposableCollection, ActionMenuNode, MenuCommandAdapterRegistry, Emitter, CompoundMenuNodeRole } from '@theia/core';
|
|
23
21
|
import { MenuModelRegistry } from '@theia/core/lib/common';
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import { NAVIGATOR_CONTEXT_MENU } from '@theia/navigator/lib/browser/navigator-contribution';
|
|
27
|
-
import { VIEW_ITEM_CONTEXT_MENU, TreeViewWidget, VIEW_ITEM_INLINE_MENU } from '../view/tree-view-widget';
|
|
28
|
-
import { DeployedPlugin, Menu, ScmCommandArg, TimelineCommandArg, TreeViewSelection } from '../../../common';
|
|
29
|
-
import { DebugStackFramesWidget } from '@theia/debug/lib/browser/view/debug-stack-frames-widget';
|
|
30
|
-
import { DebugThreadsWidget } from '@theia/debug/lib/browser/view/debug-threads-widget';
|
|
31
|
-
import { TreeWidgetSelection } from '@theia/core/lib/browser/tree/tree-widget-selection';
|
|
22
|
+
import { TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
|
23
|
+
import { DeployedPlugin, IconUrl, Menu } from '../../../common';
|
|
32
24
|
import { ScmWidget } from '@theia/scm/lib/browser/scm-widget';
|
|
33
|
-
import { ScmTreeWidget } from '@theia/scm/lib/browser/scm-tree-widget';
|
|
34
|
-
import { ScmService } from '@theia/scm/lib/browser/scm-service';
|
|
35
|
-
import { ScmRepository } from '@theia/scm/lib/browser/scm-repository';
|
|
36
|
-
import { PluginScmProvider, PluginScmResourceGroup, PluginScmResource } from '../scm-main';
|
|
37
|
-
import { ResourceContextKey } from '@theia/core/lib/browser/resource-context-key';
|
|
38
25
|
import { PluginViewWidget } from '../view/plugin-view-widget';
|
|
39
|
-
import { ViewContextKeyService } from '../view/view-context-key-service';
|
|
40
|
-
import { WebviewWidget } from '../webview/webview';
|
|
41
|
-
import { Navigatable } from '@theia/core/lib/browser/navigatable';
|
|
42
|
-
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
|
43
|
-
import { TIMELINE_ITEM_CONTEXT_MENU } from '@theia/timeline/lib/browser/timeline-tree-widget';
|
|
44
|
-
import { TimelineItem } from '@theia/timeline/lib/common/timeline-model';
|
|
45
|
-
import { COMMENT_CONTEXT, COMMENT_THREAD_CONTEXT, COMMENT_TITLE } from '../comments/comment-thread-widget';
|
|
46
26
|
import { QuickCommandService } from '@theia/core/lib/browser';
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return resourceUri ? resourceUri['codeUri'] : undefined;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
27
|
+
import {
|
|
28
|
+
CodeEditorWidgetUtil, codeToTheiaMappings, ContributionPoint, implementedVSCodeContributionPoints,
|
|
29
|
+
PLUGIN_EDITOR_TITLE_MENU, PLUGIN_SCM_TITLE_MENU, PLUGIN_VIEW_TITLE_MENU
|
|
30
|
+
} from './vscode-theia-menu-mappings';
|
|
31
|
+
import { PluginMenuCommandAdapter, ReferenceCountingSet } from './plugin-menu-command-adapter';
|
|
32
|
+
import { ContextKeyExpr } from '@theia/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey';
|
|
33
|
+
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
|
34
|
+
import { PluginSharedStyle } from '../plugin-shared-style';
|
|
35
|
+
import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService';
|
|
59
36
|
|
|
60
37
|
@injectable()
|
|
61
38
|
export class MenusContributionPointHandler {
|
|
62
39
|
|
|
63
|
-
@inject(MenuModelRegistry)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
@inject(
|
|
67
|
-
protected readonly
|
|
68
|
-
|
|
69
|
-
@inject(
|
|
70
|
-
protected readonly
|
|
71
|
-
|
|
72
|
-
@inject(ScmService)
|
|
73
|
-
protected readonly scmService: ScmService;
|
|
74
|
-
|
|
40
|
+
@inject(MenuModelRegistry) private readonly menuRegistry: MenuModelRegistry;
|
|
41
|
+
@inject(CommandRegistry) private readonly commands: CommandRegistry;
|
|
42
|
+
@inject(TabBarToolbarRegistry) private readonly tabBarToolbar: TabBarToolbarRegistry;
|
|
43
|
+
@inject(CodeEditorWidgetUtil) private readonly codeEditorWidgetUtil: CodeEditorWidgetUtil;
|
|
44
|
+
@inject(PluginMenuCommandAdapter) protected readonly commandAdapter: PluginMenuCommandAdapter;
|
|
45
|
+
@inject(MenuCommandAdapterRegistry) protected readonly commandAdapterRegistry: MenuCommandAdapterRegistry;
|
|
46
|
+
@inject(ContextKeyService) protected readonly contextKeyService: ContextKeyService;
|
|
47
|
+
@inject(PluginSharedStyle) protected readonly style: PluginSharedStyle;
|
|
75
48
|
@inject(QuickCommandService) @optional()
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
protected readonly
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
handle(plugin: DeployedPlugin): Disposable {
|
|
97
|
-
const allMenus = plugin.contributes && plugin.contributes.menus;
|
|
98
|
-
if (!allMenus) {
|
|
99
|
-
return Disposable.NULL;
|
|
100
|
-
}
|
|
101
|
-
const toDispose = new DisposableCollection();
|
|
102
|
-
|
|
103
|
-
const tree = this.getMenusTree(plugin);
|
|
104
|
-
tree.forEach(rootMenu => {
|
|
105
|
-
|
|
106
|
-
const registerMenuActions = (menus: MenuTree[], group: string | undefined, submenusOrder: string | undefined = '') => {
|
|
107
|
-
menus.forEach(menu => {
|
|
108
|
-
if (group) {
|
|
109
|
-
// Adding previous group to the start of current menu group.
|
|
110
|
-
menu.group = `${group}/${menu.group || '_'}`;
|
|
111
|
-
}
|
|
112
|
-
if (menu.isSubmenu) {
|
|
113
|
-
let [submenuGroup, submenuOrder = ''] = (menu.group || '_').split('@');
|
|
114
|
-
// Generating group in format: `<submenu group>/<submenu name>`
|
|
115
|
-
submenuGroup = `${submenuGroup}/${menu.label}`;
|
|
116
|
-
if (submenusOrder) {
|
|
117
|
-
// Adding previous submenus order to the start of current submenu order
|
|
118
|
-
// in format: `<submenu order>/<submenu order>.../<menu order>`.
|
|
119
|
-
submenuOrder = `${submenusOrder}/${submenuOrder}`;
|
|
120
|
-
}
|
|
121
|
-
registerMenuActions(menu.children, submenuGroup, submenuOrder);
|
|
122
|
-
} else {
|
|
123
|
-
menu.submenusOrder = submenusOrder;
|
|
124
|
-
toDispose.push(
|
|
125
|
-
this.registerAction(plugin, rootMenu.id!, menu)
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
registerMenuActions(rootMenu.children, undefined, undefined);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
return toDispose;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Transforms the structure of Menus & Submenus
|
|
139
|
-
* into something more tree-like.
|
|
140
|
-
*/
|
|
141
|
-
protected getMenusTree(plugin: DeployedPlugin): MenuTree[] {
|
|
142
|
-
const allMenus = plugin.contributes && plugin.contributes.menus;
|
|
143
|
-
if (!allMenus) {
|
|
144
|
-
return [];
|
|
145
|
-
}
|
|
146
|
-
const allSubmenus = plugin.contributes && plugin.contributes.submenus;
|
|
147
|
-
const tree: MenuTree[] = [];
|
|
148
|
-
|
|
149
|
-
Object.keys(allMenus).forEach(location => {
|
|
150
|
-
// Don't build menus tree for a submenu declaration at root.
|
|
151
|
-
if (allSubmenus && allSubmenus.findIndex(submenu => submenu.id === location) > -1) {
|
|
152
|
-
return;
|
|
49
|
+
private readonly quickCommandService: QuickCommandService;
|
|
50
|
+
|
|
51
|
+
protected readonly titleContributionContextKeys = new ReferenceCountingSet();
|
|
52
|
+
protected readonly onDidChangeTitleContributionEmitter = new Emitter<void>();
|
|
53
|
+
|
|
54
|
+
private initialized = false;
|
|
55
|
+
private initialize(): void {
|
|
56
|
+
this.initialized = true;
|
|
57
|
+
this.commandAdapterRegistry.registerAdapter(this.commandAdapter);
|
|
58
|
+
for (const contributionPoint of implementedVSCodeContributionPoints) {
|
|
59
|
+
this.menuRegistry.registerIndependentSubmenu(contributionPoint, '');
|
|
60
|
+
this.getMatchingMenu(contributionPoint)!.forEach(([menu, when]) => this.menuRegistry.linkSubmenu(menu, contributionPoint, { role: CompoundMenuNodeRole.Flat, when }));
|
|
61
|
+
}
|
|
62
|
+
this.tabBarToolbar.registerMenuDelegate(PLUGIN_EDITOR_TITLE_MENU, widget => this.codeEditorWidgetUtil.is(widget));
|
|
63
|
+
this.tabBarToolbar.registerMenuDelegate(PLUGIN_SCM_TITLE_MENU, widget => widget instanceof ScmWidget);
|
|
64
|
+
this.tabBarToolbar.registerMenuDelegate(PLUGIN_VIEW_TITLE_MENU, widget => widget instanceof PluginViewWidget);
|
|
65
|
+
this.tabBarToolbar.registerItem({ id: 'plugin-menu-contribution-title-contribution', command: '_never_', onDidChange: this.onDidChangeTitleContributionEmitter.event });
|
|
66
|
+
this.contextKeyService.onDidChange(event => {
|
|
67
|
+
if (event.affects(this.titleContributionContextKeys)) {
|
|
68
|
+
this.onDidChangeTitleContributionEmitter.fire();
|
|
153
69
|
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* @param menus the menus to create a tree from.
|
|
157
|
-
* @param submenusIds contains all the previous submenus ids in the current tree.
|
|
158
|
-
* @returns {MenuTree[]} the trees for the given menus.
|
|
159
|
-
*/
|
|
160
|
-
const getChildren = (menus: Menu[], submenusIds: Set<string>) => {
|
|
161
|
-
// Contains all the submenus ids of the current parent.
|
|
162
|
-
const parentSubmenusIds = new Set<string>();
|
|
163
|
-
|
|
164
|
-
return menus.reduce((children: MenuTree[], menuItem) => {
|
|
165
|
-
if (menuItem.submenu) {
|
|
166
|
-
if (parentSubmenusIds.has(menuItem.submenu)) {
|
|
167
|
-
console.warn(`Submenu ${menuItem.submenu} already registered`);
|
|
168
|
-
} else if (submenusIds.has(menuItem.submenu)) {
|
|
169
|
-
console.warn(`Found submenu cycle: ${menuItem.submenu}`);
|
|
170
|
-
} else {
|
|
171
|
-
parentSubmenusIds.add(menuItem.submenu);
|
|
172
|
-
const submenu = allSubmenus!.find(s => s.id === menuItem.submenu)!;
|
|
173
|
-
const menuTree = new MenuTree({ ...menuItem }, menuItem.submenu, submenu.label);
|
|
174
|
-
menuTree.children = getChildren(allMenus[submenu.id], new Set([...submenusIds, menuItem.submenu]));
|
|
175
|
-
children.push(menuTree);
|
|
176
|
-
}
|
|
177
|
-
} else {
|
|
178
|
-
children.push(new MenuTree({ ...menuItem }));
|
|
179
|
-
}
|
|
180
|
-
return children;
|
|
181
|
-
}, []);
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
const rootMenu = new MenuTree(undefined, location);
|
|
185
|
-
rootMenu.children = getChildren(allMenus[location], new Set());
|
|
186
|
-
tree.push(rootMenu);
|
|
187
70
|
});
|
|
71
|
+
}
|
|
188
72
|
|
|
189
|
-
|
|
73
|
+
private getMatchingMenu(contributionPoint: ContributionPoint): Array<[MenuPath] | [MenuPath, string]> | undefined {
|
|
74
|
+
return codeToTheiaMappings.get(contributionPoint);
|
|
190
75
|
}
|
|
191
76
|
|
|
192
|
-
|
|
193
|
-
const allMenus = plugin.contributes
|
|
77
|
+
handle(plugin: DeployedPlugin): Disposable {
|
|
78
|
+
const allMenus = plugin.contributes?.menus;
|
|
194
79
|
if (!allMenus) {
|
|
195
80
|
return Disposable.NULL;
|
|
196
81
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
case 'commandPalette': return this.registerCommandPaletteAction(action);
|
|
200
|
-
case 'editor/title': return this.registerEditorTitleAction(location, action);
|
|
201
|
-
case 'view/title': return this.registerViewTitleAction(location, action);
|
|
202
|
-
case 'view/item/context': return this.registerViewItemContextAction(action);
|
|
203
|
-
case 'scm/title': return this.registerScmTitleAction(location, action);
|
|
204
|
-
case 'scm/resourceGroup/context': return this.registerScmResourceGroupAction(action);
|
|
205
|
-
case 'scm/resourceFolder/context': return this.registerScmResourceFolderAction(action);
|
|
206
|
-
case 'scm/resourceState/context': return this.registerScmResourceStateAction(action);
|
|
207
|
-
case 'timeline/item/context': return this.registerTimelineItemAction(action);
|
|
208
|
-
case 'comments/commentThread/context': return this.registerCommentThreadAction(action, plugin);
|
|
209
|
-
case 'comments/comment/title': return this.registerCommentTitleAction(action);
|
|
210
|
-
case 'comments/comment/context': return this.registerCommentContextAction(action);
|
|
211
|
-
case 'debug/callstack/context': return this.registerDebugCallstackAction(action);
|
|
212
|
-
|
|
213
|
-
default: if (allMenus.hasOwnProperty(location)) {
|
|
214
|
-
return this.registerGlobalMenuAction(action, location, plugin);
|
|
215
|
-
}
|
|
216
|
-
return Disposable.NULL;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
protected static parseMenuPaths(value: string): MenuPath[] {
|
|
221
|
-
switch (value) {
|
|
222
|
-
case 'editor/context': return [EDITOR_CONTEXT_MENU];
|
|
223
|
-
case 'explorer/context': return [NAVIGATOR_CONTEXT_MENU];
|
|
82
|
+
if (!this.initialized) {
|
|
83
|
+
this.initialize();
|
|
224
84
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return this.quickCommandService.pushCommandContext(menu.command, menu.when);
|
|
85
|
+
const toDispose = new DisposableCollection();
|
|
86
|
+
const submenus = plugin.contributes?.submenus ?? [];
|
|
87
|
+
for (const submenu of submenus) {
|
|
88
|
+
const iconClass = submenu.icon && this.toIconClass(submenu.icon, toDispose);
|
|
89
|
+
this.menuRegistry.registerIndependentSubmenu(submenu.id, submenu.label, iconClass ? { iconClass } : undefined);
|
|
231
90
|
}
|
|
232
|
-
return Disposable.NULL;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
protected registerEditorTitleAction(location: string, action: Menu): Disposable {
|
|
236
|
-
return this.registerTitleAction(location, action, {
|
|
237
|
-
execute: widget => this.codeEditorWidgetUtil.is(widget) &&
|
|
238
|
-
this.commands.executeCommand(action.command!, this.codeEditorWidgetUtil.getResourceUri(widget)),
|
|
239
|
-
isEnabled: widget => this.codeEditorWidgetUtil.is(widget) && this.commands.isEnabled(action.command!, this.codeEditorWidgetUtil.getResourceUri(widget)),
|
|
240
|
-
isVisible: widget => this.codeEditorWidgetUtil.is(widget) && this.commands.isVisible(action.command!, this.codeEditorWidgetUtil.getResourceUri(widget))
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
protected registerViewTitleAction(location: string, action: Menu): Disposable {
|
|
245
|
-
return this.registerTitleAction(location, action, {
|
|
246
|
-
execute: widget => widget instanceof PluginViewWidget && this.commands.executeCommand(action.command!),
|
|
247
|
-
isEnabled: widget => widget instanceof PluginViewWidget && this.commands.isEnabled(action.command!),
|
|
248
|
-
isVisible: widget => widget instanceof PluginViewWidget && this.commands.isVisible(action.command!),
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
protected registerViewItemContextAction(menu: MenuTree): Disposable {
|
|
253
|
-
const inline = menu.group && /^inline/.test(menu.group) || false;
|
|
254
|
-
const menuPath = inline ? VIEW_ITEM_INLINE_MENU : VIEW_ITEM_CONTEXT_MENU;
|
|
255
|
-
return this.registerTreeMenuAction(menuPath, menu);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
protected registerScmResourceGroupAction(menu: MenuTree): Disposable {
|
|
259
|
-
const inline = menu.group && /^inline/.test(menu.group) || false;
|
|
260
|
-
const menuPath = inline ? ScmTreeWidget.RESOURCE_GROUP_INLINE_MENU : ScmTreeWidget.RESOURCE_GROUP_CONTEXT_MENU;
|
|
261
|
-
return this.registerScmMenuAction(menuPath, menu);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
protected registerScmResourceFolderAction(menu: MenuTree): Disposable {
|
|
265
|
-
const inline = menu.group && /^inline/.test(menu.group) || false;
|
|
266
|
-
const menuPath = inline ? ScmTreeWidget.RESOURCE_FOLDER_INLINE_MENU : ScmTreeWidget.RESOURCE_FOLDER_CONTEXT_MENU;
|
|
267
|
-
return this.registerScmMenuAction(menuPath, menu);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
protected registerScmResourceStateAction(menu: MenuTree): Disposable {
|
|
271
|
-
const inline = menu.group && /^inline/.test(menu.group) || false;
|
|
272
|
-
const menuPath = inline ? ScmTreeWidget.RESOURCE_INLINE_MENU : ScmTreeWidget.RESOURCE_CONTEXT_MENU;
|
|
273
|
-
return this.registerScmMenuAction(menuPath, menu);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
protected registerTimelineItemAction(menu: MenuTree): Disposable {
|
|
277
|
-
return this.registerMenuAction(TIMELINE_ITEM_CONTEXT_MENU, menu,
|
|
278
|
-
command => ({
|
|
279
|
-
execute: (...args) => this.commands.executeCommand(command, ...this.toTimelineArgs(...args)),
|
|
280
|
-
isEnabled: (...args) => this.commands.isEnabled(command, ...this.toTimelineArgs(...args)),
|
|
281
|
-
isVisible: (...args) => this.commands.isVisible(command, ...this.toTimelineArgs(...args))
|
|
282
|
-
}));
|
|
283
|
-
}
|
|
284
91
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
92
|
+
for (const [contributionPoint, items] of Object.entries(allMenus)) {
|
|
93
|
+
for (const item of items) {
|
|
94
|
+
try {
|
|
95
|
+
if (contributionPoint === 'commandPalette') {
|
|
96
|
+
toDispose.push(this.registerCommandPaletteAction(item));
|
|
97
|
+
} else {
|
|
98
|
+
this.checkTitleContribution(contributionPoint, item, toDispose);
|
|
99
|
+
if (item.submenu) {
|
|
100
|
+
const targets = this.getMatchingMenu(contributionPoint as ContributionPoint) ?? [contributionPoint];
|
|
101
|
+
const { group, order } = this.parseGroup(item.group);
|
|
102
|
+
targets.forEach(([target]) => toDispose.push(this.menuRegistry.linkSubmenu(target, item.submenu!, { order, when: item.when }, group)));
|
|
103
|
+
} else if (item.command) {
|
|
104
|
+
toDispose.push(this.commandAdapter.addCommand(item.command));
|
|
105
|
+
const { group, order } = this.parseGroup(item.group);
|
|
106
|
+
const node = new ActionMenuNode({
|
|
107
|
+
commandId: item.command,
|
|
108
|
+
when: item.when,
|
|
109
|
+
order,
|
|
110
|
+
}, this.commands);
|
|
111
|
+
const parent = this.menuRegistry.getMenuNode(contributionPoint, group);
|
|
112
|
+
toDispose.push(parent.addNode(node));
|
|
295
113
|
}
|
|
296
114
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
isVisible: (...args) => this.commands.isVisible(command, ...this.toCommentArgs(...args))
|
|
300
|
-
}));
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
protected registerCommentTitleAction(menu: MenuTree): Disposable {
|
|
304
|
-
return this.registerMenuAction(COMMENT_TITLE, menu,
|
|
305
|
-
command => ({
|
|
306
|
-
execute: (...args) => this.commands.executeCommand(command, ...this.toCommentArgs(...args)),
|
|
307
|
-
isEnabled: (...args) => this.commands.isEnabled(command, ...this.toCommentArgs(...args)),
|
|
308
|
-
isVisible: (...args) => this.commands.isVisible(command, ...this.toCommentArgs(...args))
|
|
309
|
-
}));
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
protected registerCommentContextAction(menu: MenuTree): Disposable {
|
|
313
|
-
return this.registerMenuAction(COMMENT_CONTEXT, menu,
|
|
314
|
-
command => ({
|
|
315
|
-
execute: (...args) => this.commands.executeCommand(command, ...this.toCommentArgs(...args)),
|
|
316
|
-
isEnabled: () => true,
|
|
317
|
-
isVisible: (...args) => this.commands.isVisible(command, ...this.toCommentArgs(...args))
|
|
318
|
-
}));
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
protected registerDebugCallstackAction(menu: MenuTree): Disposable {
|
|
322
|
-
const toDispose = new DisposableCollection();
|
|
323
|
-
[DebugStackFramesWidget.CONTEXT_MENU, DebugThreadsWidget.CONTEXT_MENU].forEach(menuPath => {
|
|
324
|
-
toDispose.push(
|
|
325
|
-
this.registerMenuAction(menuPath, menu, command => ({
|
|
326
|
-
execute: (...args) => this.commands.executeCommand(command, args[0]),
|
|
327
|
-
isEnabled: (...args) => this.commands.isEnabled(command, args[0]),
|
|
328
|
-
isVisible: (...args) => this.commands.isVisible(command, args[0])
|
|
329
|
-
})));
|
|
330
|
-
});
|
|
331
|
-
return toDispose;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
protected registerTreeMenuAction(menuPath: MenuPath, menu: MenuTree): Disposable {
|
|
335
|
-
return this.registerMenuAction(menuPath, menu, command => ({
|
|
336
|
-
execute: (...args) => this.commands.executeCommand(command, ...this.toTreeArgs(...args)),
|
|
337
|
-
isEnabled: (...args) => this.commands.isEnabled(command, ...this.toTreeArgs(...args)),
|
|
338
|
-
isVisible: (...args) => this.commands.isVisible(command, ...this.toTreeArgs(...args))
|
|
339
|
-
}));
|
|
340
|
-
}
|
|
341
|
-
protected toTreeArgs(...args: any[]): any[] {
|
|
342
|
-
const treeArgs: any[] = [];
|
|
343
|
-
for (const arg of args) {
|
|
344
|
-
if (TreeViewSelection.is(arg)) {
|
|
345
|
-
treeArgs.push(arg);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
return treeArgs;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
protected registerTitleAction(location: string, action: Menu, handler: CommandHandler): Disposable {
|
|
352
|
-
if (!action.command) {
|
|
353
|
-
return Disposable.NULL;
|
|
354
|
-
}
|
|
355
|
-
const toDispose = new DisposableCollection();
|
|
356
|
-
const id = this.createSyntheticCommandId(action.command, { prefix: `__plugin.${location.replace('/', '.')}.action.` });
|
|
357
|
-
const command: Command = { id };
|
|
358
|
-
toDispose.push(this.commands.registerCommand(command, handler));
|
|
359
|
-
|
|
360
|
-
const { when } = action;
|
|
361
|
-
const whenKeys = when && this.contextKeyService.parseKeys(when);
|
|
362
|
-
let onDidChange: Event<void> | undefined;
|
|
363
|
-
if (whenKeys && whenKeys.size) {
|
|
364
|
-
const onDidChangeEmitter = new Emitter<void>();
|
|
365
|
-
toDispose.push(onDidChangeEmitter);
|
|
366
|
-
onDidChange = onDidChangeEmitter.event;
|
|
367
|
-
Event.addMaxListeners(this.contextKeyService.onDidChange, 1);
|
|
368
|
-
toDispose.push(Disposable.create(() => {
|
|
369
|
-
Event.addMaxListeners(this.contextKeyService.onDidChange, -1);
|
|
370
|
-
}));
|
|
371
|
-
toDispose.push(this.contextKeyService.onDidChange(event => {
|
|
372
|
-
if (event.affects(whenKeys)) {
|
|
373
|
-
onDidChangeEmitter.fire(undefined);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.warn(`Failed to register a menu item for plugin ${plugin.metadata.model.id} contributed to ${contributionPoint}`, item, error);
|
|
374
117
|
}
|
|
375
|
-
}));
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// handle group and priority
|
|
379
|
-
// if group is empty or white space is will be set to navigation
|
|
380
|
-
// ' ' => ['navigation', 0]
|
|
381
|
-
// 'navigation@1' => ['navigation', 1]
|
|
382
|
-
// '1_rest-client@2' => ['1_rest-client', 2]
|
|
383
|
-
// if priority is not a number it will be set to 0
|
|
384
|
-
// navigation@test => ['navigation', 0]
|
|
385
|
-
const [group, sort] = (action.group || 'navigation').split('@');
|
|
386
|
-
const item: Mutable<TabBarToolbarItem> = { id, command: id, group: group.trim() || 'navigation', priority: ~~sort || undefined, when, onDidChange };
|
|
387
|
-
toDispose.push(this.tabBarToolbar.registerItem(item));
|
|
388
|
-
|
|
389
|
-
toDispose.push(this.onDidRegisterCommand(action.command, pluginCommand => {
|
|
390
|
-
command.category = pluginCommand.category;
|
|
391
|
-
item.tooltip = pluginCommand.label;
|
|
392
|
-
if (group === 'navigation') {
|
|
393
|
-
command.iconClass = pluginCommand.iconClass;
|
|
394
|
-
}
|
|
395
|
-
}));
|
|
396
|
-
return toDispose;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
protected registerScmTitleAction(location: string, action: Menu): Disposable {
|
|
400
|
-
if (!action.command) {
|
|
401
|
-
return Disposable.NULL;
|
|
402
|
-
}
|
|
403
|
-
const selectedRepository = () => this.toScmArg(this.scmService.selectedRepository);
|
|
404
|
-
return this.registerTitleAction(location, action, {
|
|
405
|
-
execute: widget => widget instanceof ScmWidget && this.commands.executeCommand(action.command!, selectedRepository()),
|
|
406
|
-
isEnabled: widget => widget instanceof ScmWidget && this.commands.isEnabled(action.command!, selectedRepository()),
|
|
407
|
-
isVisible: widget => widget instanceof ScmWidget && this.commands.isVisible(action.command!, selectedRepository())
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
protected registerScmMenuAction(menuPath: MenuPath, menu: MenuTree): Disposable {
|
|
411
|
-
return this.registerMenuAction(menuPath, menu, command => ({
|
|
412
|
-
execute: (...args) => this.commands.executeCommand(command, ...this.toScmArgs(...args)),
|
|
413
|
-
isEnabled: (...args) => this.commands.isEnabled(command, ...this.toScmArgs(...args)),
|
|
414
|
-
isVisible: (...args) => this.commands.isVisible(command, ...this.toScmArgs(...args))
|
|
415
|
-
}));
|
|
416
|
-
}
|
|
417
|
-
protected toScmArgs(...args: any[]): any[] {
|
|
418
|
-
const scmArgs: any[] = [];
|
|
419
|
-
for (const arg of args) {
|
|
420
|
-
const scmArg = this.toScmArg(arg);
|
|
421
|
-
if (scmArg) {
|
|
422
|
-
scmArgs.push(scmArg);
|
|
423
118
|
}
|
|
424
119
|
}
|
|
425
|
-
return scmArgs;
|
|
426
|
-
}
|
|
427
|
-
protected toScmArg(arg: any): ScmCommandArg | undefined {
|
|
428
|
-
if (arg instanceof ScmRepository && arg.provider instanceof PluginScmProvider) {
|
|
429
|
-
return {
|
|
430
|
-
sourceControlHandle: arg.provider.handle
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
if (arg instanceof PluginScmResourceGroup) {
|
|
434
|
-
return {
|
|
435
|
-
sourceControlHandle: arg.provider.handle,
|
|
436
|
-
resourceGroupHandle: arg.handle
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
if (arg instanceof PluginScmResource) {
|
|
440
|
-
return {
|
|
441
|
-
sourceControlHandle: arg.group.provider.handle,
|
|
442
|
-
resourceGroupHandle: arg.group.handle,
|
|
443
|
-
resourceStateHandle: arg.handle
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
120
|
|
|
448
|
-
|
|
449
|
-
const timelineArgs: any[] = [];
|
|
450
|
-
const arg = args[0];
|
|
451
|
-
timelineArgs.push(this.toTimelineArg(arg));
|
|
452
|
-
timelineArgs.push(CodeUri.parse(arg.uri));
|
|
453
|
-
timelineArgs.push('source' in arg ? arg.source : '');
|
|
454
|
-
return timelineArgs;
|
|
455
|
-
}
|
|
456
|
-
protected toTimelineArg(arg: TimelineItem): TimelineCommandArg {
|
|
457
|
-
return {
|
|
458
|
-
timelineHandle: arg.handle,
|
|
459
|
-
source: arg.source,
|
|
460
|
-
uri: arg.uri
|
|
461
|
-
};
|
|
121
|
+
return toDispose;
|
|
462
122
|
}
|
|
463
123
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
commentControlHandle: arg.thread.controllerHandle,
|
|
470
|
-
commentThreadHandle: arg.thread.commentThreadHandle,
|
|
471
|
-
text: arg.text,
|
|
472
|
-
commentUniqueId: arg.commentUniqueId
|
|
473
|
-
}];
|
|
474
|
-
}
|
|
475
|
-
return [{
|
|
476
|
-
commentControlHandle: arg.thread.controllerHandle,
|
|
477
|
-
commentThreadHandle: arg.thread.commentThreadHandle,
|
|
478
|
-
text: arg.text
|
|
479
|
-
}];
|
|
124
|
+
private parseGroup(rawGroup?: string): { group?: string, order?: string } {
|
|
125
|
+
if (!rawGroup) { return {}; }
|
|
126
|
+
const separatorIndex = rawGroup.lastIndexOf('@');
|
|
127
|
+
if (separatorIndex > -1) {
|
|
128
|
+
return { group: rawGroup.substring(0, separatorIndex), order: rawGroup.substring(separatorIndex + 1) || undefined };
|
|
480
129
|
}
|
|
481
|
-
return
|
|
482
|
-
commentControlHandle: arg.thread.controllerHandle,
|
|
483
|
-
commentThreadHandle: arg.thread.commentThreadHandle,
|
|
484
|
-
commentUniqueId: arg.commentUniqueId
|
|
485
|
-
}];
|
|
130
|
+
return { group: rawGroup };
|
|
486
131
|
}
|
|
487
132
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
this.logger.warn(`'${plugin.metadata.model.id}' plugin contributes items to a menu with invalid identifier: ${location}`);
|
|
492
|
-
return Disposable.NULL;
|
|
133
|
+
private registerCommandPaletteAction(menu: Menu): Disposable {
|
|
134
|
+
if (menu.command && menu.when) {
|
|
135
|
+
return this.quickCommandService.pushCommandContext(menu.command, menu.when);
|
|
493
136
|
}
|
|
494
|
-
|
|
495
|
-
const selectedResource = () => {
|
|
496
|
-
const selection = this.selectionService.selection;
|
|
497
|
-
if (TreeWidgetSelection.is(selection) && selection.source instanceof TreeViewWidget && selection[0]) {
|
|
498
|
-
return selection.source.toTreeViewSelection(selection[0]);
|
|
499
|
-
}
|
|
500
|
-
const uri = this.resourceContextKey.get();
|
|
501
|
-
return uri ? uri['codeUri'] : undefined;
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
const toDispose = new DisposableCollection();
|
|
505
|
-
menuPaths.forEach(menuPath => {
|
|
506
|
-
toDispose.push(this.registerMenuAction(menuPath, menu, command => ({
|
|
507
|
-
execute: () => this.commands.executeCommand(command, selectedResource()),
|
|
508
|
-
isEnabled: () => this.commands.isEnabled(command, selectedResource()),
|
|
509
|
-
isVisible: () => this.commands.isVisible(command, selectedResource())
|
|
510
|
-
})));
|
|
511
|
-
});
|
|
512
|
-
return toDispose;
|
|
137
|
+
return Disposable.NULL;
|
|
513
138
|
}
|
|
514
139
|
|
|
515
|
-
protected
|
|
516
|
-
if (
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const inline = Boolean(menu.group && /^inline/.test(menu.group));
|
|
524
|
-
const [group, order = undefined] = (menu.group || '_').split('@');
|
|
525
|
-
|
|
526
|
-
const command: Command = { id: commandId };
|
|
527
|
-
const action: MenuAction = { commandId, alt: altId, order, when: menu.when };
|
|
528
|
-
|
|
529
|
-
toDispose.push(this.commands.registerCommand(command, handler(menu.command)));
|
|
530
|
-
toDispose.push(this.quickCommandService?.pushCommandContext(commandId, 'false'));
|
|
531
|
-
toDispose.push(this.menuRegistry.registerMenuAction(inline ? menuPath : [...menuPath, ...group.split('/')], action));
|
|
532
|
-
toDispose.push(this.onDidRegisterCommand(menu.command, pluginCommand => {
|
|
533
|
-
command.category = pluginCommand.category;
|
|
534
|
-
command.label = pluginCommand.label;
|
|
535
|
-
if (inline) {
|
|
536
|
-
command.iconClass = pluginCommand.iconClass;
|
|
537
|
-
}
|
|
538
|
-
}));
|
|
539
|
-
|
|
540
|
-
if (menu.alt && altId) {
|
|
541
|
-
const alt: Command = { id: altId };
|
|
542
|
-
toDispose.push(this.commands.registerCommand(alt, handler(menu.alt)));
|
|
543
|
-
toDispose.push(this.quickCommandService?.pushCommandContext(altId, 'false'));
|
|
544
|
-
toDispose.push(this.onDidRegisterCommand(menu.alt, pluginCommand => {
|
|
545
|
-
alt.category = pluginCommand.category;
|
|
546
|
-
alt.label = pluginCommand.label;
|
|
547
|
-
if (inline) {
|
|
548
|
-
alt.iconClass = pluginCommand.iconClass;
|
|
140
|
+
protected checkTitleContribution(contributionPoint: ContributionPoint | string, contribution: { when?: string }, toDispose: DisposableCollection): void {
|
|
141
|
+
if (contribution.when && contributionPoint.endsWith('title')) {
|
|
142
|
+
const expression = ContextKeyExpr.deserialize(contribution.when);
|
|
143
|
+
if (expression) {
|
|
144
|
+
for (const key of expression.keys()) {
|
|
145
|
+
this.titleContributionContextKeys.add(key);
|
|
146
|
+
toDispose.push(Disposable.create(() => this.titleContributionContextKeys.delete(key)));
|
|
549
147
|
}
|
|
550
|
-
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// Register a submenu if the group is in format `<submenu group>/<submenu name>/<submenu order>.../<menu group>`
|
|
554
|
-
if (group.includes('/')) {
|
|
555
|
-
const groupSplit = group.split('/');
|
|
556
|
-
const orderSplit = (menu.submenusOrder || '').split('/');
|
|
557
|
-
const paths: string[] = [];
|
|
558
|
-
for (let i = 0, j = 0; i < groupSplit.length - 1; i += 2, j += 1) {
|
|
559
|
-
const submenuGroup = groupSplit[i];
|
|
560
|
-
const submenuLabel = groupSplit[i + 1];
|
|
561
|
-
const submenuOrder = orderSplit[j];
|
|
562
|
-
paths.push(submenuGroup, submenuLabel);
|
|
563
|
-
toDispose.push(this.menuRegistry.registerSubmenu([...menuPath, ...paths], submenuLabel, { order: submenuOrder }));
|
|
148
|
+
toDispose.push(Disposable.create(() => this.onDidChangeTitleContributionEmitter.fire()));
|
|
564
149
|
}
|
|
565
150
|
}
|
|
566
|
-
|
|
567
|
-
return toDispose;
|
|
568
151
|
}
|
|
569
152
|
|
|
570
|
-
protected
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
}
|
|
577
|
-
return id;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
protected onDidRegisterCommand(id: string, cb: (command: Command) => void): Disposable {
|
|
581
|
-
const command = this.commands.getCommand(id);
|
|
582
|
-
if (command) {
|
|
583
|
-
cb(command);
|
|
584
|
-
return Disposable.NULL;
|
|
585
|
-
}
|
|
586
|
-
const toDispose = new DisposableCollection();
|
|
587
|
-
// Registering a menu action requires the related command to be already registered.
|
|
588
|
-
// But Theia plugin registers the commands dynamically via the Commands API.
|
|
589
|
-
// Let's wait for ~2 sec. It should be enough to finish registering all the contributed commands.
|
|
590
|
-
// FIXME: remove this workaround (timer) once the https://github.com/theia-ide/theia/issues/3344 is fixed
|
|
591
|
-
const handle = setTimeout(() => toDispose.push(this.onDidRegisterCommand(id, cb)), 2000);
|
|
592
|
-
toDispose.push(Disposable.create(() => clearTimeout(handle)));
|
|
593
|
-
return toDispose;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
/**
|
|
599
|
-
* MenuTree representing a (sub)menu in the menu tree structure.
|
|
600
|
-
*/
|
|
601
|
-
export class MenuTree implements Menu {
|
|
602
|
-
|
|
603
|
-
protected _children: MenuTree[] = [];
|
|
604
|
-
command?: string;
|
|
605
|
-
alt?: string;
|
|
606
|
-
group?: string;
|
|
607
|
-
when?: string;
|
|
608
|
-
/** The orders of the menu items which lead to the submenus */
|
|
609
|
-
submenusOrder?: string;
|
|
610
|
-
|
|
611
|
-
constructor(menu?: Menu,
|
|
612
|
-
/** The location where the menu item will be open from. */
|
|
613
|
-
public readonly id?: string,
|
|
614
|
-
/** The label of the menu item which leads to the submenu. */
|
|
615
|
-
public label?: string) {
|
|
616
|
-
if (menu) {
|
|
617
|
-
this.command = menu.command;
|
|
618
|
-
this.alt = menu.alt;
|
|
619
|
-
this.group = menu.group;
|
|
620
|
-
this.when = menu.when;
|
|
153
|
+
protected toIconClass(url: IconUrl, toDispose: DisposableCollection): string | undefined {
|
|
154
|
+
if (typeof url === 'string') {
|
|
155
|
+
const asThemeIcon = ThemeIcon.fromString(url);
|
|
156
|
+
if (asThemeIcon) {
|
|
157
|
+
return ThemeIcon.asClassName(asThemeIcon);
|
|
158
|
+
}
|
|
621
159
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
return this._children;
|
|
626
|
-
}
|
|
627
|
-
set children(items: MenuTree[]) {
|
|
628
|
-
this._children.push(...items);
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
public addChild(node: MenuTree): void {
|
|
632
|
-
this._children.push(node);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
get isSubmenu(): boolean {
|
|
636
|
-
return this.label !== undefined;
|
|
160
|
+
const reference = this.style.toIconClass(url);
|
|
161
|
+
toDispose.push(reference);
|
|
162
|
+
return reference.object.iconClass;
|
|
637
163
|
}
|
|
638
164
|
}
|