@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.
Files changed (201) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +33 -2
  3. package/i18n/nls.de.json +33 -2
  4. package/i18n/nls.es.json +33 -2
  5. package/i18n/nls.fr.json +33 -2
  6. package/i18n/nls.hu.json +33 -2
  7. package/i18n/nls.it.json +33 -2
  8. package/i18n/nls.ja.json +33 -2
  9. package/i18n/nls.json +35 -4
  10. package/i18n/nls.pl.json +33 -2
  11. package/i18n/nls.pt-br.json +33 -2
  12. package/i18n/nls.pt-pt.json +33 -2
  13. package/i18n/nls.ru.json +33 -2
  14. package/i18n/nls.zh-cn.json +33 -2
  15. package/lib/browser/common-frontend-contribution.d.ts +1 -1
  16. package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
  17. package/lib/browser/common-frontend-contribution.js +6 -5
  18. package/lib/browser/common-frontend-contribution.js.map +1 -1
  19. package/lib/browser/context-key-service.d.ts +3 -1
  20. package/lib/browser/context-key-service.d.ts.map +1 -1
  21. package/lib/browser/context-menu-renderer.d.ts +5 -0
  22. package/lib/browser/context-menu-renderer.d.ts.map +1 -1
  23. package/lib/browser/frontend-application-module.d.ts.map +1 -1
  24. package/lib/browser/frontend-application-module.js +2 -0
  25. package/lib/browser/frontend-application-module.js.map +1 -1
  26. package/lib/browser/frontend-application.d.ts +3 -2
  27. package/lib/browser/frontend-application.d.ts.map +1 -1
  28. package/lib/browser/frontend-application.js.map +1 -1
  29. package/lib/browser/keybinding.d.ts.map +1 -1
  30. package/lib/browser/keybinding.js +9 -7
  31. package/lib/browser/keybinding.js.map +1 -1
  32. package/lib/browser/keybinding.spec.js +13 -3
  33. package/lib/browser/keybinding.spec.js.map +1 -1
  34. package/lib/browser/menu/browser-context-menu-renderer.d.ts +1 -1
  35. package/lib/browser/menu/browser-context-menu-renderer.d.ts.map +1 -1
  36. package/lib/browser/menu/browser-context-menu-renderer.js +2 -2
  37. package/lib/browser/menu/browser-context-menu-renderer.js.map +1 -1
  38. package/lib/browser/menu/browser-menu-plugin.d.ts +23 -24
  39. package/lib/browser/menu/browser-menu-plugin.d.ts.map +1 -1
  40. package/lib/browser/menu/browser-menu-plugin.js +62 -79
  41. package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
  42. package/lib/browser/resource-context-key.d.ts +1 -0
  43. package/lib/browser/resource-context-key.d.ts.map +1 -1
  44. package/lib/browser/resource-context-key.js +8 -6
  45. package/lib/browser/resource-context-key.js.map +1 -1
  46. package/lib/browser/shell/shell-layout-restorer.d.ts.map +1 -1
  47. package/lib/browser/shell/shell-layout-restorer.js +2 -1
  48. package/lib/browser/shell/shell-layout-restorer.js.map +1 -1
  49. package/lib/browser/shell/side-panel-toolbar.d.ts.map +1 -1
  50. package/lib/browser/shell/side-panel-toolbar.js +0 -1
  51. package/lib/browser/shell/side-panel-toolbar.js.map +1 -1
  52. package/lib/browser/shell/tab-bar-toolbar/index.d.ts +4 -0
  53. package/lib/browser/shell/tab-bar-toolbar/index.d.ts.map +1 -0
  54. package/lib/browser/shell/tab-bar-toolbar/index.js +31 -0
  55. package/lib/browser/shell/tab-bar-toolbar/index.js.map +1 -0
  56. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts +16 -0
  57. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts.map +1 -0
  58. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +36 -0
  59. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -0
  60. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts +51 -0
  61. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts.map +1 -0
  62. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js +173 -0
  63. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js.map +1 -0
  64. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.d.ts +119 -0
  65. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.d.ts.map +1 -0
  66. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.js +67 -0
  67. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.js.map +1 -0
  68. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +53 -0
  69. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -0
  70. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +264 -0
  71. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -0
  72. package/lib/browser/shell/{tab-bar-toolbar.spec.d.ts → tab-bar-toolbar/tab-bar-toolbar.spec.d.ts} +0 -0
  73. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.d.ts.map +1 -0
  74. package/lib/browser/shell/{tab-bar-toolbar.spec.js → tab-bar-toolbar/tab-bar-toolbar.spec.js} +3 -3
  75. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -0
  76. package/lib/browser/view-container.d.ts.map +1 -1
  77. package/lib/browser/view-container.js +1 -10
  78. package/lib/browser/view-container.js.map +1 -1
  79. package/lib/browser/widget-manager.d.ts.map +1 -1
  80. package/lib/browser/widget-manager.js +2 -1
  81. package/lib/browser/widget-manager.js.map +1 -1
  82. package/lib/browser/widget-manager.spec.js +13 -0
  83. package/lib/browser/widget-manager.spec.js.map +1 -1
  84. package/lib/browser/window/default-window-service.d.ts +2 -1
  85. package/lib/browser/window/default-window-service.d.ts.map +1 -1
  86. package/lib/browser/window/default-window-service.js +9 -4
  87. package/lib/browser/window/default-window-service.js.map +1 -1
  88. package/lib/browser/window/window-service.d.ts +2 -1
  89. package/lib/browser/window/window-service.d.ts.map +1 -1
  90. package/lib/browser/window/window-service.js.map +1 -1
  91. package/lib/common/color.d.ts +3 -0
  92. package/lib/common/color.d.ts.map +1 -1
  93. package/lib/common/frontend-application-state.d.ts +14 -0
  94. package/lib/common/frontend-application-state.d.ts.map +1 -1
  95. package/lib/common/frontend-application-state.js +16 -0
  96. package/lib/common/frontend-application-state.js.map +1 -1
  97. package/lib/common/menu/action-menu-node.d.ts +20 -0
  98. package/lib/common/menu/action-menu-node.d.ts.map +1 -0
  99. package/lib/common/menu/action-menu-node.js +57 -0
  100. package/lib/common/menu/action-menu-node.js.map +1 -0
  101. package/lib/common/menu/composite-menu-node.d.ts +52 -0
  102. package/lib/common/menu/composite-menu-node.d.ts.map +1 -0
  103. package/lib/common/menu/composite-menu-node.js +102 -0
  104. package/lib/common/menu/composite-menu-node.js.map +1 -0
  105. package/lib/common/menu/index.d.ts +6 -0
  106. package/lib/common/menu/index.d.ts.map +1 -0
  107. package/lib/common/menu/index.js +33 -0
  108. package/lib/common/menu/index.js.map +1 -0
  109. package/lib/common/menu/menu-adapter.d.ts +36 -0
  110. package/lib/common/menu/menu-adapter.d.ts.map +1 -0
  111. package/lib/common/menu/menu-adapter.js +101 -0
  112. package/lib/common/menu/menu-adapter.js.map +1 -0
  113. package/lib/common/{menu.d.ts → menu/menu-model-registry.d.ts} +22 -124
  114. package/lib/common/menu/menu-model-registry.d.ts.map +1 -0
  115. package/lib/common/{menu.js → menu/menu-model-registry.js} +71 -147
  116. package/lib/common/menu/menu-model-registry.js.map +1 -0
  117. package/lib/common/menu/menu-types.d.ts +120 -0
  118. package/lib/common/menu/menu-types.d.ts.map +1 -0
  119. package/lib/common/menu/menu-types.js +84 -0
  120. package/lib/common/menu/menu-types.js.map +1 -0
  121. package/lib/common/{menu.spec.d.ts → menu/menu.spec.d.ts} +0 -0
  122. package/lib/common/menu/menu.spec.d.ts.map +1 -0
  123. package/lib/common/{menu.spec.js → menu/menu.spec.js} +3 -3
  124. package/lib/common/menu/menu.spec.js.map +1 -0
  125. package/lib/common/messaging/abstract-connection-provider.d.ts +1 -1
  126. package/lib/common/messaging/abstract-connection-provider.js +3 -3
  127. package/lib/common/quick-pick-service.d.ts +1 -0
  128. package/lib/common/quick-pick-service.d.ts.map +1 -1
  129. package/lib/common/quick-pick-service.js.map +1 -1
  130. package/lib/electron-browser/menu/electron-context-menu-renderer.js +2 -2
  131. package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
  132. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +14 -5
  133. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
  134. package/lib/electron-browser/menu/electron-main-menu-factory.js +71 -82
  135. package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
  136. package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
  137. package/lib/electron-browser/menu/electron-menu-contribution.js +6 -0
  138. package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
  139. package/lib/electron-browser/messaging/electron-ws-connection-provider.js +1 -1
  140. package/lib/electron-browser/window/electron-window-service.js +1 -1
  141. package/lib/electron-browser/window/electron-window-service.js.map +1 -1
  142. package/lib/electron-common/messaging/electron-messages.d.ts +3 -14
  143. package/lib/electron-common/messaging/electron-messages.d.ts.map +1 -1
  144. package/lib/electron-common/messaging/electron-messages.js +3 -16
  145. package/lib/electron-common/messaging/electron-messages.js.map +1 -1
  146. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +3 -3
  147. package/lib/electron-main/messaging/electron-messaging-contribution.js +6 -6
  148. package/package.json +7 -6
  149. package/src/browser/common-frontend-contribution.ts +6 -5
  150. package/src/browser/context-key-service.ts +1 -1
  151. package/src/browser/context-menu-renderer.ts +5 -0
  152. package/src/browser/frontend-application-module.ts +7 -1
  153. package/src/browser/frontend-application.ts +3 -2
  154. package/src/browser/keybinding.spec.ts +13 -3
  155. package/src/browser/keybinding.ts +8 -9
  156. package/src/browser/menu/browser-context-menu-renderer.ts +2 -2
  157. package/src/browser/menu/browser-menu-plugin.ts +74 -86
  158. package/src/browser/resource-context-key.ts +9 -6
  159. package/src/browser/shell/shell-layout-restorer.ts +2 -1
  160. package/src/browser/shell/side-panel-toolbar.ts +0 -1
  161. package/src/browser/shell/tab-bar-toolbar/index.ts +19 -0
  162. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.ts +31 -0
  163. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +170 -0
  164. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.ts +186 -0
  165. package/src/browser/shell/{tab-bar-toolbar.spec.ts → tab-bar-toolbar/tab-bar-toolbar.spec.ts} +2 -2
  166. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +261 -0
  167. package/src/browser/style/alert-messages.css +6 -0
  168. package/src/browser/view-container.ts +1 -10
  169. package/src/browser/widget-manager.spec.ts +14 -0
  170. package/src/browser/widget-manager.ts +2 -1
  171. package/src/browser/window/default-window-service.ts +9 -4
  172. package/src/browser/window/window-service.ts +2 -1
  173. package/src/common/color.ts +3 -0
  174. package/src/common/frontend-application-state.ts +15 -0
  175. package/src/common/menu/action-menu-node.ts +65 -0
  176. package/src/common/menu/composite-menu-node.ts +121 -0
  177. package/src/common/menu/index.ts +21 -0
  178. package/src/common/menu/menu-adapter.ts +103 -0
  179. package/src/common/{menu.ts → menu/menu-model-registry.ts} +61 -222
  180. package/src/common/menu/menu-types.ts +183 -0
  181. package/src/common/{menu.spec.ts → menu/menu.spec.ts} +3 -2
  182. package/src/common/messaging/abstract-connection-provider.ts +4 -4
  183. package/src/common/quick-pick-service.ts +1 -0
  184. package/src/electron-browser/menu/electron-context-menu-renderer.ts +2 -2
  185. package/src/electron-browser/menu/electron-main-menu-factory.ts +82 -96
  186. package/src/electron-browser/menu/electron-menu-contribution.ts +8 -0
  187. package/src/electron-browser/messaging/electron-ws-connection-provider.ts +1 -1
  188. package/src/electron-browser/window/electron-window-service.ts +1 -1
  189. package/src/electron-common/messaging/electron-messages.ts +4 -15
  190. package/src/electron-main/messaging/electron-messaging-contribution.ts +8 -8
  191. package/lib/browser/shell/tab-bar-toolbar.d.ts +0 -186
  192. package/lib/browser/shell/tab-bar-toolbar.d.ts.map +0 -1
  193. package/lib/browser/shell/tab-bar-toolbar.js +0 -362
  194. package/lib/browser/shell/tab-bar-toolbar.js.map +0 -1
  195. package/lib/browser/shell/tab-bar-toolbar.spec.d.ts.map +0 -1
  196. package/lib/browser/shell/tab-bar-toolbar.spec.js.map +0 -1
  197. package/lib/common/menu.d.ts.map +0 -1
  198. package/lib/common/menu.js.map +0 -1
  199. package/lib/common/menu.spec.d.ts.map +0 -1
  200. package/lib/common/menu.spec.js.map +0 -1
  201. package/src/browser/shell/tab-bar-toolbar.tsx +0 -495
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theia/core",
3
- "version": "1.28.0-next.9+c0ee4dcf6bb",
3
+ "version": "1.28.0",
4
4
  "description": "Theia is a cloud & desktop IDE framework implemented in TypeScript.",
