@theia/core 1.18.0 → 1.19.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 (200) hide show
  1. package/README.md +3 -2
  2. package/lib/browser/about-dialog.d.ts.map +1 -1
  3. package/lib/browser/about-dialog.js +1 -1
  4. package/lib/browser/about-dialog.js.map +1 -1
  5. package/lib/browser/authentication-service.d.ts.map +1 -1
  6. package/lib/browser/authentication-service.js +1 -1
  7. package/lib/browser/authentication-service.js.map +1 -1
  8. package/lib/browser/common-frontend-contribution.d.ts +6 -0
  9. package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
  10. package/lib/browser/common-frontend-contribution.js +122 -118
  11. package/lib/browser/common-frontend-contribution.js.map +1 -1
  12. package/lib/browser/core-preferences.d.ts +1 -0
  13. package/lib/browser/core-preferences.d.ts.map +1 -1
  14. package/lib/browser/core-preferences.js +25 -18
  15. package/lib/browser/core-preferences.js.map +1 -1
  16. package/lib/browser/dialogs.d.ts +6 -0
  17. package/lib/browser/dialogs.d.ts.map +1 -1
  18. package/lib/browser/dialogs.js +10 -3
  19. package/lib/browser/dialogs.js.map +1 -1
  20. package/lib/browser/frontend-application-module.d.ts.map +1 -1
  21. package/lib/browser/frontend-application-module.js +3 -0
  22. package/lib/browser/frontend-application-module.js.map +1 -1
  23. package/lib/browser/frontend-application.d.ts +6 -0
  24. package/lib/browser/frontend-application.d.ts.map +1 -1
  25. package/lib/browser/frontend-application.js +13 -0
  26. package/lib/browser/frontend-application.js.map +1 -1
  27. package/lib/browser/index.d.ts +1 -0
  28. package/lib/browser/index.d.ts.map +1 -1
  29. package/lib/browser/index.js +1 -0
  30. package/lib/browser/index.js.map +1 -1
  31. package/lib/browser/keyboard/browser-keyboard-frontend-contribution.d.ts.map +1 -1
  32. package/lib/browser/keyboard/browser-keyboard-frontend-contribution.js +16 -11
  33. package/lib/browser/keyboard/browser-keyboard-frontend-contribution.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-menu-plugin.d.ts +3 -0
  37. package/lib/browser/menu/browser-menu-plugin.d.ts.map +1 -1
  38. package/lib/browser/menu/browser-menu-plugin.js +24 -4
  39. package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
  40. package/lib/browser/nls-loader.d.ts +17 -0
  41. package/lib/browser/nls-loader.d.ts.map +1 -0
  42. package/lib/browser/nls-loader.js +29 -0
  43. package/lib/browser/nls-loader.js.map +1 -0
  44. package/lib/browser/progress-status-bar-item.d.ts +1 -2
  45. package/lib/browser/progress-status-bar-item.d.ts.map +1 -1
  46. package/lib/browser/progress-status-bar-item.js.map +1 -1
  47. package/lib/browser/quick-input/quick-command-frontend-contribution.d.ts.map +1 -1
  48. package/lib/browser/quick-input/quick-command-frontend-contribution.js +2 -1
  49. package/lib/browser/quick-input/quick-command-frontend-contribution.js.map +1 -1
  50. package/lib/browser/quick-input/quick-command-service.d.ts.map +1 -1
  51. package/lib/browser/quick-input/quick-command-service.js +2 -2
  52. package/lib/browser/quick-input/quick-command-service.js.map +1 -1
  53. package/lib/browser/quick-input/quick-view-service.d.ts +1 -2
  54. package/lib/browser/quick-input/quick-view-service.d.ts.map +1 -1
  55. package/lib/browser/quick-input/quick-view-service.js.map +1 -1
  56. package/lib/browser/shell/application-shell.d.ts +3 -1
  57. package/lib/browser/shell/application-shell.d.ts.map +1 -1
  58. package/lib/browser/shell/application-shell.js +1 -2
  59. package/lib/browser/shell/application-shell.js.map +1 -1
  60. package/lib/browser/shell/shell-layout-restorer.d.ts.map +1 -1
  61. package/lib/browser/shell/shell-layout-restorer.js +5 -3
  62. package/lib/browser/shell/shell-layout-restorer.js.map +1 -1
  63. package/lib/browser/shell/tab-bar-decorator.d.ts +1 -1
  64. package/lib/browser/shell/tab-bar-decorator.d.ts.map +1 -1
  65. package/lib/browser/shell/tab-bar-decorator.js.map +1 -1
  66. package/lib/browser/shell/tab-bar-toolbar.d.ts.map +1 -1
  67. package/lib/browser/shell/tab-bar-toolbar.js +2 -1
  68. package/lib/browser/shell/tab-bar-toolbar.js.map +1 -1
  69. package/lib/browser/shell/tab-bars.d.ts +14 -1
  70. package/lib/browser/shell/tab-bars.d.ts.map +1 -1
  71. package/lib/browser/shell/tab-bars.js +99 -7
  72. package/lib/browser/shell/tab-bars.js.map +1 -1
  73. package/lib/browser/tooltip-service.d.ts +52 -0
  74. package/lib/browser/tooltip-service.d.ts.map +1 -0
  75. package/lib/browser/tooltip-service.js +89 -0
  76. package/lib/browser/tooltip-service.js.map +1 -0
  77. package/lib/browser/tree/tree-model.d.ts.map +1 -1
  78. package/lib/browser/view-container.d.ts +55 -14
  79. package/lib/browser/view-container.d.ts.map +1 -1
  80. package/lib/browser/view-container.js +284 -66
  81. package/lib/browser/view-container.js.map +1 -1
  82. package/lib/browser/window/default-window-service.js +2 -2
  83. package/lib/browser/window/default-window-service.js.map +1 -1
  84. package/lib/browser/window/window-service.d.ts +1 -7
  85. package/lib/browser/window/window-service.d.ts.map +1 -1
  86. package/lib/browser/window/window-service.js +1 -5
  87. package/lib/browser/window/window-service.js.map +1 -1
  88. package/lib/browser/window-contribution.d.ts.map +1 -1
  89. package/lib/browser/window-contribution.js +2 -2
  90. package/lib/browser/window-contribution.js.map +1 -1
  91. package/lib/common/command.d.ts.map +1 -1
  92. package/lib/common/command.js +1 -2
  93. package/lib/common/command.js.map +1 -1
  94. package/lib/common/i18n/localization.d.ts +5 -0
  95. package/lib/common/i18n/localization.d.ts.map +1 -1
  96. package/lib/common/i18n/localization.js +43 -1
  97. package/lib/common/i18n/localization.js.map +1 -1
  98. package/lib/common/index.d.ts +1 -0
  99. package/lib/common/index.d.ts.map +1 -1
  100. package/lib/common/index.js +1 -0
  101. package/lib/common/index.js.map +1 -1
  102. package/lib/{browser → common}/nls.d.ts +3 -2
  103. package/lib/common/nls.d.ts.map +1 -0
  104. package/lib/common/nls.js +29 -0
  105. package/lib/common/nls.js.map +1 -0
  106. package/lib/common/window.d.ts +29 -0
  107. package/lib/common/window.d.ts.map +1 -0
  108. package/lib/common/window.js +23 -0
  109. package/lib/common/window.js.map +1 -0
  110. package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts +9 -5
  111. package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts.map +1 -1
  112. package/lib/electron-browser/menu/electron-context-menu-renderer.js +40 -15
  113. package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
  114. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +5 -8
  115. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
  116. package/lib/electron-browser/menu/electron-main-menu-factory.js +10 -17
  117. package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
  118. package/lib/electron-browser/menu/electron-menu-contribution.d.ts +15 -7
  119. package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
  120. package/lib/electron-browser/menu/electron-menu-contribution.js +112 -42
  121. package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
  122. package/lib/electron-browser/window/electron-window-preferences.d.ts +1 -0
  123. package/lib/electron-browser/window/electron-window-preferences.d.ts.map +1 -1
  124. package/lib/electron-browser/window/electron-window-preferences.js +12 -1
  125. package/lib/electron-browser/window/electron-window-preferences.js.map +1 -1
  126. package/lib/electron-browser/window/electron-window-service.d.ts +1 -1
  127. package/lib/electron-browser/window/electron-window-service.d.ts.map +1 -1
  128. package/lib/electron-common/electron-main-window-service.d.ts +1 -1
  129. package/lib/electron-common/electron-main-window-service.d.ts.map +1 -1
  130. package/lib/electron-common/electron-main-window-service.js.map +1 -1
  131. package/lib/electron-common/messaging/electron-messages.d.ts +20 -0
  132. package/lib/electron-common/messaging/electron-messages.d.ts.map +1 -0
  133. package/lib/electron-common/messaging/electron-messages.js +23 -0
  134. package/lib/electron-common/messaging/electron-messages.js.map +1 -0
  135. package/lib/electron-main/electron-main-application.d.ts +6 -0
  136. package/lib/electron-main/electron-main-application.d.ts.map +1 -1
  137. package/lib/electron-main/electron-main-application.js +80 -24
  138. package/lib/electron-main/electron-main-application.js.map +1 -1
  139. package/lib/electron-main/electron-main-window-service-impl.d.ts +1 -1
  140. package/lib/electron-main/electron-main-window-service-impl.d.ts.map +1 -1
  141. package/lib/electron-main/electron-main-window-service-impl.js.map +1 -1
  142. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +1 -1
  143. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts.map +1 -1
  144. package/lib/electron-main/messaging/electron-messaging-contribution.js +1 -2
  145. package/lib/electron-main/messaging/electron-messaging-contribution.js.map +1 -1
  146. package/package.json +6 -4
  147. package/shared/@theia/application-package/lib/api.d.ts +1 -0
  148. package/shared/@theia/application-package/lib/api.js +1 -0
  149. package/src/browser/about-dialog.tsx +2 -2
  150. package/src/browser/authentication-service.ts +1 -2
  151. package/src/browser/common-frontend-contribution.ts +99 -95
  152. package/src/browser/core-preferences.ts +28 -18
  153. package/src/browser/dialogs.ts +10 -3
  154. package/src/browser/frontend-application-module.ts +4 -0
  155. package/src/browser/frontend-application.ts +13 -0
  156. package/src/browser/index.ts +1 -0
  157. package/src/browser/keyboard/browser-keyboard-frontend-contribution.ts +16 -11
  158. package/src/browser/menu/browser-context-menu-renderer.ts +1 -1
  159. package/src/browser/menu/browser-menu-plugin.ts +25 -5
  160. package/src/browser/nls-loader.ts +26 -0
  161. package/src/browser/progress-status-bar-item.ts +1 -2
  162. package/src/browser/quick-input/quick-command-frontend-contribution.ts +2 -2
  163. package/src/browser/quick-input/quick-command-service.ts +2 -2
  164. package/src/browser/quick-input/quick-view-service.ts +1 -2
  165. package/src/browser/shell/application-shell.ts +4 -3
  166. package/src/browser/shell/shell-layout-restorer.ts +4 -3
  167. package/src/browser/shell/tab-bar-decorator.ts +1 -1
  168. package/src/browser/shell/tab-bar-toolbar.tsx +3 -1
  169. package/src/browser/shell/tab-bars.ts +103 -8
  170. package/src/browser/style/index.css +5 -0
  171. package/src/browser/style/sidepanel.css +8 -2
  172. package/src/browser/style/tabs.css +30 -0
  173. package/src/browser/style/tooltip.css +28 -0
  174. package/src/browser/style/view-container.css +9 -9
  175. package/src/browser/tooltip-service.tsx +98 -0
  176. package/src/browser/tree/tree-model.ts +1 -1
  177. package/src/browser/view-container.ts +312 -80
  178. package/src/browser/window/default-window-service.ts +1 -1
  179. package/src/browser/window/window-service.ts +1 -9
  180. package/src/browser/window-contribution.ts +2 -2
  181. package/src/common/command.ts +1 -2
  182. package/src/common/i18n/localization.ts +44 -0
  183. package/src/common/index.ts +1 -0
  184. package/src/common/nls.ts +30 -0
  185. package/src/common/window.ts +30 -0
  186. package/src/electron-browser/menu/electron-context-menu-renderer.ts +38 -16
  187. package/src/electron-browser/menu/electron-main-menu-factory.ts +10 -15
  188. package/src/electron-browser/menu/electron-menu-contribution.ts +129 -39
  189. package/src/electron-browser/menu/electron-menu-style.css +84 -0
  190. package/src/electron-browser/window/electron-window-preferences.ts +13 -1
  191. package/src/electron-browser/window/electron-window-service.ts +1 -1
  192. package/src/electron-common/electron-main-window-service.ts +1 -2
  193. package/src/electron-common/messaging/electron-messages.ts +20 -0
  194. package/src/electron-main/electron-main-application.ts +85 -21
  195. package/src/electron-main/electron-main-window-service-impl.ts +1 -2
  196. package/src/electron-main/messaging/electron-messaging-contribution.ts +1 -2
  197. package/lib/browser/nls.d.ts.map +0 -1
  198. package/lib/browser/nls.js +0 -64
  199. package/lib/browser/nls.js.map +0 -1
  200. package/src/browser/nls.ts +0 -65
