@theia/core 1.28.0-next.7 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) 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/message-rpc/rpc-message-encoder.d.ts +12 -11
  126. package/lib/common/message-rpc/rpc-message-encoder.d.ts.map +1 -1
  127. package/lib/common/message-rpc/rpc-message-encoder.js +21 -12
  128. package/lib/common/message-rpc/rpc-message-encoder.js.map +1 -1
  129. package/lib/common/messaging/abstract-connection-provider.d.ts +1 -1
  130. package/lib/common/messaging/abstract-connection-provider.js +3 -3
  131. package/lib/common/quick-pick-service.d.ts +1 -0
  132. package/lib/common/quick-pick-service.d.ts.map +1 -1
  133. package/lib/common/quick-pick-service.js.map +1 -1
  134. package/lib/electron-browser/menu/electron-context-menu-renderer.js +2 -2
  135. package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
  136. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +14 -5
  137. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
  138. package/lib/electron-browser/menu/electron-main-menu-factory.js +71 -82
  139. package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
  140. package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
  141. package/lib/electron-browser/menu/electron-menu-contribution.js +6 -0
  142. package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
  143. package/lib/electron-browser/messaging/electron-ws-connection-provider.js +1 -1
  144. package/lib/electron-browser/window/electron-window-service.js +1 -1
  145. package/lib/electron-browser/window/electron-window-service.js.map +1 -1
  146. package/lib/electron-common/messaging/electron-messages.d.ts +3 -14
  147. package/lib/electron-common/messaging/electron-messages.d.ts.map +1 -1
  148. package/lib/electron-common/messaging/electron-messages.js +3 -16
  149. package/lib/electron-common/messaging/electron-messages.js.map +1 -1
  150. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +3 -3
  151. package/lib/electron-main/messaging/electron-messaging-contribution.js +6 -6
  152. package/package.json +7 -6
  153. package/src/browser/common-frontend-contribution.ts +6 -5
  154. package/src/browser/context-key-service.ts +1 -1
  155. package/src/browser/context-menu-renderer.ts +5 -0
  156. package/src/browser/frontend-application-module.ts +7 -1
  157. package/src/browser/frontend-application.ts +3 -2
  158. package/src/browser/keybinding.spec.ts +13 -3
  159. package/src/browser/keybinding.ts +8 -9
  160. package/src/browser/menu/browser-context-menu-renderer.ts +2 -2
  161. package/src/browser/menu/browser-menu-plugin.ts +74 -86
  162. package/src/browser/resource-context-key.ts +9 -6
  163. package/src/browser/shell/shell-layout-restorer.ts +2 -1
  164. package/src/browser/shell/side-panel-toolbar.ts +0 -1
  165. package/src/browser/shell/tab-bar-toolbar/index.ts +19 -0
  166. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.ts +31 -0
  167. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +170 -0
  168. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.ts +186 -0
  169. package/src/browser/shell/{tab-bar-toolbar.spec.ts → tab-bar-toolbar/tab-bar-toolbar.spec.ts} +2 -2
  170. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +261 -0
  171. package/src/browser/style/alert-messages.css +6 -0
  172. package/src/browser/view-container.ts +1 -10
  173. package/src/browser/widget-manager.spec.ts +14 -0
  174. package/src/browser/widget-manager.ts +2 -1
  175. package/src/browser/window/default-window-service.ts +9 -4
  176. package/src/browser/window/window-service.ts +2 -1
  177. package/src/common/color.ts +3 -0
  178. package/src/common/frontend-application-state.ts +15 -0
  179. package/src/common/menu/action-menu-node.ts +65 -0
  180. package/src/common/menu/composite-menu-node.ts +121 -0
  181. package/src/common/menu/index.ts +21 -0
  182. package/src/common/menu/menu-adapter.ts +103 -0
  183. package/src/common/{menu.ts → menu/menu-model-registry.ts} +61 -222
  184. package/src/common/menu/menu-types.ts +183 -0
  185. package/src/common/{menu.spec.ts → menu/menu.spec.ts} +3 -2
  186. package/src/common/message-rpc/rpc-message-encoder.ts +24 -13
  187. package/src/common/messaging/abstract-connection-provider.ts +4 -4
  188. package/src/common/quick-pick-service.ts +1 -0
  189. package/src/electron-browser/menu/electron-context-menu-renderer.ts +2 -2
  190. package/src/electron-browser/menu/electron-main-menu-factory.ts +82 -96
  191. package/src/electron-browser/menu/electron-menu-contribution.ts +8 -0
  192. package/src/electron-browser/messaging/electron-ws-connection-provider.ts +1 -1
  193. package/src/electron-browser/window/electron-window-service.ts +1 -1
  194. package/src/electron-common/messaging/electron-messages.ts +4 -15
  195. package/src/electron-main/messaging/electron-messaging-contribution.ts +8 -8
  196. package/lib/browser/shell/tab-bar-toolbar.d.ts +0 -186
  197. package/lib/browser/shell/tab-bar-toolbar.d.ts.map +0 -1
  198. package/lib/browser/shell/tab-bar-toolbar.js +0 -362
  199. package/lib/browser/shell/tab-bar-toolbar.js.map +0 -1
  200. package/lib/browser/shell/tab-bar-toolbar.spec.d.ts.map +0 -1
  201. package/lib/browser/shell/tab-bar-toolbar.spec.js.map +0 -1
  202. package/lib/common/menu.d.ts.map +0 -1
  203. package/lib/common/menu.js.map +0 -1
  204. package/lib/common/menu.spec.d.ts.map +0 -1
  205. package/lib/common/menu.spec.js.map +0 -1
  206. package/src/browser/shell/tab-bar-toolbar.tsx +0 -495
