Skip to content

Commit

Permalink
fix #8226: support sidebar bottom menu and add settings menu to the left
Browse files Browse the repository at this point in the history
Signed-off-by: 二凢 <dingyu.wdy@alibaba-inc.com>
  • Loading branch information
datou0412 authored and akosyakov committed Aug 26, 2020
1 parent d25a279 commit d7f9163
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 7 deletions.
24 changes: 21 additions & 3 deletions packages/core/src/browser/common-frontend-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import debounce = require('lodash.debounce');
import { injectable, inject } from 'inversify';
import { TabBar, Widget, Title } from '@phosphor/widgets';
import { MAIN_MENU_BAR, MenuContribution, MenuModelRegistry } from '../common/menu';
import { MAIN_MENU_BAR, SETTINGS_MENU, MenuContribution, MenuModelRegistry } from '../common/menu';
import { KeybindingContribution, KeybindingRegistry } from './keybinding';
import { FrontendApplicationContribution } from './frontend-application';
import { FrontendApplication, FrontendApplicationContribution } from './frontend-application';
import { CommandContribution, CommandRegistry, Command } from '../common/command';
import { UriAwareCommandHandler } from '../common/uri-command-handler';
import { SelectionService } from '../common/selection-service';
Expand Down Expand Up @@ -76,6 +76,9 @@ export namespace CommonMenus {
export const VIEW_LAYOUT = [...VIEW, '2_layout'];
export const VIEW_TOGGLE = [...VIEW, '3_toggle'];

export const SETTINGS_OPEN = [...SETTINGS_MENU, '1_settings_open'];
export const SETTINGS__THEME = [...SETTINGS_MENU, '2_settings_theme'];

// last menu item
export const HELP = [...MAIN_MENU_BAR, '9_help'];

Expand Down Expand Up @@ -324,7 +327,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
@inject(EnvVariablesServer)
protected readonly environments: EnvVariablesServer;

async configure(): Promise<void> {
async configure(app: FrontendApplication): Promise<void> {
const configDirUri = await this.environments.getConfigDirUri();
// Global settings
this.encodingRegistry.registerOverride({
Expand All @@ -351,6 +354,14 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
});
this.themeService.onThemeChange(() => this.updateThemePreference('workbench.colorTheme'));
this.iconThemes.onDidChangeCurrent(() => this.updateThemePreference('workbench.iconTheme'));

app.shell.leftPanelHandler.addMenu({
id: 'settings-menu',
iconClass: 'codicon codicon-settings-gear',
title: 'Settings',
menuPath: SETTINGS_MENU,
order: 0,
});
}

protected updateStyles(): void {
Expand Down Expand Up @@ -515,6 +526,13 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
registry.registerMenuAction(CommonMenus.FILE_SETTINGS_SUBMENU_THEME, {
commandId: CommonCommands.SELECT_ICON_THEME.id
});

registry.registerMenuAction(CommonMenus.SETTINGS__THEME, {
commandId: CommonCommands.SELECT_COLOR_THEME.id
});
registry.registerMenuAction(CommonMenus.SETTINGS__THEME, {
commandId: CommonCommands.SELECT_ICON_THEME.id
});
}

registerCommands(commandRegistry: CommandRegistry): void {
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/browser/frontend-application-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
ApplicationShell, ApplicationShellOptions, DockPanelRenderer, TabBarRenderer,
TabBarRendererFactory, ShellLayoutRestorer,
SidePanelHandler, SidePanelHandlerFactory,
SidebarBottomMenuWidget, SidebarBottomMenuWidgetFactory,
SplitPositionHandler, DockPanelRendererFactory, ApplicationShellLayoutMigration, ApplicationShellLayoutMigrationError
} from './shell';
import { StatusBar, StatusBarImpl } from './status-bar/status-bar';
Expand Down Expand Up @@ -128,6 +129,8 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo
bind(ApplicationShell).toSelf().inSingletonScope();
bind(SidePanelHandlerFactory).toAutoFactory(SidePanelHandler);
bind(SidePanelHandler).toSelf();
bind(SidebarBottomMenuWidgetFactory).toAutoFactory(SidebarBottomMenuWidget);
bind(SidebarBottomMenuWidget).toSelf();
bind(SplitPositionHandler).toSelf().inSingletonScope();

bindContributionProvider(bind, TabBarToolbarContribution);
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/browser/shell/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
export * from './application-shell';
export * from './shell-layout-restorer';
export * from './side-panel-handler';
export * from './sidebar-bottom-menu-widget';
export * from './split-panels';
export * from './tab-bars';
export * from './view-contribution';
36 changes: 33 additions & 3 deletions packages/core/src/browser/shell/side-panel-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@

import { injectable, inject } from 'inversify';
import { find, map, toArray, some } from '@phosphor/algorithm';
import { TabBar, Widget, DockPanel, Title, Panel, BoxPanel, BoxLayout, SplitPanel } from '@phosphor/widgets';
import { TabBar, Widget, DockPanel, Title, Panel, BoxPanel, BoxLayout, SplitPanel, PanelLayout } from '@phosphor/widgets';
import { MimeData } from '@phosphor/coreutils';
import { Drag } from '@phosphor/dragdrop';
import { AttachedProperty } from '@phosphor/properties';
import { TabBarRendererFactory, TabBarRenderer, SHELL_TABBAR_CONTEXT_MENU, SideTabBar } from './tab-bars';
import { SidebarBottomMenuWidget, SidebarBottomMenuWidgetFactory, SidebarBottomMenu } from './sidebar-bottom-menu-widget';
import { SplitPositionHandler, SplitPositionOptions } from './split-panels';
import { animationFrame } from '../browser';
import { FrontendApplicationStateService } from '../frontend-application-state';
Expand Down Expand Up @@ -64,6 +65,12 @@ export class SidePanelHandler {
* tab bar itself remains visible as long as there is at least one widget.
*/
tabBar: SideTabBar;
/**
* The menu placed on the sidebar bottom.
* Displayed as icons.
* Open menus when on clicks.
*/
bottomMenu: SidebarBottomMenuWidget;
/**
* A tool bar, which displays a title and widget specific command buttons.
*/
Expand Down Expand Up @@ -100,6 +107,7 @@ export class SidePanelHandler {
@inject(TabBarToolbarRegistry) protected tabBarToolBarRegistry: TabBarToolbarRegistry;
@inject(TabBarToolbarFactory) protected tabBarToolBarFactory: () => TabBarToolbar;
@inject(TabBarRendererFactory) protected tabBarRendererFactory: () => TabBarRenderer;
@inject(SidebarBottomMenuWidgetFactory) protected sidebarBottomWidgetFactory: () => SidebarBottomMenuWidget;
@inject(SplitPositionHandler) protected splitPositionHandler: SplitPositionHandler;
@inject(FrontendApplicationStateService) protected readonly applicationStateService: FrontendApplicationStateService;

Expand All @@ -113,6 +121,7 @@ export class SidePanelHandler {
this.side = side;
this.options = options;
this.tabBar = this.createSideBar();
this.bottomMenu = this.createSidebarBottomMenu();
this.toolBar = this.createToolbar();
this.dockPanel = this.createSidePanel();
this.container = this.createContainer();
Expand Down Expand Up @@ -178,6 +187,12 @@ export class SidePanelHandler {
return toolbar;
}

protected createSidebarBottomMenu(): SidebarBottomMenuWidget {
const bottomMenu = this.sidebarBottomWidgetFactory();
bottomMenu.addClass('theia-sidebar-bottom-menu');
return bottomMenu;
}

protected showContextMenu(e: MouseEvent): void {
const title = this.tabBar.currentTitle;
if (!title) {
Expand Down Expand Up @@ -214,9 +229,15 @@ export class SidePanelHandler {
throw new Error('Illegal argument: ' + side);
}
const containerLayout = new BoxLayout({ direction, spacing: 0 });
BoxPanel.setStretch(this.tabBar, 0);
containerLayout.addWidget(this.tabBar);
const sidebarContainerLayout = new PanelLayout();
const sidebarContainer = new Panel({ layout: sidebarContainerLayout });
sidebarContainer.addClass('theia-app-sidebar-container');
sidebarContainerLayout.addWidget(this.tabBar);
sidebarContainerLayout.addWidget(this.bottomMenu);

BoxPanel.setStretch(sidebarContainer, 0);
BoxPanel.setStretch(contentPanel, 1);
containerLayout.addWidget(sidebarContainer);
containerLayout.addWidget(contentPanel);
const boxPanel = new BoxPanel({ layout: containerLayout });
boxPanel.id = 'theia-' + side + '-content-panel';
Expand Down Expand Up @@ -364,6 +385,15 @@ export class SidePanelHandler {
this.dockPanel.addWidget(widget);
}

/**
* Add a menu to the sidebar bottom.
*
* If the menu is already added, it will be ignored.
*/
addMenu(menu: SidebarBottomMenu): void {
this.bottomMenu.addMenu(menu);
}

// should be a property to preserve fn identity
protected updateToolbarTitle = (): void => {
const currentTitle = this.tabBar && this.tabBar.currentTitle;
Expand Down
77 changes: 77 additions & 0 deletions packages/core/src/browser/shell/sidebar-bottom-menu-widget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/********************************************************************************
* Copyright (C) 2020 Alibaba Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { injectable, inject } from 'inversify';
import * as React from 'react';
import { ReactWidget } from '../widgets';
import { ContextMenuRenderer } from '../context-menu-renderer';
import { MenuPath } from '../../common/menu';

export const SidebarBottomMenuWidgetFactory = Symbol('SidebarBottomMenuWidgetFactory');

export interface SidebarBottomMenu {
id: string;
iconClass: string;
title: string;
menuPath: MenuPath;
order: number; // smaller one place lower
}

/**
* The menu widget placed on the bottom of the sidebar.
*/
@injectable()
export class SidebarBottomMenuWidget extends ReactWidget {
protected readonly menus: SidebarBottomMenu[];

@inject(ContextMenuRenderer)
protected readonly contextMenuRenderer: ContextMenuRenderer;

constructor() {
super();
this.menus = [];
}

addMenu(menu: SidebarBottomMenu): void {
const exists = this.menus.find(m => m.id === menu.id);
if (exists) {
return;
}
this.menus.push(menu);
this.update();
}

protected onClick(e: React.MouseEvent<HTMLElement, MouseEvent>, menuPath: MenuPath): void {
this.contextMenuRenderer.render({
menuPath,
anchor: {
x: e.clientX,
y: e.clientY,
}
});
}

protected render(): React.ReactNode {
return <React.Fragment>
{this.menus.sort((a, b) => a.order - b.order).map(menu => <i
key={menu.id}
className={menu.iconClass}
title={menu.title}
onClick={e => this.onClick(e, menu.menuPath)}
/>)}
</React.Fragment>;
}
}
39 changes: 38 additions & 1 deletion packages/core/src/browser/style/sidepanel.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
:root {
--theia-private-sidebar-tab-width: 50px;
--theia-private-sidebar-tab-height: 32px;
--theia-private-sidebar-tab-padding-top-and-bottom: 11px;
--theia-private-sidebar-tab-padding-left-and-right: 10px;
--theia-private-sidebar-scrollbar-rail-width: 7px;
--theia-private-sidebar-scrollbar-width: 5px;
--theia-private-sidebar-icon-size: 28px;
Expand All @@ -46,7 +48,7 @@

.p-TabBar.theia-app-sides .p-TabBar-tab {
position: relative;
padding: 11px 10px;
padding: var(--theia-private-sidebar-tab-padding-top-and-bottom) var(--theia-private-sidebar-tab-padding-left-and-right);
background: var(--theia-activityBar-background);
flex-direction: column;
justify-content: center;
Expand Down Expand Up @@ -171,7 +173,42 @@
color: var(--theia-sideBar-foreground);
}

.theia-app-sidebar-container {
min-width: var(--theia-private-sidebar-tab-width);
max-width: var(--theia-private-sidebar-tab-width);
background: var(--theia-activityBar-background);
display: flex;
flex-direction: column;
}

.theia-app-sidebar-container .theia-app-sides {
flex-grow: 1;
}

.theia-app-sidebar-container .theia-sidebar-bottom-menu {
flex-shrink: 0;
}

.p-Widget.theia-sidebar-bottom-menu {
background-color: var(--theia-activityBar-background);
display: flex;
flex-direction: column-reverse;
}

.p-Widget.theia-sidebar-bottom-menu i {
padding: var(--theia-private-sidebar-tab-padding-top-and-bottom) var(--theia-private-sidebar-tab-padding-left-and-right);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
color: var(--theia-activityBar-inactiveForeground);
background-color: var(--theia-activityBar-background);
font-size: var(--theia-private-sidebar-icon-size);
}

.theia-sidebar-bottom-menu i:hover {
color: var(--theia-activityBar-foreground);
}

/*-----------------------------------------------------------------------------
| Perfect scrollbar
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/common/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export type MenuPath = string[];

export const MAIN_MENU_BAR: MenuPath = ['menubar'];

export const SETTINGS_MENU: MenuPath = ['settings_menu'];

export const MenuContribution = Symbol('MenuContribution');

/**
Expand Down
4 changes: 4 additions & 0 deletions packages/keymaps/src/browser/keymaps-frontend-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export class KeymapsFrontendContribution extends AbstractViewContribution<Keybin
commandId: KeymapsCommands.OPEN_KEYMAPS.id,
order: 'a20'
});
menus.registerMenuAction(CommonMenus.SETTINGS_OPEN, {
commandId: KeymapsCommands.OPEN_KEYMAPS.id,
order: 'a20'
});
}

registerKeybindings(keybindings: KeybindingRegistry): void {
Expand Down
5 changes: 5 additions & 0 deletions packages/preferences/src/browser/preferences-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ export class PreferencesContribution extends AbstractViewContribution<Preference
label: CommonCommands.OPEN_PREFERENCES.label,
order: 'a10',
});
menus.registerMenuAction(CommonMenus.SETTINGS_OPEN, {
commandId: CommonCommands.OPEN_PREFERENCES.id,
label: CommonCommands.OPEN_PREFERENCES.label,
order: 'a10',
});
menus.registerMenuAction(PreferenceMenus.PREFERENCE_EDITOR_CONTEXT_MENU, {
commandId: PreferencesCommands.RESET_PREFERENCE.id,
label: PreferencesCommands.RESET_PREFERENCE.label,
Expand Down

0 comments on commit d7f9163

Please sign in to comment.