@theia/core 1.62.0-next.3 → 1.62.1
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 +7 -7
- package/i18n/nls.cs.json +158 -13
- package/i18n/nls.de.json +158 -13
- package/i18n/nls.es.json +158 -13
- package/i18n/nls.fr.json +158 -13
- package/i18n/nls.hu.json +158 -13
- package/i18n/nls.it.json +158 -13
- package/i18n/nls.ja.json +158 -13
- package/i18n/nls.json +159 -14
- package/i18n/nls.ko.json +158 -13
- package/i18n/nls.pl.json +158 -13
- package/i18n/nls.pt-br.json +158 -13
- package/i18n/nls.ru.json +158 -13
- package/i18n/nls.tr.json +158 -13
- package/i18n/nls.zh-cn.json +158 -13
- package/i18n/nls.zh-tw.json +158 -13
- package/lib/browser/catalog.json +206 -33
- 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 +13 -11
- package/lib/browser/common-frontend-contribution.js.map +1 -1
- package/lib/browser/context-menu-renderer.d.ts +14 -3
- package/lib/browser/context-menu-renderer.d.ts.map +1 -1
- package/lib/browser/context-menu-renderer.js +23 -1
- package/lib/browser/context-menu-renderer.js.map +1 -1
- package/lib/browser/frontend-application-module.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.js +1 -3
- package/lib/browser/frontend-application-module.js.map +1 -1
- package/lib/browser/hover-service.d.ts.map +1 -1
- package/lib/browser/hover-service.js +7 -0
- package/lib/browser/hover-service.js.map +1 -1
- package/lib/browser/menu/action-menu-node.d.ts +36 -0
- package/lib/browser/menu/action-menu-node.d.ts.map +1 -0
- package/lib/browser/menu/action-menu-node.js +113 -0
- package/lib/browser/menu/action-menu-node.js.map +1 -0
- package/lib/browser/menu/browser-context-menu-renderer.d.ts +12 -4
- package/lib/browser/menu/browser-context-menu-renderer.d.ts.map +1 -1
- package/lib/browser/menu/browser-context-menu-renderer.js +12 -13
- package/lib/browser/menu/browser-context-menu-renderer.js.map +1 -1
- package/lib/browser/menu/browser-menu-module.d.ts.map +1 -1
- package/lib/browser/menu/browser-menu-module.js +4 -0
- package/lib/browser/menu/browser-menu-module.js.map +1 -1
- package/lib/browser/menu/browser-menu-node-factory.d.ts +13 -0
- package/lib/browser/menu/browser-menu-node-factory.d.ts.map +1 -0
- package/lib/browser/menu/browser-menu-node-factory.js +54 -0
- package/lib/browser/menu/browser-menu-node-factory.js.map +1 -0
- package/lib/browser/menu/browser-menu-plugin.d.ts +12 -30
- package/lib/browser/menu/browser-menu-plugin.d.ts.map +1 -1
- package/lib/browser/menu/browser-menu-plugin.js +78 -159
- package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
- package/lib/browser/menu/composite-menu-node.d.ts +49 -0
- package/lib/browser/menu/composite-menu-node.d.ts.map +1 -0
- package/lib/browser/menu/composite-menu-node.js +127 -0
- package/lib/browser/menu/composite-menu-node.js.map +1 -0
- package/lib/browser/menu/menu.spec.d.ts.map +1 -0
- package/lib/{common → browser}/menu/menu.spec.js +38 -13
- package/lib/browser/menu/menu.spec.js.map +1 -0
- package/lib/browser/open-with-service.d.ts +1 -1
- package/lib/browser/saveable-service.d.ts.map +1 -1
- package/lib/browser/saveable-service.js +6 -1
- package/lib/browser/saveable-service.js.map +1 -1
- package/lib/browser/shell/application-shell.d.ts +7 -5
- package/lib/browser/shell/application-shell.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +82 -28
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/index.d.ts +1 -0
- package/lib/browser/shell/index.d.ts.map +1 -1
- package/lib/browser/shell/index.js +1 -0
- package/lib/browser/shell/index.js.map +1 -1
- package/lib/browser/shell/sidebar-bottom-menu-widget.d.ts.map +1 -1
- package/lib/browser/shell/sidebar-bottom-menu-widget.js +2 -1
- package/lib/browser/shell/sidebar-bottom-menu-widget.js.map +1 -1
- package/lib/browser/shell/sidebar-menu-widget.d.ts +4 -1
- package/lib/browser/shell/sidebar-menu-widget.d.ts.map +1 -1
- package/lib/browser/shell/sidebar-menu-widget.js +14 -1
- package/lib/browser/shell/sidebar-menu-widget.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts +66 -8
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +161 -8
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts +18 -32
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js +52 -88
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.d.ts +17 -21
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.js +9 -9
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +7 -39
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +30 -238
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js +13 -13
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts +56 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js +208 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js.map +1 -0
- package/lib/browser/shell/tab-bars.d.ts.map +1 -1
- package/lib/browser/shell/tab-bars.js +2 -1
- package/lib/browser/shell/tab-bars.js.map +1 -1
- package/lib/browser/shell/theia-dock-panel.d.ts +4 -10
- package/lib/browser/shell/theia-dock-panel.d.ts.map +1 -1
- package/lib/browser/shell/theia-dock-panel.js +7 -84
- package/lib/browser/shell/theia-dock-panel.js.map +1 -1
- package/lib/browser/shell/theia-split-panel.d.ts +6 -0
- package/lib/browser/shell/theia-split-panel.d.ts.map +1 -0
- package/lib/browser/shell/theia-split-panel.js +56 -0
- package/lib/browser/shell/theia-split-panel.js.map +1 -0
- package/lib/browser/tree/tree-widget.d.ts +1 -0
- package/lib/browser/tree/tree-widget.d.ts.map +1 -1
- package/lib/browser/tree/tree-widget.js +6 -0
- package/lib/browser/tree/tree-widget.js.map +1 -1
- package/lib/browser/view-container.d.ts +6 -3
- package/lib/browser/view-container.d.ts.map +1 -1
- package/lib/browser/view-container.js +36 -26
- package/lib/browser/view-container.js.map +1 -1
- package/lib/browser/window/default-secondary-window-service.d.ts +1 -0
- package/lib/browser/window/default-secondary-window-service.d.ts.map +1 -1
- package/lib/browser/window/default-secondary-window-service.js +3 -0
- package/lib/browser/window/default-secondary-window-service.js.map +1 -1
- package/lib/common/listener.d.ts +21 -0
- package/lib/common/listener.d.ts.map +1 -0
- package/lib/common/listener.js +81 -0
- package/lib/common/listener.js.map +1 -0
- package/lib/common/listener.spec.d.ts +2 -0
- package/lib/common/listener.spec.d.ts.map +1 -0
- package/lib/common/listener.spec.js +255 -0
- package/lib/common/listener.spec.js.map +1 -0
- package/lib/common/menu/index.d.ts +2 -3
- package/lib/common/menu/index.d.ts.map +1 -1
- package/lib/common/menu/index.js +2 -3
- package/lib/common/menu/index.js.map +1 -1
- package/lib/common/menu/menu-model-registry.d.ts +37 -50
- package/lib/common/menu/menu-model-registry.d.ts.map +1 -1
- package/lib/common/menu/menu-model-registry.js +176 -225
- package/lib/common/menu/menu-model-registry.js.map +1 -1
- package/lib/common/menu/menu-types.d.ts +58 -96
- package/lib/common/menu/menu-types.d.ts.map +1 -1
- package/lib/common/menu/menu-types.js +43 -39
- package/lib/common/menu/menu-types.js.map +1 -1
- package/lib/common/messaging/proxy-factory.d.ts.map +1 -1
- package/lib/common/messaging/proxy-factory.js +4 -0
- package/lib/common/messaging/proxy-factory.js.map +1 -1
- package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts +15 -5
- package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-context-menu-renderer.js +21 -14
- package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +4 -16
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.js +84 -104
- 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 +1 -4
- package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
- package/lib/electron-browser/menu/electron-menu-module.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-menu-module.js +5 -0
- package/lib/electron-browser/menu/electron-menu-module.js.map +1 -1
- package/lib/electron-browser/window/electron-secondary-window-service.d.ts +1 -0
- package/lib/electron-browser/window/electron-secondary-window-service.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-secondary-window-service.js +20 -0
- package/lib/electron-browser/window/electron-secondary-window-service.js.map +1 -1
- package/lib/electron-browser/window/electron-window-service.d.ts +3 -0
- package/lib/electron-browser/window/electron-window-service.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-window-service.js +10 -1
- package/lib/electron-browser/window/electron-window-service.js.map +1 -1
- package/lib/electron-main/theia-electron-window.d.ts.map +1 -1
- package/lib/electron-main/theia-electron-window.js +2 -0
- package/lib/electron-main/theia-electron-window.js.map +1 -1
- package/package.json +7 -8
- package/src/browser/common-frontend-contribution.ts +14 -14
- package/src/browser/context-menu-renderer.ts +33 -5
- package/src/browser/frontend-application-module.ts +1 -7
- package/src/browser/hover-service.ts +7 -0
- package/src/browser/menu/action-menu-node.ts +128 -0
- package/src/browser/menu/browser-context-menu-renderer.ts +18 -11
- package/src/browser/menu/browser-menu-module.ts +4 -0
- package/src/browser/menu/browser-menu-node-factory.ts +48 -0
- package/src/browser/menu/browser-menu-plugin.ts +80 -168
- package/src/browser/menu/composite-menu-node.ts +140 -0
- package/src/{common → browser}/menu/menu.spec.ts +47 -15
- package/src/browser/open-with-service.ts +1 -1
- package/src/browser/saveable-service.ts +6 -1
- package/src/browser/shell/application-shell.ts +91 -29
- package/src/browser/shell/index.ts +1 -0
- package/src/browser/shell/sidebar-bottom-menu-widget.tsx +2 -1
- package/src/browser/shell/sidebar-menu-widget.tsx +12 -2
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.tsx +239 -0
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +59 -102
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.ts +14 -23
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.ts +14 -14
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +34 -261
- package/src/browser/shell/tab-bar-toolbar/tab-toolbar-item.tsx +251 -0
- package/src/browser/shell/tab-bars.ts +2 -1
- package/src/browser/shell/theia-dock-panel.ts +10 -91
- package/src/browser/shell/theia-split-panel.ts +56 -0
- package/src/browser/style/hover-service.css +6 -1
- package/src/browser/style/index.css +3 -11
- package/src/browser/style/view-container.css +17 -31
- package/src/browser/tree/tree-widget.tsx +7 -0
- package/src/browser/view-container.ts +51 -30
- package/src/browser/window/default-secondary-window-service.ts +4 -0
- package/src/common/listener.spec.ts +315 -0
- package/src/common/listener.ts +88 -0
- package/src/common/menu/index.ts +2 -3
- package/src/common/menu/menu-model-registry.ts +187 -230
- package/src/common/menu/menu-types.ts +82 -128
- package/src/common/messaging/proxy-factory.ts +4 -1
- package/src/electron-browser/menu/electron-context-menu-renderer.ts +29 -13
- package/src/electron-browser/menu/electron-main-menu-factory.ts +92 -116
- package/src/electron-browser/menu/electron-menu-contribution.ts +1 -4
- package/src/electron-browser/menu/electron-menu-module.ts +6 -1
- package/src/electron-browser/window/electron-secondary-window-service.ts +22 -0
- package/src/electron-browser/window/electron-window-service.ts +11 -1
- package/src/electron-main/theia-electron-window.ts +2 -0
- package/lib/common/menu/action-menu-node.d.ts +0 -20
- package/lib/common/menu/action-menu-node.d.ts.map +0 -1
- package/lib/common/menu/action-menu-node.js +0 -57
- package/lib/common/menu/action-menu-node.js.map +0 -1
- package/lib/common/menu/composite-menu-node.d.ts +0 -47
- package/lib/common/menu/composite-menu-node.d.ts.map +0 -1
- package/lib/common/menu/composite-menu-node.js +0 -96
- package/lib/common/menu/composite-menu-node.js.map +0 -1
- package/lib/common/menu/composite-menu-node.spec.d.ts +0 -2
- package/lib/common/menu/composite-menu-node.spec.d.ts.map +0 -1
- package/lib/common/menu/composite-menu-node.spec.js +0 -68
- package/lib/common/menu/composite-menu-node.spec.js.map +0 -1
- package/lib/common/menu/menu-adapter.d.ts +0 -36
- package/lib/common/menu/menu-adapter.d.ts.map +0 -1
- package/lib/common/menu/menu-adapter.js +0 -93
- package/lib/common/menu/menu-adapter.js.map +0 -1
- package/lib/common/menu/menu.spec.d.ts.map +0 -1
- package/lib/common/menu/menu.spec.js.map +0 -1
- package/lib/common/test/mock-menu.d.ts +0 -8
- package/lib/common/test/mock-menu.d.ts.map +0 -1
- package/lib/common/test/mock-menu.js +0 -35
- package/lib/common/test/mock-menu.js.map +0 -1
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.ts +0 -31
- package/src/common/menu/action-menu-node.ts +0 -65
- package/src/common/menu/composite-menu-node.spec.ts +0 -67
- package/src/common/menu/composite-menu-node.ts +0 -116
- package/src/common/menu/menu-adapter.ts +0 -103
- package/src/common/test/mock-menu.ts +0 -35
- /package/lib/{common → browser}/menu/menu.spec.d.ts +0 -0
|
@@ -18,8 +18,8 @@ import { injectable, inject } from 'inversify';
|
|
|
18
18
|
import { Menu, MenuBar, Menu as MenuWidget, Widget } from '@lumino/widgets';
|
|
19
19
|
import { CommandRegistry as LuminoCommandRegistry } from '@lumino/commands';
|
|
20
20
|
import {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
environment, DisposableCollection,
|
|
22
|
+
AcceleratorSource,
|
|
23
23
|
ArrayUtils
|
|
24
24
|
} from '../../common';
|
|
25
25
|
import { KeybindingRegistry } from '../keybinding';
|
|
@@ -32,6 +32,8 @@ import { ApplicationShell } from '../shell';
|
|
|
32
32
|
import { CorePreferences } from '../core-preferences';
|
|
33
33
|
import { PreferenceService } from '../preferences/preference-service';
|
|
34
34
|
import { ElementExt } from '@lumino/domutils';
|
|
35
|
+
import { CommandMenu, CompoundMenuNode, MAIN_MENU_BAR, MenuNode, MenuPath, RenderedMenuNode, Submenu } from '../../common/menu/menu-types';
|
|
36
|
+
import { MenuModelRegistry } from '../../common/menu/menu-model-registry';
|
|
35
37
|
|
|
36
38
|
export abstract class MenuBarWidget extends MenuBar {
|
|
37
39
|
abstract activateMenu(label: string, ...labels: string[]): Promise<MenuWidget>;
|
|
@@ -39,10 +41,7 @@ export abstract class MenuBarWidget extends MenuBar {
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export interface BrowserMenuOptions extends MenuWidget.IOptions {
|
|
42
|
-
commands: MenuCommandRegistry,
|
|
43
44
|
context?: HTMLElement,
|
|
44
|
-
contextKeyService?: ContextMatcher;
|
|
45
|
-
rootMenuPath: MenuPath
|
|
46
45
|
};
|
|
47
46
|
|
|
48
47
|
@injectable()
|
|
@@ -54,12 +53,6 @@ export class BrowserMainMenuFactory implements MenuWidgetFactory {
|
|
|
54
53
|
@inject(ContextMenuContext)
|
|
55
54
|
protected readonly context: ContextMenuContext;
|
|
56
55
|
|
|
57
|
-
@inject(CommandRegistry)
|
|
58
|
-
protected readonly commandRegistry: CommandRegistry;
|
|
59
|
-
|
|
60
|
-
@inject(MenuCommandExecutor)
|
|
61
|
-
protected readonly menuCommandExecutor: MenuCommandExecutor;
|
|
62
|
-
|
|
63
56
|
@inject(CorePreferences)
|
|
64
57
|
protected readonly corePreferences: CorePreferences;
|
|
65
58
|
|
|
@@ -108,53 +101,31 @@ export class BrowserMainMenuFactory implements MenuWidgetFactory {
|
|
|
108
101
|
}
|
|
109
102
|
|
|
110
103
|
protected fillMenuBar(menuBar: MenuBarWidget): void {
|
|
111
|
-
const menuModel = this.menuProvider.
|
|
112
|
-
const menuCommandRegistry =
|
|
104
|
+
const menuModel = this.menuProvider.getMenuNode(MAIN_MENU_BAR) as Submenu;
|
|
105
|
+
const menuCommandRegistry = new LuminoCommandRegistry();
|
|
113
106
|
for (const menu of menuModel.children) {
|
|
114
|
-
if (CompoundMenuNode.is(menu)) {
|
|
115
|
-
const menuWidget = this.createMenuWidget(menu, { commands: menuCommandRegistry
|
|
107
|
+
if (CompoundMenuNode.is(menu) && RenderedMenuNode.is(menu)) {
|
|
108
|
+
const menuWidget = this.createMenuWidget(MAIN_MENU_BAR, menu, this.contextKeyService, { commands: menuCommandRegistry });
|
|
116
109
|
menuBar.addMenu(menuWidget);
|
|
117
110
|
}
|
|
118
111
|
}
|
|
119
112
|
}
|
|
120
113
|
|
|
121
|
-
createContextMenu(
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
const contextMenu = this.createMenuWidget(menuModel, { commands: menuCommandRegistry, context, rootMenuPath: path, contextKeyService });
|
|
114
|
+
createContextMenu(effectiveMenuPath: MenuPath, menuModel: CompoundMenuNode, contextMatcher: ContextMatcher, args?: unknown[], context?: HTMLElement): MenuWidget {
|
|
115
|
+
const menuCommandRegistry = new LuminoCommandRegistry();
|
|
116
|
+
const contextMenu = this.createMenuWidget(effectiveMenuPath, menuModel, contextMatcher, { commands: menuCommandRegistry, context }, args);
|
|
125
117
|
return contextMenu;
|
|
126
118
|
}
|
|
127
119
|
|
|
128
|
-
createMenuWidget(menu: CompoundMenuNode, options: BrowserMenuOptions): DynamicMenuWidget {
|
|
129
|
-
return new DynamicMenuWidget(menu, options, this.services);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
protected createMenuCommandRegistry(menu: CompoundMenuNode, args: unknown[] = []): MenuCommandRegistry {
|
|
133
|
-
const menuCommandRegistry = new MenuCommandRegistry(this.services);
|
|
134
|
-
this.registerMenu(menuCommandRegistry, menu, args);
|
|
135
|
-
return menuCommandRegistry;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
protected registerMenu(menuCommandRegistry: MenuCommandRegistry, menu: MenuNode, args: unknown[]): void {
|
|
139
|
-
if (CompoundMenuNode.is(menu)) {
|
|
140
|
-
menu.children.forEach(child => this.registerMenu(menuCommandRegistry, child, args));
|
|
141
|
-
} else if (CommandMenuNode.is(menu)) {
|
|
142
|
-
menuCommandRegistry.registerActionMenu(menu, args);
|
|
143
|
-
if (CommandMenuNode.hasAltHandler(menu)) {
|
|
144
|
-
menuCommandRegistry.registerActionMenu(menu.altNode, args);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
}
|
|
120
|
+
createMenuWidget(parentPath: MenuPath, menu: CompoundMenuNode, contextMatcher: ContextMatcher, options: BrowserMenuOptions, args?: unknown[]): DynamicMenuWidget {
|
|
121
|
+
return new DynamicMenuWidget(parentPath, menu, options, contextMatcher, this.services, args);
|
|
148
122
|
}
|
|
149
123
|
|
|
150
124
|
protected get services(): MenuServices {
|
|
151
125
|
return {
|
|
152
|
-
context: this.context,
|
|
153
126
|
contextKeyService: this.contextKeyService,
|
|
154
|
-
|
|
155
|
-
keybindingRegistry: this.keybindingRegistry,
|
|
127
|
+
context: this.context,
|
|
156
128
|
menuWidgetFactory: this,
|
|
157
|
-
commandExecutor: this.menuCommandExecutor,
|
|
158
129
|
};
|
|
159
130
|
}
|
|
160
131
|
|
|
@@ -235,41 +206,43 @@ export class DynamicMenuBarWidget extends MenuBarWidget {
|
|
|
235
206
|
}
|
|
236
207
|
|
|
237
208
|
export class MenuServices {
|
|
238
|
-
readonly commandRegistry: CommandRegistry;
|
|
239
|
-
readonly keybindingRegistry: KeybindingRegistry;
|
|
240
209
|
readonly contextKeyService: ContextKeyService;
|
|
241
210
|
readonly context: ContextMenuContext;
|
|
242
211
|
readonly menuWidgetFactory: MenuWidgetFactory;
|
|
243
|
-
readonly commandExecutor: MenuCommandExecutor;
|
|
244
212
|
}
|
|
245
213
|
|
|
246
214
|
export interface MenuWidgetFactory {
|
|
247
|
-
createMenuWidget(menu:
|
|
215
|
+
createMenuWidget(effectiveMenuPath: MenuPath, menu: Submenu, contextMatcher: ContextMatcher, options: BrowserMenuOptions): MenuWidget;
|
|
248
216
|
}
|
|
249
217
|
|
|
250
218
|
/**
|
|
251
219
|
* A menu widget that would recompute its items on update.
|
|
252
220
|
*/
|
|
253
221
|
export class DynamicMenuWidget extends MenuWidget {
|
|
254
|
-
|
|
222
|
+
private static nextCommmandId = 0;
|
|
255
223
|
/**
|
|
256
224
|
* We want to restore the focus after the menu closes.
|
|
257
225
|
*/
|
|
258
226
|
protected previousFocusedElement: HTMLElement | undefined;
|
|
259
227
|
|
|
260
228
|
constructor(
|
|
229
|
+
protected readonly effectiveMenuPath: MenuPath,
|
|
261
230
|
protected menu: CompoundMenuNode,
|
|
262
231
|
protected options: BrowserMenuOptions,
|
|
263
|
-
protected
|
|
232
|
+
protected contextMatcher: ContextMatcher,
|
|
233
|
+
protected services: MenuServices,
|
|
234
|
+
protected args?: unknown[]
|
|
264
235
|
) {
|
|
265
236
|
super(options);
|
|
266
|
-
if (menu
|
|
267
|
-
this.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
this.
|
|
237
|
+
if (RenderedMenuNode.is(this.menu)) {
|
|
238
|
+
if (this.menu.label) {
|
|
239
|
+
this.title.label = this.menu.label;
|
|
240
|
+
}
|
|
241
|
+
if (this.menu.icon) {
|
|
242
|
+
this.title.iconClass = this.menu.icon;
|
|
243
|
+
}
|
|
271
244
|
}
|
|
272
|
-
this.updateSubMenus(this, this.menu, this.options.commands);
|
|
245
|
+
this.updateSubMenus(this.effectiveMenuPath, this, this.menu, this.options.commands, this.contextMatcher, this.options.context);
|
|
273
246
|
}
|
|
274
247
|
|
|
275
248
|
protected override onAfterAttach(msg: Message): void {
|
|
@@ -318,8 +291,7 @@ export class DynamicMenuWidget extends MenuWidget {
|
|
|
318
291
|
this.preserveFocusedElement(previousFocusedElement);
|
|
319
292
|
this.clearItems();
|
|
320
293
|
this.runWithPreservedFocusContext(() => {
|
|
321
|
-
this.options.commands.
|
|
322
|
-
this.updateSubMenus(this, this.menu, this.options.commands);
|
|
294
|
+
this.updateSubMenus(this.effectiveMenuPath, this, this.menu, this.options.commands, this.contextMatcher, this.options.context);
|
|
323
295
|
});
|
|
324
296
|
}
|
|
325
297
|
|
|
@@ -333,8 +305,9 @@ export class DynamicMenuWidget extends MenuWidget {
|
|
|
333
305
|
super.open(x, y, options);
|
|
334
306
|
}
|
|
335
307
|
|
|
336
|
-
protected updateSubMenus(parent: MenuWidget, menu: CompoundMenuNode, commands:
|
|
337
|
-
|
|
308
|
+
protected updateSubMenus(parentPath: MenuPath, parent: MenuWidget, menu: CompoundMenuNode, commands: LuminoCommandRegistry,
|
|
309
|
+
contextMatcher: ContextMatcher, context?: HTMLElement | undefined): void {
|
|
310
|
+
const items = this.createItems(parentPath, menu.children, commands, contextMatcher, context);
|
|
338
311
|
while (items[items.length - 1]?.type === 'separator') {
|
|
339
312
|
items.pop();
|
|
340
313
|
}
|
|
@@ -350,43 +323,58 @@ export class DynamicMenuWidget extends MenuWidget {
|
|
|
350
323
|
}
|
|
351
324
|
}
|
|
352
325
|
|
|
353
|
-
protected
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if (
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
326
|
+
protected createItems(parentPath: MenuPath, nodes: MenuNode[], phCommandRegistry: LuminoCommandRegistry,
|
|
327
|
+
contextMatcher: ContextMatcher, context?: HTMLElement): MenuWidget.IItemOptions[] {
|
|
328
|
+
const result: MenuWidget.IItemOptions[] = [];
|
|
329
|
+
|
|
330
|
+
for (const node of nodes) {
|
|
331
|
+
const nodePath = [...parentPath, node.id];
|
|
332
|
+
if (node.isVisible(nodePath, contextMatcher, context, ...(this.args || []))) {
|
|
333
|
+
if (CompoundMenuNode.is(node)) {
|
|
334
|
+
if (RenderedMenuNode.is(node)) {
|
|
335
|
+
const submenu = this.services.menuWidgetFactory.createMenuWidget(nodePath, node, this.contextMatcher, this.options);
|
|
336
|
+
if (submenu.items.length > 0) {
|
|
337
|
+
result.push({ type: 'submenu', submenu });
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
const items = this.createItems(nodePath, node.children, phCommandRegistry, contextMatcher, context);
|
|
341
|
+
if (items.length > 0) {
|
|
342
|
+
if (node.id !== 'inline') {
|
|
343
|
+
result.push({ type: 'separator' });
|
|
344
|
+
}
|
|
345
|
+
result.push(...items);
|
|
346
|
+
if (node.id !== 'inline') {
|
|
347
|
+
result.push({ type: 'separator' });
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
} else if (CommandMenu.is(node)) {
|
|
352
|
+
const id = !phCommandRegistry.hasCommand(node.id) ? node.id : `${node.id}:${DynamicMenuWidget.nextCommmandId++}`;
|
|
353
|
+
phCommandRegistry.addCommand(id, {
|
|
354
|
+
execute: () => { node.run(nodePath, ...(this.args || [])); },
|
|
355
|
+
isEnabled: () => node.isEnabled(nodePath, ...(this.args || [])),
|
|
356
|
+
isToggled: () => node.isToggled ? !!node.isToggled(nodePath, ...(this.args || [])) : false,
|
|
357
|
+
isVisible: () => true,
|
|
358
|
+
label: node.label,
|
|
359
|
+
iconClass: node.icon,
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
const accelerator = (AcceleratorSource.is(node) ? node.getAccelerator(this.options.context) : []);
|
|
363
|
+
if (accelerator.length > 0) {
|
|
364
|
+
phCommandRegistry.addKeyBinding({
|
|
365
|
+
command: id,
|
|
366
|
+
keys: accelerator,
|
|
367
|
+
selector: '.p-Widget' // We have the PhosphorJS dependency anyway.
|
|
368
|
+
});
|
|
370
369
|
}
|
|
371
|
-
|
|
372
|
-
|
|
370
|
+
result.push({
|
|
371
|
+
command: id,
|
|
372
|
+
type: 'command'
|
|
373
|
+
});
|
|
373
374
|
}
|
|
374
375
|
}
|
|
375
|
-
} else if (menu.command) {
|
|
376
|
-
const node = menu.altNode && this.services.context.altPressed ? menu.altNode : (menu as MenuNode & CommandMenuNode);
|
|
377
|
-
if (commands.isVisible(node.command) && this.undefinedOrMatch(this.options.contextKeyService ?? this.services.contextKeyService, node.when, this.options.context)) {
|
|
378
|
-
parentItems.push({
|
|
379
|
-
command: node.command,
|
|
380
|
-
type: 'command'
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
376
|
}
|
|
384
|
-
return
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
protected undefinedOrMatch(contextKeyService: ContextMatcher, expression?: string, context?: HTMLElement): boolean {
|
|
388
|
-
if (expression) { return contextKeyService.match(expression, context); }
|
|
389
|
-
return true;
|
|
377
|
+
return result;
|
|
390
378
|
}
|
|
391
379
|
|
|
392
380
|
protected preserveFocusedElement(previousFocusedElement: Element | null = document.activeElement): boolean {
|
|
@@ -473,79 +461,3 @@ export class BrowserMenuBarContribution implements FrontendApplicationContributi
|
|
|
473
461
|
return logo;
|
|
474
462
|
}
|
|
475
463
|
}
|
|
476
|
-
|
|
477
|
-
/**
|
|
478
|
-
* Stores Theia-specific action menu nodes instead of Lumino commands with their handlers.
|
|
479
|
-
*/
|
|
480
|
-
export class MenuCommandRegistry extends LuminoCommandRegistry {
|
|
481
|
-
|
|
482
|
-
protected actions = new Map<string, [MenuNode & CommandMenuNode, unknown[]]>();
|
|
483
|
-
protected toDispose = new DisposableCollection();
|
|
484
|
-
|
|
485
|
-
constructor(protected services: MenuServices) {
|
|
486
|
-
super();
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
registerActionMenu(menu: MenuNode & CommandMenuNode, args: unknown[]): void {
|
|
490
|
-
const { commandRegistry } = this.services;
|
|
491
|
-
const command = commandRegistry.getCommand(menu.command);
|
|
492
|
-
if (!command) {
|
|
493
|
-
return;
|
|
494
|
-
}
|
|
495
|
-
const { id } = command;
|
|
496
|
-
if (this.actions.has(id)) {
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
this.actions.set(id, [menu, args]);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
snapshot(menuPath: MenuPath): this {
|
|
503
|
-
this.toDispose.dispose();
|
|
504
|
-
for (const [menu, args] of this.actions.values()) {
|
|
505
|
-
this.toDispose.push(this.registerCommand(menu, args, menuPath));
|
|
506
|
-
}
|
|
507
|
-
return this;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
protected registerCommand(menu: MenuNode & CommandMenuNode, args: unknown[], menuPath: MenuPath): Disposable {
|
|
511
|
-
const { commandRegistry, keybindingRegistry, commandExecutor } = this.services;
|
|
512
|
-
const command = commandRegistry.getCommand(menu.command);
|
|
513
|
-
if (!command) {
|
|
514
|
-
return Disposable.NULL;
|
|
515
|
-
}
|
|
516
|
-
const { id } = command;
|
|
517
|
-
if (this.hasCommand(id)) {
|
|
518
|
-
// several menu items can be registered for the same command in different contexts
|
|
519
|
-
return Disposable.NULL;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// We freeze the `isEnabled`, `isVisible`, and `isToggled` states so they won't change.
|
|
523
|
-
const enabled = commandExecutor.isEnabled(menuPath, id, ...args);
|
|
524
|
-
const visible = commandExecutor.isVisible(menuPath, id, ...args);
|
|
525
|
-
const toggled = commandExecutor.isToggled(menuPath, id, ...args);
|
|
526
|
-
const unregisterCommand = this.addCommand(id, {
|
|
527
|
-
execute: () => commandExecutor.executeCommand(menuPath, id, ...args),
|
|
528
|
-
label: menu.label,
|
|
529
|
-
iconClass: menu.icon,
|
|
530
|
-
isEnabled: () => enabled,
|
|
531
|
-
isVisible: () => visible,
|
|
532
|
-
isToggled: () => toggled
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
const bindings = keybindingRegistry.getKeybindingsForCommand(id);
|
|
536
|
-
// Only consider the first active keybinding.
|
|
537
|
-
if (bindings.length) {
|
|
538
|
-
const binding = bindings.length > 1 ?
|
|
539
|
-
bindings.find(b => !b.when || this.services.contextKeyService.match(b.when)) ?? bindings[0] :
|
|
540
|
-
bindings[0];
|
|
541
|
-
const keys = keybindingRegistry.acceleratorFor(binding, ' ', true);
|
|
542
|
-
this.addKeyBinding({
|
|
543
|
-
command: id,
|
|
544
|
-
keys,
|
|
545
|
-
selector: '.lm-Widget' // We have the Lumino dependency anyway.
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
return Disposable.create(() => unregisterCommand.dispose());
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
}
|
|
@@ -0,0 +1,140 @@
|
|
|
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-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { CompoundMenuNode, ContextExpressionMatcher, Group, MenuNode, MenuPath, Submenu } from '../../common/menu/menu-types';
|
|
18
|
+
import { Event } from '../../common';
|
|
19
|
+
|
|
20
|
+
export class SubMenuLink implements CompoundMenuNode {
|
|
21
|
+
constructor(private readonly delegate: Submenu, private readonly _sortString?: string, private readonly _when?: string) { }
|
|
22
|
+
|
|
23
|
+
get id(): string { return this.delegate.id; };
|
|
24
|
+
get onDidChange(): Event<void> | undefined { return this.delegate.onDidChange; };
|
|
25
|
+
get children(): MenuNode[] { return this.delegate.children; }
|
|
26
|
+
get contextKeyOverlays(): Record<string, string> | undefined { return this.delegate.contextKeyOverlays; }
|
|
27
|
+
get label(): string { return this.delegate.label; };
|
|
28
|
+
get icon(): string | undefined { return this.delegate.icon; };
|
|
29
|
+
|
|
30
|
+
get sortString(): string { return this._sortString || this.delegate.sortString; };
|
|
31
|
+
isVisible<T>(effectiveMenuPath: MenuPath, contextMatcher: ContextExpressionMatcher<T>, context: T | undefined, ...args: unknown[]): boolean {
|
|
32
|
+
return this.delegate.isVisible(effectiveMenuPath, contextMatcher, context) && this._when ? contextMatcher.match(this._when, context) : true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
isEmpty<T>(effectiveMenuPath: MenuPath, contextMatcher: ContextExpressionMatcher<T>, context: T | undefined, ...args: unknown[]): boolean {
|
|
36
|
+
return this.delegate.isEmpty(effectiveMenuPath, contextMatcher, context, args);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Node representing a (sub)menu in the menu tree structure.
|
|
42
|
+
*/
|
|
43
|
+
export abstract class AbstractCompoundMenuImpl implements MenuNode {
|
|
44
|
+
readonly children: MenuNode[] = [];
|
|
45
|
+
|
|
46
|
+
protected constructor(
|
|
47
|
+
readonly id: string,
|
|
48
|
+
protected readonly orderString?: string,
|
|
49
|
+
protected readonly when?: string
|
|
50
|
+
) {
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getOrCreate(menuPath: MenuPath, pathIndex: number, endIndex: number): CompoundMenuImpl {
|
|
54
|
+
if (pathIndex === endIndex) {
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
let child = this.getNode(menuPath[pathIndex]);
|
|
58
|
+
if (!child) {
|
|
59
|
+
child = new GroupImpl(menuPath[pathIndex]);
|
|
60
|
+
this.addNode(child);
|
|
61
|
+
}
|
|
62
|
+
if (child instanceof AbstractCompoundMenuImpl) {
|
|
63
|
+
return child.getOrCreate(menuPath, pathIndex + 1, endIndex);
|
|
64
|
+
} else {
|
|
65
|
+
throw new Error(`An item exists, but it's not a parent: ${menuPath} at ${pathIndex}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Menu nodes are sorted in ascending order based on their `sortString`.
|
|
72
|
+
*/
|
|
73
|
+
isVisible<T>(effectiveMenuPath: MenuPath, contextMatcher: ContextExpressionMatcher<T>, context: T | undefined, ...args: unknown[]): boolean {
|
|
74
|
+
return (!this.when || contextMatcher.match(this.when, context));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
isEmpty<T>(effectiveMenuPath: MenuPath, contextMatcher: ContextExpressionMatcher<T>, context: T | undefined, ...args: unknown[]): boolean {
|
|
78
|
+
for (const child of this.children) {
|
|
79
|
+
if (child.isVisible(effectiveMenuPath, contextMatcher, context, args)) {
|
|
80
|
+
if (!CompoundMenuNode.is(child) || !child.isEmpty(effectiveMenuPath, contextMatcher, context, args)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
addNode(...node: MenuNode[]): void {
|
|
89
|
+
this.children.push(...node);
|
|
90
|
+
this.children.sort(CompoundMenuNode.sortChildren);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getNode(id: string): MenuNode | undefined {
|
|
94
|
+
return this.children.find(node => node.id === id);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
removeById(id: string): void {
|
|
98
|
+
const idx = this.children.findIndex(node => node.id === id);
|
|
99
|
+
if (idx >= 0) {
|
|
100
|
+
this.children.splice(idx, 1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
removeNode(node: MenuNode): void {
|
|
105
|
+
const idx = this.children.indexOf(node);
|
|
106
|
+
if (idx >= 0) {
|
|
107
|
+
this.children.splice(idx, 1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get sortString(): string {
|
|
112
|
+
return this.orderString || this.id;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export class GroupImpl extends AbstractCompoundMenuImpl implements Group {
|
|
117
|
+
constructor(
|
|
118
|
+
id: string,
|
|
119
|
+
orderString?: string,
|
|
120
|
+
when?: string
|
|
121
|
+
) {
|
|
122
|
+
super(id, orderString, when);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export class SubmenuImpl extends AbstractCompoundMenuImpl implements Submenu {
|
|
127
|
+
|
|
128
|
+
constructor(
|
|
129
|
+
id: string,
|
|
130
|
+
readonly label: string,
|
|
131
|
+
readonly contextKeyOverlays: Record<string, string> | undefined,
|
|
132
|
+
orderString?: string,
|
|
133
|
+
readonly icon?: string,
|
|
134
|
+
when?: string,
|
|
135
|
+
) {
|
|
136
|
+
super(id, orderString, when);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export type CompoundMenuImpl = SubmenuImpl | GroupImpl;
|
|
@@ -15,12 +15,40 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import * as chai from 'chai';
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
import {
|
|
19
|
+
CommandContribution, CommandMenu, CommandRegistry, CompoundMenuNode, Group, GroupImpl, MenuAction, MenuContribution,
|
|
20
|
+
MenuModelRegistry, MenuNode, MenuNodeFactory, MutableCompoundMenuNode, Submenu,
|
|
21
|
+
SubmenuImpl,
|
|
22
|
+
SubMenuLink
|
|
23
|
+
} from '../../common';
|
|
21
24
|
|
|
22
25
|
const expect = chai.expect;
|
|
23
26
|
|
|
27
|
+
class TestMenuNodeFactory implements MenuNodeFactory {
|
|
28
|
+
createGroup(id: string, orderString?: string, when?: string): Group & MutableCompoundMenuNode {
|
|
29
|
+
return new GroupImpl(id, orderString, when);
|
|
30
|
+
}
|
|
31
|
+
createSubmenu(id: string, label: string, contextKeyOverlays: Record<string, string> | undefined, orderString?: string, icon?: string, when?: string):
|
|
32
|
+
Submenu & MutableCompoundMenuNode {
|
|
33
|
+
return new SubmenuImpl(id, label, contextKeyOverlays, orderString, icon, when);
|
|
34
|
+
}
|
|
35
|
+
createSubmenuLink(delegate: Submenu, sortString?: string, when?: string): MenuNode {
|
|
36
|
+
return new SubMenuLink(delegate, sortString, when);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
createCommandMenu(item: MenuAction): CommandMenu {
|
|
40
|
+
return {
|
|
41
|
+
isVisible: () => true,
|
|
42
|
+
isEnabled: () => true,
|
|
43
|
+
isToggled: () => false,
|
|
44
|
+
id: item.commandId,
|
|
45
|
+
label: item.label || '',
|
|
46
|
+
sortString: item.order || '',
|
|
47
|
+
run: () => Promise.resolve()
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
24
52
|
describe('menu-model-registry', () => {
|
|
25
53
|
|
|
26
54
|
describe('01 #register', () => {
|
|
@@ -49,15 +77,13 @@ describe('menu-model-registry', () => {
|
|
|
49
77
|
});
|
|
50
78
|
}
|
|
51
79
|
});
|
|
52
|
-
const
|
|
53
|
-
const main = all.children[0] as CompositeMenuNode;
|
|
80
|
+
const main = service.getMenu(['main'])!;
|
|
54
81
|
expect(main.children.length).equals(1);
|
|
55
82
|
expect(main.id, 'main');
|
|
56
|
-
|
|
57
|
-
const file = main.children[0] as CompositeMenuNode;
|
|
83
|
+
const file = main.children[0] as Submenu;
|
|
58
84
|
expect(file.children.length).equals(1);
|
|
59
85
|
expect(file.label, 'File');
|
|
60
|
-
const openGroup = file.children[0] as
|
|
86
|
+
const openGroup = file.children[0] as Submenu;
|
|
61
87
|
expect(openGroup.children.length).equals(2);
|
|
62
88
|
expect(openGroup.label).undefined;
|
|
63
89
|
});
|
|
@@ -69,16 +95,22 @@ describe('menu-model-registry', () => {
|
|
|
69
95
|
const service = createMenuRegistry({
|
|
70
96
|
registerMenus(menuRegistry: MenuModelRegistry): void {
|
|
71
97
|
menuRegistry.registerSubmenu(fileMenu, 'File');
|
|
98
|
+
menuRegistry.registerSubmenu(fileOpenMenu, 'Open');
|
|
99
|
+
menuRegistry.registerSubmenu(fileCloseMenu, 'Close');
|
|
72
100
|
// open menu should not be added to open menu
|
|
73
|
-
|
|
101
|
+
try {
|
|
102
|
+
menuRegistry.linkCompoundMenuNode({ newParentPath: fileOpenMenu, submenuPath: fileOpenMenu });
|
|
103
|
+
} catch (e) {
|
|
104
|
+
// expected
|
|
105
|
+
}
|
|
74
106
|
// close menu should be added
|
|
75
|
-
menuRegistry.
|
|
107
|
+
menuRegistry.linkCompoundMenuNode({ newParentPath: fileOpenMenu, submenuPath: fileCloseMenu });
|
|
76
108
|
}
|
|
77
109
|
}, {
|
|
78
110
|
registerCommands(reg: CommandRegistry): void { }
|
|
79
111
|
});
|
|
80
|
-
const
|
|
81
|
-
expect(menuStructureToString(
|
|
112
|
+
const main = service.getMenu(['main']) as CompoundMenuNode;
|
|
113
|
+
expect(menuStructureToString(main)).equals('File(0_open(1_close()),1_close())');
|
|
82
114
|
});
|
|
83
115
|
});
|
|
84
116
|
});
|
|
@@ -86,14 +118,14 @@ describe('menu-model-registry', () => {
|
|
|
86
118
|
function createMenuRegistry(menuContrib: MenuContribution, commandContrib: CommandContribution): MenuModelRegistry {
|
|
87
119
|
const cmdReg = new CommandRegistry({ getContributions: () => [commandContrib] });
|
|
88
120
|
cmdReg.onStart();
|
|
89
|
-
const menuReg = new MenuModelRegistry({ getContributions: () => [menuContrib] }, cmdReg);
|
|
121
|
+
const menuReg = new MenuModelRegistry({ getContributions: () => [menuContrib] }, cmdReg, new TestMenuNodeFactory());
|
|
90
122
|
menuReg.onStart();
|
|
91
123
|
return menuReg;
|
|
92
124
|
}
|
|
93
125
|
|
|
94
|
-
function menuStructureToString(node:
|
|
126
|
+
function menuStructureToString(node: CompoundMenuNode): string {
|
|
95
127
|
return node.children.map(c => {
|
|
96
|
-
if (c
|
|
128
|
+
if (CompoundMenuNode.is(c)) {
|
|
97
129
|
return `${c.id}(${menuStructureToString(c)})`;
|
|
98
130
|
}
|
|
99
131
|
return c.id;
|
|
@@ -49,7 +49,7 @@ export interface OpenWithHandler {
|
|
|
49
49
|
*/
|
|
50
50
|
canHandle(uri: URI): number;
|
|
51
51
|
/**
|
|
52
|
-
* Test whether this handler
|
|
52
|
+
* Test whether this handler can open the given URI
|
|
53
53
|
* and return the order of this handler in the list.
|
|
54
54
|
*/
|
|
55
55
|
getOrder?(uri: URI): number;
|
|
@@ -222,7 +222,12 @@ export class SaveableService implements FrontendApplicationContribution {
|
|
|
222
222
|
if (!Saveable.isDirty(widget)) {
|
|
223
223
|
return false;
|
|
224
224
|
}
|
|
225
|
-
|
|
225
|
+
const saveable = Saveable.get(widget);
|
|
226
|
+
if (!saveable) {
|
|
227
|
+
console.warn('Saveable.get returned undefined on a known saveable widget. This is unexpected.');
|
|
228
|
+
}
|
|
229
|
+
// Enter branch if saveable absent since we cannot check autosaveability more definitely.
|
|
230
|
+
if (this.autoSave !== 'off' && (!saveable || this.shouldAutoSave(widget, saveable))) {
|
|
226
231
|
return true;
|
|
227
232
|
}
|
|
228
233
|
const notLastWithDocument = !Saveable.closingWidgetWouldLoseSaveable(widget, Array.from(this.saveThrottles.keys()));
|