@@ -0,0 +1,186 @@
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 * as React from 'react';
18
+ import { ArrayUtils, Event, MenuPath } from '../../../common';
19
+ import { Widget } from '../../widgets';
20
+
21
+ /** Items whose group is exactly 'navigation' will be rendered inline. */
22
+ export const NAVIGATION = 'navigation';
23
+ export const TAB_BAR_TOOLBAR_CONTEXT_MENU = ['TAB_BAR_TOOLBAR_CONTEXT_MENU'];
24
+
25
+ export interface TabBarDelegator extends Widget {
26
+ getTabBarDelegate(): Widget | undefined;
27
+ }
28
+
29
+ export namespace TabBarDelegator {
30
+ export const is = (candidate?: Widget): candidate is TabBarDelegator => {
31
+ if (candidate) {
32
+ const asDelegator = candidate as TabBarDelegator;
33
+ return typeof asDelegator.getTabBarDelegate === 'function';
34
+ }
35
+ return false;
36
+ };
37
+ }
38
+
39
+ interface RegisteredToolbarItem {
40
+ /**
41
+ * The unique ID of the toolbar item.
42
+ */
43
+ id: string;
44
+ }
45
+
46
+ interface RenderedToolbarItem {
47
+ /**
48
+ * Optional icon for the item.
49
+ */
50
+ icon?: string | (() => string);
51
+
52
+ /**
53
+ * Optional text of the item.
54
+ *
55
+ * Strings in the format `$(iconIdentifier~animationType) will be treated as icon references.
56
+ * If the iconIdentifier begins with fa-, Font Awesome icons will be used; otherwise it will be treated as Codicon name.
57
+ *
58
+ * You can find Codicon classnames here: https://microsoft.github.io/vscode-codicons/dist/codicon.html
59
+ * You can find Font Awesome classnames here: http://fontawesome.io/icons/
60
+ * The type of animation can be either `spin` or `pulse`.
61
+ */
62
+ text?: string;
63
+
64
+ /**
65
+ * Optional tooltip for the item.
66
+ */
67
+ tooltip?: string;
68
+ }
69
+
70
+ interface SelfRenderingToolbarItem {
71
+ render(widget?: Widget): React.ReactNode;
72
+ }
73
+
74
+ interface ExecutableToolbarItem {
75
+ /**
76
+ * The command to execute when the item is selected.
77
+ */
78
+ command: string;
79
+ }
80
+
81
+ export interface MenuToolbarItem {
82
+ /**
83
+ * A menu path with which this item is associated.
84
+ * If accompanied by a command, this data will be passed to the {@link MenuCommandExecutor}.
85
+ * If no command is present, this menu will be opened.
86
+ */
87
+ menuPath: MenuPath;
88
+ }
89
+
90
+ interface ConditionalToolbarItem {
91
+ /**
92
+ * https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts
93
+ */
94
+ when?: string;
95
+ /**
96
+ * Checked before the item is shown.
97
+ */
98
+ isVisible?(widget?: Widget): boolean;
99
+ /**
100
+ * When defined, the container tool-bar will be updated if this event is fired.
101
+ *
102
+ * Note: currently, each item of the container toolbar will be re-rendered if any of the items have changed.
103
+ */
104
+ onDidChange?: Event<void>;
105
+ }
106
+
107
+ interface InlineToolbarItemMetadata {
108
+ /**
109
+ * Priority among the items. Can be negative. The smaller the number the left-most the item will be placed in the toolbar. It is `0` by default.
110
+ */
111
+ priority?: number;
112
+ group: 'navigation' | undefined;
113
+ }
114
+
115
+ interface MenuToolbarItemMetadata {
116
+ /**
117
+ * Optional group for the item. Default `navigation`.
118
+ * `navigation` group will be inlined, while all the others will appear in the `...` dropdown.
119
+ * A group in format `submenu_group_1/submenu 1/.../submenu_group_n/ submenu n/item_group` means that the item will be located in a submenu(s) of the `...` dropdown.
120
+ * The submenu's title is named by the submenu section name, e.g. `group/<submenu name>/subgroup`.
121
+ */
122
+ group: string;
123
+ /**
124
+ * Optional ordering string for placing the item within its group
125
+ */
126
+ order?: string;
127
+ }
128
+
129
+ /**
130
+ * Representation of an item in the tab
131
+ */
132
+ export interface TabBarToolbarItem extends RegisteredToolbarItem,
133
+ ExecutableToolbarItem,
134
+ RenderedToolbarItem,
135
+ Omit<ConditionalToolbarItem, 'isVisible'>,
136
+ Pick<InlineToolbarItemMetadata, 'priority'>,
137
+ Partial<MenuToolbarItemMetadata> { }
138
+
139
+ /**
140
+ * Tab-bar toolbar item backed by a `React.ReactNode`.
141
+ * Unlike the `TabBarToolbarItem`, this item is not connected to the command service.
142
+ */
143
+ export interface ReactTabBarToolbarItem extends RegisteredToolbarItem,
144
+ SelfRenderingToolbarItem,
145
+ ConditionalToolbarItem,
146
+ Pick<InlineToolbarItemMetadata, 'priority'>,
147
+ Pick<Partial<MenuToolbarItemMetadata>, 'group'> { }
148
+
149
+ export interface AnyToolbarItem extends RegisteredToolbarItem,
150
+ Partial<ExecutableToolbarItem>,
151
+ Partial<RenderedToolbarItem>,
152
+ Partial<SelfRenderingToolbarItem>,
153
+ Partial<ConditionalToolbarItem>,
154
+ Partial<MenuToolbarItem>,
155
+ Pick<InlineToolbarItemMetadata, 'priority'>,
156
+ Partial<MenuToolbarItemMetadata> { }
157
+
158
+ export interface MenuDelegate extends MenuToolbarItem, Required<Pick<ConditionalToolbarItem, 'isVisible'>> { }
159
+
160
+ export namespace TabBarToolbarItem {
161
+
162
+ /**
163
+ * Compares the items by `priority` in ascending. Undefined priorities will be treated as `0`.
164
+ */
165
+ export const PRIORITY_COMPARATOR = (left: TabBarToolbarItem, right: TabBarToolbarItem) => {
166
+ const leftGroup = left.group ?? NAVIGATION;
167
+ const rightGroup = right.group ?? NAVIGATION;
168
+ if (leftGroup === NAVIGATION && rightGroup !== NAVIGATION) { return ArrayUtils.Sort.LeftBeforeRight; }
169
+ if (rightGroup === NAVIGATION && leftGroup !== NAVIGATION) { return ArrayUtils.Sort.RightBeforeLeft; }
170
+ if (leftGroup !== rightGroup) { return leftGroup.localeCompare(rightGroup); }
171
+ return (left.priority || 0) - (right.priority || 0);
172
+ };
173
+
174
+ export function is(arg: Object | undefined): arg is TabBarToolbarItem {
175
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
176
+ return !!arg && 'command' in arg && typeof (arg as any).command === 'string';
177
+ }
178
+
179
+ }
180
+
181
+ export namespace MenuToolbarItem {
182
+ export function getMenuPath(item: AnyToolbarItem): MenuPath | undefined {
183
+ const asDelegate = item as MenuToolbarItem;
184
+ return Array.isArray(asDelegate.menuPath) ? asDelegate.menuPath : undefined;
185
+ }
186
+ }
@@ -14,11 +14,11 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { enableJSDOM } from '../test/jsdom';
17
+ import { enableJSDOM } from '../../test/jsdom';
18
18
 
