Path: blob/main/src/vs/workbench/browser/actions/layoutActions.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { ILocalizedString, localize, localize2 } from '../../../nls.js';6import { MenuId, MenuRegistry, registerAction2, Action2 } from '../../../platform/actions/common/actions.js';7import { Categories } from '../../../platform/action/common/actionCommonCategories.js';8import { IConfigurationService } from '../../../platform/configuration/common/configuration.js';9import { alert } from '../../../base/browser/ui/aria/aria.js';10import { EditorActionsLocation, EditorTabsMode, IWorkbenchLayoutService, LayoutSettings, Parts, Position, ZenModeSettings, positionToString } from '../../services/layout/browser/layoutService.js';11import { ServicesAccessor, IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';12import { KeyMod, KeyCode, KeyChord } from '../../../base/common/keyCodes.js';13import { isWindows, isLinux, isWeb, isMacintosh, isNative } from '../../../base/common/platform.js';14import { IsMacNativeContext } from '../../../platform/contextkey/common/contextkeys.js';15import { KeybindingsRegistry, KeybindingWeight } from '../../../platform/keybinding/common/keybindingsRegistry.js';16import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';17import { IViewDescriptorService, ViewContainerLocation, IViewDescriptor, ViewContainerLocationToString } from '../../common/views.js';18import { IViewsService } from '../../services/views/common/viewsService.js';19import { QuickPickItem, IQuickInputService, IQuickPickItem, IQuickPickSeparator, IQuickPick } from '../../../platform/quickinput/common/quickInput.js';20import { IDialogService } from '../../../platform/dialogs/common/dialogs.js';21import { IPaneCompositePartService } from '../../services/panecomposite/browser/panecomposite.js';22import { ToggleAuxiliaryBarAction } from '../parts/auxiliarybar/auxiliaryBarActions.js';23import { TogglePanelAction } from '../parts/panel/panelActions.js';24import { ICommandService } from '../../../platform/commands/common/commands.js';25import { AuxiliaryBarVisibleContext, PanelAlignmentContext, PanelVisibleContext, SideBarVisibleContext, FocusedViewContext, InEditorZenModeContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, IsMainWindowFullscreenContext, PanelPositionContext, IsAuxiliaryWindowFocusedContext, TitleBarStyleContext, IsAuxiliaryWindowContext } from '../../common/contextkeys.js';26import { Codicon } from '../../../base/common/codicons.js';27import { ThemeIcon } from '../../../base/common/themables.js';28import { DisposableStore } from '../../../base/common/lifecycle.js';29import { registerIcon } from '../../../platform/theme/common/iconRegistry.js';30import { ICommandActionTitle } from '../../../platform/action/common/action.js';31import { mainWindow } from '../../../base/browser/window.js';32import { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js';33import { MenuSettings, TitlebarStyle } from '../../../platform/window/common/window.js';34import { IPreferencesService } from '../../services/preferences/common/preferences.js';35import { QuickInputAlignmentContextKey } from '../../../platform/quickinput/browser/quickInput.js';36import { IEditorGroupsService } from '../../services/editor/common/editorGroupsService.js';3738// Register Icons39const menubarIcon = registerIcon('menuBar', Codicon.layoutMenubar, localize('menuBarIcon', "Represents the menu bar"));40const activityBarLeftIcon = registerIcon('activity-bar-left', Codicon.layoutActivitybarLeft, localize('activityBarLeft', "Represents the activity bar in the left position"));41const activityBarRightIcon = registerIcon('activity-bar-right', Codicon.layoutActivitybarRight, localize('activityBarRight', "Represents the activity bar in the right position"));42const panelLeftIcon = registerIcon('panel-left', Codicon.layoutSidebarLeft, localize('panelLeft', "Represents a side bar in the left position"));43const panelLeftOffIcon = registerIcon('panel-left-off', Codicon.layoutSidebarLeftOff, localize('panelLeftOff', "Represents a side bar in the left position toggled off"));44const panelRightIcon = registerIcon('panel-right', Codicon.layoutSidebarRight, localize('panelRight', "Represents side bar in the right position"));45const panelRightOffIcon = registerIcon('panel-right-off', Codicon.layoutSidebarRightOff, localize('panelRightOff', "Represents side bar in the right position toggled off"));46const panelIcon = registerIcon('panel-bottom', Codicon.layoutPanel, localize('panelBottom', "Represents the bottom panel"));47const statusBarIcon = registerIcon('statusBar', Codicon.layoutStatusbar, localize('statusBarIcon', "Represents the status bar"));4849const panelAlignmentLeftIcon = registerIcon('panel-align-left', Codicon.layoutPanelLeft, localize('panelBottomLeft', "Represents the bottom panel alignment set to the left"));50const panelAlignmentRightIcon = registerIcon('panel-align-right', Codicon.layoutPanelRight, localize('panelBottomRight', "Represents the bottom panel alignment set to the right"));51const panelAlignmentCenterIcon = registerIcon('panel-align-center', Codicon.layoutPanelCenter, localize('panelBottomCenter', "Represents the bottom panel alignment set to the center"));52const panelAlignmentJustifyIcon = registerIcon('panel-align-justify', Codicon.layoutPanelJustify, localize('panelBottomJustify', "Represents the bottom panel alignment set to justified"));5354const quickInputAlignmentTopIcon = registerIcon('quickInputAlignmentTop', Codicon.arrowUp, localize('quickInputAlignmentTop', "Represents quick input alignment set to the top"));55const quickInputAlignmentCenterIcon = registerIcon('quickInputAlignmentCenter', Codicon.circle, localize('quickInputAlignmentCenter', "Represents quick input alignment set to the center"));5657const fullscreenIcon = registerIcon('fullscreen', Codicon.screenFull, localize('fullScreenIcon', "Represents full screen"));58const centerLayoutIcon = registerIcon('centerLayoutIcon', Codicon.layoutCentered, localize('centerLayoutIcon', "Represents centered layout mode"));59const zenModeIcon = registerIcon('zenMode', Codicon.target, localize('zenModeIcon', "Represents zen mode"));6061export const ToggleActivityBarVisibilityActionId = 'workbench.action.toggleActivityBarVisibility';6263// --- Toggle Centered Layout6465registerAction2(class extends Action2 {6667constructor() {68super({69id: 'workbench.action.toggleCenteredLayout',70title: {71...localize2('toggleCenteredLayout', "Toggle Centered Layout"),72mnemonicTitle: localize({ key: 'miToggleCenteredLayout', comment: ['&& denotes a mnemonic'] }, "&&Centered Layout"),73},74precondition: IsAuxiliaryWindowFocusedContext.toNegated(),75category: Categories.View,76f1: true,77toggled: IsMainEditorCenteredLayoutContext,78menu: [{79id: MenuId.MenubarAppearanceMenu,80group: '1_toggle_view',81order: 382}]83});84}8586run(accessor: ServicesAccessor): void {87const layoutService = accessor.get(IWorkbenchLayoutService);88const editorGroupService = accessor.get(IEditorGroupsService);8990layoutService.centerMainEditorLayout(!layoutService.isMainEditorLayoutCentered());91editorGroupService.activeGroup.focus();92}93});9495// --- Set Sidebar Position96const sidebarPositionConfigurationKey = 'workbench.sideBar.location';9798class MoveSidebarPositionAction extends Action2 {99constructor(id: string, title: ICommandActionTitle, private readonly position: Position) {100super({101id,102title,103f1: false104});105}106107async run(accessor: ServicesAccessor): Promise<void> {108const layoutService = accessor.get(IWorkbenchLayoutService);109const configurationService = accessor.get(IConfigurationService);110111const position = layoutService.getSideBarPosition();112if (position !== this.position) {113return configurationService.updateValue(sidebarPositionConfigurationKey, positionToString(this.position));114}115}116}117118class MoveSidebarRightAction extends MoveSidebarPositionAction {119static readonly ID = 'workbench.action.moveSideBarRight';120121constructor() {122super(MoveSidebarRightAction.ID, localize2('moveSidebarRight', "Move Primary Side Bar Right"), Position.RIGHT);123}124}125126class MoveSidebarLeftAction extends MoveSidebarPositionAction {127static readonly ID = 'workbench.action.moveSideBarLeft';128129constructor() {130super(MoveSidebarLeftAction.ID, localize2('moveSidebarLeft', "Move Primary Side Bar Left"), Position.LEFT);131}132}133134registerAction2(MoveSidebarRightAction);135registerAction2(MoveSidebarLeftAction);136137// --- Toggle Sidebar Position138139export class ToggleSidebarPositionAction extends Action2 {140141static readonly ID = 'workbench.action.toggleSidebarPosition';142static readonly LABEL = localize('toggleSidebarPosition', "Toggle Primary Side Bar Position");143144static getLabel(layoutService: IWorkbenchLayoutService): string {145return layoutService.getSideBarPosition() === Position.LEFT ? localize('moveSidebarRight', "Move Primary Side Bar Right") : localize('moveSidebarLeft', "Move Primary Side Bar Left");146}147148constructor() {149super({150id: ToggleSidebarPositionAction.ID,151title: localize2('toggleSidebarPosition', "Toggle Primary Side Bar Position"),152category: Categories.View,153f1: true154});155}156157run(accessor: ServicesAccessor): Promise<void> {158const layoutService = accessor.get(IWorkbenchLayoutService);159const configurationService = accessor.get(IConfigurationService);160161const position = layoutService.getSideBarPosition();162const newPositionValue = (position === Position.LEFT) ? 'right' : 'left';163164return configurationService.updateValue(sidebarPositionConfigurationKey, newPositionValue);165}166}167168registerAction2(ToggleSidebarPositionAction);169170const configureLayoutIcon = registerIcon('configure-layout-icon', Codicon.layout, localize('cofigureLayoutIcon', 'Icon represents workbench layout configuration.'));171MenuRegistry.appendMenuItem(MenuId.LayoutControlMenu, {172submenu: MenuId.LayoutControlMenuSubmenu,173title: localize('configureLayout', "Configure Layout"),174icon: configureLayoutIcon,175group: '1_workbench_layout',176when: ContextKeyExpr.and(177IsAuxiliaryWindowContext.negate(),178ContextKeyExpr.equals('config.workbench.layoutControl.type', 'menu')179)180});181182183MenuRegistry.appendMenuItems([{184id: MenuId.ViewContainerTitleContext,185item: {186group: '3_workbench_layout_move',187command: {188id: ToggleSidebarPositionAction.ID,189title: localize('move side bar right', "Move Primary Side Bar Right")190},191when: ContextKeyExpr.and(ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'), ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))),192order: 1193}194}, {195id: MenuId.ViewContainerTitleContext,196item: {197group: '3_workbench_layout_move',198command: {199id: ToggleSidebarPositionAction.ID,200title: localize('move sidebar left', "Move Primary Side Bar Left")201},202when: ContextKeyExpr.and(ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))),203order: 1204}205}, {206id: MenuId.ViewContainerTitleContext,207item: {208group: '3_workbench_layout_move',209command: {210id: ToggleSidebarPositionAction.ID,211title: localize('move second sidebar left', "Move Secondary Side Bar Left")212},213when: ContextKeyExpr.and(ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'), ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.AuxiliaryBar))),214order: 1215}216}, {217id: MenuId.ViewContainerTitleContext,218item: {219group: '3_workbench_layout_move',220command: {221id: ToggleSidebarPositionAction.ID,222title: localize('move second sidebar right', "Move Secondary Side Bar Right")223},224when: ContextKeyExpr.and(ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.AuxiliaryBar))),225order: 1226}227}]);228229MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {230group: '3_workbench_layout_move',231command: {232id: ToggleSidebarPositionAction.ID,233title: localize({ key: 'miMoveSidebarRight', comment: ['&& denotes a mnemonic'] }, "&&Move Primary Side Bar Right")234},235when: ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'),236order: 2237});238239MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {240group: '3_workbench_layout_move',241command: {242id: ToggleSidebarPositionAction.ID,243title: localize({ key: 'miMoveSidebarLeft', comment: ['&& denotes a mnemonic'] }, "&&Move Primary Side Bar Left")244},245when: ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'),246order: 2247});248249// --- Toggle Editor Visibility250251registerAction2(class extends Action2 {252253constructor() {254super({255id: 'workbench.action.toggleEditorVisibility',256title: {257...localize2('toggleEditor', "Toggle Editor Area Visibility"),258mnemonicTitle: localize({ key: 'miShowEditorArea', comment: ['&& denotes a mnemonic'] }, "Show &&Editor Area"),259},260category: Categories.View,261f1: true,262toggled: MainEditorAreaVisibleContext,263// the workbench grid currently prevents us from supporting panel maximization with non-center panel alignment264precondition: ContextKeyExpr.and(IsAuxiliaryWindowFocusedContext.toNegated(), ContextKeyExpr.or(PanelAlignmentContext.isEqualTo('center'), PanelPositionContext.notEqualsTo('bottom')))265});266}267268run(accessor: ServicesAccessor): void {269accessor.get(IWorkbenchLayoutService).toggleMaximizedPanel();270}271});272273MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {274group: '2_appearance',275title: localize({ key: 'miAppearance', comment: ['&& denotes a mnemonic'] }, "&&Appearance"),276submenu: MenuId.MenubarAppearanceMenu,277order: 1278});279280// Toggle Sidebar Visibility281282export class ToggleSidebarVisibilityAction extends Action2 {283284static readonly ID = 'workbench.action.toggleSidebarVisibility';285static readonly LABEL = localize('compositePart.hideSideBarLabel', "Hide Primary Side Bar");286287constructor() {288super({289id: ToggleSidebarVisibilityAction.ID,290title: localize2('toggleSidebar', 'Toggle Primary Side Bar Visibility'),291toggled: {292condition: SideBarVisibleContext,293title: localize('primary sidebar', "Primary Side Bar"),294mnemonicTitle: localize({ key: 'primary sidebar mnemonic', comment: ['&& denotes a mnemonic'] }, "&&Primary Side Bar"),295},296metadata: {297description: localize('openAndCloseSidebar', 'Open/Show and Close/Hide Sidebar'),298},299category: Categories.View,300f1: true,301keybinding: {302weight: KeybindingWeight.WorkbenchContrib,303primary: KeyMod.CtrlCmd | KeyCode.KeyB304},305menu: [306{307id: MenuId.LayoutControlMenuSubmenu,308group: '0_workbench_layout',309order: 0310},311{312id: MenuId.MenubarAppearanceMenu,313group: '2_workbench_layout',314order: 1315}316]317});318}319320run(accessor: ServicesAccessor): void {321const layoutService = accessor.get(IWorkbenchLayoutService);322const isCurrentlyVisible = layoutService.isVisible(Parts.SIDEBAR_PART);323324layoutService.setPartHidden(isCurrentlyVisible, Parts.SIDEBAR_PART);325326// Announce visibility change to screen readers327const alertMessage = isCurrentlyVisible328? localize('sidebarHidden', "Primary Side Bar hidden")329: localize('sidebarVisible', "Primary Side Bar shown");330alert(alertMessage);331}332}333334registerAction2(ToggleSidebarVisibilityAction);335336MenuRegistry.appendMenuItems([337{338id: MenuId.ViewContainerTitleContext,339item: {340group: '3_workbench_layout_move',341command: {342id: ToggleSidebarVisibilityAction.ID,343title: localize('compositePart.hideSideBarLabel', "Hide Primary Side Bar"),344},345when: ContextKeyExpr.and(SideBarVisibleContext, ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))),346order: 2347}348}, {349id: MenuId.LayoutControlMenu,350item: {351group: '2_pane_toggles',352command: {353id: ToggleSidebarVisibilityAction.ID,354title: localize('toggleSideBar', "Toggle Primary Side Bar"),355icon: panelLeftOffIcon,356toggled: { condition: SideBarVisibleContext, icon: panelLeftIcon }357},358when: ContextKeyExpr.and(359IsAuxiliaryWindowContext.negate(),360ContextKeyExpr.or(361ContextKeyExpr.equals('config.workbench.layoutControl.type', 'toggles'),362ContextKeyExpr.equals('config.workbench.layoutControl.type', 'both')),363ContextKeyExpr.equals('config.workbench.sideBar.location', 'left')364),365order: 0366}367}, {368id: MenuId.LayoutControlMenu,369item: {370group: '2_pane_toggles',371command: {372id: ToggleSidebarVisibilityAction.ID,373title: localize('toggleSideBar', "Toggle Primary Side Bar"),374icon: panelRightOffIcon,375toggled: { condition: SideBarVisibleContext, icon: panelRightIcon }376},377when: ContextKeyExpr.and(378IsAuxiliaryWindowContext.negate(),379ContextKeyExpr.or(380ContextKeyExpr.equals('config.workbench.layoutControl.type', 'toggles'),381ContextKeyExpr.equals('config.workbench.layoutControl.type', 'both')),382ContextKeyExpr.equals('config.workbench.sideBar.location', 'right')383),384order: 2385}386}387]);388389// --- Toggle Statusbar Visibility390391export class ToggleStatusbarVisibilityAction extends Action2 {392393static readonly ID = 'workbench.action.toggleStatusbarVisibility';394395private static readonly statusbarVisibleKey = 'workbench.statusBar.visible';396397constructor() {398super({399id: ToggleStatusbarVisibilityAction.ID,400title: {401...localize2('toggleStatusbar', "Toggle Status Bar Visibility"),402mnemonicTitle: localize({ key: 'miStatusbar', comment: ['&& denotes a mnemonic'] }, "S&&tatus Bar"),403},404category: Categories.View,405f1: true,406toggled: ContextKeyExpr.equals('config.workbench.statusBar.visible', true),407menu: [{408id: MenuId.MenubarAppearanceMenu,409group: '2_workbench_layout',410order: 3411}]412});413}414415run(accessor: ServicesAccessor): Promise<void> {416const layoutService = accessor.get(IWorkbenchLayoutService);417const configurationService = accessor.get(IConfigurationService);418419const visibility = layoutService.isVisible(Parts.STATUSBAR_PART, mainWindow);420const newVisibilityValue = !visibility;421422return configurationService.updateValue(ToggleStatusbarVisibilityAction.statusbarVisibleKey, newVisibilityValue);423}424}425426registerAction2(ToggleStatusbarVisibilityAction);427428// ------------------- Editor Tabs Layout --------------------------------429430abstract class AbstractSetShowTabsAction extends Action2 {431432constructor(private readonly settingName: string, private readonly value: string, title: ICommandActionTitle, id: string, precondition: ContextKeyExpression, description: string | ILocalizedString | undefined) {433super({434id,435title,436category: Categories.View,437precondition,438metadata: description ? { description } : undefined,439f1: true440});441}442443run(accessor: ServicesAccessor): Promise<void> {444const configurationService = accessor.get(IConfigurationService);445return configurationService.updateValue(this.settingName, this.value);446}447}448449// --- Hide Editor Tabs450451export class HideEditorTabsAction extends AbstractSetShowTabsAction {452453static readonly ID = 'workbench.action.hideEditorTabs';454455constructor() {456const precondition = ContextKeyExpr.and(ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_TABS_MODE}`, EditorTabsMode.NONE).negate(), InEditorZenModeContext.negate())!;457const title = localize2('hideEditorTabs', 'Hide Editor Tabs');458super(LayoutSettings.EDITOR_TABS_MODE, EditorTabsMode.NONE, title, HideEditorTabsAction.ID, precondition, localize2('hideEditorTabsDescription', "Hide Tab Bar"));459}460}461462export class ZenHideEditorTabsAction extends AbstractSetShowTabsAction {463464static readonly ID = 'workbench.action.zenHideEditorTabs';465466constructor() {467const precondition = ContextKeyExpr.and(ContextKeyExpr.equals(`config.${ZenModeSettings.SHOW_TABS}`, EditorTabsMode.NONE).negate(), InEditorZenModeContext)!;468const title = localize2('hideEditorTabsZenMode', 'Hide Editor Tabs in Zen Mode');469super(ZenModeSettings.SHOW_TABS, EditorTabsMode.NONE, title, ZenHideEditorTabsAction.ID, precondition, localize2('hideEditorTabsZenModeDescription', "Hide Tab Bar in Zen Mode"));470}471}472473// --- Show Multiple Editor Tabs474475export class ShowMultipleEditorTabsAction extends AbstractSetShowTabsAction {476477static readonly ID = 'workbench.action.showMultipleEditorTabs';478479constructor() {480const precondition = ContextKeyExpr.and(ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_TABS_MODE}`, EditorTabsMode.MULTIPLE).negate(), InEditorZenModeContext.negate())!;481const title = localize2('showMultipleEditorTabs', 'Show Multiple Editor Tabs');482483super(LayoutSettings.EDITOR_TABS_MODE, EditorTabsMode.MULTIPLE, title, ShowMultipleEditorTabsAction.ID, precondition, localize2('showMultipleEditorTabsDescription', "Show Tab Bar with multiple tabs"));484}485}486487export class ZenShowMultipleEditorTabsAction extends AbstractSetShowTabsAction {488489static readonly ID = 'workbench.action.zenShowMultipleEditorTabs';490491constructor() {492const precondition = ContextKeyExpr.and(ContextKeyExpr.equals(`config.${ZenModeSettings.SHOW_TABS}`, EditorTabsMode.MULTIPLE).negate(), InEditorZenModeContext)!;493const title = localize2('showMultipleEditorTabsZenMode', 'Show Multiple Editor Tabs in Zen Mode');494495super(ZenModeSettings.SHOW_TABS, EditorTabsMode.MULTIPLE, title, ZenShowMultipleEditorTabsAction.ID, precondition, localize2('showMultipleEditorTabsZenModeDescription', "Show Tab Bar in Zen Mode"));496}497}498499// --- Show Single Editor Tab500501export class ShowSingleEditorTabAction extends AbstractSetShowTabsAction {502503static readonly ID = 'workbench.action.showEditorTab';504505constructor() {506const precondition = ContextKeyExpr.and(ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_TABS_MODE}`, EditorTabsMode.SINGLE).negate(), InEditorZenModeContext.negate())!;507const title = localize2('showSingleEditorTab', 'Show Single Editor Tab');508509super(LayoutSettings.EDITOR_TABS_MODE, EditorTabsMode.SINGLE, title, ShowSingleEditorTabAction.ID, precondition, localize2('showSingleEditorTabDescription', "Show Tab Bar with one Tab"));510}511}512513export class ZenShowSingleEditorTabAction extends AbstractSetShowTabsAction {514515static readonly ID = 'workbench.action.zenShowEditorTab';516517constructor() {518const precondition = ContextKeyExpr.and(ContextKeyExpr.equals(`config.${ZenModeSettings.SHOW_TABS}`, EditorTabsMode.SINGLE).negate(), InEditorZenModeContext)!;519const title = localize2('showSingleEditorTabZenMode', 'Show Single Editor Tab in Zen Mode');520521super(ZenModeSettings.SHOW_TABS, EditorTabsMode.SINGLE, title, ZenShowSingleEditorTabAction.ID, precondition, localize2('showSingleEditorTabZenModeDescription', "Show Tab Bar in Zen Mode with one Tab"));522}523}524525registerAction2(HideEditorTabsAction);526registerAction2(ZenHideEditorTabsAction);527registerAction2(ShowMultipleEditorTabsAction);528registerAction2(ZenShowMultipleEditorTabsAction);529registerAction2(ShowSingleEditorTabAction);530registerAction2(ZenShowSingleEditorTabAction);531532// --- Tab Bar Submenu in View Appearance Menu533534MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {535submenu: MenuId.EditorTabsBarShowTabsSubmenu,536title: localize('tabBar', "Tab Bar"),537group: '3_workbench_layout_move',538order: 10,539when: InEditorZenModeContext.negate()540});541542MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {543submenu: MenuId.EditorTabsBarShowTabsZenModeSubmenu,544title: localize('tabBar', "Tab Bar"),545group: '3_workbench_layout_move',546order: 10,547when: InEditorZenModeContext548});549550// --- Show Editor Actions in Title Bar551552export class EditorActionsTitleBarAction extends Action2 {553554static readonly ID = 'workbench.action.editorActionsTitleBar';555556constructor() {557super({558id: EditorActionsTitleBarAction.ID,559title: localize2('moveEditorActionsToTitleBar', "Move Editor Actions to Title Bar"),560category: Categories.View,561precondition: ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_ACTIONS_LOCATION}`, EditorActionsLocation.TITLEBAR).negate(),562metadata: { description: localize2('moveEditorActionsToTitleBarDescription', "Move Editor Actions from the tab bar to the title bar") },563f1: true564});565}566567run(accessor: ServicesAccessor): Promise<void> {568const configurationService = accessor.get(IConfigurationService);569return configurationService.updateValue(LayoutSettings.EDITOR_ACTIONS_LOCATION, EditorActionsLocation.TITLEBAR);570}571}572registerAction2(EditorActionsTitleBarAction);573574// --- Editor Actions Default Position575576export class EditorActionsDefaultAction extends Action2 {577578static readonly ID = 'workbench.action.editorActionsDefault';579580constructor() {581super({582id: EditorActionsDefaultAction.ID,583title: localize2('moveEditorActionsToTabBar', "Move Editor Actions to Tab Bar"),584category: Categories.View,585precondition: ContextKeyExpr.and(586ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_ACTIONS_LOCATION}`, EditorActionsLocation.DEFAULT).negate(),587ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_TABS_MODE}`, EditorTabsMode.NONE).negate(),588),589metadata: { description: localize2('moveEditorActionsToTabBarDescription', "Move Editor Actions from the title bar to the tab bar") },590f1: true591});592}593594run(accessor: ServicesAccessor): Promise<void> {595const configurationService = accessor.get(IConfigurationService);596return configurationService.updateValue(LayoutSettings.EDITOR_ACTIONS_LOCATION, EditorActionsLocation.DEFAULT);597}598}599registerAction2(EditorActionsDefaultAction);600601// --- Hide Editor Actions602603export class HideEditorActionsAction extends Action2 {604605static readonly ID = 'workbench.action.hideEditorActions';606607constructor() {608super({609id: HideEditorActionsAction.ID,610title: localize2('hideEditorActons', "Hide Editor Actions"),611category: Categories.View,612precondition: ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_ACTIONS_LOCATION}`, EditorActionsLocation.HIDDEN).negate(),613metadata: { description: localize2('hideEditorActonsDescription', "Hide Editor Actions in the tab and title bar") },614f1: true615});616}617618run(accessor: ServicesAccessor): Promise<void> {619const configurationService = accessor.get(IConfigurationService);620return configurationService.updateValue(LayoutSettings.EDITOR_ACTIONS_LOCATION, EditorActionsLocation.HIDDEN);621}622}623registerAction2(HideEditorActionsAction);624625// --- Hide Editor Actions626627export class ShowEditorActionsAction extends Action2 {628629static readonly ID = 'workbench.action.showEditorActions';630631constructor() {632super({633id: ShowEditorActionsAction.ID,634title: localize2('showEditorActons', "Show Editor Actions"),635category: Categories.View,636precondition: ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_ACTIONS_LOCATION}`, EditorActionsLocation.HIDDEN),637metadata: { description: localize2('showEditorActonsDescription', "Make Editor Actions visible.") },638f1: true639});640}641642run(accessor: ServicesAccessor): Promise<void> {643const configurationService = accessor.get(IConfigurationService);644return configurationService.updateValue(LayoutSettings.EDITOR_ACTIONS_LOCATION, EditorActionsLocation.DEFAULT);645}646}647registerAction2(ShowEditorActionsAction);648649// --- Editor Actions Position Submenu in View Appearance Menu650651MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {652submenu: MenuId.EditorActionsPositionSubmenu,653title: localize('editorActionsPosition', "Editor Actions Position"),654group: '3_workbench_layout_move',655order: 11656});657658// --- Configure Tabs Layout659660export class ConfigureEditorTabsAction extends Action2 {661662static readonly ID = 'workbench.action.configureEditorTabs';663664constructor() {665super({666id: ConfigureEditorTabsAction.ID,667title: localize2('configureTabs', "Configure Tabs"),668category: Categories.View,669});670}671672run(accessor: ServicesAccessor) {673const preferencesService = accessor.get(IPreferencesService);674preferencesService.openSettings({ jsonEditor: false, query: 'workbench.editor tab' });675}676}677registerAction2(ConfigureEditorTabsAction);678679// --- Configure Editor680681export class ConfigureEditorAction extends Action2 {682683static readonly ID = 'workbench.action.configureEditor';684685constructor() {686super({687id: ConfigureEditorAction.ID,688title: localize2('configureEditors', "Configure Editors"),689category: Categories.View,690});691}692693run(accessor: ServicesAccessor) {694const preferencesService = accessor.get(IPreferencesService);695preferencesService.openSettings({ jsonEditor: false, query: 'workbench.editor' });696}697}698registerAction2(ConfigureEditorAction);699700// --- Toggle Pinned Tabs On Separate Row701702registerAction2(class extends Action2 {703704constructor() {705super({706id: 'workbench.action.toggleSeparatePinnedEditorTabs',707title: localize2('toggleSeparatePinnedEditorTabs', "Separate Pinned Editor Tabs"),708category: Categories.View,709precondition: ContextKeyExpr.equals(`config.${LayoutSettings.EDITOR_TABS_MODE}`, EditorTabsMode.MULTIPLE),710metadata: { description: localize2('toggleSeparatePinnedEditorTabsDescription', "Toggle whether pinned editor tabs are shown on a separate row above unpinned tabs.") },711f1: true712});713}714715run(accessor: ServicesAccessor): Promise<void> {716const configurationService = accessor.get(IConfigurationService);717718const oldettingValue = configurationService.getValue<string>('workbench.editor.pinnedTabsOnSeparateRow');719const newSettingValue = !oldettingValue;720721return configurationService.updateValue('workbench.editor.pinnedTabsOnSeparateRow', newSettingValue);722}723});724725// --- Toggle Zen Mode726727registerAction2(class extends Action2 {728729constructor() {730super({731id: 'workbench.action.toggleZenMode',732title: {733...localize2('toggleZenMode', "Toggle Zen Mode"),734mnemonicTitle: localize({ key: 'miToggleZenMode', comment: ['&& denotes a mnemonic'] }, "Zen Mode"),735},736precondition: IsAuxiliaryWindowFocusedContext.toNegated(),737category: Categories.View,738f1: true,739keybinding: {740weight: KeybindingWeight.WorkbenchContrib,741primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyZ)742},743toggled: InEditorZenModeContext,744menu: [{745id: MenuId.MenubarAppearanceMenu,746group: '1_toggle_view',747order: 2748}]749});750}751752run(accessor: ServicesAccessor): void {753return accessor.get(IWorkbenchLayoutService).toggleZenMode();754}755});756757KeybindingsRegistry.registerCommandAndKeybindingRule({758id: 'workbench.action.exitZenMode',759weight: KeybindingWeight.EditorContrib - 1000,760handler(accessor: ServicesAccessor) {761const layoutService = accessor.get(IWorkbenchLayoutService);762const contextKeyService = accessor.get(IContextKeyService);763if (InEditorZenModeContext.getValue(contextKeyService)) {764layoutService.toggleZenMode();765}766},767when: InEditorZenModeContext,768primary: KeyChord(KeyCode.Escape, KeyCode.Escape)769});770771// --- Toggle Menu Bar772773if (isWindows || isLinux || isWeb) {774registerAction2(class ToggleMenubarAction extends Action2 {775776constructor() {777super({778id: 'workbench.action.toggleMenuBar',779title: {780...localize2('toggleMenuBar', "Toggle Menu Bar"),781mnemonicTitle: localize({ key: 'miMenuBar', comment: ['&& denotes a mnemonic'] }, "Menu &&Bar"),782},783category: Categories.View,784f1: true,785toggled: ContextKeyExpr.and(IsMacNativeContext.toNegated(), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'hidden'), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'toggle'), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'compact')),786menu: [{787id: MenuId.MenubarAppearanceMenu,788group: '2_workbench_layout',789order: 0790}]791});792}793794run(accessor: ServicesAccessor): void {795return accessor.get(IWorkbenchLayoutService).toggleMenuBar();796}797});798799// Add separately to title bar context menu so we can use a different title800for (const menuId of [MenuId.TitleBarContext, MenuId.TitleBarTitleContext]) {801MenuRegistry.appendMenuItem(menuId, {802command: {803id: 'workbench.action.toggleMenuBar',804title: localize('miMenuBarNoMnemonic', "Menu Bar"),805toggled: ContextKeyExpr.and(IsMacNativeContext.toNegated(), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'hidden'), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'toggle'), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'compact'))806},807when: ContextKeyExpr.and(IsAuxiliaryWindowFocusedContext.toNegated(), ContextKeyExpr.notEquals(TitleBarStyleContext.key, TitlebarStyle.NATIVE), IsMainWindowFullscreenContext.negate()),808group: '2_config',809order: 0810});811}812}813814// --- Reset View Locations815816registerAction2(class extends Action2 {817818constructor() {819super({820id: 'workbench.action.resetViewLocations',821title: localize2('resetViewLocations', "Reset View Locations"),822category: Categories.View,823f1: true824});825}826827run(accessor: ServicesAccessor): void {828return accessor.get(IViewDescriptorService).reset();829}830});831832// --- Move View833834registerAction2(class extends Action2 {835836constructor() {837super({838id: 'workbench.action.moveView',839title: localize2('moveView', "Move View"),840category: Categories.View,841f1: true842});843}844845async run(accessor: ServicesAccessor): Promise<void> {846const viewDescriptorService = accessor.get(IViewDescriptorService);847const instantiationService = accessor.get(IInstantiationService);848const quickInputService = accessor.get(IQuickInputService);849const contextKeyService = accessor.get(IContextKeyService);850const paneCompositePartService = accessor.get(IPaneCompositePartService);851852const focusedViewId = FocusedViewContext.getValue(contextKeyService);853let viewId: string;854855if (focusedViewId && viewDescriptorService.getViewDescriptorById(focusedViewId)?.canMoveView) {856viewId = focusedViewId;857}858859try {860viewId = await this.getView(quickInputService, viewDescriptorService, paneCompositePartService, viewId!);861if (!viewId) {862return;863}864865const moveFocusedViewAction = new MoveFocusedViewAction();866instantiationService.invokeFunction(accessor => moveFocusedViewAction.run(accessor, viewId));867} catch { }868}869870private getViewItems(viewDescriptorService: IViewDescriptorService, paneCompositePartService: IPaneCompositePartService): Array<QuickPickItem> {871const results: Array<QuickPickItem> = [];872873const viewlets = paneCompositePartService.getVisiblePaneCompositeIds(ViewContainerLocation.Sidebar);874viewlets.forEach(viewletId => {875const container = viewDescriptorService.getViewContainerById(viewletId)!;876const containerModel = viewDescriptorService.getViewContainerModel(container);877878let hasAddedView = false;879containerModel.visibleViewDescriptors.forEach(viewDescriptor => {880if (viewDescriptor.canMoveView) {881if (!hasAddedView) {882results.push({883type: 'separator',884label: localize('sidebarContainer', "Side Bar / {0}", containerModel.title)885});886hasAddedView = true;887}888889results.push({890id: viewDescriptor.id,891label: viewDescriptor.name.value892});893}894});895});896897const panels = paneCompositePartService.getPinnedPaneCompositeIds(ViewContainerLocation.Panel);898panels.forEach(panel => {899const container = viewDescriptorService.getViewContainerById(panel)!;900const containerModel = viewDescriptorService.getViewContainerModel(container);901902let hasAddedView = false;903containerModel.visibleViewDescriptors.forEach(viewDescriptor => {904if (viewDescriptor.canMoveView) {905if (!hasAddedView) {906results.push({907type: 'separator',908label: localize('panelContainer', "Panel / {0}", containerModel.title)909});910hasAddedView = true;911}912913results.push({914id: viewDescriptor.id,915label: viewDescriptor.name.value916});917}918});919});920921922const sidePanels = paneCompositePartService.getPinnedPaneCompositeIds(ViewContainerLocation.AuxiliaryBar);923sidePanels.forEach(panel => {924const container = viewDescriptorService.getViewContainerById(panel)!;925const containerModel = viewDescriptorService.getViewContainerModel(container);926927let hasAddedView = false;928containerModel.visibleViewDescriptors.forEach(viewDescriptor => {929if (viewDescriptor.canMoveView) {930if (!hasAddedView) {931results.push({932type: 'separator',933label: localize('secondarySideBarContainer', "Secondary Side Bar / {0}", containerModel.title)934});935hasAddedView = true;936}937938results.push({939id: viewDescriptor.id,940label: viewDescriptor.name.value941});942}943});944});945946return results;947}948949private async getView(quickInputService: IQuickInputService, viewDescriptorService: IViewDescriptorService, paneCompositePartService: IPaneCompositePartService, viewId?: string): Promise<string> {950const disposables = new DisposableStore();951const quickPick = disposables.add(quickInputService.createQuickPick({ useSeparators: true }));952quickPick.placeholder = localize('moveFocusedView.selectView', "Select a View to Move");953quickPick.items = this.getViewItems(viewDescriptorService, paneCompositePartService);954quickPick.selectedItems = quickPick.items.filter(item => (item as IQuickPickItem).id === viewId) as IQuickPickItem[];955956return new Promise((resolve, reject) => {957disposables.add(quickPick.onDidAccept(() => {958const viewId = quickPick.selectedItems[0];959if (viewId.id) {960resolve(viewId.id);961} else {962reject();963}964965quickPick.hide();966}));967968disposables.add(quickPick.onDidHide(() => {969disposables.dispose();970reject();971}));972973quickPick.show();974});975}976});977978// --- Move Focused View979980class MoveFocusedViewAction extends Action2 {981982constructor() {983super({984id: 'workbench.action.moveFocusedView',985title: localize2('moveFocusedView', "Move Focused View"),986category: Categories.View,987precondition: FocusedViewContext.notEqualsTo(''),988f1: true989});990}991992run(accessor: ServicesAccessor, viewId?: string): void {993const viewDescriptorService = accessor.get(IViewDescriptorService);994const viewsService = accessor.get(IViewsService);995const quickInputService = accessor.get(IQuickInputService);996const contextKeyService = accessor.get(IContextKeyService);997const dialogService = accessor.get(IDialogService);998const paneCompositePartService = accessor.get(IPaneCompositePartService);9991000const focusedViewId = viewId || FocusedViewContext.getValue(contextKeyService);10011002if (focusedViewId === undefined || focusedViewId.trim() === '') {1003dialogService.error(localize('moveFocusedView.error.noFocusedView', "There is no view currently focused."));1004return;1005}10061007const viewDescriptor = viewDescriptorService.getViewDescriptorById(focusedViewId);1008if (!viewDescriptor || !viewDescriptor.canMoveView) {1009dialogService.error(localize('moveFocusedView.error.nonMovableView', "The currently focused view is not movable."));1010return;1011}10121013const disposables = new DisposableStore();1014const quickPick = disposables.add(quickInputService.createQuickPick({ useSeparators: true }));1015quickPick.placeholder = localize('moveFocusedView.selectDestination', "Select a Destination for the View");1016quickPick.title = localize({ key: 'moveFocusedView.title', comment: ['{0} indicates the title of the view the user has selected to move.'] }, "View: Move {0}", viewDescriptor.name.value);10171018const items: Array<IQuickPickItem | IQuickPickSeparator> = [];1019const currentContainer = viewDescriptorService.getViewContainerByViewId(focusedViewId)!;1020const currentLocation = viewDescriptorService.getViewLocationById(focusedViewId)!;1021const isViewSolo = viewDescriptorService.getViewContainerModel(currentContainer).allViewDescriptors.length === 1;10221023if (!(isViewSolo && currentLocation === ViewContainerLocation.Panel)) {1024items.push({1025id: '_.panel.newcontainer',1026label: localize({ key: 'moveFocusedView.newContainerInPanel', comment: ['Creates a new top-level tab in the panel.'] }, "New Panel Entry"),1027});1028}10291030if (!(isViewSolo && currentLocation === ViewContainerLocation.Sidebar)) {1031items.push({1032id: '_.sidebar.newcontainer',1033label: localize('moveFocusedView.newContainerInSidebar', "New Side Bar Entry")1034});1035}10361037if (!(isViewSolo && currentLocation === ViewContainerLocation.AuxiliaryBar)) {1038items.push({1039id: '_.auxiliarybar.newcontainer',1040label: localize('moveFocusedView.newContainerInSidePanel', "New Secondary Side Bar Entry")1041});1042}10431044items.push({1045type: 'separator',1046label: localize('sidebar', "Side Bar")1047});10481049const pinnedViewlets = paneCompositePartService.getVisiblePaneCompositeIds(ViewContainerLocation.Sidebar);1050items.push(...pinnedViewlets1051.filter(viewletId => {1052if (viewletId === viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) {1053return false;1054}10551056return !viewDescriptorService.getViewContainerById(viewletId)!.rejectAddedViews;1057})1058.map(viewletId => {1059return {1060id: viewletId,1061label: viewDescriptorService.getViewContainerModel(viewDescriptorService.getViewContainerById(viewletId)!)!.title1062};1063}));10641065items.push({1066type: 'separator',1067label: localize('panel', "Panel")1068});10691070const pinnedPanels = paneCompositePartService.getPinnedPaneCompositeIds(ViewContainerLocation.Panel);1071items.push(...pinnedPanels1072.filter(panel => {1073if (panel === viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) {1074return false;1075}10761077return !viewDescriptorService.getViewContainerById(panel)!.rejectAddedViews;1078})1079.map(panel => {1080return {1081id: panel,1082label: viewDescriptorService.getViewContainerModel(viewDescriptorService.getViewContainerById(panel)!)!.title1083};1084}));10851086items.push({1087type: 'separator',1088label: localize('secondarySideBar', "Secondary Side Bar")1089});10901091const pinnedAuxPanels = paneCompositePartService.getPinnedPaneCompositeIds(ViewContainerLocation.AuxiliaryBar);1092items.push(...pinnedAuxPanels1093.filter(panel => {1094if (panel === viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) {1095return false;1096}10971098return !viewDescriptorService.getViewContainerById(panel)!.rejectAddedViews;1099})1100.map(panel => {1101return {1102id: panel,1103label: viewDescriptorService.getViewContainerModel(viewDescriptorService.getViewContainerById(panel)!)!.title1104};1105}));11061107quickPick.items = items;11081109disposables.add(quickPick.onDidAccept(() => {1110const destination = quickPick.selectedItems[0];11111112if (destination.id === '_.panel.newcontainer') {1113viewDescriptorService.moveViewToLocation(viewDescriptor, ViewContainerLocation.Panel, this.desc.id);1114viewsService.openView(focusedViewId, true);1115} else if (destination.id === '_.sidebar.newcontainer') {1116viewDescriptorService.moveViewToLocation(viewDescriptor, ViewContainerLocation.Sidebar, this.desc.id);1117viewsService.openView(focusedViewId, true);1118} else if (destination.id === '_.auxiliarybar.newcontainer') {1119viewDescriptorService.moveViewToLocation(viewDescriptor, ViewContainerLocation.AuxiliaryBar, this.desc.id);1120viewsService.openView(focusedViewId, true);1121} else if (destination.id) {1122viewDescriptorService.moveViewsToContainer([viewDescriptor], viewDescriptorService.getViewContainerById(destination.id)!, undefined, this.desc.id);1123viewsService.openView(focusedViewId, true);1124}11251126quickPick.hide();1127}));11281129disposables.add(quickPick.onDidHide(() => disposables.dispose()));11301131quickPick.show();1132}1133}11341135registerAction2(MoveFocusedViewAction);11361137// --- Reset Focused View Location11381139registerAction2(class extends Action2 {11401141constructor() {1142super({1143id: 'workbench.action.resetFocusedViewLocation',1144title: localize2('resetFocusedViewLocation', "Reset Focused View Location"),1145category: Categories.View,1146f1: true,1147precondition: FocusedViewContext.notEqualsTo('')1148});1149}11501151run(accessor: ServicesAccessor): void {1152const viewDescriptorService = accessor.get(IViewDescriptorService);1153const contextKeyService = accessor.get(IContextKeyService);1154const dialogService = accessor.get(IDialogService);1155const viewsService = accessor.get(IViewsService);11561157const focusedViewId = FocusedViewContext.getValue(contextKeyService);11581159let viewDescriptor: IViewDescriptor | null = null;1160if (focusedViewId !== undefined && focusedViewId.trim() !== '') {1161viewDescriptor = viewDescriptorService.getViewDescriptorById(focusedViewId);1162}11631164if (!viewDescriptor) {1165dialogService.error(localize('resetFocusedView.error.noFocusedView', "There is no view currently focused."));1166return;1167}11681169const defaultContainer = viewDescriptorService.getDefaultContainerById(viewDescriptor.id);1170if (!defaultContainer || defaultContainer === viewDescriptorService.getViewContainerByViewId(viewDescriptor.id)) {1171return;1172}11731174viewDescriptorService.moveViewsToContainer([viewDescriptor], defaultContainer, undefined, this.desc.id);1175viewsService.openView(viewDescriptor.id, true);1176}1177});11781179// --- Resize View11801181abstract class BaseResizeViewAction extends Action2 {11821183protected static readonly RESIZE_INCREMENT = 60; // This is a css pixel size11841185protected resizePart(widthChange: number, heightChange: number, layoutService: IWorkbenchLayoutService, partToResize?: Parts): void {11861187let part: Parts | undefined;1188if (partToResize === undefined) {1189const isEditorFocus = layoutService.hasFocus(Parts.EDITOR_PART);1190const isSidebarFocus = layoutService.hasFocus(Parts.SIDEBAR_PART);1191const isPanelFocus = layoutService.hasFocus(Parts.PANEL_PART);1192const isAuxiliaryBarFocus = layoutService.hasFocus(Parts.AUXILIARYBAR_PART);11931194if (isSidebarFocus) {1195part = Parts.SIDEBAR_PART;1196} else if (isPanelFocus) {1197part = Parts.PANEL_PART;1198} else if (isEditorFocus) {1199part = Parts.EDITOR_PART;1200} else if (isAuxiliaryBarFocus) {1201part = Parts.AUXILIARYBAR_PART;1202}1203} else {1204part = partToResize;1205}12061207if (part) {1208layoutService.resizePart(part, widthChange, heightChange);1209}1210}1211}12121213class IncreaseViewSizeAction extends BaseResizeViewAction {12141215constructor() {1216super({1217id: 'workbench.action.increaseViewSize',1218title: localize2('increaseViewSize', 'Increase Current View Size'),1219f1: true,1220precondition: IsAuxiliaryWindowFocusedContext.toNegated()1221});1222}12231224run(accessor: ServicesAccessor): void {1225this.resizePart(BaseResizeViewAction.RESIZE_INCREMENT, BaseResizeViewAction.RESIZE_INCREMENT, accessor.get(IWorkbenchLayoutService));1226}1227}12281229class IncreaseViewWidthAction extends BaseResizeViewAction {12301231constructor() {1232super({1233id: 'workbench.action.increaseViewWidth',1234title: localize2('increaseEditorWidth', 'Increase Editor Width'),1235f1: true,1236precondition: IsAuxiliaryWindowFocusedContext.toNegated()1237});1238}12391240run(accessor: ServicesAccessor): void {1241this.resizePart(BaseResizeViewAction.RESIZE_INCREMENT, 0, accessor.get(IWorkbenchLayoutService), Parts.EDITOR_PART);1242}1243}12441245class IncreaseViewHeightAction extends BaseResizeViewAction {12461247constructor() {1248super({1249id: 'workbench.action.increaseViewHeight',1250title: localize2('increaseEditorHeight', 'Increase Editor Height'),1251f1: true,1252precondition: IsAuxiliaryWindowFocusedContext.toNegated()1253});1254}12551256run(accessor: ServicesAccessor): void {1257this.resizePart(0, BaseResizeViewAction.RESIZE_INCREMENT, accessor.get(IWorkbenchLayoutService), Parts.EDITOR_PART);1258}1259}12601261class DecreaseViewSizeAction extends BaseResizeViewAction {12621263constructor() {1264super({1265id: 'workbench.action.decreaseViewSize',1266title: localize2('decreaseViewSize', 'Decrease Current View Size'),1267f1: true,1268precondition: IsAuxiliaryWindowFocusedContext.toNegated()1269});1270}12711272run(accessor: ServicesAccessor): void {1273this.resizePart(-BaseResizeViewAction.RESIZE_INCREMENT, -BaseResizeViewAction.RESIZE_INCREMENT, accessor.get(IWorkbenchLayoutService));1274}1275}12761277class DecreaseViewWidthAction extends BaseResizeViewAction {1278constructor() {1279super({1280id: 'workbench.action.decreaseViewWidth',1281title: localize2('decreaseEditorWidth', 'Decrease Editor Width'),1282f1: true,1283precondition: IsAuxiliaryWindowFocusedContext.toNegated()1284});1285}12861287run(accessor: ServicesAccessor): void {1288this.resizePart(-BaseResizeViewAction.RESIZE_INCREMENT, 0, accessor.get(IWorkbenchLayoutService), Parts.EDITOR_PART);1289}1290}12911292class DecreaseViewHeightAction extends BaseResizeViewAction {12931294constructor() {1295super({1296id: 'workbench.action.decreaseViewHeight',1297title: localize2('decreaseEditorHeight', 'Decrease Editor Height'),1298f1: true,1299precondition: IsAuxiliaryWindowFocusedContext.toNegated()1300});1301}13021303run(accessor: ServicesAccessor): void {1304this.resizePart(0, -BaseResizeViewAction.RESIZE_INCREMENT, accessor.get(IWorkbenchLayoutService), Parts.EDITOR_PART);1305}1306}13071308registerAction2(IncreaseViewSizeAction);1309registerAction2(IncreaseViewWidthAction);1310registerAction2(IncreaseViewHeightAction);13111312registerAction2(DecreaseViewSizeAction);1313registerAction2(DecreaseViewWidthAction);1314registerAction2(DecreaseViewHeightAction);13151316//#region Quick Input Alignment Actions13171318registerAction2(class AlignQuickInputTopAction extends Action2 {13191320constructor() {1321super({1322id: 'workbench.action.alignQuickInputTop',1323title: localize2('alignQuickInputTop', 'Align Quick Input Top'),1324f1: false1325});1326}13271328run(accessor: ServicesAccessor): void {1329const quickInputService = accessor.get(IQuickInputService);1330quickInputService.setAlignment('top');1331}1332});13331334registerAction2(class AlignQuickInputCenterAction extends Action2 {13351336constructor() {1337super({1338id: 'workbench.action.alignQuickInputCenter',1339title: localize2('alignQuickInputCenter', 'Align Quick Input Center'),1340f1: false1341});1342}13431344run(accessor: ServicesAccessor): void {1345const quickInputService = accessor.get(IQuickInputService);1346quickInputService.setAlignment('center');1347}1348});13491350//#endregion13511352type ContextualLayoutVisualIcon = { iconA: ThemeIcon; iconB: ThemeIcon; whenA: ContextKeyExpression };1353type LayoutVisualIcon = ThemeIcon | ContextualLayoutVisualIcon;13541355function isContextualLayoutVisualIcon(icon: LayoutVisualIcon): icon is ContextualLayoutVisualIcon {1356return (icon as ContextualLayoutVisualIcon).iconA !== undefined;1357}13581359interface CustomizeLayoutItem {1360id: string;1361active: ContextKeyExpression;1362label: string;1363activeIcon: ThemeIcon;1364visualIcon?: LayoutVisualIcon;1365activeAriaLabel: string;1366inactiveIcon?: ThemeIcon;1367inactiveAriaLabel?: string;1368useButtons: boolean;1369}13701371const CreateToggleLayoutItem = (id: string, active: ContextKeyExpression, label: string, visualIcon?: LayoutVisualIcon): CustomizeLayoutItem => {1372return {1373id,1374active,1375label,1376visualIcon,1377activeIcon: Codicon.eye,1378inactiveIcon: Codicon.eyeClosed,1379activeAriaLabel: localize('selectToHide', "Select to Hide"),1380inactiveAriaLabel: localize('selectToShow', "Select to Show"),1381useButtons: true,1382};1383};13841385const CreateOptionLayoutItem = (id: string, active: ContextKeyExpression, label: string, visualIcon?: LayoutVisualIcon): CustomizeLayoutItem => {1386return {1387id,1388active,1389label,1390visualIcon,1391activeIcon: Codicon.check,1392activeAriaLabel: localize('active', "Active"),1393useButtons: false1394};1395};13961397const MenuBarToggledContext = ContextKeyExpr.and(IsMacNativeContext.toNegated(), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'hidden'), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'toggle'), ContextKeyExpr.notEquals(`config.${MenuSettings.MenuBarVisibility}`, 'compact')) as ContextKeyExpression;1398const ToggleVisibilityActions: CustomizeLayoutItem[] = [];1399if (!isMacintosh || !isNative) {1400ToggleVisibilityActions.push(CreateToggleLayoutItem('workbench.action.toggleMenuBar', MenuBarToggledContext, localize('menuBar', "Menu Bar"), menubarIcon));1401}14021403ToggleVisibilityActions.push(...[1404CreateToggleLayoutItem(ToggleActivityBarVisibilityActionId, ContextKeyExpr.notEquals('config.workbench.activityBar.location', 'hidden'), localize('activityBar', "Activity Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: activityBarLeftIcon, iconB: activityBarRightIcon }),1405CreateToggleLayoutItem(ToggleSidebarVisibilityAction.ID, SideBarVisibleContext, localize('sideBar', "Primary Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelLeftIcon, iconB: panelRightIcon }),1406CreateToggleLayoutItem(ToggleAuxiliaryBarAction.ID, AuxiliaryBarVisibleContext, localize('secondarySideBar', "Secondary Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelRightIcon, iconB: panelLeftIcon }),1407CreateToggleLayoutItem(TogglePanelAction.ID, PanelVisibleContext, localize('panel', "Panel"), panelIcon),1408CreateToggleLayoutItem(ToggleStatusbarVisibilityAction.ID, ContextKeyExpr.equals('config.workbench.statusBar.visible', true), localize('statusBar', "Status Bar"), statusBarIcon),1409]);14101411const MoveSideBarActions: CustomizeLayoutItem[] = [1412CreateOptionLayoutItem(MoveSidebarLeftAction.ID, ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), localize('leftSideBar', "Left"), panelLeftIcon),1413CreateOptionLayoutItem(MoveSidebarRightAction.ID, ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), localize('rightSideBar', "Right"), panelRightIcon),1414];14151416const AlignPanelActions: CustomizeLayoutItem[] = [1417CreateOptionLayoutItem('workbench.action.alignPanelLeft', PanelAlignmentContext.isEqualTo('left'), localize('leftPanel', "Left"), panelAlignmentLeftIcon),1418CreateOptionLayoutItem('workbench.action.alignPanelRight', PanelAlignmentContext.isEqualTo('right'), localize('rightPanel', "Right"), panelAlignmentRightIcon),1419CreateOptionLayoutItem('workbench.action.alignPanelCenter', PanelAlignmentContext.isEqualTo('center'), localize('centerPanel', "Center"), panelAlignmentCenterIcon),1420CreateOptionLayoutItem('workbench.action.alignPanelJustify', PanelAlignmentContext.isEqualTo('justify'), localize('justifyPanel', "Justify"), panelAlignmentJustifyIcon),1421];14221423const QuickInputActions: CustomizeLayoutItem[] = [1424CreateOptionLayoutItem('workbench.action.alignQuickInputTop', QuickInputAlignmentContextKey.isEqualTo('top'), localize('top', "Top"), quickInputAlignmentTopIcon),1425CreateOptionLayoutItem('workbench.action.alignQuickInputCenter', QuickInputAlignmentContextKey.isEqualTo('center'), localize('center', "Center"), quickInputAlignmentCenterIcon),1426];14271428const MiscLayoutOptions: CustomizeLayoutItem[] = [1429CreateOptionLayoutItem('workbench.action.toggleFullScreen', IsMainWindowFullscreenContext, localize('fullscreen', "Full Screen"), fullscreenIcon),1430CreateOptionLayoutItem('workbench.action.toggleZenMode', InEditorZenModeContext, localize('zenMode', "Zen Mode"), zenModeIcon),1431CreateOptionLayoutItem('workbench.action.toggleCenteredLayout', IsMainEditorCenteredLayoutContext, localize('centeredLayout', "Centered Layout"), centerLayoutIcon),1432];14331434const LayoutContextKeySet = new Set<string>();1435for (const { active } of [...ToggleVisibilityActions, ...MoveSideBarActions, ...AlignPanelActions, ...QuickInputActions, ...MiscLayoutOptions]) {1436for (const key of active.keys()) {1437LayoutContextKeySet.add(key);1438}1439}14401441registerAction2(class CustomizeLayoutAction extends Action2 {14421443private _currentQuickPick?: IQuickPick<IQuickPickItem, { useSeparators: true }>;14441445constructor() {1446super({1447id: 'workbench.action.customizeLayout',1448title: localize2('customizeLayout', "Customize Layout..."),1449f1: true,1450icon: configureLayoutIcon,1451menu: [1452{1453id: MenuId.LayoutControlMenuSubmenu,1454group: 'z_end',1455},1456{1457id: MenuId.LayoutControlMenu,1458when: ContextKeyExpr.and(1459IsAuxiliaryWindowContext.toNegated(),1460ContextKeyExpr.equals('config.workbench.layoutControl.type', 'both')1461),1462group: '1_layout'1463}1464]1465});1466}14671468getItems(contextKeyService: IContextKeyService, keybindingService: IKeybindingService): QuickPickItem[] {1469const toQuickPickItem = (item: CustomizeLayoutItem): IQuickPickItem => {1470const toggled = item.active.evaluate(contextKeyService.getContext(null));1471let label = item.useButtons ?1472item.label :1473item.label + (toggled && item.activeIcon ? ` $(${item.activeIcon.id})` : (!toggled && item.inactiveIcon ? ` $(${item.inactiveIcon.id})` : ''));1474const ariaLabel =1475item.label + (toggled && item.activeAriaLabel ? ` (${item.activeAriaLabel})` : (!toggled && item.inactiveAriaLabel ? ` (${item.inactiveAriaLabel})` : ''));14761477if (item.visualIcon) {1478let icon = item.visualIcon;1479if (isContextualLayoutVisualIcon(icon)) {1480const useIconA = icon.whenA.evaluate(contextKeyService.getContext(null));1481icon = useIconA ? icon.iconA : icon.iconB;1482}14831484label = `$(${icon.id}) ${label}`;1485}14861487const icon = toggled ? item.activeIcon : item.inactiveIcon;14881489return {1490type: 'item',1491id: item.id,1492label,1493ariaLabel,1494keybinding: keybindingService.lookupKeybinding(item.id, contextKeyService),1495buttons: !item.useButtons ? undefined : [1496{1497alwaysVisible: false,1498tooltip: ariaLabel,1499iconClass: icon ? ThemeIcon.asClassName(icon) : undefined1500}1501]1502};1503};1504return [1505{1506type: 'separator',1507label: localize('toggleVisibility', "Visibility")1508},1509...ToggleVisibilityActions.map(toQuickPickItem),1510{1511type: 'separator',1512label: localize('sideBarPosition', "Primary Side Bar Position")1513},1514...MoveSideBarActions.map(toQuickPickItem),1515{1516type: 'separator',1517label: localize('panelAlignment', "Panel Alignment")1518},1519...AlignPanelActions.map(toQuickPickItem),1520{1521type: 'separator',1522label: localize('quickOpen', "Quick Input Position")1523},1524...QuickInputActions.map(toQuickPickItem),1525{1526type: 'separator',1527label: localize('layoutModes', "Modes"),1528},1529...MiscLayoutOptions.map(toQuickPickItem),1530];1531}15321533run(accessor: ServicesAccessor): void {1534if (this._currentQuickPick) {1535this._currentQuickPick.hide();1536return;1537}15381539const configurationService = accessor.get(IConfigurationService);1540const contextKeyService = accessor.get(IContextKeyService);1541const commandService = accessor.get(ICommandService);1542const quickInputService = accessor.get(IQuickInputService);1543const keybindingService = accessor.get(IKeybindingService);15441545const disposables = new DisposableStore();15461547const quickPick = disposables.add(quickInputService.createQuickPick({ useSeparators: true }));15481549this._currentQuickPick = quickPick;1550quickPick.items = this.getItems(contextKeyService, keybindingService);1551quickPick.ignoreFocusOut = true;1552quickPick.hideInput = true;1553quickPick.title = localize('customizeLayoutQuickPickTitle', "Customize Layout");15541555const closeButton = {1556alwaysVisible: true,1557iconClass: ThemeIcon.asClassName(Codicon.close),1558tooltip: localize('close', "Close")1559};15601561const resetButton = {1562alwaysVisible: true,1563iconClass: ThemeIcon.asClassName(Codicon.discard),1564tooltip: localize('restore defaults', "Restore Defaults")1565};15661567quickPick.buttons = [1568resetButton,1569closeButton1570];15711572let selectedItem: CustomizeLayoutItem | undefined = undefined;1573disposables.add(contextKeyService.onDidChangeContext(changeEvent => {1574if (changeEvent.affectsSome(LayoutContextKeySet)) {1575quickPick.items = this.getItems(contextKeyService, keybindingService);1576if (selectedItem) {1577quickPick.activeItems = quickPick.items.filter(item => (item as CustomizeLayoutItem).id === selectedItem?.id) as IQuickPickItem[];1578}15791580setTimeout(() => quickInputService.focus(), 0);1581}1582}));15831584disposables.add(quickPick.onDidAccept(event => {1585if (quickPick.selectedItems.length) {1586selectedItem = quickPick.selectedItems[0] as CustomizeLayoutItem;1587commandService.executeCommand(selectedItem.id);1588}1589}));15901591disposables.add(quickPick.onDidTriggerItemButton(event => {1592if (event.item) {1593selectedItem = event.item as CustomizeLayoutItem;1594commandService.executeCommand(selectedItem.id);1595}1596}));15971598disposables.add(quickPick.onDidTriggerButton((button) => {1599if (button === closeButton) {1600quickPick.hide();1601} else if (button === resetButton) {16021603const resetSetting = (id: string) => {1604const config = configurationService.inspect(id);1605configurationService.updateValue(id, config.defaultValue);1606};16071608// Reset all layout options1609resetSetting('workbench.activityBar.location');1610resetSetting('workbench.sideBar.location');1611resetSetting('workbench.statusBar.visible');1612resetSetting('workbench.panel.defaultLocation');16131614if (!isMacintosh || !isNative) {1615resetSetting('window.menuBarVisibility');1616}16171618commandService.executeCommand('workbench.action.alignPanelCenter');1619commandService.executeCommand('workbench.action.alignQuickInputTop');1620}1621}));16221623disposables.add(quickPick.onDidHide(() => {1624quickPick.dispose();1625}));16261627disposables.add(quickPick.onDispose(() => {1628this._currentQuickPick = undefined;1629disposables.dispose();1630}));16311632quickPick.show();1633}1634});163516361637