Skip to content

Commit 6f80dc1

Browse files
authored
Fix #9779: add support for window.menuBarVisibility (#9830)
Signed-off-by: ChayaLau <[email protected]>
1 parent 5cc8eaf commit 6f80dc1

18 files changed

+406
-125
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
- [vsx-registry] `VSXExtensionsContribution` no longer implements `TabBarToolbarContribution` and is not bound as such. Extensions of the class that expect such behavior should reimplement it with caution. See caveats in PR. [#9798](https://github.com/eclipse-theia/theia/pull/9798)
1414
- [core] `handleExpansionToggleDblClickEvent` in `TreeWidget` can no longer be overridden. Instead, `doHandleExpansionToggleDblClickEvent` can be overridden. [#9877](https://github.com/eclipse-theia/theia/pull/9877)
1515
- [core] `ViewContainerPart` methods and properties related to hiding and showing toolbar removed: `toHideToolbar`, `hideToolbar`, `showToolbar`, `toolbarHidden`. `ViewContainerPart` toolbars are now hidden or shown using CSS properties. [#9935](https://github.com/eclipse-theia/theia/pull/9935)
16+
- [core] `SidePanelHandler.addMenu` and `SidePanelHandler.removeMenu` no longer exists, instead added `addBottomMenu` and `addTopMenu` for adding menu, `removeTopMenu` and `removeBottomMenu` for removing menu.
17+
- `SidebarBottomMenu` interface is renamed `SidebarMenu` and handles not only bottom menu's.
18+
- Changed style class name from `theia-sidebar-bottom-menu` to `theia-sidebar-menu`
19+
- [preferences] `TheiaDockPanel` constructor takes a new parameter `preferences`.
20+
[#9830](https://github.com/eclipse-theia/theia/pull/9830)
1621

1722
## v1.16.0 - 7/29/2021
1823

examples/api-samples/src/electron-browser/updater/sample-updater-frontend-contribution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class ElectronMenuUpdater {
9090
this.setMenu();
9191
}
9292

93-
private setMenu(menu: Menu = this.factory.createMenuBar(), electronWindow: BrowserWindow = remote.getCurrentWindow()): void {
93+
private setMenu(menu: Menu | null = this.factory.createMenuBar(), electronWindow: BrowserWindow = remote.getCurrentWindow()): void {
9494
if (isOSX) {
9595
remote.Menu.setApplicationMenu(menu);
9696
} else {

packages/core/src/browser/common-frontend-contribution.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ import { environment } from '@theia/application-package/lib/environment';
4343
import { IconThemeService } from './icon-theme-service';
4444
import { ColorContribution } from './color-application-contribution';
4545
import { ColorRegistry, Color } from './color-registry';
46-
import { CorePreferences } from './core-preferences';
46+
import { CoreConfiguration, CorePreferences } from './core-preferences';
4747
import { ThemeService } from './theming';
48-
import { PreferenceService, PreferenceScope } from './preferences';
48+
import { PreferenceService, PreferenceScope, PreferenceChangeEvent } from './preferences';
4949
import { ClipboardService } from './clipboard-service';
5050
import { EncodingRegistry } from './encoding-registry';
5151
import { UTF8 } from '../common/encodings';
@@ -358,17 +358,11 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
358358
this.updateStyles();
359359
this.updateThemeFromPreference('workbench.colorTheme');
360360
this.updateThemeFromPreference('workbench.iconTheme');
361-
this.preferences.onPreferenceChanged(e => {
362-
if (e.preferenceName === 'workbench.editor.highlightModifiedTabs') {
363-
this.updateStyles();
364-
} else if (e.preferenceName === 'workbench.colorTheme' || e.preferenceName === 'workbench.iconTheme') {
365-
this.updateThemeFromPreference(e.preferenceName);
366-
}
367-
});
361+
this.preferences.onPreferenceChanged(e => this.handlePreferenceChange(e, app));
368362
this.themeService.onDidColorThemeChange(() => this.updateThemePreference('workbench.colorTheme'));
369363
this.iconThemes.onDidChangeCurrent(() => this.updateThemePreference('workbench.iconTheme'));
370364

371-
app.shell.leftPanelHandler.addMenu({
365+
app.shell.leftPanelHandler.addBottomMenu({
372366
id: 'settings-menu',
373367
iconClass: 'codicon codicon-settings-gear',
374368
title: 'Settings',
@@ -383,11 +377,11 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
383377
order: 1,
384378
};
385379
this.authenticationService.onDidRegisterAuthenticationProvider(() => {
386-
app.shell.leftPanelHandler.addMenu(accountsMenu);
380+
app.shell.leftPanelHandler.addBottomMenu(accountsMenu);
387381
});
388382
this.authenticationService.onDidUnregisterAuthenticationProvider(() => {
389383
if (this.authenticationService.getProviderIds().length === 0) {
390-
app.shell.leftPanelHandler.removeMenu(accountsMenu.id);
384+
app.shell.leftPanelHandler.removeBottomMenu(accountsMenu.id);
391385
}
392386
});
393387
}
@@ -425,6 +419,36 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
425419
}
426420
}
427421

422+
protected handlePreferenceChange(e: PreferenceChangeEvent<CoreConfiguration>, app: FrontendApplication): void {
423+
switch (e.preferenceName) {
424+
case 'workbench.editor.highlightModifiedTabs': {
425+
this.updateStyles();
426+
break;
427+
}
428+
case 'workbench.colorTheme':
429+
case 'workbench.iconTheme': {
430+
this.updateThemeFromPreference(e.preferenceName);
431+
break;
432+
}
433+
case 'window.menuBarVisibility': {
434+
const { newValue } = e;
435+
const mainMenuId = 'main-menu';
436+
if (newValue === 'compact') {
437+
this.shell.leftPanelHandler.addTopMenu({
438+
id: mainMenuId,
439+
iconClass: 'codicon codicon-menu',
440+
title: 'Application Menu',
441+
menuPath: ['menubar'],
442+
order: 0,
443+
});
444+
} else {
445+
app.shell.leftPanelHandler.removeTopMenu(mainMenuId);
446+
}
447+
break;
448+
}
449+
}
450+
}
451+
428452
onStart(): void {
429453
this.storageService.getData<{ recent: Command[] }>(RECENT_COMMANDS_STORAGE_KEY, { recent: [] })
430454
.then(tasks => this.commandRegistry.recent = tasks.recent);

packages/core/src/browser/core-preferences.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { interfaces } from 'inversify';
1818
import { createPreferenceProxy, PreferenceProxy, PreferenceService, PreferenceContribution, PreferenceSchema } from './preferences';
1919
import { SUPPORTED_ENCODINGS } from './supported-encodings';
2020
import { FrontendApplicationConfigProvider } from './frontend-application-config-provider';
21+
import { isOSX } from '../common/os';
2122

2223
export const corePreferenceSchema: PreferenceSchema = {
2324
'type': 'object',
@@ -97,6 +98,21 @@ export const corePreferenceSchema: PreferenceSchema = {
9798
default: 'code',
9899
description: 'Whether to interpret keypresses by the `code` of the physical key, or by the `keyCode` provided by the OS.'
99100
},
101+
'window.menuBarVisibility': {
102+
type: 'string',
103+
enum: ['classic', 'visible', 'hidden', 'compact'],
104+
markdownEnumDescriptions: [
105+
'Menu is displayed at the top of the window and only hidden in full screen mode.',
106+
'Menu is always visible at the top of the window even in full screen mode.',
107+
'Menu is always hidden.',
108+
'Menu is displayed as a compact button in the sidebar.'
109+
],
110+
default: 'classic',
111+
scope: 'application',
112+
markdownDescription: `Control the visibility of the menu bar.
113+
A setting of 'compact' will move the menu into the sidebar.`,
114+
included: !isOSX
115+
},
100116
}
101117
};
102118

@@ -112,6 +128,7 @@ export interface CoreConfiguration {
112128
'workbench.silentNotifications': boolean;
113129
'files.encoding': string
114130
'workbench.tree.renderIndentGuides': 'onHover' | 'none' | 'always';
131+
'window.menuBarVisibility': 'classic' | 'visible' | 'hidden' | 'compact';
115132
}
116133

117134
export const CorePreferenceContribution = Symbol('CorePreferenceContribution');

packages/core/src/browser/frontend-application-module.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ import {
4343
ApplicationShell, ApplicationShellOptions, DockPanelRenderer, TabBarRenderer,
4444
TabBarRendererFactory, ShellLayoutRestorer,
4545
SidePanelHandler, SidePanelHandlerFactory,
46-
SidebarBottomMenuWidget, SidebarBottomMenuWidgetFactory,
47-
SplitPositionHandler, DockPanelRendererFactory, ApplicationShellLayoutMigration, ApplicationShellLayoutMigrationError
46+
SidebarMenuWidget, SidebarTopMenuWidgetFactory,
47+
SplitPositionHandler, DockPanelRendererFactory, ApplicationShellLayoutMigration, ApplicationShellLayoutMigrationError, SidebarBottomMenuWidgetFactory
4848
} from './shell';
4949
import { StatusBar, StatusBarImpl } from './status-bar/status-bar';
5050
import { LabelParser } from './label-parser';
@@ -104,6 +104,7 @@ import {
104104
} from './quick-input';
105105
import { QuickAccessContribution } from './quick-input/quick-access';
106106
import { QuickCommandService } from './quick-input/quick-command-service';
107+
import { SidebarBottomMenuWidget } from './shell/sidebar-bottom-menu-widget';
107108

108109
export { bindResourceProvider, bindMessageService, bindPreferenceService };
109110

@@ -133,8 +134,10 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo
133134
bind(ApplicationShell).toSelf().inSingletonScope();
134135
bind(SidePanelHandlerFactory).toAutoFactory(SidePanelHandler);
135136
bind(SidePanelHandler).toSelf();
136-
bind(SidebarBottomMenuWidgetFactory).toAutoFactory(SidebarBottomMenuWidget);
137+
bind(SidebarTopMenuWidgetFactory).toAutoFactory(SidebarMenuWidget);
138+
bind(SidebarMenuWidget).toSelf();
137139
bind(SidebarBottomMenuWidget).toSelf();
140+
bind(SidebarBottomMenuWidgetFactory).toAutoFactory(SidebarBottomMenuWidget);
138141
bind(SplitPositionHandler).toSelf().inSingletonScope();
139142

140143
bindContributionProvider(bind, TabBarToolbarContribution);

packages/core/src/browser/menu/browser-menu-plugin.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { ContextKeyService } from '../context-key-service';
2727
import { ContextMenuContext } from './context-menu-context';
2828
import { waitForRevealed } from '../widgets';
2929
import { ApplicationShell } from '../shell';
30+
import { CorePreferences } from '../core-preferences';
3031

3132
export abstract class MenuBarWidget extends MenuBar {
3233
abstract activateMenu(label: string, ...labels: string[]): Promise<MenuWidget>;
@@ -45,6 +46,9 @@ export class BrowserMainMenuFactory implements MenuWidgetFactory {
4546
@inject(CommandRegistry)
4647
protected readonly commandRegistry: CommandRegistry;
4748

49+
@inject(CorePreferences)
50+
protected readonly corePreferences: CorePreferences;
51+
4852
@inject(KeybindingRegistry)
4953
protected readonly keybindingRegistry: KeybindingRegistry;
5054

@@ -54,15 +58,31 @@ export class BrowserMainMenuFactory implements MenuWidgetFactory {
5458
createMenuBar(): MenuBarWidget {
5559
const menuBar = new DynamicMenuBarWidget();
5660
menuBar.id = 'theia:menubar';
57-
this.fillMenuBar(menuBar);
58-
const listener = this.keybindingRegistry.onKeybindingsChanged(() => {
59-
menuBar.clearMenus();
60-
this.fillMenuBar(menuBar);
61+
const preferenceListener = this.corePreferences.onPreferenceChanged(preference => {
62+
if (preference.preferenceName === 'window.menuBarVisibility') {
63+
this.showMenuBar(menuBar, preference.newValue);
64+
}
65+
});
66+
const keybindingListener = this.keybindingRegistry.onKeybindingsChanged(() => {
67+
const preference = this.corePreferences['window.menuBarVisibility'];
68+
this.showMenuBar(menuBar, preference);
69+
});
70+
menuBar.disposed.connect(() => {
71+
preferenceListener.dispose();
72+
keybindingListener.dispose();
6173
});
62-
menuBar.disposed.connect(() => listener.dispose());
6374
return menuBar;
6475
}
6576

77+
protected showMenuBar(menuBar: DynamicMenuBarWidget, preference: string | undefined): void {
78+
if (preference && ['classic', 'visible'].includes(preference)) {
79+
menuBar.clearMenus();
80+
this.fillMenuBar(menuBar);
81+
} else {
82+
menuBar.clearMenus();
83+
}
84+
}
85+
6686
protected fillMenuBar(menuBar: MenuBarWidget): void {
6787
const menuModel = this.menuProvider.getMenu(MAIN_MENU_BAR);
6888
const menuCommandRegistry = this.createMenuCommandRegistry(menuModel);

packages/core/src/browser/shell/application-shell.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import { TabBarToolbarRegistry, TabBarToolbarFactory, TabBarToolbar } from './ta
3636
import { ContextKeyService } from '../context-key-service';
3737
import { Emitter } from '../../common/event';
3838
import { waitForRevealed, waitForClosed } from '../widgets';
39+
import { CorePreferences } from '../core-preferences';
40+
import { environment } from '../../common';
3941

4042
/** The class name added to ApplicationShell instances. */
4143
const APPLICATION_SHELL_CLASS = 'theia-ApplicationShell';
@@ -204,7 +206,8 @@ export class ApplicationShell extends Widget {
204206
@inject(SidePanelHandlerFactory) sidePanelHandlerFactory: () => SidePanelHandler,
205207
@inject(SplitPositionHandler) protected splitPositionHandler: SplitPositionHandler,
206208
@inject(FrontendApplicationStateService) protected readonly applicationStateService: FrontendApplicationStateService,
207-
@inject(ApplicationShellOptions) @optional() options: RecursivePartial<ApplicationShell.Options> = {}
209+
@inject(ApplicationShellOptions) @optional() options: RecursivePartial<ApplicationShell.Options> = {},
210+
@inject(CorePreferences) protected readonly corePreferences: CorePreferences
208211
) {
209212
super(options as Widget.IOptions);
210213
this.addClass(APPLICATION_SHELL_CLASS);
@@ -250,6 +253,17 @@ export class ApplicationShell extends Widget {
250253
protected init(): void {
251254
this.initSidebarVisibleKeyContext();
252255
this.initFocusKeyContexts();
256+
257+
if (!environment.electron.is()) {
258+
this.corePreferences.ready.then(() => {
259+
this.setTopPanelVisibily(this.corePreferences['window.menuBarVisibility']);
260+
});
261+
this.corePreferences.onPreferenceChanged(preference => {
262+
if (preference.preferenceName === 'window.menuBarVisibility') {
263+
this.setTopPanelVisibily(preference.newValue);
264+
}
265+
});
266+
}
253267
}
254268

255269
protected initSidebarVisibleKeyContext(): void {
@@ -279,6 +293,11 @@ export class ApplicationShell extends Widget {
279293
this.activeChanged.connect(updateFocusContextKeys);
280294
}
281295

296+
protected setTopPanelVisibily(preference: string): void {
297+
const hiddenPreferences = ['compact', 'hidden'];
298+
this.topPanel.setHidden(hiddenPreferences.includes(preference));
299+
}
300+
282301
protected onBeforeAttach(msg: Message): void {
283302
document.addEventListener('p-dragenter', this, true);
284303
document.addEventListener('p-dragover', this, true);
@@ -448,7 +467,7 @@ export class ApplicationShell extends Widget {
448467
mode: 'multiple-document',
449468
renderer,
450469
spacing: 0
451-
});
470+
}, this.corePreferences);
452471
dockPanel.id = MAIN_AREA_ID;
453472
dockPanel.widgetAdded.connect((_, widget) => this.fireDidAddWidget(widget));
454473
dockPanel.widgetRemoved.connect((_, widget) => this.fireDidRemoveWidget(widget));
@@ -466,7 +485,7 @@ export class ApplicationShell extends Widget {
466485
mode: 'multiple-document',
467486
renderer,
468487
spacing: 0
469-
});
488+
}, this.corePreferences);
470489
dockPanel.id = BOTTOM_AREA_ID;
471490
dockPanel.widgetAdded.connect((sender, widget) => {
472491
this.refreshBottomPanelToggleButton();
@@ -493,6 +512,7 @@ export class ApplicationShell extends Widget {
493512
protected createTopPanel(): Panel {
494513
const topPanel = new Panel();
495514
topPanel.id = 'theia-top-panel';
515+
topPanel.hide();
496516
return topPanel;
497517
}
498518

packages/core/src/browser/shell/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
export * from './application-shell';
1818
export * from './shell-layout-restorer';
1919
export * from './side-panel-handler';
20-
export * from './sidebar-bottom-menu-widget';
20+
export * from './sidebar-menu-widget';
2121
export * from './split-panels';
2222
export * from './tab-bars';
2323
export * from './view-contribution';

0 commit comments

Comments
 (0)