@@ -25,6 +25,7 @@ import { FrontendApplicationStateService } from './frontend-application-state';
25
25
  import { preventNavigation, parseCssTime, animationFrame } from './browser';
26
26
  import { CorePreferences } from './core-preferences';
27
27
  import { WindowService } from './window/window-service';
28
+ import { TooltipService } from './tooltip-service';
28
29
 
29
30
  /**
30
31
  * Clients can implement to get a callback for contributing widgets to a shell on start.
@@ -100,6 +101,9 @@ export class FrontendApplication {
100
101
  @inject(WindowService)
101
102
  protected readonly windowsService: WindowService;
102
103
 
104
+ @inject(TooltipService)
105
+ protected readonly tooltipService: TooltipService;
106
+
103
107
  constructor(
104
108
  @inject(CommandRegistry) protected readonly commands: CommandRegistry,
105
109
  @inject(MenuModelRegistry) protected readonly menus: MenuModelRegistry,
@@ -130,6 +134,7 @@ export class FrontendApplication {
130
134
 
131
135
  const host = await this.getHost();
132
136
  this.attachShell(host);
137
+ this.attachTooltip(host);
133
138
  await animationFrame();
134
139
  this.stateService.state = 'attached_shell';
135
140
 
@@ -221,6 +226,13 @@ export class FrontendApplication {
221
226
  Widget.attach(this.shell, host, ref);
222
227
  }
223
228
 
229
+ /**
230
+ * Attach the tooltip container to the host element.
231
+ */
232
+ protected attachTooltip(host: HTMLElement): void {
233
+ this.tooltipService.attachTo(host);
234
+ }
235
+
224
236
  /**
225
237
  * If a startup indicator is present, it is first hidden with the `theia-hidden` CSS class and then
226
238
  * removed after a while. The delay until removal is taken from the CSS transition duration.
@@ -231,6 +243,7 @@ export class FrontendApplication {
231
243
  return new Promise(resolve => {
232
244
  window.requestAnimationFrame(() => {
233
245
  startupElem.classList.add('theia-hidden');
246
+ console.log(`Finished loading frontend application after ${(performance.now() / 1000).toFixed(3)} seconds`);
234
247
  const preloadStyle = window.getComputedStyle(startupElem);
235
248
  const transitionDuration = parseCssTime(preloadStyle.transitionDuration, 0);
236
249
  window.setTimeout(() => {
@@ -40,3 +40,4 @@ export * from './diff-uris';
40
40
  export * from './core-preferences';
41
41
  export * from './view-container';
42
42
  export * from './breadcrumbs';
43
+ export * from './tooltip-service';
@@ -19,16 +19,18 @@ import { isOSX } from '../../common/os';
19
19
  import { CommandContribution, CommandRegistry, Command } from '../../common/command';
20
20
  import { BrowserKeyboardLayoutProvider, KeyboardLayoutData } from './browser-keyboard-layout-provider';
21
21
  import { QuickPickValue, QuickInputService, QuickPickItem } from '../quick-input';
22
+ import { nls } from '../../common/nls';
22
23
 
23
24
  export namespace KeyboardCommands {
24
25
 
26
+ const KEYBOARD_CATEGORY_KEY = 'vscode/settingsLayout/keyboard';
25
27
  const KEYBOARD_CATEGORY = 'Keyboard';
26
28
 
27
- export const CHOOSE_KEYBOARD_LAYOUT: Command = {
29
+ export const CHOOSE_KEYBOARD_LAYOUT = Command.toLocalizedCommand({
28
30
  id: 'core.keyboard.choose',
29
31
  category: KEYBOARD_CATEGORY,
30
32
  label: 'Choose Keyboard Layout',
31
- };
33
+ }, 'theia/core/keyboard/choose', KEYBOARD_CATEGORY_KEY);
32
34
 
33
35
  }
34
36
 
@@ -50,9 +52,9 @@ export class BrowserKeyboardFrontendContribution implements CommandContribution
50
52
  protected async chooseLayout(): Promise<KeyboardLayoutData | undefined> {
51
53
  const current = this.layoutProvider.currentLayoutData;
52
54
  const autodetect: QuickPickValue<'autodetect'> = {
53
- label: 'Auto-detect',
54
- description: this.layoutProvider.currentLayoutSource !== 'user-choice' ? `(current: ${current.name})` : undefined,
55
- detail: 'Try to detect the keyboard layout from browser information and pressed keys.',
55
+ label: nls.localize('vscode/editorStatus/autoDetect', 'Auto-detect'),
56
+ description: this.layoutProvider.currentLayoutSource !== 'user-choice' ? nls.localize('theia/core/keyboard/current', '(current: {0})', current.name) : undefined,
57
+ detail: nls.localize('theia/core/keyboard/tryDetect', 'Try to detect the keyboard layout from browser information and pressed keys.'),
56
58
  value: 'autodetect'
57
59
  };
58
60
  const pcLayouts = this.layoutProvider.allLayoutData
@@ -64,20 +66,22 @@ export class BrowserKeyboardFrontendContribution implements CommandContribution
64
66
  .sort((a, b) => compare(a.name, b.name))
65
67
  .map(layout => this.toQuickPickValue(layout, current === layout));
66
68
  let layouts: Array<QuickPickValue<KeyboardLayoutData | 'autodetect'> | QuickPickItem>;
69
+ const macKeyboards = nls.localize('theia/core/keyboard/mac', 'Mac Keyboards');
70
+ const pcKeyboards = nls.localize('theia/core/keyboard/pc', 'PC Keyboards');
67
71
  if (isOSX) {
68
72
  layouts = [
69
73
  autodetect,
70
- { type: 'separator', label: 'Mac Keyboards' }, ...macLayouts,
71
- { type: 'separator', label: 'PC Keyboards' }, ...pcLayouts
74
+ { type: 'separator', label: macKeyboards }, ...macLayouts,
75
+ { type: 'separator', label: pcKeyboards }, ...pcLayouts
72
76
  ];
73
77
  } else {
74
78
  layouts = [
75
79
  autodetect,
76
- { type: 'separator', label: 'PC Keyboards' }, ...pcLayouts,
77
- { type: 'separator', label: 'Mac Keyboards' }, ...macLayouts
80
+ { type: 'separator', label: pcKeyboards }, ...pcLayouts,
81
+ { type: 'separator', label: macKeyboards }, ...macLayouts
78
82
  ];
79
83
  }
80
- const selectedItem = await this.quickInputService?.showQuickPick(layouts, { placeholder: 'Choose a keyboard layout' });
84
+ const selectedItem = await this.quickInputService?.showQuickPick(layouts, { placeholder: nls.localize('theia/core/keyboard/chooseLayout', 'Choose a keyboard layout') });
81
85
  if (selectedItem && ('value' in selectedItem)) {
82
86
  return this.layoutProvider.setLayoutData(selectedItem.value);
83
87
  }
@@ -86,7 +90,8 @@ export class BrowserKeyboardFrontendContribution implements CommandContribution
86
90
  protected toQuickPickValue(layout: KeyboardLayoutData, isCurrent: boolean): QuickPickValue<KeyboardLayoutData> {
87
91
  return {
88
92
  label: layout.name,
89
- description: `${layout.hardware === 'mac' ? 'Mac' : 'PC'} (${layout.language})${isCurrent ? ' - current layout' : ''}`,
93
+ description:
94
+ `${layout.hardware === 'mac' ? 'Mac' : 'PC'} (${layout.language})${isCurrent ? nls.localize('theia/core/keyboard/currentLayout', ' - current layout') : ''}`,
90
95
  value: layout
91
96
  };
92
97
  }
@@ -36,7 +36,7 @@ export class BrowserContextMenuRenderer extends ContextMenuRenderer {
36
36
  super();
37
37
  }
38
38
 
39
- protected doRender({ menuPath, anchor, args, onHide }: RenderContextMenuOptions): BrowserContextMenuAccess {
39
+ protected doRender({ menuPath, anchor, args, onHide }: RenderContextMenuOptions): ContextMenuAccess {
40
40
  const contextMenu = this.menuFactory.createContextMenu(menuPath, args);
41
41
  const { x, y } = coordinateFromAnchor(anchor);
42
42
  if (onHide) {
@@ -18,7 +18,7 @@ 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,
21
+ CommandRegistry, ActionMenuNode, CompositeMenuNode, environment,
22
22
  MenuModelRegistry, MAIN_MENU_BAR, MenuPath, DisposableCollection, Disposable, MenuNode
23
23
  } from '../../common';
24
24
  import { KeybindingRegistry } from '../keybinding';
@@ -28,6 +28,7 @@ import { ContextMenuContext } from './context-menu-context';
28
28
  import { waitForRevealed } from '../widgets';
29
29
  import { ApplicationShell } from '../shell';
30
30
  import { CorePreferences } from '../core-preferences';
31
+ import { PreferenceService } from '../preferences/preference-service';
31
32
 
32
33
  export abstract class MenuBarWidget extends MenuBar {
33
34
  abstract activateMenu(label: string, ...labels: string[]): Promise<MenuWidget>;
@@ -371,21 +372,40 @@ export class BrowserMenuBarContribution implements FrontendApplicationContributi
371
372
  @inject(ApplicationShell)
372
373
  protected readonly shell: ApplicationShell;
373
374
 
375
+ @inject(PreferenceService)
376
+ protected readonly preferenceService: PreferenceService;
377
+
374
378
  constructor(
375
379
  @inject(BrowserMainMenuFactory) protected readonly factory: BrowserMainMenuFactory
376
380
  ) { }
377
381
 
378
382
  onStart(app: FrontendApplication): void {
379
- const logo = this.createLogo();
380
- app.shell.addWidget(logo, { area: 'top' });
381
- const menu = this.factory.createMenuBar();
382
- app.shell.addWidget(menu, { area: 'top' });
383
+ this.appendMenu(app.shell);
383
384
  }
384
385
 
385
386
  get menuBar(): MenuBarWidget | undefined {
386
387
  return this.shell.topPanel.widgets.find(w => w instanceof MenuBarWidget) as MenuBarWidget | undefined;
387
388
  }
388
389
 
390
+ protected appendMenu(shell: ApplicationShell): void {
391
+ const logo = this.createLogo();
392
+ shell.addWidget(logo, { area: 'top' });
393
+ const menu = this.factory.createMenuBar();
394
+ shell.addWidget(menu, { area: 'top' });
395
+ // Hiding the menu is only necessary in electron
396
+ // In the browser we hide the whole top panel
397
+ if (environment.electron.is()) {
398
+ this.preferenceService.ready.then(() => {
399
+ menu.setHidden(['compact', 'hidden'].includes(this.preferenceService.get('window.menuBarVisibility', '')));
400
+ });
401
+ this.preferenceService.onPreferenceChanged(change => {
402
+ if (change.preferenceName === 'window.menuBarVisibility') {
403
+ menu.setHidden(['compact', 'hidden'].includes(change.newValue));
404
+ }
405
+ });
406
+ }
407
+ }
408
+
389
409
  protected createLogo(): Widget {
390
410
  const logo = new Widget();
391
411
  logo.id = 'theia:icon';
@@ -0,0 +1,26 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 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 { nls } from '../common/nls';
18
+ import { Endpoint } from './endpoint';
19
+
20
+ export async function loadTranslations(): Promise<void> {
21
+ if (nls.locale) {
22
+ const endpoint = new Endpoint({ path: '/i18n/' + nls.locale }).getRestUrl().toString();
23
+ const response = await fetch(endpoint);
24
+ nls.localization = await response.json();
25
+ }
26
+ }
@@ -16,8 +16,7 @@
16
16
 
17
17
  import { injectable, inject } from 'inversify';
18
18
  import { CancellationToken } from 'vscode-ws-jsonrpc';
19
- import { ProgressClient } from '../common';
20
- import { ProgressMessage, ProgressUpdate } from '../common';
19
+ import { ProgressClient, ProgressMessage, ProgressUpdate } from '../common';
21
20
  import { StatusBar, StatusBarAlignment } from './status-bar';
22
21
  import { Deferred } from '../common/promise-util';
23
22
  import throttle = require('lodash.throttle');
@@ -14,7 +14,7 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
  import { injectable, inject, optional } from 'inversify';
17
- import { CommandRegistry, CommandContribution, MenuContribution, MenuModelRegistry } from '../../common';
17
+ import { CommandRegistry, CommandContribution, MenuContribution, MenuModelRegistry, nls } from '../../common';
18
18
  import { KeybindingRegistry, KeybindingContribution } from '../keybinding';
19
19
  import { CommonMenus } from '../common-frontend-contribution';
20
20
  import { CLEAR_COMMAND_HISTORY, quickCommand, QuickCommandService } from './quick-command-service';
@@ -43,7 +43,7 @@ export class QuickCommandFrontendContribution implements CommandContribution, Ke
43
43
  registerMenus(menus: MenuModelRegistry): void {
44
44
  menus.registerMenuAction(CommonMenus.VIEW_PRIMARY, {
45
45
  commandId: quickCommand.id,
46
- label: 'Find Command...'
46
+ label: nls.localize('vscode/quickAccess.contribution/commandsQuickAccess', 'Find Command...')
47
47
  });
48
48
  }
49
49
 
@@ -28,10 +28,10 @@ export const quickCommand: Command = {
28
28
  id: 'workbench.action.showCommands'
29
29
  };
30
30
 
31
- export const CLEAR_COMMAND_HISTORY: Command = {
31
+ export const CLEAR_COMMAND_HISTORY = Command.toLocalizedCommand({
32
32
  id: 'clear.command.history',
33
33
  label: 'Clear Command History'
34
- };
34
+ }, 'vscode/commandsQuickAccess/clearCommandHistory');
35
35
 
36
36
  @injectable()
37
37
  export class QuickCommandService implements QuickAccessContribution, QuickAccessProvider {
@@ -18,8 +18,7 @@ import { inject, injectable } from 'inversify';
18
18
  import { filterItems, QuickPickItem, QuickPicks } from '..';
19
19
  import { CancellationToken, Disposable } from '../../common';
20
20
  import { ContextKeyService } from '../context-key-service';
21
- import { QuickAccessProvider, QuickAccessRegistry } from './quick-access';
22
- import { QuickAccessContribution } from './quick-access';
21
+ import { QuickAccessContribution, QuickAccessProvider, QuickAccessRegistry } from './quick-access';
23
22
 
24
23
  export interface QuickViewItem {
25
24
  readonly label: string;
@@ -23,7 +23,7 @@ import {
23
23
  } from '@phosphor/widgets';
24
24
  import { Message } from '@phosphor/messaging';
25
25
  import { IDragEvent } from '@phosphor/dragdrop';
26
- import { RecursivePartial, Event as CommonEvent, DisposableCollection, Disposable } from '../../common';
26
+ import { RecursivePartial, Event as CommonEvent, DisposableCollection, Disposable, environment } from '../../common';
27
27
  import { animationFrame } from '../browser';
28
28
  import { Saveable, SaveableWidget, SaveOptions } from '../saveable';
29
29
  import { StatusBarImpl, StatusBarEntry, StatusBarAlignment } from '../status-bar/status-bar';
@@ -37,7 +37,6 @@ import { ContextKeyService } from '../context-key-service';
37
37
  import { Emitter } from '../../common/event';
38
38
  import { waitForRevealed, waitForClosed } from '../widgets';
39
39
  import { CorePreferences } from '../core-preferences';
40
- import { environment } from '../../common';
41
40
  import { BreadcrumbsRendererFactory } from '../breadcrumbs/breadcrumbs-renderer';
42
41
 
43
42
  /** The class name added to ApplicationShell instances. */
