Skip to content

Commit

Permalink
add layout control to title bar
Browse files Browse the repository at this point in the history
  • Loading branch information
sbatten committed Nov 10, 2021
1 parent 71f615b commit 00b931f
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 49 deletions.
1 change: 1 addition & 0 deletions src/vs/platform/actions/common/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export class MenuId {
static readonly ExplorerContext = new MenuId('ExplorerContext');
static readonly ExtensionContext = new MenuId('ExtensionContext');
static readonly GlobalActivity = new MenuId('GlobalActivity');
static readonly LayoutControlMenu = new MenuId('LayoutControlMenu');
static readonly MenubarMainMenu = new MenuId('MenubarMainMenu');
static readonly MenubarAppearanceMenu = new MenuId('MenubarAppearanceMenu');
static readonly MenubarDebugMenu = new MenuId('MenubarDebugMenu');
Expand Down
103 changes: 64 additions & 39 deletions src/vs/workbench/browser/actions/layoutActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ export class ToggleActivityBarVisibilityAction extends Action2 {
category: CATEGORIES.View,
f1: true,
toggled: ContextKeyExpr.equals('config.workbench.activityBar.visible', true),
menu: {
menu: [{
id: MenuId.MenubarAppearanceMenu,
group: '2_workbench_layout',
order: 4
}
}, {
id: MenuId.LayoutControlMenu,
group: '0_workbench_layout',
order: 3
}]
});
}

Expand Down Expand Up @@ -226,11 +230,15 @@ registerAction2(class extends Action2 {
category: CATEGORIES.View,
f1: true,
toggled: EditorAreaVisibleContext,
menu: {
menu: [{
id: MenuId.MenubarAppearanceMenu,
group: '2_workbench_layout',
order: 5
}
}, {
id: MenuId.LayoutControlMenu,
group: '0_workbench_layout',
order: 5
}]
});
}

Expand Down Expand Up @@ -274,40 +282,53 @@ class ToggleSidebarVisibilityAction extends Action2 {

registerAction2(ToggleSidebarVisibilityAction);

MenuRegistry.appendMenuItems([{
id: MenuId.ViewContainerTitleContext,
item: {
group: '3_workbench_layout_move',
command: {
id: ToggleSidebarVisibilityAction.ID,
title: localize('compositePart.hideSideBarLabel', "Hide Side Bar"),
},
when: ContextKeyExpr.and(SideBarVisibleContext, ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))),
order: 2
}
}, {
id: MenuId.ViewTitleContext,
item: {
group: '3_workbench_layout_move',
command: {
id: ToggleSidebarVisibilityAction.ID,
title: localize('compositePart.hideSideBarLabel', "Hide Side Bar"),
},
when: ContextKeyExpr.and(SideBarVisibleContext, ContextKeyExpr.equals('viewLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))),
order: 2
}
}, {
id: MenuId.MenubarAppearanceMenu,
item: {
group: '2_workbench_layout',
command: {
id: ToggleSidebarVisibilityAction.ID,
title: localize({ key: 'miShowSidebar', comment: ['&& denotes a mnemonic'] }, "Show &&Side Bar"),
toggled: SideBarVisibleContext
},
order: 1
MenuRegistry.appendMenuItems([
{
id: MenuId.ViewContainerTitleContext,
item: {
group: '3_workbench_layout_move',
command: {
id: ToggleSidebarVisibilityAction.ID,
title: localize('compositePart.hideSideBarLabel', "Hide Side Bar"),
},
when: ContextKeyExpr.and(SideBarVisibleContext, ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))),
order: 2
}
}, {
id: MenuId.ViewTitleContext,
item: {
group: '3_workbench_layout_move',
command: {
id: ToggleSidebarVisibilityAction.ID,
title: localize('compositePart.hideSideBarLabel', "Hide Side Bar"),
},
when: ContextKeyExpr.and(SideBarVisibleContext, ContextKeyExpr.equals('viewLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))),
order: 2
}
}, {
id: MenuId.MenubarAppearanceMenu,
item: {
group: '2_workbench_layout',
command: {
id: ToggleSidebarVisibilityAction.ID,
title: localize({ key: 'miShowSidebar', comment: ['&& denotes a mnemonic'] }, "Show &&Side Bar"),
toggled: SideBarVisibleContext
},
order: 1
}
}, {
id: MenuId.LayoutControlMenu,
item: {
group: '0_workbench_layout',
command: {
id: ToggleSidebarVisibilityAction.ID,
title: localize('miShowSidebarNoMnnemonic', "Show Side Bar"),
toggled: SideBarVisibleContext
},
order: 0
}
}
}]);
]);

// --- Toggle Statusbar Visibility

Expand All @@ -328,11 +349,15 @@ export class ToggleStatusbarVisibilityAction extends Action2 {
category: CATEGORIES.View,
f1: true,
toggled: ContextKeyExpr.equals('config.workbench.statusBar.visible', true),
menu: {
menu: [{
id: MenuId.MenubarAppearanceMenu,
group: '2_workbench_layout',
order: 3
}
}, {
id: MenuId.LayoutControlMenu,
group: '0_workbench_layout',
order: 1
}]
});
}

