From 8be7dce50058ebededb17af09cedcc855bd18e23 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 23 May 2018 08:18:54 +0200 Subject: [PATCH] grid - introduce and use command for predefined editor layouts --- src/vs/workbench/browser/layout.ts | 6 +- .../parts/editor/editor.contribution.ts | 14 +- .../browser/parts/editor/editorActions.ts | 404 ++++++++++-------- .../browser/parts/editor/editorCommands.ts | 77 +++- .../browser/parts/editor/editorPart.ts | 11 +- .../group/common/editorGroupsService.ts | 9 +- .../workbench/test/workbenchTestServices.ts | 6 +- 7 files changed, 337 insertions(+), 190 deletions(-) diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 90fd9ecf35b..f37850d441d 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -688,8 +688,6 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr const sizeChangePxHeight = this.workbenchSize.height * (sizeChange / 100); let doLayout = false; - - switch (part) { case Parts.SIDEBAR_PART: this.sidebarWidth = this.sidebarWidth + sizeChangePxWidth; // Sidebar can not become smaller than MIN_PART_WIDTH @@ -728,8 +726,8 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr } else { const activeGroup = this.editorGroupService.activeGroup; - this.editorGroupService.resizeGroup(activeGroup, sizeChangePxWidth); - doLayout = false; + const activeGroupSize = this.editorGroupService.getSize(activeGroup); + this.editorGroupService.setSize(activeGroup, activeGroupSize + sizeChangePxWidth); } } diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 480f1198558..03208f9d117 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -35,7 +35,8 @@ import { OpenPreviousEditorInGroup, OpenNextRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorAction, OpenNextRecentlyUsedEditorInGroupAction, MoveEditorToPreviousGroupAction, MoveEditorToNextGroupAction, MoveEditorToFirstGroupAction, MoveEditorLeftInGroupAction, ClearRecentFilesAction, OpenLastEditorInGroup, SplitEditorGroupHorizontalAction, SplitEditorGroupVerticalAction, ShowEditorsInActiveGroupAction, MoveEditorToLastGroupAction, OpenFirstEditorInGroup, MoveGroupUpAction, MoveGroupDownAction, FocusLastGroupAction, SplitEditorGroupLeftAction, SplitEditorGroupRightAction, - SplitEditorGroupUpAction, SplitEditorGroupDownAction, MoveEditorToLeftGroupAction, MoveEditorToRightGroupAction, MoveEditorToAboveGroupAction, MoveEditorToBelowGroupAction, CloseAllEditorGroupsAction, JoinAllGroupsAction, FocusLeftGroup, FocusAboveGroup, FocusRightGroup, FocusBelowGroup + SplitEditorGroupUpAction, SplitEditorGroupDownAction, MoveEditorToLeftGroupAction, MoveEditorToRightGroupAction, MoveEditorToAboveGroupAction, MoveEditorToBelowGroupAction, CloseAllEditorGroupsAction, + JoinAllGroupsAction, FocusLeftGroup, FocusAboveGroup, FocusRightGroup, FocusBelowGroup, EditorLayoutSingleAction, EditorLayoutTwoColumnsAction, EditorLayoutThreeColumnsAction, EditorLayoutTwoByTwoGridAction, EditorLayoutTwoRowsAction, EditorLayoutThreeRowsAction, EditorLayoutThreeColumnsTopAction, EditorLayoutThreeColumnsRightAction, EditorLayoutGoldenRatioAction } from 'vs/workbench/browser/parts/editor/editorActions'; import * as editorCommands from 'vs/workbench/browser/parts/editor/editorCommands'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -357,6 +358,15 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateLastAction, Na registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPreviousEditorFromHistoryAction, OpenPreviousEditorFromHistoryAction.ID, OpenPreviousEditorFromHistoryAction.LABEL), 'Open Previous Editor from History'); registry.registerWorkbenchAction(new SyncActionDescriptor(ClearEditorHistoryAction, ClearEditorHistoryAction.ID, ClearEditorHistoryAction.LABEL), 'Clear Editor History'); registry.registerWorkbenchAction(new SyncActionDescriptor(RevertAndCloseEditorAction, RevertAndCloseEditorAction.ID, RevertAndCloseEditorAction.LABEL), 'View: Revert and Close Editor', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutSingleAction, EditorLayoutSingleAction.ID, EditorLayoutSingleAction.LABEL), 'View: Single Column Editor Layout', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoColumnsAction, EditorLayoutTwoColumnsAction.ID, EditorLayoutTwoColumnsAction.LABEL), 'View: Two Columns Editor Layout', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutThreeColumnsAction, EditorLayoutThreeColumnsAction.ID, EditorLayoutThreeColumnsAction.LABEL), 'View: Three Columns Editor Layout', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoRowsAction, EditorLayoutTwoRowsAction.ID, EditorLayoutTwoRowsAction.LABEL), 'View: Two Rows Editor Layout', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutThreeRowsAction, EditorLayoutThreeRowsAction.ID, EditorLayoutThreeRowsAction.LABEL), 'View: Three Rows Editor Layout', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoByTwoGridAction, EditorLayoutTwoByTwoGridAction.ID, EditorLayoutTwoByTwoGridAction.LABEL), 'View: Grid Editor Layout (2x2)', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutThreeColumnsTopAction, EditorLayoutThreeColumnsTopAction.ID, EditorLayoutThreeColumnsTopAction.LABEL), 'View: Three Columns Top Editor Layout', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutThreeColumnsRightAction, EditorLayoutThreeColumnsRightAction.ID, EditorLayoutThreeColumnsRightAction.LABEL), 'View: Three Columns Right Editor Layout', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutGoldenRatioAction, EditorLayoutGoldenRatioAction.ID, EditorLayoutGoldenRatioAction.LABEL), 'View: Golden Ratio Editor Layout', category); // Register Editor Picker Actions including quick navigate support const openNextEditorKeybinding = { primary: KeyMod.CtrlCmd | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyCode.Tab } }; @@ -406,7 +416,7 @@ MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: edi MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: editorCommands.SPLIT_EDITOR_DOWN, title: nls.localize('splitDown', "Split Down") }, group: '1_split', order: 20 }); MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: editorCommands.SPLIT_EDITOR_LEFT, title: nls.localize('splitLeft', "Split Left") }, group: '1_split', order: 30 }); MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: editorCommands.SPLIT_EDITOR_RIGHT, title: nls.localize('splitRight', "Split Right") }, group: '1_split', order: 40 }); -MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: editorCommands.CLOSE_EDITOR_GROUP_COMMAND_ID, title: nls.localize('close', "Close") }, group: '3_close', order: 10 }); +MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: editorCommands.CLOSE_EDITOR_GROUP_COMMAND_ID, title: nls.localize('close', "Close") }, group: '3_close', order: 10, when: ContextKeyExpr.has('multipleEditorGroups') }); // Editor Title Context Menu MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_EDITOR_COMMAND_ID, title: nls.localize('close', "Close") }, group: '1_close', order: 10 }); diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 7d686bfa178..9c4b55d4436 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -19,12 +19,29 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IWindowsService } from 'vs/platform/windows/common/windows'; -import { CLOSE_EDITOR_COMMAND_ID, NAVIGATE_ALL_EDITORS_GROUP_PREFIX, MOVE_ACTIVE_EDITOR_COMMAND_ID, NAVIGATE_IN_ACTIVE_GROUP_PREFIX, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor } from 'vs/workbench/browser/parts/editor/editorCommands'; -import { IEditorGroupsService, IEditorGroup, GroupsArrangement, EditorsOrder, GroupLocation, GroupDirection, preferredGroupDirection, IFindGroupScope } from 'vs/workbench/services/group/common/editorGroupsService'; +import { CLOSE_EDITOR_COMMAND_ID, NAVIGATE_ALL_EDITORS_GROUP_PREFIX, MOVE_ACTIVE_EDITOR_COMMAND_ID, NAVIGATE_IN_ACTIVE_GROUP_PREFIX, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, EditorGroupLayout, mergeAllGroups } from 'vs/workbench/browser/parts/editor/editorCommands'; +import { IEditorGroupsService, IEditorGroup, GroupsArrangement, EditorsOrder, GroupLocation, GroupDirection, preferredGroupDirection, IFindGroupScope, GroupOrientation } from 'vs/workbench/services/group/common/editorGroupsService'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +export class ExecuteCommandAction extends Action { + + constructor( + id: string, + label: string, + private commandId: string, + private commandService: ICommandService, + private commandArgs?: any + ) { + super(id, label); + } + + public run(): TPromise { + return this.commandService.executeCommand(this.commandId, this.commandArgs); + } +} + export class BaseSplitEditorGroupAction extends Action { constructor( @@ -153,7 +170,7 @@ export class SplitEditorGroupHorizontalAction extends BaseSplitEditorGroupAction } } -export class SplitEditorGroupLeftAction extends Action { +export class SplitEditorGroupLeftAction extends ExecuteCommandAction { public static readonly ID = SPLIT_EDITOR_LEFT; public static readonly LABEL = nls.localize('splitEditorGroupLeft', "Split Editor Left"); @@ -161,17 +178,13 @@ export class SplitEditorGroupLeftAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - return this.commandService.executeCommand(SPLIT_EDITOR_LEFT); + super(id, label, SPLIT_EDITOR_LEFT, commandService); } } -export class SplitEditorGroupRightAction extends Action { +export class SplitEditorGroupRightAction extends ExecuteCommandAction { public static readonly ID = SPLIT_EDITOR_RIGHT; public static readonly LABEL = nls.localize('splitEditorGroupRight', "Split Editor Right"); @@ -179,17 +192,13 @@ export class SplitEditorGroupRightAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - return this.commandService.executeCommand(SPLIT_EDITOR_RIGHT); + super(id, label, SPLIT_EDITOR_RIGHT, commandService); } } -export class SplitEditorGroupUpAction extends Action { +export class SplitEditorGroupUpAction extends ExecuteCommandAction { public static readonly ID = SPLIT_EDITOR_UP; public static readonly LABEL = nls.localize('splitEditorGroupUp', "Split Editor Up"); @@ -197,17 +206,13 @@ export class SplitEditorGroupUpAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - return this.commandService.executeCommand(SPLIT_EDITOR_UP); + super(id, label, SPLIT_EDITOR_UP, commandService); } } -export class SplitEditorGroupDownAction extends Action { +export class SplitEditorGroupDownAction extends ExecuteCommandAction { public static readonly ID = SPLIT_EDITOR_DOWN; public static readonly LABEL = nls.localize('splitEditorGroupDown', "Split Editor Down"); @@ -215,13 +220,9 @@ export class SplitEditorGroupDownAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - return this.commandService.executeCommand(SPLIT_EDITOR_DOWN); + super(id, label, SPLIT_EDITOR_DOWN, commandService); } } @@ -274,10 +275,7 @@ export class JoinAllGroupsAction extends Action { } public run(context?: IEditorIdentifier): TPromise { - const firstGroup = this.editorGroupService.groups[0]; - while (this.editorGroupService.count > 1) { - this.editorGroupService.mergeGroup(this.editorGroupService.findGroup({ location: GroupLocation.NEXT }, firstGroup), firstGroup); - } + mergeAllGroups(this.editorGroupService); return TPromise.as(true); } @@ -1328,7 +1326,7 @@ export class ClearEditorHistoryAction extends Action { } } -export class MoveEditorLeftInGroupAction extends Action { +export class MoveEditorLeftInGroupAction extends ExecuteCommandAction { public static readonly ID = 'workbench.action.moveEditorLeftInGroup'; public static readonly LABEL = nls.localize('moveEditorLeft', "Move Editor Left"); @@ -1336,20 +1334,13 @@ export class MoveEditorLeftInGroupAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'left' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'left' } as ActiveEditorMoveArguments); } } -export class MoveEditorRightInGroupAction extends Action { +export class MoveEditorRightInGroupAction extends ExecuteCommandAction { public static readonly ID = 'workbench.action.moveEditorRightInGroup'; public static readonly LABEL = nls.localize('moveEditorRight', "Move Editor Right"); @@ -1357,20 +1348,13 @@ export class MoveEditorRightInGroupAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'right' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'right' } as ActiveEditorMoveArguments); } } -export class MoveEditorToPreviousGroupAction extends Action { +export class MoveEditorToPreviousGroupAction extends ExecuteCommandAction { public static readonly ID = 'workbench.action.moveEditorToPreviousGroup'; public static readonly LABEL = nls.localize('moveEditorToPreviousGroup', "Move Editor into Previous Group"); @@ -1378,104 +1362,13 @@ export class MoveEditorToPreviousGroupAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'previous', by: 'group' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'previous', by: 'group' } as ActiveEditorMoveArguments); } } -export class MoveEditorToAboveGroupAction extends Action { - - public static readonly ID = 'workbench.action.moveEditorToAboveGroup'; - public static readonly LABEL = nls.localize('moveEditorToAboveGroup', "Move Editor into Above Group"); - - constructor( - id: string, - label: string, - @ICommandService private commandService: ICommandService - ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'up', by: 'group' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); - } -} - -export class MoveEditorToBelowGroupAction extends Action { - - public static readonly ID = 'workbench.action.moveEditorToBelowGroup'; - public static readonly LABEL = nls.localize('moveEditorToBelowGroup', "Move Editor into Below Group"); - - constructor( - id: string, - label: string, - @ICommandService private commandService: ICommandService - ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'down', by: 'group' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); - } -} - -export class MoveEditorToLeftGroupAction extends Action { - - public static readonly ID = 'workbench.action.moveEditorToLeftGroup'; - public static readonly LABEL = nls.localize('moveEditorToLeftGroup', "Move Editor into Left Group"); - - constructor( - id: string, - label: string, - @ICommandService private commandService: ICommandService - ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'left', by: 'group' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); - } -} - -export class MoveEditorToRightGroupAction extends Action { - - public static readonly ID = 'workbench.action.moveEditorToRightGroup'; - public static readonly LABEL = nls.localize('moveEditorToRightGroup', "Move Editor into Right Group"); - - constructor( - id: string, - label: string, - @ICommandService private commandService: ICommandService - ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'right', by: 'group' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); - } -} - -export class MoveEditorToNextGroupAction extends Action { +export class MoveEditorToNextGroupAction extends ExecuteCommandAction { public static readonly ID = 'workbench.action.moveEditorToNextGroup'; public static readonly LABEL = nls.localize('moveEditorToNextGroup', "Move Editor into Next Group"); @@ -1483,20 +1376,69 @@ export class MoveEditorToNextGroupAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'next', by: 'group' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'next', by: 'group' } as ActiveEditorMoveArguments); } } -export class MoveEditorToFirstGroupAction extends Action { +export class MoveEditorToAboveGroupAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.moveEditorToAboveGroup'; + public static readonly LABEL = nls.localize('moveEditorToAboveGroup', "Move Editor into Above Group"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'up', by: 'group' } as ActiveEditorMoveArguments); + } +} + +export class MoveEditorToBelowGroupAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.moveEditorToBelowGroup'; + public static readonly LABEL = nls.localize('moveEditorToBelowGroup', "Move Editor into Below Group"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'down', by: 'group' } as ActiveEditorMoveArguments); + } +} + +export class MoveEditorToLeftGroupAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.moveEditorToLeftGroup'; + public static readonly LABEL = nls.localize('moveEditorToLeftGroup', "Move Editor into Left Group"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'left', by: 'group' } as ActiveEditorMoveArguments); + } +} + +export class MoveEditorToRightGroupAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.moveEditorToRightGroup'; + public static readonly LABEL = nls.localize('moveEditorToRightGroup', "Move Editor into Right Group"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'right', by: 'group' } as ActiveEditorMoveArguments); + } +} + +export class MoveEditorToFirstGroupAction extends ExecuteCommandAction { public static readonly ID = 'workbench.action.moveEditorToFirstGroup'; public static readonly LABEL = nls.localize('moveEditorToFirstGroup', "Move Editor into First Group"); @@ -1504,20 +1446,13 @@ export class MoveEditorToFirstGroupAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); - } - - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'first', by: 'group' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); - - return TPromise.as(true); + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'first', by: 'group' } as ActiveEditorMoveArguments); } } -export class MoveEditorToLastGroupAction extends Action { +export class MoveEditorToLastGroupAction extends ExecuteCommandAction { public static readonly ID = 'workbench.action.moveEditorToLastGroup'; public static readonly LABEL = nls.localize('moveEditorToLastGroup', "Move Editor into Last Group"); @@ -1525,15 +1460,134 @@ export class MoveEditorToLastGroupAction extends Action { constructor( id: string, label: string, - @ICommandService private commandService: ICommandService + @ICommandService commandService: ICommandService ) { - super(id, label); + super(id, label, MOVE_ACTIVE_EDITOR_COMMAND_ID, commandService, { to: 'last', by: 'group' } as ActiveEditorMoveArguments); } +} - public run(): TPromise { - const args: ActiveEditorMoveArguments = { to: 'last', by: 'group' }; - this.commandService.executeCommand(MOVE_ACTIVE_EDITOR_COMMAND_ID, args); +export class EditorLayoutSingleAction extends ExecuteCommandAction { - return TPromise.as(true); + public static readonly ID = 'workbench.action.editorLayoutSingle'; + public static readonly LABEL = nls.localize('editorLayoutSingle', "Single Column Editor Layout"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{}] } as EditorGroupLayout); + } +} + +export class EditorLayoutTwoColumnsAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.editorLayoutTwoColumns'; + public static readonly LABEL = nls.localize('editorLayoutTwoColumns', "Two Columns Editor Layout"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{}, {}], orientation: GroupOrientation.HORIZONTAL } as EditorGroupLayout); + } +} + +export class EditorLayoutThreeColumnsAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.editorLayoutThreeColumns'; + public static readonly LABEL = nls.localize('editorLayoutThreeColumns', "Three Columns Editor Layout"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{}, {}, {}], orientation: GroupOrientation.HORIZONTAL } as EditorGroupLayout); + } +} + +export class EditorLayoutTwoRowsAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.editorLayoutTwoRows'; + public static readonly LABEL = nls.localize('editorLayoutTwoRows', "Two Rows Editor Layout"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{}, {}], orientation: GroupOrientation.VERTICAL } as EditorGroupLayout); + } +} + +export class EditorLayoutThreeRowsAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.editorLayoutThreeRows'; + public static readonly LABEL = nls.localize('editorLayoutThreeRows', "Three Rows Editor Layout"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{}, {}, {}], orientation: GroupOrientation.VERTICAL } as EditorGroupLayout); + } +} + +export class EditorLayoutTwoByTwoGridAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.editorLayoutTwoByTwoGrid'; + public static readonly LABEL = nls.localize('editorLayoutTwoByTwoGrid', "Grid Editor Layout (2x2)"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{ groups: [{}, {}] }, { groups: [{}, {}] }] } as EditorGroupLayout); + } +} + +export class EditorLayoutThreeColumnsTopAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.editorLayoutThreeColumnsTop'; + public static readonly LABEL = nls.localize('editorLayoutThreeColumnsTop', "Three Columns Top Editor Layout"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{ groups: [{}, {}, {}] }, {}], orientation: GroupOrientation.VERTICAL } as EditorGroupLayout); + } +} + +export class EditorLayoutThreeColumnsRightAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.editorLayoutThreeColumnsRight'; + public static readonly LABEL = nls.localize('editorLayoutThreeColumnsRight', "Three Columns Right Editor Layout"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{}, { groups: [{}, {}, {}] }], orientation: GroupOrientation.HORIZONTAL } as EditorGroupLayout); + } +} + +export class EditorLayoutGoldenRatioAction extends ExecuteCommandAction { + + public static readonly ID = 'workbench.action.editorLayoutGoldenRatio'; + public static readonly LABEL = nls.localize('editorLayoutGoldenRatio', "Golden Ratio Editor Layout"); + + constructor( + id: string, + label: string, + @ICommandService commandService: ICommandService + ) { + super(id, label, LAYOUT_EDITOR_GROUPS_COMMAND_ID, commandService, { groups: [{ size: 0.618 }, { size: 0.382, groups: [{ size: 0.618 }, { size: 0.382 }] }], orientation: GroupOrientation.HORIZONTAL } as EditorGroupLayout); } } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 7d457c9182a..1d7898c3a67 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -19,7 +19,7 @@ import { IDiffEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IListService } from 'vs/platform/list/browser/listService'; import { List } from 'vs/base/browser/ui/list/listWidget'; import { distinct } from 'vs/base/common/arrays'; -import { IEditorGroupsService, IEditorGroup, GroupDirection, GroupLocation, GroupsOrder, preferredGroupDirection } from 'vs/workbench/services/group/common/editorGroupsService'; +import { IEditorGroupsService, IEditorGroup, GroupDirection, GroupLocation, GroupsOrder, preferredGroupDirection, GroupOrientation } from 'vs/workbench/services/group/common/editorGroupsService'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -32,6 +32,7 @@ export const CLOSE_EDITOR_GROUP_COMMAND_ID = 'workbench.action.closeEditorGroup' export const CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID = 'workbench.action.closeOtherEditors'; export const MOVE_ACTIVE_EDITOR_COMMAND_ID = 'moveActiveEditor'; +export const LAYOUT_EDITOR_GROUPS_COMMAND_ID = 'layoutEditorGroups'; export const KEEP_EDITOR_COMMAND_ID = 'workbench.action.keepEditor'; export const SHOW_EDITORS_IN_GROUP = 'workbench.action.showEditorsInGroup'; export const TOGGLE_DIFF_INLINE_MODE = 'toggle.diff.editorMode'; @@ -192,6 +193,79 @@ function moveActiveEditorToGroup(args: ActiveEditorMoveArguments, control: IEdit } } +function registerEditorGroupsLayoutCommand(): void { + CommandsRegistry.registerCommand(LAYOUT_EDITOR_GROUPS_COMMAND_ID, applyEditorGroupLayout); +} + +export interface GroupLayoutArgument { + size?: number; + groups?: Array; +} + +export interface EditorGroupLayout { + orientation: GroupOrientation; + groups: GroupLayoutArgument[]; +} + +function applyEditorGroupLayout(accessor: ServicesAccessor, args: EditorGroupLayout): void { + if (!args || typeof args !== 'object') { + return; + } + + const editorGroupService = accessor.get(IEditorGroupsService); + + // Reduce to one editor group + mergeAllGroups(editorGroupService); + + // Apply orientation + if (typeof args.orientation === 'number') { + editorGroupService.setGroupOrientation(args.orientation); + } + + // Build layout + function buildLayout(groups: IEditorGroup[], descriptions: GroupLayoutArgument[], direction: GroupDirection): void { + if (descriptions.length === 0) { + return; // we need at least one group to layout + } + + // Add a group for each item in the description + let totalProportions = 0; + descriptions.forEach((description, index) => { + if (index > 0) { + groups.push(editorGroupService.addGroup(groups[index - 1], direction)); + } + + if (typeof description.size === 'number') { + totalProportions += description.size; + } + }); + + // Apply proportions if they are valid (sum() === 1) + if (totalProportions === 1) { + const totalSize = groups.map(group => editorGroupService.getSize(group)).reduce(((prev, cur) => prev + cur)); + descriptions.forEach((description, index) => { + editorGroupService.setSize(groups[index], totalSize * description.size); + }); + } + + // Continue building layout if description.groups is array-type + descriptions.forEach((description, index) => { + if (Array.isArray(description.groups)) { + buildLayout([groups[index]], description.groups, direction === GroupDirection.RIGHT ? GroupDirection.DOWN : GroupDirection.RIGHT); + } + }); + } + + buildLayout([editorGroupService.groups[0]], args.groups, editorGroupService.orientation === GroupOrientation.HORIZONTAL ? GroupDirection.RIGHT : GroupDirection.DOWN); +} + +export function mergeAllGroups(editorGroupService: IEditorGroupsService): void { + const firstGroup = editorGroupService.groups[0]; + while (editorGroupService.count > 1) { + editorGroupService.mergeGroup(editorGroupService.findGroup({ location: GroupLocation.NEXT }, firstGroup), firstGroup); + } +} + function registerDiffEditorCommands(): void { KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'workbench.action.compareEditor.nextChange', @@ -633,6 +707,7 @@ function isEditorIdentifier(thing: any): thing is IEditorIdentifier { export function setup(): void { registerActiveEditorMoveCommand(); + registerEditorGroupsLayoutCommand(); registerDiffEditorCommands(); registerOpenEditorAtIndexCommands(); registerCloseEditorCommands(); diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 6ac6ea260ea..e0017a49e16 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -273,13 +273,16 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro return groupView; } - resizeGroup(group: IEditorGroupView | GroupIdentifier, sizeDelta: number): IEditorGroupView { + getSize(group: IEditorGroupView | GroupIdentifier): number { const groupView = this.assertGroupView(group); - const currentSize = this.gridWidget.getViewSize(groupView); - this.gridWidget.resizeView(groupView, currentSize + sizeDelta); + return this.gridWidget.getViewSize(groupView); + } - return groupView; + setSize(group: IEditorGroupView | GroupIdentifier, size: number): void { + const groupView = this.assertGroupView(group); + + this.gridWidget.resizeView(groupView, size); } arrangeGroups(arrangement: GroupsArrangement): void { diff --git a/src/vs/workbench/services/group/common/editorGroupsService.ts b/src/vs/workbench/services/group/common/editorGroupsService.ts index 8af604074b0..3315de28f02 100644 --- a/src/vs/workbench/services/group/common/editorGroupsService.ts +++ b/src/vs/workbench/services/group/common/editorGroupsService.ts @@ -197,9 +197,14 @@ export interface IEditorGroupsService { activateGroup(group: IEditorGroup | GroupIdentifier): IEditorGroup; /** - * Resize the group given the provided size delta. + * Returns the size of a group. */ - resizeGroup(group: IEditorGroup | GroupIdentifier, sizeDelta: number): IEditorGroup; + getSize(group: IEditorGroup | GroupIdentifier): number; + + /** + * Sets the size of a group. + */ + setSize(group: IEditorGroup | GroupIdentifier, size: number): void; /** * Arrange all groups according to the provided arrangement. diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 91a7410c3cf..a84830b74de 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -541,10 +541,12 @@ export class TestEditorGroupsService implements IEditorGroupsService { return null; } - resizeGroup(group: number | IEditorGroup, sizeDelta: number): IEditorGroup { - return null; + getSize(group: number | IEditorGroup): number { + return 100; } + setSize(group: number | IEditorGroup, size: number): void { } + arrangeGroups(arrangement: GroupsArrangement): void { } setGroupOrientation(orientation: any): void { }