@@ -59,7 +58,9 @@ export type ApplicationShellLayoutVersion =
59
58
  /** git history view is replaced by a more generic scm history view, backward compatible to 3.0 */
60
59
  4.0 |
61
60
  /** Replace custom/font-awesome icons with codicons */
62
- 5.0;
61
+ 5.0 |
62
+ /** added the ability to drag and drop view parts between view containers */
63
+ 6.0;
63
64
 
64
65
  /**
65
66
  * When a version is increased, make sure to introduce a migration (ApplicationShellLayoutMigration) to this version.
@@ -25,6 +25,7 @@ import { ThemeService } from '../theming';
25
25
  import { ContributionProvider } from '../../common/contribution-provider';
26
26
  import { MaybePromise } from '../../common/types';
27
27
  import { ApplicationShell, applicationShellLayoutVersion, ApplicationShellLayoutVersion } from './application-shell';
28
+ import { CommonCommands } from '../common-frontend-contribution';
28
29
 
29
30
  /**
30
31
  * A contract for widgets that want to store and restore their inner state, between sessions.
@@ -109,11 +110,11 @@ export interface ApplicationShellLayoutMigration {
109
110
  onWillInflateWidget?(desc: WidgetDescription, context: ApplicationShellLayoutMigrationContext): MaybePromise<WidgetDescription | undefined>;
110
111
  }
111
112
 
112
- export const RESET_LAYOUT: Command = {
113
+ export const RESET_LAYOUT = Command.toLocalizedCommand({
113
114
  id: 'reset.layout',
114
- category: 'View',
115
+ category: CommonCommands.VIEW_CATEGORY,
115
116
  label: 'Reset Workbench Layout'
116
- };
117
+ }, 'theia/core/resetWorkbenchLayout', CommonCommands.VIEW_CATEGORY_KEY);
117
118
 
118
119
  @injectable()
119
120
  export class ShellLayoutRestorer implements CommandContribution {
@@ -57,7 +57,7 @@ export class TabBarDecoratorService implements FrontendApplicationContribution {
57
57
  this.contributions.getContributions().map(decorator => decorator.onDidChangeDecorations(this.fireDidChangeDecorations));
58
58
  }
59
59
 
60
- protected fireDidChangeDecorations = debounce(() => this.onDidChangeDecorationsEmitter.fire(undefined), 150);
60
+ fireDidChangeDecorations = debounce(() => this.onDidChangeDecorationsEmitter.fire(undefined), 150);
61
61
 
62
62
  /**
63
63
  * Assign tabs the decorators provided by all the contributions.
@@ -27,6 +27,7 @@ import { ContextKeyService } from '../context-key-service';
27
27
  import { Event, Emitter } from '../../common/event';
28
28
  import { ContextMenuRenderer, Anchor } from '../context-menu-renderer';
29
29
  import { MenuModelRegistry } from '../../common/menu';
30
+ import { nls } from '../../common/nls';
30
31
 
31
32
  /**
32
33
  * Clients should implement this interface if they want to contribute to the tab-bar toolbar.
@@ -403,7 +404,8 @@ export class TabBarToolbar extends ReactWidget {
403
404
 
404
405
  protected renderMore(): React.ReactNode {
405
406
  return !!this.more.size && <div key='__more__' className={TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM + ' enabled'}>
406
- <div id='__more__' className={codicon('ellipsis', true)} onClick={this.showMoreContextMenu} title='More Actions...' />
407
+ <div id='__more__' className={codicon('ellipsis', true)} onClick={this.showMoreContextMenu}
408
+ title={nls.localize('vscode/compositePart/viewsAndMoreActions', 'More Actions...')} />
407
409
  </div>;
408
410
  }
409
411
 
@@ -30,6 +30,7 @@ import { TabBarDecoratorService } from './tab-bar-decorator';
30
30
  import { IconThemeService } from '../icon-theme-service';
31
31
  import { BreadcrumbsRenderer, BreadcrumbsRendererFactory } from '../breadcrumbs/breadcrumbs-renderer';
32
32
  import { NavigatableWidget } from '../navigatable-types';
33
+ import { IDragEvent } from '@phosphor/dragdrop';
33
34
 
34
35
  /** The class name added to hidden content nodes, which are required to render vertical side bars. */