19
19
  let disableJSDOM = enableJSDOM();
20
20
  import { expect } from 'chai';
21
- import { TabBarToolbarItem } from './tab-bar-toolbar';
21
+ import { TabBarToolbarItem } from './tab-bar-toolbar-types';
22
22
 
23
23
  disableJSDOM();
24
24
 
@@ -0,0 +1,261 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2018 TypeFox 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 { inject, injectable } from 'inversify';
18
+ import * as React from 'react';
19
+ import { CommandRegistry, CompoundMenuNodeRole, Disposable, DisposableCollection, MenuCommandExecutor, MenuModelRegistry, MenuPath, nls } from '../../../common';
20
+ import { Anchor, ContextMenuAccess, ContextMenuRenderer } from '../../context-menu-renderer';
21
+ import { LabelIcon, LabelParser } from '../../label-parser';
22
+ import { ACTION_ITEM, codicon, ReactWidget, Widget } from '../../widgets';
23
+ import { TabBarToolbarRegistry } from './tab-bar-toolbar-registry';
24
+ import { AnyToolbarItem, ReactTabBarToolbarItem, TabBarDelegator, TabBarToolbarItem, TAB_BAR_TOOLBAR_CONTEXT_MENU } from './tab-bar-toolbar-types';
25
+
26
+ /**
27
+ * Factory for instantiating tab-bar toolbars.
28
+ */
29
+ export const TabBarToolbarFactory = Symbol('TabBarToolbarFactory');
30
+ export interface TabBarToolbarFactory {
31
+ (): TabBarToolbar;
32
+ }
33
+
34
+ /**
35
+ * Tab-bar toolbar widget representing the active [tab-bar toolbar items](TabBarToolbarItem).
36
+ */
37
+ @injectable()
38
+ export class TabBarToolbar extends ReactWidget {
39
+
40
+ protected current: Widget | undefined;
41
+ protected inline = new Map<string, TabBarToolbarItem | ReactTabBarToolbarItem>();
42
+ protected more = new Map<string, TabBarToolbarItem>();
43
+
44
+ @inject(CommandRegistry) protected readonly commands: CommandRegistry;
45
+ @inject(LabelParser) protected readonly labelParser: LabelParser;
46
+ @inject(MenuModelRegistry) protected readonly menus: MenuModelRegistry;
47
+ @inject(MenuCommandExecutor) protected readonly menuCommandExecutor: MenuCommandExecutor;
48
+ @inject(ContextMenuRenderer) protected readonly contextMenuRenderer: ContextMenuRenderer;
49
+ @inject(TabBarToolbarRegistry) protected readonly toolbarRegistry: TabBarToolbarRegistry;
50
+
51
+ constructor() {
52
+ super();
53
+ this.addClass(TabBarToolbar.Styles.TAB_BAR_TOOLBAR);
54
+ this.hide();
55
+ }
56
+
57
+ updateItems(items: Array<TabBarToolbarItem | ReactTabBarToolbarItem>, current: Widget | undefined): void {
58
+ this.inline.clear();
59
+ this.more.clear();
60
+ for (const item of items.sort(TabBarToolbarItem.PRIORITY_COMPARATOR).reverse()) {
61
+ if ('render' in item || item.group === undefined || item.group === 'navigation') {
62
+ this.inline.set(item.id, item);
63
+ } else {
64
+ this.more.set(item.id, item);
65
+ }
66
+ }
67
+ this.setCurrent(current);
68
+ if (!items.length) {
69
+ this.hide();
70
+ }
71
+ this.onRender.push(Disposable.create(() => {
72
+ if (items.length) {
73
+ this.show();
74
+ }
75
+ }));
76
+ this.update();
77
+ }
78
+
79
+ updateTarget(current?: Widget): void {
80
+ const operativeWidget = TabBarDelegator.is(current) ? current.getTabBarDelegate() : current;
81
+ const items = operativeWidget ? this.toolbarRegistry.visibleItems(operativeWidget) : [];
82
+ this.updateItems(items, operativeWidget);
83
+ }
84
+
85
+ protected readonly toDisposeOnSetCurrent = new DisposableCollection();
86
+ protected setCurrent(current: Widget | undefined): void {
87
+ this.toDisposeOnSetCurrent.dispose();
88
+ this.toDispose.push(this.toDisposeOnSetCurrent);
89
+ this.current = current;
90
+ if (current) {
91
+ const resetCurrent = () => {
92
+ this.setCurrent(undefined);
93
+ this.update();
94
+ };
95
+ current.disposed.connect(resetCurrent);
96
+ this.toDisposeOnSetCurrent.push(Disposable.create(() =>
97
+ current.disposed.disconnect(resetCurrent)
98
+ ));
99
+ }
100
+ }
101
+
102
+ protected render(): React.ReactNode {
103
+ return <React.Fragment>
104
+ {this.renderMore()}
105
+ {[...this.inline.values()].map(item => TabBarToolbarItem.is(item) ? this.renderItem(item) : item.render(this.current))}
106
+ </React.Fragment>;
107
+ }
108
+
109
+ protected renderItem(item: AnyToolbarItem): React.ReactNode {
110
+ let innerText = '';
111
+ const classNames = [];
112
+ if (item.text) {
113
+ for (const labelPart of this.labelParser.parse(item.text)) {
114
+ if (typeof labelPart !== 'string' && LabelIcon.is(labelPart)) {
115
+ const className = `fa fa-${labelPart.name}${labelPart.animation ? ' fa-' + labelPart.animation : ''}`;
116
+ classNames.push(...className.split(' '));
117
+ } else {
118
+ innerText = labelPart;
119
+ }
120
+ }
121
+ }
122
+ const command = item.command ? this.commands.getCommand(item.command) : undefined;
123
+ let iconClass = (typeof item.icon === 'function' && item.icon()) || item.icon as string || (command && command.iconClass);
124
+ if (iconClass) {
125
+ iconClass += ` ${ACTION_ITEM}`;
126
+ classNames.push(iconClass);
127
+ }
128
+ const tooltip = item.tooltip || (command && command.label);
129
+ const toolbarItemClassNames = this.getToolbarItemClassNames(command?.id ?? item.command);
130
+ if (item.menuPath && !item.command) { toolbarItemClassNames.push('enabled'); }
131
+ return <div key={item.id}
132
+ className={toolbarItemClassNames.join(' ')}
133
+ onMouseDown={this.onMouseDownEvent}
134
+ onMouseUp={this.onMouseUpEvent}
135
+ onMouseOut={this.onMouseUpEvent} >
136
+ <div id={item.id} className={classNames.join(' ')}
137
+ onClick={this.executeCommand}
138
+ title={tooltip}>{innerText}
139
+ </div>
140
+ </div>;
141
+ }
142
+
143
+ protected getToolbarItemClassNames(commandId: string | undefined): string[] {
144
+ const classNames = [TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM];
145
+ if (commandId) {
146
+ if (this.commandIsEnabled(commandId)) {
147
+ classNames.push('enabled');
148
+ }
149
+ if (this.commandIsToggled(commandId)) {
150
+ classNames.push('toggled');
151
+ }
152
+ }
153
+ return classNames;
154
+ }
155
+
156
+ protected renderMore(): React.ReactNode {
157
+ return !!this.more.size && <div key='__more__' className={TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM + ' enabled'}>
158
+ <div id='__more__' className={codicon('ellipsis', true)} onClick={this.showMoreContextMenu}
159
+ title={nls.localizeByDefault('More Actions...')} />
160
+ </div>;
161
+ }
162
+
163
+ protected showMoreContextMenu = (event: React.MouseEvent) => {
164
+ event.stopPropagation();
165
+ event.preventDefault();
166
+ const anchor = this.toAnchor(event);
167
+ this.renderMoreContextMenu(anchor);
168
+ };
169
+
170
+ protected toAnchor(event: React.MouseEvent): Anchor {
171
+ const itemBox = event.currentTarget.closest('.' + TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM)?.getBoundingClientRect();
172
+ return itemBox ? { y: itemBox.bottom, x: itemBox.left } : event.nativeEvent;
173
+ }
174
+
175
+ renderMoreContextMenu(anchor: Anchor, subpath?: MenuPath): ContextMenuAccess {
176
+ const toDisposeOnHide = new DisposableCollection();
177
+ this.addClass('menu-open');
178
+ toDisposeOnHide.push(Disposable.create(() => this.removeClass('menu-open')));
179
+ if (subpath) {
180
+ toDisposeOnHide.push(this.menus.linkSubmenu(TAB_BAR_TOOLBAR_CONTEXT_MENU, subpath, { role: CompoundMenuNodeRole.Flat, when: '' }));
181
+ } else {
182
+ for (const item of this.more.values() as IterableIterator<AnyToolbarItem>) {
183
+ if (item.menuPath && !item.command) {
184
+ toDisposeOnHide.push(this.menus.linkSubmenu(TAB_BAR_TOOLBAR_CONTEXT_MENU, item.menuPath, { role: CompoundMenuNodeRole.Flat, when: '' }, item.group));
185
+ } else if (item.command) {
186
+ // Register a submenu for the item, if the group is in format `<submenu group>/<submenu name>/.../<item group>`
187
+ if (item.group?.includes('/')) {
188
+ const split = item.group.split('/');
189
+ const paths: string[] = [];
190
+ for (let i = 0; i < split.length - 1; i += 2) {
191
+ paths.push(split[i], split[i + 1]);
192
+ toDisposeOnHide.push(this.menus.registerSubmenu([...TAB_BAR_TOOLBAR_CONTEXT_MENU, ...paths], split[i + 1], { order: item.order }));
193
+ }
194
+ }
195
+ toDisposeOnHide.push(this.menus.registerMenuAction([...TAB_BAR_TOOLBAR_CONTEXT_MENU, ...item.group!.split('/')], {
196
+ label: item.tooltip,
197
+ commandId: item.command,
198
+ when: item.when,
199
+ order: item.order,
200
+ }));
201
+ }
202
+ }
203
+ }
204
+ return this.contextMenuRenderer.render({
205
+ menuPath: TAB_BAR_TOOLBAR_CONTEXT_MENU,
206
+ args: [this.current],
207
+ anchor,
208
+ context: this.current?.node,
209
+ onHide: () => toDisposeOnHide.dispose()
210
+ });
211
+ }
212
+
213
+ shouldHandleMouseEvent(event: MouseEvent): boolean {
214
+ return event.target instanceof Element && this.node.contains(event.target);
215
+ }
216
+
217
+ protected commandIsEnabled(command: string): boolean {
218
+ return this.commands.isEnabled(command, this.current);
219
+ }
220
+
221
+ protected commandIsToggled(command: string): boolean {
222
+ return this.commands.isToggled(command, this.current);
223
+ }
224
+
225
+ protected executeCommand = (e: React.MouseEvent<HTMLElement>) => {
226
+ e.preventDefault();
227
+ e.stopPropagation();
228
+
229
+ const item: AnyToolbarItem | undefined = this.inline.get(e.currentTarget.id);
230
+ if (item?.command && item.menuPath) {
231
+ this.menuCommandExecutor.executeCommand(item.menuPath, item.command, this.current);
232
+ } else if (item?.command) {
233
+ this.commands.executeCommand(item.command, this.current);
234
+ } else if (item?.menuPath) {
235
+ this.renderMoreContextMenu(this.toAnchor(e), item.menuPath);
236
+ }
237
+ this.update();
238
+ };
239
+
240
+ protected onMouseDownEvent = (e: React.MouseEvent<HTMLElement>) => {
241
+ if (e.button === 0) {
242
+ e.currentTarget.classList.add('active');
243
+ }
244
+ };
245
+
246
+ protected onMouseUpEvent = (e: React.MouseEvent<HTMLElement>) => {
247
+ e.currentTarget.classList.remove('active');
248
+ };
249
+
250
+ }
251
+
252
+ export namespace TabBarToolbar {
253
+
254
+ export namespace Styles {
255
+
256
+ export const TAB_BAR_TOOLBAR = 'p-TabBar-toolbar';
257
+ export const TAB_BAR_TOOLBAR_ITEM = 'item';
258
+
259
+ }
260
+
261
+ }
@@ -25,6 +25,12 @@
25
25
  padding-right: 3px;