5
5
  "main": "lib/common/index.js",
6
6
  "typings": "lib/common/index.d.ts",
@@ -16,8 +16,8 @@
16
16
  "@phosphor/signaling": "1",
17
17
  "@phosphor/virtualdom": "1",
18
18
  "@phosphor/widgets": "1",
19
- "@theia/application-package": "1.28.0-next.9+c0ee4dcf6bb",
20
- "@theia/request": "1.28.0-next.9+c0ee4dcf6bb",
19
+ "@theia/application-package": "1.28.0",
20
+ "@theia/request": "1.28.0",
21
21
  "@types/body-parser": "^1.16.4",
22
22
  "@types/cookie": "^0.3.3",
23
23
  "@types/dompurify": "^2.2.2",
@@ -41,6 +41,7 @@
41
41
  "drivelist": "^9.0.2",
42
42
  "es6-promise": "^4.2.4",
43
43
  "express": "^4.16.3",
44
+ "fast-json-stable-stringify": "^2.1.0",
44
45
  "file-icons-js": "~1.0.3",
45
46
  "font-awesome": "^4.7.0",
46
47
  "fs-extra": "^4.0.2",
@@ -193,12 +194,12 @@
193
194
  "watch": "theiaext watch"
194
195
  },
195
196
  "devDependencies": {
196
- "@theia/ext-scripts": "1.27.0",
197
- "@theia/re-exports": "1.27.0",
197
+ "@theia/ext-scripts": "1.28.0",
198
+ "@theia/re-exports": "1.28.0",
198
199
  "minimist": "^1.2.0"
199
200
  },