Expand Down
13 changes: 13 additions & 0 deletions src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ class FocusAuxiliaryBarAction extends Action {
}

MenuRegistry.appendMenuItems([
{
id: MenuId.LayoutControlMenu,
item: {
group: '0_workbench_layout',
command: {
id: ToggleAuxiliaryBarAction.ID,
title: localize({ key: 'miShowAuxiliaryBar', comment: ['&& denotes a mnemonic'] }, "Show Si&&de Panel"),
toggled: ActiveAuxiliaryContext
},
when: ContextKeyExpr.equals('config.workbench.experimental.sidePanel.enabled', true),
order: 4
}
},
{
id: MenuId.MenubarAppearanceMenu,
item: {
Expand Down
11 changes: 11 additions & 0 deletions src/vs/workbench/browser/parts/panel/panelActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,17 @@ MenuRegistry.appendMenuItems([
},
order: 5
}
}, {
id: MenuId.LayoutControlMenu,
item: {
group: '0_workbench_layout',
command: {
id: TogglePanelAction.ID,
title: localize({ key: 'miShowPanel', comment: ['&& denotes a mnemonic'] }, "Show &&Panel"),
toggled: ActivePanelContext
},
order: 4
}
}, {
id: MenuId.ViewTitleContext,
item: {
Expand Down
12 changes: 12 additions & 0 deletions src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,18 @@
background-color: transparent;
}

.monaco-workbench .part.titlebar > .window-controls-container.show-layout-control {
width: 160px;
}

.monaco-workbench .part.titlebar > .window-controls-container > .layout-dropdown-container {
display: none;
}

.monaco-workbench .part.titlebar > .window-controls-container.show-layout-control > .layout-dropdown-container {
display: inline-block;
}

.monaco-workbench .part.titlebar > .window-controls-container > .window-icon {
display: inline-block;
line-height: 30px;
Expand Down
78 changes: 73 additions & 5 deletions src/vs/workbench/browser/parts/titlebar/titlebarPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { getZoomFactor } from 'vs/base/browser/browser';
import { MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility } from 'vs/platform/windows/common/windows';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { IAction } from 'vs/base/common/actions';
import { IAction, SubmenuAction } from 'vs/base/common/actions';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
Expand All @@ -28,21 +28,25 @@ import { trim } from 'vs/base/common/strings';
import { EventType, EventHelper, Dimension, isAncestor, append, $, addDisposableListener, runAtThisOrScheduleAtNextAnimationFrame, prepend } from 'vs/base/browser/dom';
import { CustomMenubarControl } from 'vs/workbench/browser/parts/titlebar/menubarControl';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { template } from 'vs/base/common/labels';
import { mnemonicButtonLabel, template } from 'vs/base/common/labels';
import { ILabelService } from 'vs/platform/label/common/label';
import { Emitter } from 'vs/base/common/event';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { RunOnceScheduler } from 'vs/base/common/async';
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IMenuService, IMenu, MenuId } from 'vs/platform/actions/common/actions';
import { IMenuService, IMenu, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IProductService } from 'vs/platform/product/common/productService';
import { Schemas } from 'vs/base/common/network';
import { withNullAsUndefined } from 'vs/base/common/types';
import { Codicon, iconRegistry } from 'vs/base/common/codicons';
import { getVirtualWorkspaceLocation } from 'vs/platform/remote/common/remoteHosts';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';

export class TitlebarPart extends Part implements ITitleService {

Expand All @@ -66,10 +70,13 @@ export class TitlebarPart extends Part implements ITitleService {
declare readonly _serviceBrand: undefined;

protected title!: HTMLElement;

protected customMenubar: CustomMenubarControl | undefined;
protected appIcon: HTMLElement | undefined;
private appIconBadge: HTMLElement | undefined;
protected menubar?: HTMLElement;
protected windowControls: HTMLElement | undefined;
private layoutToolbar: ActionBar | undefined;
protected lastLayoutDimensions: Dimension | undefined;
private titleBarStyle: 'native' | 'custom';

Expand All @@ -91,12 +98,13 @@ export class TitlebarPart extends Part implements ITitleService {
@IWorkbenchEnvironmentService protected readonly environmentService: IWorkbenchEnvironmentService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IInstantiationService protected readonly instantiationService: IInstantiationService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@IThemeService themeService: IThemeService,
@ILabelService private readonly labelService: ILabelService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IMenuService menuService: IMenuService,
@IContextKeyService contextKeyService: IContextKeyService,
@IMenuService private readonly menuService: IMenuService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IHostService private readonly hostService: IHostService,
@IProductService private readonly productService: IProductService,
) {
Expand Down Expand Up @@ -143,6 +151,10 @@ export class TitlebarPart extends Part implements ITitleService {
}
}
}

if (this.titleBarStyle !== 'native' && this.windowControls && event.affectsConfiguration('workbench.experimental.layoutControl.enabled')) {
this.windowControls.classList.toggle('show-layout-control', this.layoutControlEnabled);
}
}

protected onMenubarVisibilityChanged(visible: boolean): void {
Expand Down Expand Up @@ -395,6 +407,54 @@ export class TitlebarPart extends Part implements ITitleService {
this.titleUpdater.schedule();
}

if (this.titleBarStyle !== 'native') {
this.windowControls = append(this.element, $('div.window-controls-container'));
this.windowControls.classList.toggle('show-layout-control', this.layoutControlEnabled);

const layoutDropdownContainer = append(this.windowControls, $('div.layout-dropdown-container'));
this.layoutToolbar = new ActionBar(layoutDropdownContainer,
{
ariaLabel: localize('layoutMenu', "Configure Layout"),
actionViewItemProvider: action => {
if (action instanceof SubmenuAction) {
return new DropdownMenuActionViewItem(action, action.actions, this.contextMenuService, {

classNames: Codicon.editorLayout.classNamesArray,
anchorAlignmentProvider: () => AnchorAlignment.RIGHT,
keybindingProvider: action => this.keybindingService.lookupKeybinding(action.id)
});
}
return undefined;
}
});


const menu = this._register(this.menuService.createMenu(MenuId.LayoutControlMenu, this.contextKeyService));
const updateLayoutMenu = () => {
if (!this.layoutToolbar) {
return;
}

const actions: IAction[] = [];
const toDispose = createAndFillInContextMenuActions(menu, undefined, { primary: [], secondary: actions });

this.layoutToolbar.clear();
this.layoutToolbar.push(new SubmenuAction('stenir', localize('layoutMenu', "Configure Layout"), actions.map(action => {
if (action instanceof MenuItemAction) {
(action as IAction).label = mnemonicButtonLabel(typeof action.item.title === 'string'
? action.item.title
: action.item.title.mnemonicTitle ?? action.item.title.value, true);
}
return action;
})));

toDispose.dispose();
};

menu.onDidChange(updateLayoutMenu);
updateLayoutMenu();
}

// Context menu on title
[EventType.CONTEXT_MENU, EventType.MOUSE_DOWN].forEach(event => {
this._register(addDisposableListener(this.title, event, e => {
Expand All @@ -413,6 +473,10 @@ export class TitlebarPart extends Part implements ITitleService {
return;
}

if (e.target && this.layoutToolbar && isAncestor(e.target as HTMLElement, this.layoutToolbar.getContainer())) {
return;
}

const active = document.activeElement;
setTimeout(() => {
if (active instanceof HTMLElement) {
Expand Down Expand Up @@ -507,6 +571,10 @@ export class TitlebarPart extends Part implements ITitleService {
return getMenuBarVisibility(this.configurationService);
}

private get layoutControlEnabled(): boolean {
return this.configurationService.getValue<boolean>('workbench.experimental.layoutControl.enabled');
}

updateLayout(dimension: Dimension): void {
this.lastLayoutDimensions = dimension;

Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/browser/workbench.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,11 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
// On Mac, the delay is 1500.
'default': isMacintosh ? 1500 : 500
},
'workbench.experimental.layoutControl.enabled': {
'type': 'boolean',
'default': product.quality !== 'stable' && isWindows,
'description': localize('layoutControlEnabled', "Controls whether the layout control button in the custom title bar is enabled."),
},
'workbench.experimental.sidePanel.enabled': {
'type': 'boolean',
'default': false,
Expand Down

0 comments on commit 00b931f

Please sign in to comment.