26
26
  }
27
27
 
28
+ .theia-alert-message-container .theia-message-header,
29
+ .theia-alert-message-container .theia-message-content {
30
+ text-overflow: ellipsis;
31
+ overflow: hidden;
32
+ }
33
+
28
34
  /* information message */
29
35
  .theia-info-alert {
30
36
  background-color: var(--theia-inputValidation-infoBackground);
@@ -282,16 +282,7 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
282
282
  }
283
283
  }
284
284
  this.updateToolbarItems(allParts);
285
- const caption = title?.caption || title?.label;
286
- if (caption) {
287
- this.title.caption = caption;
288
- if (visibleParts.length === 1) {
289
- const partCaption = visibleParts[0].wrapped.title.caption || visibleParts[0].wrapped.title.label;
290
- if (partCaption) {
291
- this.title.caption += ': ' + partCaption;
292
- }
293
- }
294
- }
285
+ this.title.caption = title?.caption || title?.label;
295
286
  if (title.iconClass) {
296
287
  this.title.iconClass = title.iconClass;
297
288
  }
@@ -63,4 +63,18 @@ describe('widget-manager', () => {
63
63
  expect(wA).equals(await widgetManager.getOrCreateWidget('test', 'widgetA'));
64
64
  });
65
65
 
66
+ it('produces the same widget key regardless of object key order', () => {
67
+ const options1 = {
68
+ factoryId: 'a',
69
+ key1: 1,
70
+ key2: 2,
71
+ };
72
+ const options2 = {
73
+ key2: 2,
74
+ key1: 1,
75
+ factoryId: 'a',
76
+ };
77
+ expect(widgetManager['toKey'](options1)).equals(widgetManager['toKey'](options2));
78
+ });
79
+
66
80
  });