35
36
  const HIDDEN_CONTENT_CLASS = 'theia-TabBar-hidden-content';
@@ -229,11 +230,11 @@ export class TabBarRenderer extends TabBar.Renderer {
229
230
  }
230
231
 
231
232
  renderBadge(data: SideBarRenderData, isInSidePanel?: boolean): VirtualElement {
232
- const badge: number | undefined = this.getDecorationData(data.title, 'badge')[0];
233
- if (!badge) {
233
+ const totalBadge = this.getDecorationData(data.title, 'badge').reduce((sum, badge) => sum! + badge!, 0);
234
+ if (!totalBadge) {
234
235
  return h.div({});
235
236
  }
236
- const limitedBadge = badge >= 100 ? '99+' : badge;
237
+ const limitedBadge = totalBadge >= 100 ? '99+' : totalBadge;
237
238
  return isInSidePanel
238
239
  ? h.div({ className: 'theia-badge-decorator-sidebar' }, `${limitedBadge}`)
239
240
  : h.div({ className: 'theia-badge-decorator-horizontal' }, `${limitedBadge}`);
@@ -279,7 +280,6 @@ export class TabBarRenderer extends TabBar.Renderer {
279
280
  */
280
281
  protected getDecorationData<K extends keyof WidgetDecoration.Data>(title: Title<Widget>, key: K): WidgetDecoration.Data[K][] {
281
282
  return this.getDecorations(title).filter(data => data[key] !== undefined).map(data => data[key]);
282
-
283
283
  }
284
284
 
285
285
  /**
@@ -383,8 +383,8 @@ export class TabBarRenderer extends TabBar.Renderer {
383
383
  * @param {SideBarRenderData} data Data used to render the tab icon.
384
384
  * @param {boolean} isInSidePanel An optional check which determines if the tab is in the side-panel.
385
385
  */
386
- renderIcon(data: SideBarRenderData, inSidePanel?: boolean): VirtualElement {
387
- if (!inSidePanel && this.iconThemeService && this.iconThemeService.current === 'none') {
386
+ renderIcon(data: SideBarRenderData, isInSidePanel?: boolean): VirtualElement {
387
+ if (!isInSidePanel && this.iconThemeService && this.iconThemeService.current === 'none') {
388
388
  return h.div();
389
389
  }
390
390
  let top: string | undefined;
@@ -401,13 +401,13 @@ export class TabBarRenderer extends TabBar.Renderer {
401
401
  if (decorationData.length > 0) {
402
402
  const baseIcon: VirtualElement = h.div({ className: baseClassName, style }, data.title.iconLabel);
403
403
  const wrapperClassName: string = WidgetDecoration.Styles.ICON_WRAPPER_CLASS;
404
- const decoratorSizeClassName: string = inSidePanel ? WidgetDecoration.Styles.DECORATOR_SIDEBAR_SIZE_CLASS : WidgetDecoration.Styles.DECORATOR_SIZE_CLASS;
404
+ const decoratorSizeClassName: string = isInSidePanel ? WidgetDecoration.Styles.DECORATOR_SIDEBAR_SIZE_CLASS : WidgetDecoration.Styles.DECORATOR_SIZE_CLASS;
405
405
 
406
406
  decorationData
407
407
  .filter(notEmpty)
408
408
  .map(overlay => [overlay.position, overlay] as [WidgetDecoration.IconOverlayPosition, WidgetDecoration.IconOverlay | WidgetDecoration.IconClassOverlay])
409
409
  .forEach(([position, overlay]) => {
410
- const iconAdditionalClasses: string[] = [decoratorSizeClassName, WidgetDecoration.IconOverlayPosition.getStyle(position, inSidePanel)];
410
+ const iconAdditionalClasses: string[] = [decoratorSizeClassName, WidgetDecoration.IconOverlayPosition.getStyle(position, isInSidePanel)];
411
411
  const overlayIconStyle = (color?: string) => {
412
412
  if (color === undefined) {
413
413
  return {};
@@ -772,6 +772,18 @@ export class SideTabBar extends ScrollableTabBar {
772
772
  protected onAfterAttach(msg: Message): void {
773
773
  super.onAfterAttach(msg);
774
774
  this.renderTabBar();
775
+ this.node.addEventListener('p-dragenter', this);
776
+ this.node.addEventListener('p-dragover', this);
777
+ this.node.addEventListener('p-dragleave', this);
778
+ document.addEventListener('p-drop', this);
779
+ }
780
+
781
+ protected onAfterDetach(msg: Message): void {
782
+ super.onAfterDetach(msg);
783
+ this.node.removeEventListener('p-dragenter', this);
784
+ this.node.removeEventListener('p-dragover', this);
785
+ this.node.removeEventListener('p-dragleave', this);
786
+ document.removeEventListener('p-drop', this);
775
787
  }
776
788
 
777
789
  protected onUpdateRequest(msg: Message): void {
@@ -869,6 +881,15 @@ export class SideTabBar extends ScrollableTabBar {
869
881
  this.onMouseMove(event as MouseEvent);
870
882
  super.handleEvent(event);
871
883
  break;
884
+ case 'p-dragenter':
885
+ this.onDragEnter(event as IDragEvent);
886
+ break;
887
+ case 'p-dragover':
888
+ this.onDragOver(event as IDragEvent);
889
+ break;
890
+ case 'p-dragleave': case 'p-drop':
891
+ this.cancelViewContainerDND();
892
+ break;
872
893
  default:
873
894
  super.handleEvent(event);
874
895
  }
@@ -934,4 +955,78 @@ export class SideTabBar extends ScrollableTabBar {
934
955
  }
935
956
  }
936
957
 
958
+ toCancelViewContainerDND = new DisposableCollection();
959
+ protected cancelViewContainerDND = () => {
960
+ this.toCancelViewContainerDND.dispose();
961
+ };
962
+
963
+ /**
964
+ * Handles `viewContainerPart` drag enter.
965
+ */
966
+ protected onDragEnter = (event: IDragEvent) => {
967
+ this.cancelViewContainerDND();
968
+ if (event.mimeData.getData('application/vnd.phosphor.view-container-factory')) {
969
+ event.preventDefault();
970
+ event.stopPropagation();
971
+ }
972
+ };
973
+
974
+ /**
975
+ * Handle `viewContainerPart` drag over,
976
+ * Defines the appropriate `drpAction` and opens the tab on which the mouse stands on for more than 800 ms.
977
+ */
978
+ protected onDragOver = (event: IDragEvent) => {
979
+ const factory = event.mimeData.getData('application/vnd.phosphor.view-container-factory');
980
+ const widget = factory && factory();
981
+ if (!widget) {
982
+ event.dropAction = 'none';
983
+ return;
984
+ }
985
+ event.preventDefault();
986
+ event.stopPropagation();
987
+ if (!this.toCancelViewContainerDND.disposed) {
988
+ event.dropAction = event.proposedAction;
989
+ return;
990
+ }
991
+
992
+ const { target, clientX, clientY } = event;
993
+ if (target instanceof HTMLElement) {
994
+ if (widget.options.disableDraggingToOtherContainers || widget.viewContainer.disableDNDBetweenContainers) {
995
+ event.dropAction = 'none';
996
+ target.classList.add('theia-cursor-no-drop');
997
+ this.toCancelViewContainerDND.push(Disposable.create(() => {
998
+ target.classList.remove('theia-cursor-no-drop');
999
+ }));
1000
+ } else {
1001
+ event.dropAction = event.proposedAction;
1002
+ }
1003
+ const { top, bottom, left, right, height } = target.getBoundingClientRect();
1004
+ const mouseOnTop = (clientY - top) < (height / 2);
1005
+ const dropTargetClass = `drop-target-${mouseOnTop ? 'top' : 'bottom'}`;
1006
+ const tabs = this.contentNode.children;
1007
+ const targetTab = ArrayExt.findFirstValue(tabs, t => ElementExt.hitTest(t, clientX, clientY));
1008
+ if (!targetTab) {
1009
+ return;
1010
+ }
1011
+ targetTab.classList.add(dropTargetClass);
1012
+ this.toCancelViewContainerDND.push(Disposable.create(() => {
1013
+ if (targetTab) {
1014
+ targetTab.classList.remove(dropTargetClass);
1015
+ }
1016
+ }));
1017
+ const openTabTimer = setTimeout(() => {
1018
+ const title = this.titles.find(t => (this.renderer as TabBarRenderer).createTabId(t) === targetTab.id);
1019
+ if (title) {
1020
+ const mouseStillOnTab = clientX >= left && clientX <= right && clientY >= top && clientY <= bottom;
1021
+ if (mouseStillOnTab) {
1022
+ this.currentTitle = title;
1023
+ }
1024
+ }
1025
+ }, 800);
1026
+ this.toCancelViewContainerDND.push(Disposable.create(() => {
1027
+ clearTimeout(openTabTimer);
1028
+ }));
1029
+ }
1030
+ };
1031
+
937
1032
  }
@@ -235,6 +235,10 @@ button.secondary[disabled], .theia-button.secondary[disabled] {
235
235
  z-index: 999;
236
236
  }
237
237
 
238
+ .theia-cursor-no-drop, .theia-cursor-no-drop:active {
239
+ cursor: no-drop;
240
+ }
241
+
238
242
  /*-----------------------------------------------------------------------------
239
243
  | Import children style files
240
244
  |----------------------------------------------------------------------------*/
@@ -259,3 +263,4 @@ button.secondary[disabled], .theia-button.secondary[disabled] {
259
263
  @import './quick-title-bar.css';
260
264
  @import './progress-bar.css';
261
265
  @import './breadcrumbs.css';
266
+ @import './tooltip.css';
@@ -128,6 +128,11 @@
128
128
  -webkit-mask-position: 50% 50%;
129
129
  }
130
130
 
131
+ /* inactive legacy/plugin icons */
132
+ .p-TabBar.theia-app-sides .p-TabBar-tabIcon:not(.codicon) {
133
+ background: var(--theia-activityBar-inactiveForeground);
134
+ }
135
+
131
136
  /* inactive file icons */
132
137
  .p-TabBar.theia-app-sides .file-icon.p-TabBar-tabIcon {
133
138
  background: inherit !important;
@@ -144,8 +149,9 @@
144
149
  color: var(--theia-activityBar-foreground);
145
150
  }
146
151
 
147
- .p-TabBar.theia-app-sides .p-TabBar-tabIcon.theia-plugin-view-container:hover,
148
- .p-TabBar.theia-app-sides .p-mod-current .p-TabBar-tabIcon.theia-plugin-view-container {
152
+ /* active legacy/plugin icons */
153
+ .p-TabBar.theia-app-sides .p-TabBar-tabIcon:not(.codicon):hover,
154
+ .p-TabBar.theia-app-sides .p-mod-current .p-TabBar-tabIcon:not(.codicon) {
149
155
  background-color: var(--theia-activityBar-foreground);
150
156
  }
151
157
 
@@ -10,6 +10,7 @@
10
10
  --theia-tabbar-toolbar-z-index: 1001;
11
11
  --theia-toolbar-active-transform-scale: 1.272019649;
12
12
  --theia-horizontal-toolbar-height: calc(var(--theia-private-horizontal-tab-height) + var(--theia-private-horizontal-tab-scrollbar-rail-height) / 2);
13
+ --theia-dragover-tab-border-width: 2px;
13
14
  }
14
15
 
15
16
  /*-----------------------------------------------------------------------------
@@ -39,6 +40,19 @@
39
40
  align-items: center;
40
41
  }
41
42
 
43
+ .p-TabBar[data-orientation='vertical'] .p-TabBar-tab {
44
+ border-top: var(--theia-dragover-tab-border-width) solid transparent !important;
45
+ border-bottom: var(--theia-dragover-tab-border-width) solid transparent !important;
46
+ }
47
+
48
+ .p-TabBar[data-orientation='vertical'] .p-TabBar-tab.drop-target-top {
49
+ border-top-color: var(--theia-activityBar-activeBorder) !important;
50
+ }
51
+
52
+ .p-TabBar[data-orientation='vertical'] .p-TabBar-tab.drop-target-bottom {
53
+ border-bottom-color: var(--theia-activityBar-activeBorder) !important;
54
+ }
55
+
42
56
  .p-TabBar[data-orientation='horizontal'] .p-TabBar-tab .theia-tab-icon-label,
43
57
  .p-TabBar-tab.p-mod-drag-image .theia-tab-icon-label {
44
58
  display: flex;
@@ -185,11 +199,13 @@ body.theia-editor-highlightModifiedTabs
185
199
  background-repeat: no-repeat;
186
200
  }
187
201
 
202
+ /* common icons */
188
203
  .p-TabBar.theia-app-centers .p-TabBar-tabIcon,
189
204
  .p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon {
190
205
  min-height: 14px;
191
206
  background-size: 13px;
192
207
  background-position-y: 3px;
208
+ background: var(--theia-icon-foreground);
193
209
  -webkit-mask-repeat: no-repeat;
194
210
  -webkit-mask-size: auto 13px;
195
211
  mask-repeat: no-repeat;
@@ -197,6 +213,20 @@ body.theia-editor-highlightModifiedTabs
197
213
  padding-right: 8px;
198
214
  }
199
215
 
216
+ /* codicons */
217
+ .p-TabBar.theia-app-centers .p-TabBar-tabIcon.codicon,
218
+ .p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon.codicon {
219
+ background: none;
220
+ }
221
+
222
+ /* file icons */
223
+ .p-TabBar[data-orientation='horizontal'] .p-TabBar-tabIcon.file-icon,
224
+ .p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon.file-icon {
225
+ background: none;
226
+ padding-bottom: 0px;
227
+ min-height: 20px;
228
+ }
229
+
200
230
  .p-TabBar[data-orientation='horizontal'] .p-TabBar-tabIcon.fa,
201
231
  .p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon.fa {
202
232
  background: none;