200
201
  "nyc": {
201
202
  "extends": "../../configs/nyc.json"
202
203
  },
203
- "gitHead": "c0ee4dcf6bb10be905cc5a58d04b10faa3800d67"
204
+ "gitHead": "79d58c87a7bd76f435000a2ac59803b04e1c78be"
204
205
  }
@@ -272,10 +272,10 @@ export namespace CommonCommands {
272
272
  category: VIEW_CATEGORY,
273
273
  label: 'Show Menu Bar'
274
274
  });
275
- export const NEW_FILE = Command.toDefaultLocalizedCommand({
275
+ export const NEW_UNTITLED_FILE = Command.toDefaultLocalizedCommand({
276
276
  id: 'workbench.action.files.newUntitledFile',
277
277
  category: FILE_CATEGORY,
278
- label: 'New File'
278
+ label: 'New Untitled File'
279
279
  });
280
280
  export const SAVE = Command.toDefaultLocalizedCommand({
281
281
  id: 'core.save',
@@ -721,7 +721,8 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
721
721
  registry.registerSubmenu(CommonMenus.VIEW_APPEARANCE_SUBMENU, nls.localizeByDefault('Appearance'));
722
722
 
723
723
  registry.registerMenuAction(CommonMenus.FILE_NEW, {
724
- commandId: CommonCommands.NEW_FILE.id,
724
+ commandId: CommonCommands.NEW_UNTITLED_FILE.id,
725
+ label: nls.localizeByDefault('New File'),
725
726
  order: 'a'
726
727
  });
727
728
  }
@@ -963,7 +964,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
963
964
  commandRegistry.registerCommand(CommonCommands.CONFIGURE_DISPLAY_LANGUAGE, {
964
965
  execute: () => this.configureDisplayLanguage()
965
966
  });
966
- commandRegistry.registerCommand(CommonCommands.NEW_FILE, {
967
+ commandRegistry.registerCommand(CommonCommands.NEW_UNTITLED_FILE, {
967
968
  execute: async () => {
968
969
  const untitledUri = this.untitledResourceResolver.createUntitledURI('', await this.workingDirProvider.getUserWorkingDir());
969
970
  this.untitledResourceResolver.resolve(untitledUri);
@@ -1104,7 +1105,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
1104
1105
  when: 'activeEditorIsPinned'
1105
1106
  },
1106
1107
  {
1107
- command: CommonCommands.NEW_FILE.id,
1108
+ command: CommonCommands.NEW_UNTITLED_FILE.id,
1108
1109
  keybinding: this.isElectron() ? 'ctrlcmd+n' : 'alt+n',
1109
1110
  }
1110
1111
  );
@@ -34,7 +34,7 @@ export namespace ContextKey {
34
34
  }
35
35
 
36
36
  export interface ContextKeyChangeEvent {
37
- affects(keys: Set<string>): boolean;
37
+ affects(keys: { has(key: string): boolean }): boolean;
38
38
  }
39
39
 
40
40
  export const ContextKeyService = Symbol('ContextKeyService');
@@ -112,5 +112,10 @@ export interface RenderContextMenuOptions {
112
112
  * Default is `true`.
113
113
  */
114
114
  includeAnchorArg?: boolean;
115
+ /**
116
+ * A DOM context to use when evaluating any `when` clauses
117
+ * of menu items registered for this item.
118
+ */
119
+ context?: HTMLElement;
115
120
  onHide?: () => void;
116
121
  }
@@ -31,7 +31,11 @@ import {
31
31
  InMemoryResources,
32
32
  messageServicePath,
33
33
  InMemoryTextResourceResolver,
34
- UntitledResourceResolver
34
+ UntitledResourceResolver,
35
+ MenuCommandAdapterRegistry,
36
+ MenuCommandExecutor,
37
+ MenuCommandAdapterRegistryImpl,
38
+ MenuCommandExecutorImpl
35
39
  } from '../common';
36
40
  import { KeybindingRegistry, KeybindingContext, KeybindingContribution } from './keybinding';
37
41
  import { FrontendApplication, FrontendApplicationContribution, DefaultFrontendApplicationContribution } from './frontend-application';
@@ -241,6 +245,8 @@ export const frontendApplicationModule = new ContainerModule((bind, _unbind, _is
241
245
 
242
246
  bind(MenuModelRegistry).toSelf().inSingletonScope();
243
247
  bindContributionProvider(bind, MenuContribution);
248
+ bind(MenuCommandAdapterRegistry).to(MenuCommandAdapterRegistryImpl).inSingletonScope();
249
+ bind(MenuCommandExecutor).to(MenuCommandExecutorImpl).inSingletonScope();
244
250
 
245
251
  bind(KeyboardLayoutService).toSelf().inSingletonScope();
246
252
  bind(KeybindingRegistry).toSelf().inSingletonScope();
@@ -26,6 +26,7 @@ import { preventNavigation, parseCssTime, animationFrame } from './browser';
26
26
  import { CorePreferences } from './core-preferences';
27
27
  import { WindowService } from './window/window-service';
28
28
  import { TooltipService } from './tooltip-service';
29
+ import { StopReason } from '../common/frontend-application-state';
29
30
 
30
31
  /**
31
32
  * Clients can implement to get a callback for contributing widgets to a shell on start.
@@ -81,11 +82,11 @@ export interface OnWillStopAction<T = unknown> {
81
82
  /**
82
83
  * @resolves to a prepared value to be passed into the `action` function.
83
84
  */
84
- prepare?: () => MaybePromise<T>;
85
+ prepare?: (stopReason?: StopReason) => MaybePromise<T>;
85
86
  /**
86
87
  * @resolves to `true` if it is safe to close the application; `false` otherwise.
87
88
  */
88
- action: (prepared: T) => MaybePromise<boolean>;
89
+ action: (prepared: T, stopReason?: StopReason) => MaybePromise<boolean>;
89
90
  /**
90
91
  * A descriptive string for the reason preventing close.
91
92
  */
@@ -165,20 +165,30 @@ describe('keybindings', () => {
165
165
  }
166
166
  });
167
167
 
168
- it('should remove all keybindings from a command that has multiple keybindings', () => {
168
+ it('should remove all disabled keybindings from a command that has multiple keybindings', () => {
169
169
  const keybindings: Keybinding[] = [{
170
170
  command: TEST_COMMAND2.id,
171
171
  keybinding: 'F3'
172
- }];
172
+ },
173
+ {
174
+ command: '-' + TEST_COMMAND2.id,
175
+ context: 'testContext',
176
+ keybinding: 'ctrl+f1'
177
+ },
178
+ ];
173
179
 
174
180
  keybindingRegistry.setKeymap(KeybindingScope.USER, keybindings);
175
181
 
176
182
  const bindings = keybindingRegistry.getKeybindingsForCommand(TEST_COMMAND2.id);
177
183
  if (bindings) {
178
- expect(bindings.length).to.be.equal(1);
184
+ // a USER one and a DEFAULT one
185
+ expect(bindings.length).to.be.equal(2);
179
186
  const keyCode = KeyCode.parse(bindings[0].keybinding);
180
187
  expect(keyCode.key).to.be.equal(Key.F3);
181
188
  expect(keyCode.ctrl).to.be.false;
189
+ const keyCode2 = KeyCode.parse(bindings[1].keybinding);
190
+ expect(keyCode2.key).to.be.equal(Key.F2);
191
+ expect(keyCode2.ctrl).to.be.true;
182
192
  }
183
193
  });
184
194
 
@@ -434,20 +434,19 @@ export class KeybindingRegistry {
434
434
  */
435
435
  getKeybindingsForCommand(commandId: string): ScopedKeybinding[] {
436
436
  const result: ScopedKeybinding[] = [];
437
-
437
+ const disabledBindings: ScopedKeybinding[] = [];
438
438
  for (let scope = KeybindingScope.END - 1; scope >= KeybindingScope.DEFAULT; scope--) {
439
439
  this.keymaps[scope].forEach(binding => {
440
+ if (binding.command?.startsWith('-')) {
441
+ disabledBindings.push(binding);
442
+ }
440
443
  const command = this.commandRegistry.getCommand(binding.command);
441
- if (command) {
442
- if (command.id === commandId) {
443
- result.push({ ...binding, scope });
444
- }
444
+ if (command
445
+ && command.id === commandId
446
+ && !disabledBindings.some(disabled => common.Keybinding.equals(disabled, { ...binding, command: '-' + binding.command }, false, true))) {
447
+ result.push({ ...binding, scope });
445
448
  }
446
449
  });
447
-
448
- if (result.length > 0) {
449
- return result;
450
- }
451
450
  }
452
451
  return result;
453
452
  }
@@ -36,8 +36,8 @@ export class BrowserContextMenuRenderer extends ContextMenuRenderer {
36
36
  super();
37
37
  }
38
38
 
39
- protected doRender({ menuPath, anchor, args, onHide }: RenderContextMenuOptions): ContextMenuAccess {
40
- const contextMenu = this.menuFactory.createContextMenu(menuPath, args);
39
+ protected doRender({ menuPath, anchor, args, onHide, context }: RenderContextMenuOptions): ContextMenuAccess {
40
+ const contextMenu = this.menuFactory.createContextMenu(menuPath, args, context);
41
41
  const { x, y } = coordinateFromAnchor(anchor);
42
42
  if (onHide) {
43
43
  contextMenu.aboutToClose.connect(() => onHide!());
@@ -18,8 +18,8 @@ import { injectable, inject } from 'inversify';
18
18
  import { MenuBar, Menu as MenuWidget, Widget } from '@phosphor/widgets';
19
19
  import { CommandRegistry as PhosphorCommandRegistry } from '@phosphor/commands';
20
20
  import {
21
- CommandRegistry, ActionMenuNode, CompositeMenuNode, environment,
22
- MenuModelRegistry, MAIN_MENU_BAR, MenuPath, DisposableCollection, Disposable, MenuNode
21
+ CommandRegistry, CompositeMenuNode, environment,
22
+ MenuModelRegistry, MAIN_MENU_BAR, MenuPath, DisposableCollection, Disposable, MenuNode, MenuCommandExecutor, CompoundMenuNode, CompoundMenuNodeRole, CommandMenuNode
23
23
  } from '../../common';
24
24
  import { KeybindingRegistry } from '../keybinding';
25
25
  import { FrontendApplicationContribution, FrontendApplication } from '../frontend-application';
@@ -35,6 +35,12 @@ export abstract class MenuBarWidget extends MenuBar {
35
35
  abstract triggerMenuItem(label: string, ...labels: string[]): Promise<MenuWidget.IItem>;
36
36
  }
37
37
 
38
+ export interface BrowserMenuOptions extends MenuWidget.IOptions {
39
+ commands: MenuCommandRegistry,
40
+ context?: HTMLElement,
41
+ rootMenuPath: MenuPath
42
+ };
43
+
38
44
  @injectable()
39
45
  export class BrowserMainMenuFactory implements MenuWidgetFactory {
40
46
 
@@ -47,6 +53,9 @@ export class BrowserMainMenuFactory implements MenuWidgetFactory {
47
53
  @inject(CommandRegistry)
48
54
  protected readonly commandRegistry: CommandRegistry;
49
55
 
56
+ @inject(MenuCommandExecutor)
57
+ protected readonly menuCommandExecutor: MenuCommandExecutor;
58
+
50
59
  @inject(CorePreferences)
51
60
  protected readonly corePreferences: CorePreferences;
52
61
 
@@ -92,50 +101,39 @@ export class BrowserMainMenuFactory implements MenuWidgetFactory {
92
101
  const menuCommandRegistry = this.createMenuCommandRegistry(menuModel);
93
102
  for (const menu of menuModel.children) {
94
103
  if (menu instanceof CompositeMenuNode) {
95
- const menuWidget = this.createMenuWidget(menu, { commands: menuCommandRegistry });
104
+ const menuWidget = this.createMenuWidget(menu, { commands: menuCommandRegistry, rootMenuPath: MAIN_MENU_BAR });
96
105
  menuBar.addMenu(menuWidget);
97
106
  }
98
107
  }
99
108
  }
100
109
 
101
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
102
- createContextMenu(path: MenuPath, args?: any[]): MenuWidget {
110
+ createContextMenu(path: MenuPath, args?: unknown[], context?: HTMLElement): MenuWidget {
103
111
  const menuModel = this.menuProvider.getMenu(path);
104
- const menuCommandRegistry = this.createMenuCommandRegistry(menuModel, args).snapshot();
105
- const contextMenu = this.createMenuWidget(menuModel, { commands: menuCommandRegistry });
112
+ const menuCommandRegistry = this.createMenuCommandRegistry(menuModel, args).snapshot(path);
113
+ const contextMenu = this.createMenuWidget(menuModel, { commands: menuCommandRegistry, context, rootMenuPath: path });
106
114
  return contextMenu;
107
115
  }
108
116
 
109
- createMenuWidget(menu: CompositeMenuNode, options: MenuWidget.IOptions & { commands: MenuCommandRegistry }): DynamicMenuWidget {
117
+ createMenuWidget(menu: CompositeMenuNode, options: BrowserMenuOptions): DynamicMenuWidget {
110
118
  return new DynamicMenuWidget(menu, options, this.services);
111
119
  }
112
120
 
113
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
114
- protected createMenuCommandRegistry(menu: CompositeMenuNode, args: any[] = []): MenuCommandRegistry {
121
+ protected createMenuCommandRegistry(menu: CompositeMenuNode, args: unknown[] = []): MenuCommandRegistry {
115
122
  const menuCommandRegistry = new MenuCommandRegistry(this.services);
116
123
  this.registerMenu(menuCommandRegistry, menu, args);
117
124
  return menuCommandRegistry;
118
125
  }
119
126
 
120
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
121
- protected registerMenu(menuCommandRegistry: MenuCommandRegistry, menu: CompositeMenuNode, args: any[]): void {
122
- for (const child of menu.children) {
123
- if (child instanceof ActionMenuNode) {
124
- menuCommandRegistry.registerActionMenu(child, args);
125
- if (child.altNode) {
126
- menuCommandRegistry.registerActionMenu(child.altNode, args);
127
- }
128
- } else if (child instanceof CompositeMenuNode) {
129
- this.registerMenu(menuCommandRegistry, child, args);
130
- } else {
131
- this.handleDefault(menuCommandRegistry, child, args);
127
+ protected registerMenu(menuCommandRegistry: MenuCommandRegistry, menu: MenuNode, args: unknown[]): void {
128
+ if (CompoundMenuNode.is(menu)) {
129
+ menu.children.forEach(child => this.registerMenu(menuCommandRegistry, child, args));
130
+ } else if (CommandMenuNode.is(menu)) {
131
+ menuCommandRegistry.registerActionMenu(menu, args);
132
+ if (menu.altNode) {
133
+ menuCommandRegistry.registerActionMenu(menu.altNode, args);
132
134
  }
133
- }
134
- }
135
135
 
136
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
137
- protected handleDefault(menuCommandRegistry: MenuCommandRegistry, menuNode: MenuNode, args: any[]): void {
138
- // NOOP
136
+ }
139
137
  }
140
138
 
141
139
  protected get services(): MenuServices {
@@ -144,7 +142,8 @@ export class BrowserMainMenuFactory implements MenuWidgetFactory {
144
142
  contextKeyService: this.contextKeyService,
145
143
  commandRegistry: this.commandRegistry,
146
144
  keybindingRegistry: this.keybindingRegistry,
147
- menuWidgetFactory: this
145
+ menuWidgetFactory: this,
146
+ commandExecutor: this.menuCommandExecutor,
148
147
  };
149
148
  }
150
149
 
@@ -225,10 +224,11 @@ export class MenuServices {
225
224
  readonly contextKeyService: ContextKeyService;
226
225
  readonly context: ContextMenuContext;
227
226
  readonly menuWidgetFactory: MenuWidgetFactory;
227
+ readonly commandExecutor: MenuCommandExecutor;
228
228
  }
229
229
 
230
230
  export interface MenuWidgetFactory {
231
- createMenuWidget(menu: CompositeMenuNode, options: MenuWidget.IOptions & { commands: MenuCommandRegistry }): MenuWidget;
231
+ createMenuWidget(menu: MenuNode & Required<Pick<MenuNode, 'children'>>, options: BrowserMenuOptions): MenuWidget;
232
232
  }
233
233
 
234
234
  /**
@@ -243,7 +243,7 @@ export class DynamicMenuWidget extends MenuWidget {
243
243
 
244
244
  constructor(
245
245
  protected menu: CompositeMenuNode,
246
- protected options: MenuWidget.IOptions & { commands: MenuCommandRegistry },
246
+ protected options: BrowserMenuOptions,
247
247
  protected services: MenuServices
248
248
  ) {
249
249
  super(options);
@@ -260,7 +260,7 @@ export class DynamicMenuWidget extends MenuWidget {
260
260
  this.preserveFocusedElement(previousFocusedElement);
261
261
  this.clearItems();
262
262
  this.runWithPreservedFocusContext(() => {
263
- this.options.commands.snapshot();
263
+ this.options.commands.snapshot(this.options.rootMenuPath);
264
264
  this.updateSubMenus(this, this.menu, this.options.commands);
265
265
  });
266
266
  }
@@ -275,59 +275,51 @@ export class DynamicMenuWidget extends MenuWidget {
275
275
  super.open(x, y, options);
276
276
  }
277
277
 
278
- private updateSubMenus(parent: MenuWidget, menu: CompositeMenuNode, commands: MenuCommandRegistry): void {
278
+ protected updateSubMenus(parent: MenuWidget, menu: CompositeMenuNode, commands: MenuCommandRegistry): void {
279
279
  const items = this.buildSubMenus([], menu, commands);
280
+ while (items[items.length - 1]?.type === 'separator') {
281
+ items.pop();
282
+ }
280
283
  for (const item of items) {
281
284
  parent.addItem(item);
282
285
  }
283
286
  }
284
287
 
285
- private buildSubMenus(items: MenuWidget.IItemOptions[], menu: CompositeMenuNode, commands: MenuCommandRegistry): MenuWidget.IItemOptions[] {
286
- for (const item of menu.children) {
287
- if (item instanceof CompositeMenuNode) {
288
- if (item.children.length) { // do not render empty nodes
289
- if (item.isSubmenu) { // submenu node
290
- const submenu = this.services.menuWidgetFactory.createMenuWidget(item, this.options);
291
- if (!submenu.items.length) {
292
- continue;
293
- }
294
- items.push({
295
- type: 'submenu',
296
- submenu,
297
- });
298
- } else { // group node
299
- const submenu = this.buildSubMenus([], item, commands);
300
- if (!submenu.length) {
301
- continue;
302
- }
303
- if (items.length) { // do not put a separator above the first group
304
- items.push({
305
- type: 'separator'
306
- });
307
- }
308
- items.push(...submenu); // render children
288
+ protected buildSubmenusCalled = 0;
289
+
290
+ protected buildSubMenus(parentItems: MenuWidget.IItemOptions[], menu: MenuNode, commands: MenuCommandRegistry): MenuWidget.IItemOptions[] {
291
+ if (CompoundMenuNode.is(menu) && menu.children.length && this.undefinedOrMatch(menu.when, this.options.context)) {
292
+ const role = menu === this.menu ? CompoundMenuNodeRole.Group : CompoundMenuNode.getRole(menu);
293
+ if (role === CompoundMenuNodeRole.Submenu) {
294
+ const submenu = this.services.menuWidgetFactory.createMenuWidget(menu, this.options);
295
+ parentItems.push({ type: 'submenu', submenu });
296
+ } else if (role === CompoundMenuNodeRole.Group && menu.id !== 'inline') {
297
+ const children = CompoundMenuNode.getFlatChildren(menu.children);
298
+ const myItems: MenuWidget.IItemOptions[] = [];
299
+ children.forEach(child => this.buildSubMenus(myItems, child, commands));
300
+ if (myItems.length) {
301
+ if (parentItems.length && parentItems[parentItems.length - 1].type !== 'separator') {
302
+ parentItems.push({ type: 'separator' });
309
303
  }
304
+ parentItems.push(...myItems);
305
+ parentItems.push({ type: 'separator' });
310
306
  }
311
- } else if (item instanceof ActionMenuNode) {
312
- const { context, contextKeyService } = this.services;
313
- const node = item.altNode && context.altPressed ? item.altNode : item;
314
- const { when } = node.action;
315
- if (!(commands.isVisible(node.action.commandId) && (!when || contextKeyService.match(when)))) {
316
- continue;
317
- }
318
- items.push({
319
- command: node.action.commandId,
307
+ }
308
+ } else if (menu.command) {
309
+ const node = menu.altNode && this.services.context.altPressed ? menu.altNode : (menu as MenuNode & CommandMenuNode);
310
+ if (commands.isVisible(node.command) && this.undefinedOrMatch(node.when, this.options.context)) {
311
+ parentItems.push({
312
+ command: node.command,
320
313
  type: 'command'
321
314
  });
322
- } else {
323
- items.push(...this.handleDefault(item));
324
315
  }
325
316
  }
326
- return items;
317
+ return parentItems;
327
318
  }
328
319
 
329
- protected handleDefault(menuNode: MenuNode): MenuWidget.IItemOptions[] {
330
- return [];
320
+ protected undefinedOrMatch(expression?: string, context?: HTMLElement): boolean {
321
+ if (expression) { return this.services.contextKeyService.match(expression, context); }
322
+ return true;
331
323
  }
332
324
 
333
325
  protected preserveFocusedElement(previousFocusedElement: Element | null = document.activeElement): boolean {
@@ -418,19 +410,16 @@ export class BrowserMenuBarContribution implements FrontendApplicationContributi
418
410
  */
419
411
  export class MenuCommandRegistry extends PhosphorCommandRegistry {
420
412
 
421
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
422
- protected actions = new Map<string, [ActionMenuNode, any[]]>();
413
+ protected actions = new Map<string, [MenuNode & CommandMenuNode, unknown[]]>();
423
414
  protected toDispose = new DisposableCollection();
424
415
 
425
416
  constructor(protected services: MenuServices) {
426
417
  super();
427
418
  }
428
419
 
429
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
430
- registerActionMenu(menu: ActionMenuNode, args: any[]): void {
431
- const { commandId } = menu.action;
420
+ registerActionMenu(menu: MenuNode & CommandMenuNode, args: unknown[]): void {
432
421
  const { commandRegistry } = this.services;
433
- const command = commandRegistry.getCommand(commandId);
422
+ const command = commandRegistry.getCommand(menu.command);
434
423
  if (!command) {
435
424
  return;
436
425
  }
@@ -441,18 +430,17 @@ export class MenuCommandRegistry extends PhosphorCommandRegistry {
441
430
  this.actions.set(id, [menu, args]);
442
431
  }
443
432
 
444
- snapshot(): this {
433
+ snapshot(menuPath: MenuPath): this {
445
434
  this.toDispose.dispose();
446
435
  for (const [menu, args] of this.actions.values()) {
447
- this.toDispose.push(this.registerCommand(menu, args));
436
+ this.toDispose.push(this.registerCommand(menu, args, menuPath));
448
437
  }
449
438
  return this;
450
439
  }
451
440
 
452
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
453
- protected registerCommand(menu: ActionMenuNode, args: any[]): Disposable {
454
- const { commandRegistry, keybindingRegistry } = this.services;
455
- const command = commandRegistry.getCommand(menu.action.commandId);
441
+ protected registerCommand(menu: MenuNode & CommandMenuNode, args: unknown[], menuPath: MenuPath): Disposable {
442
+ const { commandRegistry, keybindingRegistry, commandExecutor } = this.services;
443
+ const command = commandRegistry.getCommand(menu.command);
456
444
  if (!command) {
457
445
  return Disposable.NULL;
458
446
  }
@@ -463,11 +451,11 @@ export class MenuCommandRegistry extends PhosphorCommandRegistry {
463
451
  }
464
452
 
465
453
  // We freeze the `isEnabled`, `isVisible`, and `isToggled` states so they won't change.
466
- const enabled = commandRegistry.isEnabled(id, ...args);
467
- const visible = commandRegistry.isVisible(id, ...args);
468
- const toggled = commandRegistry.isToggled(id, ...args);
454
+ const enabled = commandExecutor.isEnabled(menuPath, id, ...args);
455
+ const visible = commandExecutor.isVisible(menuPath, id, ...args);
456
+ const toggled = commandExecutor.isToggled(menuPath, id, ...args);
469
457
  const unregisterCommand = this.addCommand(id, {
470
- execute: () => commandRegistry.executeCommand(id, ...args),
458
+ execute: () => commandExecutor.executeCommand(menuPath, id, ...args),
471
459
  label: menu.label,
472
460
  icon: menu.icon,
473
461
  isEnabled: () => enabled,
@@ -36,6 +36,7 @@ export class ResourceContextKey {
36
36
  protected resourceLangId: ContextKey<string>;
37
37
  protected resourceDirName: ContextKey<string>;
38
38
  protected resourcePath: ContextKey<string>;
39
+ protected resourceSet: ContextKey<boolean>;
39
40
 
40
41
  @postConstruct()
41
42
  protected init(): void {
@@ -46,6 +47,7 @@ export class ResourceContextKey {
46
47
  this.resourceLangId = this.contextKeyService.createKey<string>('resourceLangId', undefined);
47
48
  this.resourceDirName = this.contextKeyService.createKey<string>('resourceDirName', undefined);
48
49
  this.resourcePath = this.contextKeyService.createKey<string>('resourcePath', undefined);
50
+ this.resourceSet = this.contextKeyService.createKey<boolean>('resourceSet', false);
49
51
  }
50
52
 
51
53
  get(): URI | undefined {
@@ -54,13 +56,14 @@ export class ResourceContextKey {
54
56
  }
55
57
 
56
58
  set(resourceUri: URI | undefined): void {
57
- this.resource.set(resourceUri && resourceUri['codeUri']);
58
- this.resourceSchemeKey.set(resourceUri && resourceUri.scheme);
59
- this.resourceFileName.set(resourceUri && resourceUri.path.base);
60
- this.resourceExtname.set(resourceUri && resourceUri.path.ext);
59
+ this.resource.set(resourceUri?.['codeUri']);
60
+ this.resourceSchemeKey.set(resourceUri?.scheme);
61
+ this.resourceFileName.set(resourceUri?.path.base);
62
+ this.resourceExtname.set(resourceUri?.path.ext);
61
63
  this.resourceLangId.set(resourceUri && this.getLanguageId(resourceUri));
62
- this.resourceDirName.set(resourceUri && resourceUri.path.dir.fsPath());
63
- this.resourcePath.set(resourceUri && resourceUri.path.fsPath());
64
+ this.resourceDirName.set(resourceUri?.path.dir.fsPath());
65
+ this.resourcePath.set(resourceUri?.path.fsPath());
66
+ this.resourceSet.set(Boolean(resourceUri));
64
67
  }
65
68
 
66
69
  protected getLanguageId(uri: URI | undefined): string | undefined {
@@ -27,6 +27,7 @@ import { MaybePromise } from '../../common/types';
27
27
  import { ApplicationShell, applicationShellLayoutVersion, ApplicationShellLayoutVersion } from './application-shell';
28
28
  import { CommonCommands } from '../common-frontend-contribution';
29
29
  import { WindowService } from '../window/window-service';
30
+ import { StopReason } from '../../common/frontend-application-state';
30
31
 
31
32
  /**
32
33
  * A contract for widgets that want to store and restore their inner state, between sessions.
@@ -139,7 +140,7 @@ export class ShellLayoutRestorer implements CommandContribution {
139
140
  }
140
141
 
141
142
  protected async resetLayout(): Promise<void> {
142
- if (await this.windowService.isSafeToShutDown()) {
143
+ if (await this.windowService.isSafeToShutDown(StopReason.Reload)) {
143
144
  this.logger.info('>>> Resetting layout...');
144
145
  this.shouldStoreLayout = false;
145
146
  this.storageService.setData(this.storageKey, undefined);
@@ -101,7 +101,6 @@ export class SidePanelToolbar extends BaseWidget {
101
101
  }
102
102
  }
103
103
 
104
- /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
105
104
  showMoreContextMenu(anchor: Anchor): ContextMenuAccess {
106
105
  if (this.toolbar) {
107
106
  return this.toolbar.renderMoreContextMenu(anchor);
@@ -0,0 +1,19 @@
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
+ export * from './tab-bar-toolbar';
18
+ export * from './tab-bar-toolbar-registry';
19
+ export * from './tab-bar-toolbar-types';
@@ -0,0 +1,31 @@
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
+ import { MenuNode, MenuPath } from '../../../common';
18
+ import { NAVIGATION, TabBarToolbarItem } from './tab-bar-toolbar-types';
19
+
20
+ export const TOOLBAR_WRAPPER_ID_SUFFIX = '-as-tabbar-toolbar-item';
21
+
22
+ export class ToolbarMenuNodeWrapper implements TabBarToolbarItem {
23
+ constructor(protected readonly menuNode: MenuNode, readonly group?: string, readonly menuPath?: MenuPath) { }
24
+ get id(): string { return this.menuNode.id + TOOLBAR_WRAPPER_ID_SUFFIX; }
25
+ get command(): string { return this.menuNode.command ?? ''; };
26
+ get icon(): string | undefined { return this.menuNode.icon; }
27
+ get tooltip(): string | undefined { return this.menuNode.label; }
28
+ get when(): string | undefined { return this.menuNode.when; }
29
+ get text(): string | undefined { return (this.group === NAVIGATION || this.group === undefined) ? undefined : this.menuNode.label; }
30
+ }
31
+