@@ -17,6 +17,7 @@
17
17
  import { inject, named, injectable } from 'inversify';
18
18
  import { Widget } from '@phosphor/widgets';
19
19
  import { ILogger, Emitter, Event, ContributionProvider, MaybePromise, WaitUntilEvent } from '../common';
20
+ import stableJsonStringify = require('fast-json-stable-stringify');
20
21
 
21
22
  /* eslint-disable @typescript-eslint/no-explicit-any */
22
23
  export const WidgetFactory = Symbol('WidgetFactory');
@@ -256,7 +257,7 @@ export class WidgetManager {
256
257
  * @returns the widget construction options represented as a string.
257
258
  */
258
259
  protected toKey(options: WidgetConstructionOptions): string {
259
- return JSON.stringify(options);
260
+ return stableJsonStringify(options);
260
261
  }
261
262
 
262
263
  /**
@@ -22,6 +22,7 @@ import { FrontendApplicationContribution, FrontendApplication, OnWillStopAction
22
22
  import { WindowService } from './window-service';
23
23
  import { DEFAULT_WINDOW_HASH } from '../../common/window';
24
24
  import { confirmExit } from '../dialogs';
25
+ import { StopReason } from '../../common/frontend-application-state';
25
26
 
26
27
  @injectable()
27
28
  export class DefaultWindowService implements WindowService, FrontendApplicationContribution {
@@ -97,16 +98,16 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
97
98
  window.addEventListener('unload', () => this.onUnloadEmitter.fire());
98
99
  }
99
100
 
100
- async isSafeToShutDown(): Promise<boolean> {
101
+ async isSafeToShutDown(stopReason: StopReason): Promise<boolean> {
101
102
  const vetoes = this.collectContributionUnloadVetoes();
102
103
  if (vetoes.length === 0) {
103
104
  return true;
104
105
  }
105
- const preparedValues = await Promise.all(vetoes.map(e => e.prepare?.()));
106
+ const preparedValues = await Promise.all(vetoes.map(e => e.prepare?.(stopReason)));
106
107
  console.debug('Shutdown prevented by', vetoes.map(({ reason }) => reason).join(', '));
107
108
  for (let i = 0; i < vetoes.length; i++) {
108
109
  try {
109
- const result = await vetoes[i].action(preparedValues[i]);
110
+ const result = await vetoes[i].action(preparedValues[i], stopReason);
110
111
  if (!result) {
111
112
  return false;
112
113
  }
@@ -156,6 +157,10 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
156
157
  }
157
158
 
158
159
  reload(): void {
159
- window.location.reload();
160
+ this.isSafeToShutDown(StopReason.Reload).then(isSafe => {
161
+ if (isSafe) {
162
+ window.location.reload();
163
+ }
164
+ });
160
165
  }
161
166
  }
@@ -14,6 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
+ import { StopReason } from '../../common/frontend-application-state';
17
18
  import { Event } from '../../common/event';
18
19
  import { NewWindowOptions } from '../../common/window';
19
20
 
@@ -49,7 +50,7 @@ export interface WindowService {
49
50
  * will not be called again in the current session. I.e. if this return `true`, the shutdown should proceed without
50
51
  * further condition.
51
52
  */
52
- isSafeToShutDown(): Promise<boolean>;
53
+ isSafeToShutDown(reason: StopReason): Promise<boolean>;
53
54
 
54
55
  /**
55
56
  * Will prevent subsequent checks of `FrontendApplicationContribution#willStop`. Should only be used after requesting
@@ -85,7 +85,10 @@ export interface HSLA {
85
85
  export interface ColorDefaults {
86
86
  light?: Color
87
87
  dark?: Color
88
+ /** @deprecated @since 1.28.0 Please use hcDark and hcLight. This field will be ignored unless `hcDark` is absent. */
88
89
  hc?: Color
90
+ hcDark?: Color;
91
+ hcLight?: Color;
89
92
  }
90
93
 
91
94
  export interface ColorDefinition {
@@ -21,3 +21,18 @@ export type FrontendApplicationState =
21
21
  | 'initialized_layout'
22
22
  | 'ready'
23
23
  | 'closing_window';
24
+
25
+ export enum StopReason {
26
+ /**
27
+ * Closing the window with no prospect of restart.
28
+ */
29
+ Close,
30
+ /**
31
+ * Reload without closing the window.
32
+ */
33
+ Reload,
34
+ /**
35
+ * Reload that includes closing the window.
36
+ */
37
+ Restart,
38
+ }