@theia/core 1.28.0-next.9 → 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/README.md +6 -6
- package/i18n/nls.cs.json +33 -2
- package/i18n/nls.de.json +33 -2
- package/i18n/nls.es.json +33 -2
- package/i18n/nls.fr.json +33 -2
- package/i18n/nls.hu.json +33 -2
- package/i18n/nls.it.json +33 -2
- package/i18n/nls.ja.json +33 -2
- package/i18n/nls.json +35 -4
- package/i18n/nls.pl.json +33 -2
- package/i18n/nls.pt-br.json +33 -2
- package/i18n/nls.pt-pt.json +33 -2
- package/i18n/nls.ru.json +33 -2
- package/i18n/nls.zh-cn.json +33 -2
- package/lib/browser/common-frontend-contribution.d.ts +1 -1
- package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/common-frontend-contribution.js +6 -5
- package/lib/browser/common-frontend-contribution.js.map +1 -1
- package/lib/browser/context-key-service.d.ts +3 -1
- package/lib/browser/context-key-service.d.ts.map +1 -1
- package/lib/browser/context-menu-renderer.d.ts +5 -0
- package/lib/browser/context-menu-renderer.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.js +2 -0
- package/lib/browser/frontend-application-module.js.map +1 -1
- package/lib/browser/frontend-application.d.ts +3 -2
- package/lib/browser/frontend-application.d.ts.map +1 -1
- package/lib/browser/frontend-application.js.map +1 -1
- package/lib/browser/keybinding.d.ts.map +1 -1
- package/lib/browser/keybinding.js +9 -7
- package/lib/browser/keybinding.js.map +1 -1
- package/lib/browser/keybinding.spec.js +13 -3
- package/lib/browser/keybinding.spec.js.map +1 -1
- package/lib/browser/menu/browser-context-menu-renderer.d.ts +1 -1
- package/lib/browser/menu/browser-context-menu-renderer.d.ts.map +1 -1
- package/lib/browser/menu/browser-context-menu-renderer.js +2 -2
- package/lib/browser/menu/browser-context-menu-renderer.js.map +1 -1
- package/lib/browser/menu/browser-menu-plugin.d.ts +23 -24
- package/lib/browser/menu/browser-menu-plugin.d.ts.map +1 -1
- package/lib/browser/menu/browser-menu-plugin.js +62 -79
- package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
- package/lib/browser/resource-context-key.d.ts +1 -0
- package/lib/browser/resource-context-key.d.ts.map +1 -1
- package/lib/browser/resource-context-key.js +8 -6
- package/lib/browser/resource-context-key.js.map +1 -1
- package/lib/browser/shell/shell-layout-restorer.d.ts.map +1 -1
- package/lib/browser/shell/shell-layout-restorer.js +2 -1
- package/lib/browser/shell/shell-layout-restorer.js.map +1 -1
- package/lib/browser/shell/side-panel-toolbar.d.ts.map +1 -1
- package/lib/browser/shell/side-panel-toolbar.js +0 -1
- package/lib/browser/shell/side-panel-toolbar.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/index.d.ts +4 -0
- package/lib/browser/shell/tab-bar-toolbar/index.d.ts.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/index.js +31 -0
- package/lib/browser/shell/tab-bar-toolbar/index.js.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts +16 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +36 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts +51 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js +173 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.d.ts +119 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.d.ts.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.js +67 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.js.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +53 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +264 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -0
- package/lib/browser/shell/{tab-bar-toolbar.spec.d.ts → tab-bar-toolbar/tab-bar-toolbar.spec.d.ts} +0 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.d.ts.map +1 -0
- package/lib/browser/shell/{tab-bar-toolbar.spec.js → tab-bar-toolbar/tab-bar-toolbar.spec.js} +3 -3
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -0
- package/lib/browser/view-container.d.ts.map +1 -1
- package/lib/browser/view-container.js +1 -10
- package/lib/browser/view-container.js.map +1 -1
- package/lib/browser/widget-manager.d.ts.map +1 -1
- package/lib/browser/widget-manager.js +2 -1
- package/lib/browser/widget-manager.js.map +1 -1
- package/lib/browser/widget-manager.spec.js +13 -0
- package/lib/browser/widget-manager.spec.js.map +1 -1
- package/lib/browser/window/default-window-service.d.ts +2 -1
- package/lib/browser/window/default-window-service.d.ts.map +1 -1
- package/lib/browser/window/default-window-service.js +9 -4
- package/lib/browser/window/default-window-service.js.map +1 -1
- package/lib/browser/window/window-service.d.ts +2 -1
- package/lib/browser/window/window-service.d.ts.map +1 -1
- package/lib/browser/window/window-service.js.map +1 -1
- package/lib/common/color.d.ts +3 -0
- package/lib/common/color.d.ts.map +1 -1
- package/lib/common/frontend-application-state.d.ts +14 -0
- package/lib/common/frontend-application-state.d.ts.map +1 -1
- package/lib/common/frontend-application-state.js +16 -0
- package/lib/common/frontend-application-state.js.map +1 -1
- package/lib/common/menu/action-menu-node.d.ts +20 -0
- package/lib/common/menu/action-menu-node.d.ts.map +1 -0
- package/lib/common/menu/action-menu-node.js +57 -0
- package/lib/common/menu/action-menu-node.js.map +1 -0
- package/lib/common/menu/composite-menu-node.d.ts +52 -0
- package/lib/common/menu/composite-menu-node.d.ts.map +1 -0
- package/lib/common/menu/composite-menu-node.js +102 -0
- package/lib/common/menu/composite-menu-node.js.map +1 -0
- package/lib/common/menu/index.d.ts +6 -0
- package/lib/common/menu/index.d.ts.map +1 -0
- package/lib/common/menu/index.js +33 -0
- package/lib/common/menu/index.js.map +1 -0
- package/lib/common/menu/menu-adapter.d.ts +36 -0
- package/lib/common/menu/menu-adapter.d.ts.map +1 -0
- package/lib/common/menu/menu-adapter.js +101 -0
- package/lib/common/menu/menu-adapter.js.map +1 -0
- package/lib/common/{menu.d.ts → menu/menu-model-registry.d.ts} +22 -124
- package/lib/common/menu/menu-model-registry.d.ts.map +1 -0
- package/lib/common/{menu.js → menu/menu-model-registry.js} +71 -147
- package/lib/common/menu/menu-model-registry.js.map +1 -0
- package/lib/common/menu/menu-types.d.ts +120 -0
- package/lib/common/menu/menu-types.d.ts.map +1 -0
- package/lib/common/menu/menu-types.js +84 -0
- package/lib/common/menu/menu-types.js.map +1 -0
- package/lib/common/{menu.spec.d.ts → menu/menu.spec.d.ts} +0 -0
- package/lib/common/menu/menu.spec.d.ts.map +1 -0
- package/lib/common/{menu.spec.js → menu/menu.spec.js} +3 -3
- package/lib/common/menu/menu.spec.js.map +1 -0
- package/lib/common/messaging/abstract-connection-provider.d.ts +1 -1
- package/lib/common/messaging/abstract-connection-provider.js +3 -3
- package/lib/common/quick-pick-service.d.ts +1 -0
- package/lib/common/quick-pick-service.d.ts.map +1 -1
- package/lib/common/quick-pick-service.js.map +1 -1
- package/lib/electron-browser/menu/electron-context-menu-renderer.js +2 -2
- package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +14 -5
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.js +71 -82
- package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.js +6 -0
- package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
- package/lib/electron-browser/messaging/electron-ws-connection-provider.js +1 -1
- package/lib/electron-browser/window/electron-window-service.js +1 -1
- package/lib/electron-browser/window/electron-window-service.js.map +1 -1
- package/lib/electron-common/messaging/electron-messages.d.ts +3 -14
- package/lib/electron-common/messaging/electron-messages.d.ts.map +1 -1
- package/lib/electron-common/messaging/electron-messages.js +3 -16
- package/lib/electron-common/messaging/electron-messages.js.map +1 -1
- package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +3 -3
- package/lib/electron-main/messaging/electron-messaging-contribution.js +6 -6
- package/package.json +7 -6
- package/src/browser/common-frontend-contribution.ts +6 -5
- package/src/browser/context-key-service.ts +1 -1
- package/src/browser/context-menu-renderer.ts +5 -0
- package/src/browser/frontend-application-module.ts +7 -1
- package/src/browser/frontend-application.ts +3 -2
- package/src/browser/keybinding.spec.ts +13 -3
- package/src/browser/keybinding.ts +8 -9
- package/src/browser/menu/browser-context-menu-renderer.ts +2 -2
- package/src/browser/menu/browser-menu-plugin.ts +74 -86
- package/src/browser/resource-context-key.ts +9 -6
- package/src/browser/shell/shell-layout-restorer.ts +2 -1
- package/src/browser/shell/side-panel-toolbar.ts +0 -1
- package/src/browser/shell/tab-bar-toolbar/index.ts +19 -0
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.ts +31 -0
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +170 -0
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.ts +186 -0
- package/src/browser/shell/{tab-bar-toolbar.spec.ts → tab-bar-toolbar/tab-bar-toolbar.spec.ts} +2 -2
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +261 -0
- package/src/browser/style/alert-messages.css +6 -0
- package/src/browser/view-container.ts +1 -10
- package/src/browser/widget-manager.spec.ts +14 -0
- package/src/browser/widget-manager.ts +2 -1
- package/src/browser/window/default-window-service.ts +9 -4
- package/src/browser/window/window-service.ts +2 -1
- package/src/common/color.ts +3 -0
- package/src/common/frontend-application-state.ts +15 -0
- package/src/common/menu/action-menu-node.ts +65 -0
- package/src/common/menu/composite-menu-node.ts +121 -0
- package/src/common/menu/index.ts +21 -0
- package/src/common/menu/menu-adapter.ts +103 -0
- package/src/common/{menu.ts → menu/menu-model-registry.ts} +61 -222
- package/src/common/menu/menu-types.ts +183 -0
- package/src/common/{menu.spec.ts → menu/menu.spec.ts} +3 -2
- package/src/common/messaging/abstract-connection-provider.ts +4 -4
- package/src/common/quick-pick-service.ts +1 -0
- package/src/electron-browser/menu/electron-context-menu-renderer.ts +2 -2
- package/src/electron-browser/menu/electron-main-menu-factory.ts +82 -96
- package/src/electron-browser/menu/electron-menu-contribution.ts +8 -0
- package/src/electron-browser/messaging/electron-ws-connection-provider.ts +1 -1
- package/src/electron-browser/window/electron-window-service.ts +1 -1
- package/src/electron-common/messaging/electron-messages.ts +4 -15
- package/src/electron-main/messaging/electron-messaging-contribution.ts +8 -8
- package/lib/browser/shell/tab-bar-toolbar.d.ts +0 -186
- package/lib/browser/shell/tab-bar-toolbar.d.ts.map +0 -1
- package/lib/browser/shell/tab-bar-toolbar.js +0 -362
- package/lib/browser/shell/tab-bar-toolbar.js.map +0 -1
- package/lib/browser/shell/tab-bar-toolbar.spec.d.ts.map +0 -1
- package/lib/browser/shell/tab-bar-toolbar.spec.js.map +0 -1
- package/lib/common/menu.d.ts.map +0 -1
- package/lib/common/menu.js.map +0 -1
- package/lib/common/menu.spec.d.ts.map +0 -1
- package/lib/common/menu.spec.js.map +0 -1
- package/src/browser/shell/tab-bar-toolbar.tsx +0 -495
|
@@ -15,74 +15,12 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { injectable, inject, named } from 'inversify';
|
|
18
|
-
import { Disposable } from '
|
|
19
|
-
import { CommandRegistry, Command } from '
|
|
20
|
-
import { ContributionProvider } from '
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*/
|
|
25
|
-
export interface MenuAction {
|
|
26
|
-
/**
|
|
27
|
-
* The command to execute.
|
|
28
|
-
*/
|
|
29
|
-
commandId: string
|
|
30
|
-
/**
|
|
31
|
-
* In addition to the mandatory command property, an alternative command can be defined.
|
|
32
|
-
* It will be shown and invoked when pressing Alt while opening a menu.
|
|
33
|
-
*/
|
|
34
|
-
alt?: string;
|
|
35
|
-
/**
|
|
36
|
-
* A specific label for this action. If not specified the command label or command id will be used.
|
|
37
|
-
*/
|
|
38
|
-
label?: string
|
|
39
|
-
/**
|
|
40
|
-
* Icon class(es). If not specified the icon class associated with the specified command
|
|
41
|
-
* (i.e. `command.iconClass`) will be used if it exists.
|
|
42
|
-
*/
|
|
43
|
-
icon?: string
|
|
44
|
-
/**
|
|
45
|
-
* Menu entries are sorted in ascending order based on their `order` strings. If omitted the determined
|
|
46
|
-
* label will be used instead.
|
|
47
|
-
*/
|
|
48
|
-
order?: string
|
|
49
|
-
/**
|
|
50
|
-
* Optional expression which will be evaluated by the {@link ContextKeyService} to determine visibility
|
|
51
|
-
* of the action, e.g. `resourceLangId == markdown`.
|
|
52
|
-
*/
|
|
53
|
-
when?: string
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export namespace MenuAction {
|
|
57
|
-
/* Determine whether object is a MenuAction */
|
|
58
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
59
|
-
export function is(arg: MenuAction | any): arg is MenuAction {
|
|
60
|
-
return !!arg && arg === Object(arg) && 'commandId' in arg;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Additional options when creating a new submenu.
|
|
66
|
-
*/
|
|
67
|
-
export interface SubMenuOptions {
|
|
68
|
-
/**
|
|
69
|
-
* The class to use for the submenu icon.
|
|
70
|
-
*/
|
|
71
|
-
iconClass?: string
|
|
72
|
-
/**
|
|
73
|
-
* Menu entries are sorted in ascending order based on their `order` strings. If omitted the determined
|
|
74
|
-
* label will be used instead.
|
|
75
|
-
*/
|
|
76
|
-
order?: string
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export type MenuPath = string[];
|
|
80
|
-
|
|
81
|
-
export const MAIN_MENU_BAR: MenuPath = ['menubar'];
|
|
82
|
-
|
|
83
|
-
export const SETTINGS_MENU: MenuPath = ['settings_menu'];
|
|
84
|
-
export const ACCOUNTS_MENU: MenuPath = ['accounts_menu'];
|
|
85
|
-
export const ACCOUNTS_SUBMENU = [...ACCOUNTS_MENU, '1_accounts_submenu'];
|
|
18
|
+
import { Disposable } from '../disposable';
|
|
19
|
+
import { CommandRegistry, Command } from '../command';
|
|
20
|
+
import { ContributionProvider } from '../contribution-provider';
|
|
21
|
+
import { CompositeMenuNode, CompositeMenuNodeWrapper } from './composite-menu-node';
|
|
22
|
+
import { MenuAction, MenuNode, MenuPath, SubMenuOptions } from './menu-types';
|
|
23
|
+
import { ActionMenuNode } from './action-menu-node';
|
|
86
24
|
|
|
87
25
|
export const MenuContribution = Symbol('MenuContribution');
|
|
88
26
|
|
|
@@ -128,6 +66,7 @@ export interface MenuContribution {
|
|
|
128
66
|
@injectable()
|
|
129
67
|
export class MenuModelRegistry {
|
|
130
68
|
protected readonly root = new CompositeMenuNode('');
|
|
69
|
+
protected readonly independentSubmenus = new Map<string, CompositeMenuNode>();
|
|
131
70
|
|
|
132
71
|
constructor(
|
|
133
72
|
@inject(ContributionProvider) @named(MenuContribution)
|
|
@@ -156,11 +95,24 @@ export class MenuModelRegistry {
|
|
|
156
95
|
*
|
|
157
96
|
* @returns a disposable which, when called, will remove the menu node again.
|
|
158
97
|
*/
|
|
159
|
-
registerMenuNode(menuPath: MenuPath, menuNode: MenuNode): Disposable {
|
|
160
|
-
const parent = this.
|
|
98
|
+
registerMenuNode(menuPath: MenuPath | string, menuNode: MenuNode, group?: string): Disposable {
|
|
99
|
+
const parent = this.getMenuNode(menuPath, group);
|
|
161
100
|
return parent.addNode(menuNode);
|
|
162
101
|
}
|
|
163
102
|
|
|
103
|
+
getMenuNode(menuPath: MenuPath | string, group?: string): CompositeMenuNode {
|
|
104
|
+
if (typeof menuPath === 'string') {
|
|
105
|
+
const target = this.independentSubmenus.get(menuPath);
|
|
106
|
+
if (!target) { throw new Error(`Could not find submenu with id ${menuPath}`); }
|
|
107
|
+
if (group) {
|
|
108
|
+
return this.findSubMenu(target, group);
|
|
109
|
+
}
|
|
110
|
+
return target;
|
|
111
|
+
} else {
|
|
112
|
+
return this.findGroup(group ? menuPath.concat(group) : menuPath);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
164
116
|
/**
|
|
165
117
|
* Register a new menu at the given path with the given label.
|
|
166
118
|
* (If the menu already exists without a label, iconClass or order this method can be used to set them.)
|
|
@@ -186,7 +138,7 @@ export class MenuModelRegistry {
|
|
|
186
138
|
const parent = this.findGroup(groupPath, options);
|
|
187
139
|
let groupNode = this.findSubMenu(parent, menuId, options);
|
|
188
140
|
if (!groupNode) {
|
|
189
|
-
groupNode = new CompositeMenuNode(menuId, label, options);
|
|
141
|
+
groupNode = new CompositeMenuNode(menuId, label, options, parent);
|
|
190
142
|
return parent.addNode(groupNode);
|
|
191
143
|
} else {
|
|
192
144
|
if (!groupNode.label) {
|
|
@@ -206,6 +158,21 @@ export class MenuModelRegistry {
|
|
|
206
158
|
}
|
|
207
159
|
}
|
|
208
160
|
|
|
161
|
+
registerIndependentSubmenu(id: string, label: string, options?: SubMenuOptions): Disposable {
|
|
162
|
+
if (this.independentSubmenus.has(id)) {
|
|
163
|
+
console.debug(`Independent submenu with path ${id} registered, but given ID already exists.`);
|
|
164
|
+
}
|
|
165
|
+
this.independentSubmenus.set(id, new CompositeMenuNode(id, label, options));
|
|
166
|
+
return { dispose: () => this.independentSubmenus.delete(id) };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
linkSubmenu(parentPath: MenuPath | string, childId: string | MenuPath, options?: SubMenuOptions, group?: string): Disposable {
|
|
170
|
+
const child = this.getMenuNode(childId);
|
|
171
|
+
const parent = this.getMenuNode(parentPath, group);
|
|
172
|
+
const wrapper = new CompositeMenuNodeWrapper(child, parent, options);
|
|
173
|
+
return parent.addNode(wrapper);
|
|
174
|
+
}
|
|
175
|
+
|
|
209
176
|
/**
|
|
210
177
|
* Unregister all menu nodes with the same id as the given menu action.
|
|
211
178
|
*
|
|
@@ -258,6 +225,10 @@ export class MenuModelRegistry {
|
|
|
258
225
|
recurse(this.root);
|
|
259
226
|
}
|
|
260
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Finds a submenu as a descendant of the `root` node.
|
|
230
|
+
* See {@link MenuModelRegistry.findSubMenu findSubMenu}.
|
|
231
|
+
*/
|
|
261
232
|
protected findGroup(menuPath: MenuPath, options?: SubMenuOptions): CompositeMenuNode {
|
|
262
233
|
let currentMenu = this.root;
|
|
263
234
|
for (const segment of menuPath) {
|
|
@@ -266,6 +237,10 @@ export class MenuModelRegistry {
|
|
|
266
237
|
return currentMenu;
|
|
267
238
|
}
|
|
268
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Finds or creates a submenu as an immediate child of `current`.
|
|
242
|
+
* @throws if a node with the given `menuId` exists but is not a {@link CompositeMenuNode}.
|
|
243
|
+
*/
|
|
269
244
|
protected findSubMenu(current: CompositeMenuNode, menuId: string, options?: SubMenuOptions): CompositeMenuNode {
|
|
270
245
|
const sub = current.children.find(e => e.id === menuId);
|
|
271
246
|
if (sub instanceof CompositeMenuNode) {
|
|
@@ -274,7 +249,7 @@ export class MenuModelRegistry {
|
|
|
274
249
|
if (sub) {
|
|
275
250
|
throw new Error(`'${menuId}' is not a menu group.`);
|
|
276
251
|
}
|
|
277
|
-
const newSub = new CompositeMenuNode(menuId, undefined, options);
|
|
252
|
+
const newSub = new CompositeMenuNode(menuId, undefined, options, current);
|
|
278
253
|
current.addNode(newSub);
|
|
279
254
|
return newSub;
|
|
280
255
|
}
|
|
@@ -290,160 +265,24 @@ export class MenuModelRegistry {
|
|
|
290
265
|
getMenu(menuPath: MenuPath = []): CompositeMenuNode {
|
|
291
266
|
return this.findGroup(menuPath);
|
|
292
267
|
}
|
|
293
|
-
}
|
|
294
268
|
|
|
295
|
-
/**
|
|
296
|
-
* Base interface of the nodes used in the menu tree structure.
|
|
297
|
-
*/
|
|
298
|
-
export interface MenuNode {
|
|
299
269
|
/**
|
|
300
|
-
* the
|
|
270
|
+
* Returns the {@link MenuPath path} at which a given menu node can be accessed from this registry, if it can be determined.
|
|
271
|
+
* Returns `undefined` if the `parent` of any node in the chain is unknown.
|
|
301
272
|
*/
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
readonly sortString: string
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Node representing a (sub)menu in the menu tree structure.
|
|
315
|
-
*/
|
|
316
|
-
export class CompositeMenuNode implements MenuNode {
|
|
317
|
-
protected readonly _children: MenuNode[] = [];
|
|
318
|
-
public iconClass?: string;
|
|
319
|
-
public order?: string;
|
|
320
|
-
|
|
321
|
-
constructor(
|
|
322
|
-
public readonly id: string,
|
|
323
|
-
public label?: string,
|
|
324
|
-
options?: SubMenuOptions
|
|
325
|
-
) {
|
|
326
|
-
if (options) {
|
|
327
|
-
this.iconClass = options.iconClass;
|
|
328
|
-
this.order = options.order;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
get children(): ReadonlyArray<MenuNode> {
|
|
333
|
-
return this._children;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Inserts the given node at the position indicated by `sortString`.
|
|
338
|
-
*
|
|
339
|
-
* @returns a disposable which, when called, will remove the given node again.
|
|
340
|
-
*/
|
|
341
|
-
public addNode(node: MenuNode): Disposable {
|
|
342
|
-
this._children.push(node);
|
|
343
|
-
this._children.sort((m1, m2) => {
|
|
344
|
-
// The navigation group is special as it will always be sorted to the top/beginning of a menu.
|
|
345
|
-
if (CompositeMenuNode.isNavigationGroup(m1)) {
|
|
346
|
-
return -1;
|
|
347
|
-
}
|
|
348
|
-
if (CompositeMenuNode.isNavigationGroup(m2)) {
|
|
349
|
-
return 1;
|
|
273
|
+
getPath(node: MenuNode): MenuPath | undefined {
|
|
274
|
+
const identifiers = [];
|
|
275
|
+
const visited: MenuNode[] = [];
|
|
276
|
+
let next: MenuNode | undefined = node;
|
|
277
|
+
|
|
278
|
+
while (next && !visited.includes(next)) {
|
|
279
|
+
if (next === this.root) {
|
|
280
|
+
return identifiers.reverse();
|
|
350
281
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
return 1;
|
|
355
|
-
} else {
|
|
356
|
-
return 0;
|
|
357
|
-
}
|
|
358
|
-
});
|
|
359
|
-
return {
|
|
360
|
-
dispose: () => {
|
|
361
|
-
const idx = this._children.indexOf(node);
|
|
362
|
-
if (idx >= 0) {
|
|
363
|
-
this._children.splice(idx, 1);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Removes the first node with the given id.
|
|
371
|
-
*
|
|
372
|
-
* @param id node id.
|
|
373
|
-
*/
|
|
374
|
-
public removeNode(id: string): void {
|
|
375
|
-
const node = this._children.find(n => n.id === id);
|
|
376
|
-
if (node) {
|
|
377
|
-
const idx = this._children.indexOf(node);
|
|
378
|
-
if (idx >= 0) {
|
|
379
|
-
this._children.splice(idx, 1);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
get sortString(): string {
|
|
385
|
-
return this.order || this.id;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
get isSubmenu(): boolean {
|
|
389
|
-
return this.label !== undefined;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* Indicates whether the given node is the special `navigation` menu.
|
|
394
|
-
*
|
|
395
|
-
* @param node the menu node to check.
|
|
396
|
-
* @returns `true` when the given node is a {@link CompositeMenuNode} with id `navigation`,
|
|
397
|
-
* `false` otherwise.
|
|
398
|
-
*/
|
|
399
|
-
static isNavigationGroup(node: MenuNode): node is CompositeMenuNode {
|
|
400
|
-
return node instanceof CompositeMenuNode && node.id === 'navigation';
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Node representing an action in the menu tree structure.
|
|
406
|
-
* It's based on {@link MenuAction} for which it tries to determine the
|
|
407
|
-
* best label, icon and sortString with the given data.
|
|
408
|
-
*/
|
|
409
|
-
export class ActionMenuNode implements MenuNode {
|
|
410
|
-
|
|
411
|
-
readonly altNode: ActionMenuNode | undefined;
|
|
412
|
-
|
|
413
|
-
constructor(
|
|
414
|
-
public readonly action: MenuAction,
|
|
415
|
-
protected readonly commands: CommandRegistry
|
|
416
|
-
) {
|
|
417
|
-
if (action.alt) {
|
|
418
|
-
this.altNode = new ActionMenuNode({ commandId: action.alt }, commands);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
get id(): string {
|
|
423
|
-
return this.action.commandId;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
get label(): string {
|
|
427
|
-
if (this.action.label) {
|
|
428
|
-
return this.action.label;
|
|
282
|
+
visited.push(next);
|
|
283
|
+
identifiers.push(next.id);
|
|
284
|
+
next = next.parent;
|
|
429
285
|
}
|
|
430
|
-
|
|
431
|
-
if (!cmd) {
|
|
432
|
-
console.debug(`No label for action menu node: No command "${this.action.commandId}" exists.`);
|
|
433
|
-
return '';
|
|
434
|
-
}
|
|
435
|
-
return cmd.label || cmd.id;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
get icon(): string | undefined {
|
|
439
|
-
if (this.action.icon) {
|
|
440
|
-
return this.action.icon;
|
|
441
|
-
}
|
|
442
|
-
const command = this.commands.getCommand(this.action.commandId);
|
|
443
|
-
return command && command.iconClass;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
get sortString(): string {
|
|
447
|
-
return this.action.order || this.label;
|
|
286
|
+
return undefined;
|
|
448
287
|
}
|
|
449
288
|
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2022 Ericsson and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A menu entry representing an action, e.g. "New File".
|
|
19
|
+
*/
|
|
20
|
+
export interface MenuAction extends MenuNodeRenderingData, Pick<MenuNodeMetadata, 'when'> {
|
|
21
|
+
/**
|
|
22
|
+
* The command to execute.
|
|
23
|
+
*/
|
|
24
|
+
commandId: string;
|
|
25
|
+
/**
|
|
26
|
+
* In addition to the mandatory command property, an alternative command can be defined.
|
|
27
|
+
* It will be shown and invoked when pressing Alt while opening a menu.
|
|
28
|
+
*/
|
|
29
|
+
alt?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Menu entries are sorted in ascending order based on their `order` strings. If omitted the determined
|
|
32
|
+
* label will be used instead.
|
|
33
|
+
*/
|
|
34
|
+
order?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export namespace MenuAction {
|
|
38
|
+
/* Determine whether object is a MenuAction */
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
+
export function is(arg: MenuAction | any): arg is MenuAction {
|
|
41
|
+
return !!arg && arg === Object(arg) && 'commandId' in arg;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Additional options when creating a new submenu.
|
|
47
|
+
*/
|
|
48
|
+
export interface SubMenuOptions extends Pick<MenuAction, 'order'>, Pick<MenuNodeMetadata, 'when'>, Partial<Pick<CompoundMenuNodeMetadata, 'role'>> {
|
|
49
|
+
/**
|
|
50
|
+
* The class to use for the submenu icon.
|
|
51
|
+
*/
|
|
52
|
+
iconClass?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type MenuPath = string[];
|
|
56
|
+
|
|
57
|
+
export const MAIN_MENU_BAR: MenuPath = ['menubar'];
|
|
58
|
+
|
|
59
|
+
export const SETTINGS_MENU: MenuPath = ['settings_menu'];
|
|
60
|
+
export const ACCOUNTS_MENU: MenuPath = ['accounts_menu'];
|
|
61
|
+
export const ACCOUNTS_SUBMENU = [...ACCOUNTS_MENU, '1_accounts_submenu'];
|
|
62
|
+
|
|
63
|
+
export interface MenuNodeMetadata {
|
|
64
|
+
/**
|
|
65
|
+
* technical identifier.
|
|
66
|
+
*/
|
|
67
|
+
readonly id: string;
|
|
68
|
+
/**
|
|
69
|
+
* Menu nodes are sorted in ascending order based on their `sortString`.
|
|
70
|
+
*/
|
|
71
|
+
readonly sortString: string;
|
|
72
|
+
/**
|
|
73
|
+
* Condition under which the menu node should be rendered.
|
|
74
|
+
* See https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts
|
|
75
|
+
*/
|
|
76
|
+
readonly when?: string;
|
|
77
|
+
/**
|
|
78
|
+
* A reference to the parent node - useful for determining the menu path by which the node can be accessed.
|
|
79
|
+
*/
|
|
80
|
+
readonly parent?: MenuNode;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface MenuNodeRenderingData {
|
|
84
|
+
/**
|
|
85
|
+
* Optional label. Will be rendered as text of the menu item.
|
|
86
|
+
*/
|
|
87
|
+
readonly label?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Icon classes for the menu node. If present, these will produce an icon to the left of the label in browser-style menus.
|
|
90
|
+
*/
|
|
91
|
+
readonly icon?: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const enum CompoundMenuNodeRole {
|
|
95
|
+
/** Indicates that the node should be rendered as submenu that opens a new menu on hover */
|
|
96
|
+
Submenu,
|
|
97
|
+
/** Indicates that the node's children should be rendered as group separated from other items by a separator */
|
|
98
|
+
Group,
|
|
99
|
+
/** Indicates that the node's children should be treated as though they were direct children of the node's parent */
|
|
100
|
+
Flat,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface CompoundMenuNode {
|
|
104
|
+
/**
|
|
105
|
+
* Items that are grouped under this menu.
|
|
106
|
+
*/
|
|
107
|
+
readonly children: ReadonlyArray<MenuNode>
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export namespace CompoundMenuNode {
|
|
111
|
+
export function is(node: MenuNode): node is MenuNode & CompoundMenuNode { return Array.isArray(node.children); }
|
|
112
|
+
export function getRole(node: MenuNode): CompoundMenuNodeRole | undefined {
|
|
113
|
+
if (!is(node)) { return undefined; }
|
|
114
|
+
return node.role ?? (node.label ? CompoundMenuNodeRole.Submenu : CompoundMenuNodeRole.Group);
|
|
115
|
+
}
|
|
116
|
+
export function sortChildren(m1: MenuNode, m2: MenuNode): number {
|
|
117
|
+
// The navigation group is special as it will always be sorted to the top/beginning of a menu.
|
|
118
|
+
if (isNavigationGroup(m1)) {
|
|
119
|
+
return -1;
|
|
120
|
+
}
|
|
121
|
+
if (isNavigationGroup(m2)) {
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
return m1.sortString.localeCompare(m2.sortString);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Collapses the children of any subemenus with role {@link CompoundMenuNodeRole Flat} and sorts */
|
|
128
|
+
export function getFlatChildren(children: ReadonlyArray<MenuNode>): MenuNode[] {
|
|
129
|
+
const childrenToMerge: ReadonlyArray<MenuNode>[] = [];
|
|
130
|
+
return children.filter(child => {
|
|
131
|
+
if (getRole(child) === CompoundMenuNodeRole.Flat) {
|
|
132
|
+
childrenToMerge.push((child as CompoundMenuNode).children);
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}).concat(...childrenToMerge).sort(sortChildren);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Indicates whether the given node is the special `navigation` menu.
|
|
141
|
+
*
|
|
142
|
+
* @param node the menu node to check.
|
|
143
|
+
* @returns `true` when the given node is a {@link CompoundMenuNode} with id `navigation`,
|
|
144
|
+
* `false` otherwise.
|
|
145
|
+
*/
|
|
146
|
+
export function isNavigationGroup(node: MenuNode): node is MenuNode & CompoundMenuNode {
|
|
147
|
+
return is(node) && node.id === 'navigation';
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface CompoundMenuNodeMetadata {
|
|
152
|
+
/**
|
|
153
|
+
* @deprecated @since 1.28 use `role` instead.
|
|
154
|
+
* Whether the item should be rendered as a submenu.
|
|
155
|
+
*/
|
|
156
|
+
readonly isSubmenu: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* How the node and its children should be rendered. See {@link CompoundMenuNodeRole}.
|
|
159
|
+
*/
|
|
160
|
+
readonly role: CompoundMenuNodeRole;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface CommandMenuNode {
|
|
164
|
+
command: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export namespace CommandMenuNode {
|
|
168
|
+
export function is(candidate: MenuNode): candidate is MenuNode & CommandMenuNode { return Boolean(candidate.command); }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface AlternativeHandlerMenuNode {
|
|
172
|
+
altNode: MenuNodeMetadata & MenuNodeRenderingData & CommandMenuNode;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Base interface of the nodes used in the menu tree structure.
|
|
177
|
+
*/
|
|
178
|
+
export interface MenuNode extends MenuNodeMetadata,
|
|
179
|
+
MenuNodeRenderingData,
|
|
180
|
+
Partial<CompoundMenuNode>,
|
|
181
|
+
Partial<CommandMenuNode>,
|
|
182
|
+
Partial<CompoundMenuNodeMetadata>,
|
|
183
|
+
Partial<AlternativeHandlerMenuNode> { }
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { CommandContribution, CommandRegistry } from '
|
|
18
|
-
import {
|
|
17
|
+
import { CommandContribution, CommandRegistry } from '../command';
|
|
18
|
+
import { MenuContribution, MenuModelRegistry } from './menu-model-registry';
|
|
19
19
|
import * as chai from 'chai';
|
|
20
|
+
import { CompositeMenuNode } from './composite-menu-node';
|
|
20
21
|
|
|
21
22
|
const expect = chai.expect;
|
|
22
23
|
|
|
@@ -71,7 +71,7 @@ export abstract class AbstractConnectionProvider<AbstractOptions extends object>
|
|
|
71
71
|
return factory.createProxy();
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
protected
|
|
74
|
+
protected channelMultiplexer?: ChannelMultiplexer;
|
|
75
75
|
|
|
76
76
|
// A set of channel opening functions that are executed if the backend reconnects to restore the
|
|
77
77
|
// the channels that were open before the disconnect occurred.
|
|
@@ -80,7 +80,7 @@ export abstract class AbstractConnectionProvider<AbstractOptions extends object>
|
|
|
80
80
|
protected initializeMultiplexer(): void {
|
|
81
81
|
const mainChannel = this.createMainChannel();
|
|
82
82
|
mainChannel.onMessage(() => this.onIncomingMessageActivityEmitter.fire());
|
|
83
|
-
this.
|
|
83
|
+
this.channelMultiplexer = new ChannelMultiplexer(mainChannel);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/**
|
|
@@ -93,10 +93,10 @@ export abstract class AbstractConnectionProvider<AbstractOptions extends object>
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
async openChannel(path: string, handler: (channel: Channel) => void, options?: AbstractOptions): Promise<void> {
|
|
96
|
-
if (!this.
|
|
96
|
+
if (!this.channelMultiplexer) {
|
|
97
97
|
throw new Error('The channel multiplexer has not been initialized yet!');
|
|
98
98
|
}
|
|
99
|
-
const newChannel = await this.
|
|
99
|
+
const newChannel = await this.channelMultiplexer.open(path);
|
|
100
100
|
newChannel.onClose(() => {
|
|
101
101
|
const { reconnecting } = { reconnecting: true, ...options };
|
|
102
102
|
if (reconnecting) {
|
|
@@ -195,6 +195,7 @@ export interface QuickPick<T extends QuickPickItemOrSeparator> extends QuickInpu
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
export interface PickOptions<T extends QuickPickItem> {
|
|
198
|
+
title?: string;
|
|
198
199
|
placeHolder?: string;
|
|
199
200
|
matchOnDescription?: boolean;
|
|
200
201
|
matchOnDetail?: boolean;
|
|
@@ -101,8 +101,8 @@ export class ElectronContextMenuRenderer extends BrowserContextMenuRenderer {
|
|
|
101
101
|
|
|
102
102
|
protected override doRender(options: RenderContextMenuOptions): ContextMenuAccess {
|
|
103
103
|
if (this.useNativeStyle) {
|
|
104
|
-
const { menuPath, anchor, args, onHide } = options;
|
|
105
|
-
const menu = this.electronMenuFactory.createElectronContextMenu(menuPath, args);
|
|
104
|
+
const { menuPath, anchor, args, onHide, context } = options;
|
|
105
|
+
const menu = this.electronMenuFactory.createElectronContextMenu(menuPath, args, context);
|
|
106
106
|
const { x, y } = coordinateFromAnchor(anchor);
|
|
107
107
|
const zoom = electron.webFrame.getZoomFactor();
|
|
108
108
|
// TODO: Remove the offset once Electron fixes https://github.com/electron/electron/issues/31641
|