mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
Merge pull request #43863 from Microsoft/tyriar/split_simplify
Tyriar/split simplify
This commit is contained in:
commit
e64896d4cb
|
@ -163,7 +163,7 @@ export interface ITerminalService {
|
|||
setActiveInstance(terminalInstance: ITerminalInstance): void;
|
||||
setActiveInstanceByIndex(terminalIndex: number): void;
|
||||
getActiveOrCreateInstance(wasNewTerminalAction?: boolean): ITerminalInstance;
|
||||
splitInstanceVertically(instance: ITerminalInstance): void;
|
||||
splitInstance(instance: ITerminalInstance): void;
|
||||
|
||||
getActiveTab(): ITerminalTab;
|
||||
setActiveTabToNext(): void;
|
||||
|
@ -196,7 +196,9 @@ export interface ITerminalTab {
|
|||
onDisposed: Event<ITerminalTab>;
|
||||
onInstancesChanged: Event<void>;
|
||||
|
||||
focusDirection(direction: Direction): void;
|
||||
focusPreviousPane(): void;
|
||||
focusNextPane(): void;
|
||||
resizePane(direction: Direction): void;
|
||||
setActiveInstanceByIndex(index: number): void;
|
||||
attachToElement(element: HTMLElement): void;
|
||||
setVisible(visible: boolean): void;
|
||||
|
|
|
@ -230,7 +230,7 @@ export abstract class TerminalService implements ITerminalService {
|
|||
this.setActiveTabByIndex(newIndex);
|
||||
}
|
||||
|
||||
public splitInstanceVertically(instanceToSplit: ITerminalInstance): void {
|
||||
public splitInstance(instanceToSplit: ITerminalInstance): void {
|
||||
const tab = this._getTabForInstance(instanceToSplit);
|
||||
if (!tab) {
|
||||
return;
|
||||
|
|
|
@ -76,11 +76,15 @@
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-workbench .panel.integrated-terminal .split-view-view:not(:first-child) {
|
||||
/* border-color is set by theme key terminal.border */
|
||||
/* border-color is set by theme key terminal.border */
|
||||
.monaco-workbench .panel.integrated-terminal .monaco-split-view2.horizontal .split-view-view:not(:first-child) {
|
||||
border-left-width: 1px;
|
||||
border-left-style: solid;
|
||||
}
|
||||
.monaco-workbench .panel.integrated-terminal .monaco-split-view2.vertical .split-view-view:not(:first-child) {
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
}
|
||||
|
||||
.monaco-workbench .panel.integrated-terminal.enable-ligatures {
|
||||
font-variant-ligatures: normal;
|
||||
|
|
|
@ -18,7 +18,7 @@ import { getTerminalDefaultShellUnixLike, getTerminalDefaultShellWindows } from
|
|||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX, MoveToLineStartTerminalAction, MoveToLineEndTerminalAction, SplitVerticalTerminalAction, FocusTerminalLeftAction, FocusTerminalRightAction, FocusTerminalUpAction, FocusTerminalDownAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
|
||||
import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX, MoveToLineStartTerminalAction, MoveToLineEndTerminalAction, SplitTerminalAction, FocusPreviousPaneTerminalAction, FocusNextPaneTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, ResizePaneDownTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ShowAllCommandsAction } from 'vs/workbench/parts/quickopen/browser/commandsHandler';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
|
@ -273,9 +273,13 @@ configurationRegistry.registerConfiguration({
|
|||
MoveToLineEndTerminalAction.ID,
|
||||
TogglePanelAction.ID,
|
||||
'workbench.action.quickOpenView',
|
||||
SplitVerticalTerminalAction.ID,
|
||||
FocusTerminalLeftAction.ID,
|
||||
FocusTerminalRightAction.ID
|
||||
SplitTerminalAction.ID,
|
||||
FocusPreviousPaneTerminalAction.ID,
|
||||
FocusNextPaneTerminalAction.ID,
|
||||
ResizePaneLeftTerminalAction.ID,
|
||||
ResizePaneRightTerminalAction.ID,
|
||||
ResizePaneUpTerminalAction.ID,
|
||||
ResizePaneDownTerminalAction.ID
|
||||
].sort()
|
||||
},
|
||||
'terminal.integrated.env.osx': {
|
||||
|
@ -412,26 +416,42 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(MoveToLineEndTer
|
|||
primary: null,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.RightArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Move To Line End', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitVerticalTerminalAction, SplitVerticalTerminalAction.ID, SplitVerticalTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitTerminalAction, SplitTerminalAction.ID, SplitTerminalAction.LABEL, {
|
||||
primary: null,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_D }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Split Vertically', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalLeftAction, FocusTerminalLeftAction.ID, FocusTerminalLeftAction.LABEL, {
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Split', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousPaneTerminalAction, FocusPreviousPaneTerminalAction.ID, FocusPreviousPaneTerminalAction.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.LeftArrow,
|
||||
mac: { primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.LeftArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Terminal To Left', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalRightAction, FocusTerminalRightAction.ID, FocusTerminalRightAction.LABEL, {
|
||||
secondary: [KeyMod.Alt | KeyCode.UpArrow],
|
||||
mac: {
|
||||
primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.LeftArrow,
|
||||
secondary: [KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.UpArrow]
|
||||
}
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Previous Pane', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextPaneTerminalAction, FocusNextPaneTerminalAction.ID, FocusNextPaneTerminalAction.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.RightArrow,
|
||||
mac: { primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.RightArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Terminal To Right', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalDownAction, FocusTerminalDownAction.ID, FocusTerminalDownAction.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.DownArrow,
|
||||
mac: { primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.DownArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Terminal Below', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalUpAction, FocusTerminalUpAction.ID, FocusTerminalUpAction.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.UpArrow,
|
||||
mac: { primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.UpArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Terminal Above', category);
|
||||
secondary: [KeyMod.Alt | KeyCode.DownArrow],
|
||||
mac: {
|
||||
primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.RightArrow,
|
||||
secondary: [KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.DownArrow]
|
||||
}
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Next Pane', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneLeftTerminalAction, ResizePaneLeftTerminalAction.ID, ResizePaneLeftTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Left', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneRightTerminalAction, ResizePaneRightTerminalAction.ID, ResizePaneRightTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Right', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneUpTerminalAction, ResizePaneUpTerminalAction.ID, ResizePaneUpTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.UpArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Up', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneDownTerminalAction, ResizePaneDownTerminalAction.ID, ResizePaneDownTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.DownArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Down', category);
|
||||
|
||||
terminalCommands.setup();
|
||||
|
||||
|
|
|
@ -296,9 +296,9 @@ export class CreateNewInActiveWorkspaceTerminalAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
export class SplitVerticalTerminalAction extends Action {
|
||||
public static readonly ID = 'workbench.action.terminal.splitVertical';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.splitVertical', "Split the terminal vertically");
|
||||
export class SplitTerminalAction extends Action {
|
||||
public static readonly ID = 'workbench.action.terminal.split';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.split', "Split Terminal");
|
||||
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
|
@ -312,7 +312,49 @@ export class SplitVerticalTerminalAction extends Action {
|
|||
if (!instance) {
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
this._terminalService.splitInstanceVertically(instance);
|
||||
this._terminalService.splitInstance(instance);
|
||||
return this._terminalService.showPanel(true);
|
||||
}
|
||||
}
|
||||
|
||||
export class FocusPreviousPaneTerminalAction extends Action {
|
||||
public static readonly ID = 'workbench.action.terminal.focusPreviousPane';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.focusPreviousPane', "Focus Previous Pane");
|
||||
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public run(event?: any): TPromise<any> {
|
||||
const tab = this._terminalService.getActiveTab();
|
||||
if (!tab) {
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
tab.focusPreviousPane();
|
||||
return this._terminalService.showPanel(true);
|
||||
}
|
||||
}
|
||||
|
||||
export class FocusNextPaneTerminalAction extends Action {
|
||||
public static readonly ID = 'workbench.action.terminal.focusNextPane';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.focusNextPane', "Focus Next Pane");
|
||||
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public run(event?: any): TPromise<any> {
|
||||
const tab = this._terminalService.getActiveTab();
|
||||
if (!tab) {
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
tab.focusNextPane();
|
||||
return this._terminalService.showPanel(true);
|
||||
}
|
||||
}
|
||||
|
@ -328,46 +370,57 @@ export abstract class BaseFocusDirectionTerminalAction extends Action {
|
|||
|
||||
public run(event?: any): TPromise<any> {
|
||||
const tab = this._terminalService.getActiveTab();
|
||||
if (!tab) {
|
||||
return TPromise.as(void 0);
|
||||
if (tab) {
|
||||
tab.resizePane(this._direction);
|
||||
}
|
||||
tab.focusDirection(this._direction);
|
||||
return this._terminalService.showPanel(true);
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
}
|
||||
|
||||
export class FocusTerminalLeftAction extends BaseFocusDirectionTerminalAction {
|
||||
public static readonly ID = 'workbench.action.terminal.focusTerminalLeft';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.focusTerminalLeft', "Focus terminal to the left");
|
||||
export class ResizePaneLeftTerminalAction extends BaseFocusDirectionTerminalAction {
|
||||
public static readonly ID = 'workbench.action.terminal.resizePaneLeft';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.resizePaneLeft', "Resize Pane Left");
|
||||
|
||||
constructor(id: string, label: string, @ITerminalService terminalService: ITerminalService) {
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
@ITerminalService readonly terminalService: ITerminalService
|
||||
) {
|
||||
super(id, label, Direction.Left, terminalService);
|
||||
}
|
||||
}
|
||||
|
||||
export class FocusTerminalRightAction extends BaseFocusDirectionTerminalAction {
|
||||
public static readonly ID = 'workbench.action.terminal.focusTerminalRight';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.focusTerminalRight', "Focus terminal to the right");
|
||||
export class ResizePaneRightTerminalAction extends BaseFocusDirectionTerminalAction {
|
||||
public static readonly ID = 'workbench.action.terminal.resizePaneRight';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.resizePaneRight', "Resize Pane Right");
|
||||
|
||||
constructor(id: string, label: string, @ITerminalService terminalService: ITerminalService) {
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
@ITerminalService readonly terminalService: ITerminalService
|
||||
) {
|
||||
super(id, label, Direction.Right, terminalService);
|
||||
}
|
||||
}
|
||||
|
||||
export class FocusTerminalUpAction extends BaseFocusDirectionTerminalAction {
|
||||
public static readonly ID = 'workbench.action.terminal.focusTerminalUp';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.focusTerminalUp', "Focus terminal above");
|
||||
export class ResizePaneUpTerminalAction extends BaseFocusDirectionTerminalAction {
|
||||
public static readonly ID = 'workbench.action.terminal.resizePaneUp';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.resizePaneUp', "Resize Pane Up");
|
||||
|
||||
constructor(id: string, label: string, @ITerminalService terminalService: ITerminalService) {
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
@ITerminalService readonly terminalService: ITerminalService
|
||||
) {
|
||||
super(id, label, Direction.Up, terminalService);
|
||||
}
|
||||
}
|
||||
|
||||
export class FocusTerminalDownAction extends BaseFocusDirectionTerminalAction {
|
||||
public static readonly ID = 'workbench.action.terminal.focusTerminalDown';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.focusTerminalDown', "Focus terminal below");
|
||||
export class ResizePaneDownTerminalAction extends BaseFocusDirectionTerminalAction {
|
||||
public static readonly ID = 'workbench.action.terminal.resizePaneDown';
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.resizePaneDown', "Resize Pane Down");
|
||||
|
||||
constructor(id: string, label: string, @ITerminalService terminalService: ITerminalService) {
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
@ITerminalService readonly terminalService: ITerminalService
|
||||
) {
|
||||
super(id, label, Direction.Down, terminalService);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ export class TerminalInstance implements ITerminalInstance {
|
|||
|
||||
// Only attach xterm.js to the DOM if the terminal panel has been opened before.
|
||||
if (_container) {
|
||||
this.attachToElement(_container);
|
||||
this._attachToElement(_container);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -337,6 +337,25 @@ export class TerminalInstance implements ITerminalInstance {
|
|||
}
|
||||
|
||||
public attachToElement(container: HTMLElement): void {
|
||||
// The container did not change, do nothing
|
||||
if (this._container === container) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Attach has not occured yet
|
||||
if (!this._wrapperElement) {
|
||||
this._attachToElement(container);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Verify listeners still work
|
||||
// The container changed, reattach
|
||||
this._container.removeChild(this._wrapperElement);
|
||||
this._container = container;
|
||||
this._container.appendChild(this._wrapperElement);
|
||||
}
|
||||
|
||||
public _attachToElement(container: HTMLElement): void {
|
||||
this._xtermReadyPromise.then(() => {
|
||||
if (this._wrapperElement) {
|
||||
throw new Error('The terminal instance has already been attached to a container');
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal
|
|||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { TerminalFindWidget } from './terminalFindWidget';
|
||||
import { editorHoverBackground, editorHoverBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { KillTerminalAction, SwitchTerminalAction, SwitchTerminalActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction, CreateNewTerminalAction, SplitVerticalTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
|
||||
import { KillTerminalAction, SwitchTerminalAction, SwitchTerminalActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction, CreateNewTerminalAction, SplitTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
|
||||
import { Panel } from 'vs/workbench/browser/panel';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
@ -149,7 +149,7 @@ export class TerminalPanel extends Panel {
|
|||
new Separator(),
|
||||
this._instantiationService.createInstance(ClearTerminalAction, ClearTerminalAction.ID, nls.localize('clear', "Clear")),
|
||||
new Separator(),
|
||||
this._instantiationService.createInstance(SplitVerticalTerminalAction, SplitVerticalTerminalAction.ID, nls.localize('splitVertically', "Split Vertically"))
|
||||
this._instantiationService.createInstance(SplitTerminalAction, SplitTerminalAction.ID, nls.localize('splitVertically', "Split Vertically"))
|
||||
];
|
||||
this._contextMenuActions.forEach(a => {
|
||||
this._register(a);
|
||||
|
@ -298,7 +298,7 @@ export class TerminalPanel extends Panel {
|
|||
|
||||
const borderColor = theme.getColor(TERMINAL_BORDER_COLOR) || theme.getColor(PANEL_BORDER);
|
||||
if (borderColor) {
|
||||
css += `.monaco-workbench .panel.integrated-terminal .split-view-view:not(:first-child) { border-left-color: ${borderColor.toString()}; }`;
|
||||
css += `.monaco-workbench .panel.integrated-terminal .split-view-view:not(:first-child) { border-color: ${borderColor.toString()}; }`;
|
||||
}
|
||||
|
||||
// Borrow the editor's hover background for now
|
||||
|
|
|
@ -237,8 +237,5 @@ export class TerminalService extends AbstractTerminalService implements ITermina
|
|||
this._configHelper.panelContainer = panelContainer;
|
||||
this._terminalContainer = terminalContainer;
|
||||
this._terminalTabs.forEach(tab => tab.attachToElement(this._terminalContainer));
|
||||
this._terminalInstances.forEach(terminalInstance => {
|
||||
terminalInstance.attachToElement(this._terminalContainer);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ITerminalInstance, IShellLaunchConfig, ITerminalTab, Direction } from 'vs/workbench/parts/terminal/common/terminal';
|
||||
import { ITerminalInstance, IShellLaunchConfig, ITerminalTab, Direction, ITerminalService } from 'vs/workbench/parts/terminal/common/terminal';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';
|
||||
import { IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
@ -11,61 +11,97 @@ import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/t
|
|||
import Event, { Emitter, anyEvent } from 'vs/base/common/event';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { SplitView, Orientation, IView } from 'vs/base/browser/ui/splitview/splitview';
|
||||
import { IPartService, Position } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
class SplitPane implements IView {
|
||||
public minimumSize: number = 100;
|
||||
public maximumSize: number = Number.MAX_VALUE;
|
||||
|
||||
public instance: ITerminalInstance;
|
||||
public orientation: Orientation | undefined;
|
||||
|
||||
protected _size: number;
|
||||
|
||||
private _splitView: SplitView | undefined;
|
||||
class SplitPaneContainer {
|
||||
private _height: number;
|
||||
private _width: number;
|
||||
private _splitView: SplitView;
|
||||
private _children: SplitPane[] = [];
|
||||
private _container: HTMLElement;
|
||||
private _isContainerSet: boolean = false;
|
||||
private _onDidChange: Event<number | undefined> = Event.None;
|
||||
|
||||
public get children(): SplitPane[] { return this._children; }
|
||||
// If the user sizes the panes manually, the proportional resizing will not be applied.
|
||||
// Proportional resizing will come back when: a sash is reset, an instance is added/removed or
|
||||
// the panel position moves.
|
||||
private _isManuallySized: boolean = false;
|
||||
|
||||
private _onDidChange: Event<number | undefined> = Event.None;
|
||||
public get onDidChange(): Event<number | undefined> { return this._onDidChange; }
|
||||
|
||||
constructor(
|
||||
private _parent?: SplitPane,
|
||||
public orthogonalSize?: number,
|
||||
private _needsReattach?: boolean
|
||||
private _container: HTMLElement,
|
||||
public orientation: Orientation
|
||||
) {
|
||||
}
|
||||
|
||||
protected branch(container: HTMLElement, orientation: Orientation, instance: ITerminalInstance): void {
|
||||
this.orientation = orientation;
|
||||
container.removeChild((<any>this.instance)._wrapperElement);
|
||||
|
||||
this._splitView = new SplitView(container, { orientation });
|
||||
this._width = this._container.offsetWidth;
|
||||
this._height = this._container.offsetHeight;
|
||||
this._splitView = new SplitView(this._container, { orientation: this.orientation });
|
||||
// TODO: Dispose listeners
|
||||
this._splitView.onDidSashReset(() => this._resetSize());
|
||||
this.layout(this._size);
|
||||
this.orthogonalLayout(this.orthogonalSize);
|
||||
|
||||
this.addChild(this.orthogonalSize / 2, this._size, this.instance, 0, this._isContainerSet);
|
||||
this.addChild(this.orthogonalSize / 2, this._size, instance);
|
||||
|
||||
// Instance is now owned by the first child
|
||||
this.instance = null;
|
||||
this._splitView.onDidSashChange(() => this._isManuallySized = true);
|
||||
this._splitView.layout(this.orientation === Orientation.HORIZONTAL ? this._width : this._height);
|
||||
}
|
||||
|
||||
public split(instance: ITerminalInstance): void {
|
||||
if (this._parent && this._parent.orientation === this.orientation) {
|
||||
// TODO: Splitting sizes can be a bit weird when not splitting the right-most pane
|
||||
// If we kept proportions when adding the view to the splitview it would be alright
|
||||
const index = this._parent._children.indexOf(this);
|
||||
this._parent.addChild(this._size / 2, this.orthogonalSize, instance, index + 1);
|
||||
} else {
|
||||
this.branch(this._container, this.orientation, instance);
|
||||
public split(instance: ITerminalInstance, index: number = this._children.length): void {
|
||||
const size = this.orientation === Orientation.HORIZONTAL ? this._width : this._height;
|
||||
this._addChild(size / (this._children.length + 1), instance, index);
|
||||
}
|
||||
|
||||
private _resetSize(): void {
|
||||
// TODO: Optimize temrinal instance layout
|
||||
let totalSize = 0;
|
||||
for (let i = 0; i < this._splitView.length; i++) {
|
||||
totalSize += this._splitView.getViewSize(i);
|
||||
}
|
||||
const newSize = Math.floor(totalSize / this._splitView.length);
|
||||
for (let i = 0; i < this._splitView.length - 1; i++) {
|
||||
this._splitView.resizeView(i, newSize);
|
||||
}
|
||||
this._isManuallySized = false;
|
||||
}
|
||||
|
||||
public resizePane(index: number, direction: Direction, amount: number): void {
|
||||
// TODO: Should resize pane up/down resize the panel?
|
||||
|
||||
// Only resize the correct dimension
|
||||
const isHorizontal = direction === Direction.Left || direction === Direction.Right;
|
||||
if (isHorizontal && this.orientation !== Orientation.HORIZONTAL ||
|
||||
!isHorizontal && this.orientation !== Orientation.VERTICAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only resize when there is mor ethan one pane
|
||||
if (this._children.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get sizes
|
||||
const sizes = [];
|
||||
for (let i = 0; i < this._splitView.length; i++) {
|
||||
sizes.push(this._splitView.getViewSize(i));
|
||||
}
|
||||
|
||||
// Remove size from right pane, unless index is the last pane in which case use left pane
|
||||
const isSizingEndPane = index !== this._children.length - 1;
|
||||
const indexToChange = isSizingEndPane ? index + 1 : index - 1;
|
||||
if (isSizingEndPane && direction === Direction.Left) {
|
||||
amount *= -1;
|
||||
} else if (!isSizingEndPane && direction === Direction.Right) {
|
||||
amount *= -1;
|
||||
} else if (isSizingEndPane && direction === Direction.Up) {
|
||||
amount *= -1;
|
||||
} else if (!isSizingEndPane && direction === Direction.Down) {
|
||||
amount *= -1;
|
||||
}
|
||||
sizes[index] += amount;
|
||||
sizes[indexToChange] -= amount;
|
||||
|
||||
// Apply
|
||||
for (let i = 0; i < this._splitView.length - 1; i++) {
|
||||
this._splitView.resizeView(i, sizes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private addChild(size: number, orthogonalSize: number, instance: ITerminalInstance, index?: number, needsReattach?: boolean): void {
|
||||
const child = new SplitPane(this, orthogonalSize, needsReattach);
|
||||
private _addChild(size: number, instance: ITerminalInstance, index: number): void {
|
||||
const child = new SplitPane(this.orientation === Orientation.HORIZONTAL ? this._height : this._width);
|
||||
child.orientation = this.orientation;
|
||||
child.instance = instance;
|
||||
this._splitView.addView(child, size, index);
|
||||
|
@ -76,47 +112,87 @@ class SplitPane implements IView {
|
|||
this._children.push(child);
|
||||
}
|
||||
|
||||
this._resetSize();
|
||||
|
||||
this._onDidChange = anyEvent(...this._children.map(c => c.onDidChange));
|
||||
}
|
||||
|
||||
private _resetSize(): void {
|
||||
let totalSize = 0;
|
||||
for (let i = 0; i < this._splitView.length; i++) {
|
||||
totalSize += this._splitView.getViewSize(i);
|
||||
public remove(instance: ITerminalInstance): void {
|
||||
let index = null;
|
||||
for (let i = 0; i < this._children.length; i++) {
|
||||
if (this._children[i].instance === instance) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
const newSize = Math.floor(totalSize / this._splitView.length);
|
||||
for (let i = 0; i < this._splitView.length - 1; i++) {
|
||||
this._splitView.resizeView(i, newSize);
|
||||
if (index !== null) {
|
||||
this._children.splice(index, 1);
|
||||
this._splitView.removeView(index);
|
||||
this._resetSize();
|
||||
}
|
||||
}
|
||||
|
||||
public remove(): void {
|
||||
if (!this._parent) {
|
||||
public layout(width: number, height: number): void {
|
||||
if (!this._isManuallySized) {
|
||||
this._resetSize();
|
||||
}
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
if (this.orientation === Orientation.HORIZONTAL) {
|
||||
this._splitView.layout(width);
|
||||
this._children.forEach(c => c.orthogonalLayout(height));
|
||||
} else {
|
||||
this._splitView.layout(height);
|
||||
this._children.forEach(c => c.orthogonalLayout(width));
|
||||
}
|
||||
}
|
||||
|
||||
public setOrientation(orientation: Orientation): void {
|
||||
if (this.orientation === orientation) {
|
||||
return;
|
||||
}
|
||||
this.orientation = orientation;
|
||||
|
||||
this._parent.removeChild(this);
|
||||
// Remove old split view
|
||||
while (this._container.children.length > 0) {
|
||||
this._container.removeChild(this._container.children[0]);
|
||||
}
|
||||
this._splitView.dispose();
|
||||
|
||||
// Create new split view with updated orientation
|
||||
this._splitView = new SplitView(this._container, { orientation });
|
||||
this._splitView.onDidSashReset(() => this._resetSize());
|
||||
this._children.forEach(child => {
|
||||
child.orientation = orientation;
|
||||
this._splitView.addView(child, 1);
|
||||
});
|
||||
|
||||
// Allow time for a layout to occur
|
||||
this.layout(this._container.offsetWidth, this._container.offsetHeight);
|
||||
this._resetSize();
|
||||
}
|
||||
}
|
||||
|
||||
public removeChild(child: SplitPane): void {
|
||||
const index = this._children.indexOf(child);
|
||||
this._children.splice(index, 1);
|
||||
this._splitView.removeView(index);
|
||||
class SplitPane implements IView {
|
||||
public minimumSize: number = 40;
|
||||
public maximumSize: number = Number.MAX_VALUE;
|
||||
|
||||
public instance: ITerminalInstance;
|
||||
public orientation: Orientation | undefined;
|
||||
protected _size: number;
|
||||
|
||||
private _onDidChange: Event<number | undefined> = Event.None;
|
||||
public get onDidChange(): Event<number | undefined> { return this._onDidChange; }
|
||||
|
||||
constructor(
|
||||
public orthogonalSize: number
|
||||
) {
|
||||
}
|
||||
|
||||
public render(container: HTMLElement): void {
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
this._container = container;
|
||||
if (!this._isContainerSet && this.instance) {
|
||||
if (this._needsReattach) {
|
||||
(<any>this.instance).reattachToElement(container);
|
||||
} else {
|
||||
this.instance.attachToElement(container);
|
||||
}
|
||||
this._isContainerSet = true;
|
||||
}
|
||||
this.instance.attachToElement(container);
|
||||
}
|
||||
|
||||
public layout(size: number): void {
|
||||
|
@ -126,76 +202,23 @@ class SplitPane implements IView {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.instance) {
|
||||
if (this.orientation === Orientation.VERTICAL) {
|
||||
this.instance.layout({ width: this.orthogonalSize, height: this._size });
|
||||
} else {
|
||||
this.instance.layout({ width: this._size, height: this.orthogonalSize });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (const child of this.children) {
|
||||
child.orthogonalLayout(this._size);
|
||||
if (this.orientation === Orientation.VERTICAL) {
|
||||
this.instance.layout({ width: this.orthogonalSize, height: this._size });
|
||||
} else {
|
||||
this.instance.layout({ width: this._size, height: this.orthogonalSize });
|
||||
}
|
||||
}
|
||||
|
||||
public orthogonalLayout(size: number): void {
|
||||
this.orthogonalSize = size;
|
||||
|
||||
if (this._splitView) {
|
||||
this._splitView.layout(this.orthogonalSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RootSplitPane extends SplitPane {
|
||||
private static _lastKnownWidth: number;
|
||||
private static _lastKnownHeight: number;
|
||||
|
||||
private _width: number;
|
||||
private _height: number;
|
||||
|
||||
protected branch(container: HTMLElement, orientation: Orientation, instance: ITerminalInstance): void {
|
||||
if (orientation === Orientation.VERTICAL) {
|
||||
this._size = this._width || RootSplitPane._lastKnownWidth;
|
||||
this.orthogonalSize = this._height || RootSplitPane._lastKnownHeight;
|
||||
} else {
|
||||
this._size = this._height || RootSplitPane._lastKnownHeight;
|
||||
this.orthogonalSize = this._width || RootSplitPane._lastKnownWidth;
|
||||
}
|
||||
|
||||
super.branch(container, orientation, instance);
|
||||
}
|
||||
|
||||
public layoutBox(width: number, height: number): void {
|
||||
RootSplitPane._lastKnownWidth = width;
|
||||
RootSplitPane._lastKnownHeight = height;
|
||||
if (this.orientation === Orientation.VERTICAL) {
|
||||
this.layout(width);
|
||||
this.orthogonalLayout(height);
|
||||
} else if (this.orientation === Orientation.HORIZONTAL) {
|
||||
this.layout(height);
|
||||
this.orthogonalLayout(width);
|
||||
} else {
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this.instance.layout({ width, height });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const directionOrientation: { [direction: number]: Orientation } = {
|
||||
[Direction.Left]: Orientation.HORIZONTAL,
|
||||
[Direction.Right]: Orientation.HORIZONTAL,
|
||||
[Direction.Up]: Orientation.VERTICAL,
|
||||
[Direction.Down]: Orientation.VERTICAL
|
||||
};
|
||||
|
||||
export class TerminalTab extends Disposable implements ITerminalTab {
|
||||
private _terminalInstances: ITerminalInstance[] = [];
|
||||
private _rootSplitPane: RootSplitPane;
|
||||
private _splitPaneContainer: SplitPaneContainer | undefined;
|
||||
private _tabElement: HTMLElement;
|
||||
private _panelPosition: Position = Position.BOTTOM;
|
||||
|
||||
private _activeInstanceIndex: number;
|
||||
|
||||
|
@ -211,7 +234,9 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
configHelper: TerminalConfigHelper,
|
||||
private _container: HTMLElement,
|
||||
shellLaunchConfig: IShellLaunchConfig,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@IPartService private readonly _partService: IPartService
|
||||
) {
|
||||
super();
|
||||
this._onDisposed = new Emitter<ITerminalTab>();
|
||||
|
@ -226,9 +251,6 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
this._initInstanceListeners(instance);
|
||||
this._activeInstanceIndex = 0;
|
||||
|
||||
this._rootSplitPane = new RootSplitPane();
|
||||
this._rootSplitPane.instance = instance;
|
||||
|
||||
if (this._container) {
|
||||
this.attachToElement(this._container);
|
||||
}
|
||||
|
@ -272,10 +294,9 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
this.activeInstance.focus(true);
|
||||
}
|
||||
|
||||
// Find the instance's SplitPane and unsplit it
|
||||
const pane = this._findSplitPane(instance);
|
||||
if (pane) {
|
||||
pane.remove();
|
||||
// Remove the instance from the split pane if it has been created
|
||||
if (this._splitPaneContainer) {
|
||||
this._splitPaneContainer.remove(instance);
|
||||
}
|
||||
|
||||
// Fire events and dispose tab if it was the last instance
|
||||
|
@ -286,44 +307,6 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
}
|
||||
}
|
||||
|
||||
private _findSplitPane(instance: ITerminalInstance): SplitPane {
|
||||
const openList: SplitPane[] = [this._rootSplitPane];
|
||||
while (openList.length > 0) {
|
||||
const current = openList.shift();
|
||||
if (current.instance === instance) {
|
||||
return current;
|
||||
}
|
||||
openList.push.apply(openList, current.children);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: Should this live inside SplitPane?
|
||||
private _findSplitPanePath(instance: ITerminalInstance, path: SplitPane[] = [this._rootSplitPane]): SplitPane[] {
|
||||
// Gets all split panes from the root to the pane containing the instance.
|
||||
const pane = path[path.length - 1];
|
||||
|
||||
// Base case: path found
|
||||
if (pane.instance === instance) {
|
||||
return path;
|
||||
}
|
||||
|
||||
// Rescurse child panes
|
||||
for (let i = 0; i < pane.children.length; i++) {
|
||||
const child = pane.children[i];
|
||||
|
||||
const subPath = path.slice();
|
||||
subPath.push(child);
|
||||
const result = this._findSplitPanePath(instance, subPath);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// No children contain instance
|
||||
return null;
|
||||
}
|
||||
|
||||
private _setActiveInstance(instance: ITerminalInstance): void {
|
||||
this.setActiveInstanceByIndex(this._getIndexFromId(instance.id));
|
||||
}
|
||||
|
@ -343,7 +326,7 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
|
||||
public setActiveInstanceByIndex(index: number): void {
|
||||
// Check for invalid value
|
||||
if (index >= this._terminalInstances.length) {
|
||||
if (index < 0 || index >= this._terminalInstances.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -360,7 +343,12 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
this._tabElement = document.createElement('div');
|
||||
this._tabElement.classList.add('terminal-tab');
|
||||
this._container.appendChild(this._tabElement);
|
||||
this._rootSplitPane.render(this._tabElement);
|
||||
if (!this._splitPaneContainer) {
|
||||
this._panelPosition = this._partService.getPanelPosition();
|
||||
const orientation = this._panelPosition === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL;
|
||||
this._splitPaneContainer = new SplitPaneContainer(this._tabElement, orientation);
|
||||
this.terminalInstances.forEach(instance => this._splitPaneContainer.split(instance));
|
||||
}
|
||||
}
|
||||
|
||||
public get title(): string {
|
||||
|
@ -388,25 +376,14 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
configHelper,
|
||||
undefined,
|
||||
shellLaunchConfig);
|
||||
// TODO: Should this be pulled from the splitpanes instead? Currently there are 2 sources of truth.
|
||||
// _terminalInstances is also the order they were created, not the order in which they appear
|
||||
this._terminalInstances.push(instance);
|
||||
this._terminalInstances.splice(this._activeInstanceIndex + 1, 0, instance);
|
||||
this._initInstanceListeners(instance);
|
||||
|
||||
if (this._rootSplitPane.instance) {
|
||||
this._rootSplitPane.orientation = Orientation.HORIZONTAL;
|
||||
this._rootSplitPane.split(instance);
|
||||
} else {
|
||||
// The original branch has already occured, find the inner SplitPane and split it
|
||||
const activePane = this._findSplitPane(this.activeInstance);
|
||||
activePane.orientation = Orientation.HORIZONTAL;
|
||||
activePane.split(instance);
|
||||
}
|
||||
if (this._tabElement) {
|
||||
this._rootSplitPane.render(this._tabElement);
|
||||
}
|
||||
this._setActiveInstance(instance);
|
||||
|
||||
if (this._splitPaneContainer) {
|
||||
this._splitPaneContainer.split(instance, this._activeInstanceIndex);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -415,67 +392,37 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
}
|
||||
|
||||
public layout(width: number, height: number): void {
|
||||
this._rootSplitPane.layoutBox(width, height);
|
||||
if (this._splitPaneContainer) {
|
||||
// Check if the panel position changed and rotate panes if so
|
||||
const newPanelPosition = this._partService.getPanelPosition();
|
||||
if (newPanelPosition !== this._panelPosition) {
|
||||
const newOrientation = newPanelPosition === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL;
|
||||
this._splitPaneContainer.setOrientation(newOrientation);
|
||||
}
|
||||
this._panelPosition = newPanelPosition;
|
||||
|
||||
this._splitPaneContainer.layout(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public focusDirection(direction: Direction): void {
|
||||
const activeInstance = this.activeInstance;
|
||||
if (!activeInstance) {
|
||||
return null;
|
||||
}
|
||||
public focusPreviousPane(): void {
|
||||
this.setActiveInstanceByIndex(this._activeInstanceIndex - 1);
|
||||
}
|
||||
|
||||
const desiredOrientation = directionOrientation[direction];
|
||||
const isUpOrLeft = direction === Direction.Left || direction === Direction.Up;
|
||||
public focusNextPane(): void {
|
||||
this.setActiveInstanceByIndex(this._activeInstanceIndex + 1);
|
||||
}
|
||||
|
||||
// Find the closest horizontal SplitPane ancestor with a child to the left
|
||||
let closestHorizontalPane: SplitPane = null;
|
||||
const panePath = this._findSplitPanePath(activeInstance);
|
||||
let index = panePath.length - 1;
|
||||
let ancestorIndex: number;
|
||||
while (--index >= 0) {
|
||||
const pane = panePath[index];
|
||||
// Continue up the path if not the desired orientation
|
||||
if (pane.orientation !== desiredOrientation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find index of the panePath pane and break out of loop if it's not the left-most child
|
||||
ancestorIndex = pane.children.indexOf(panePath[index + 1]);
|
||||
// Make sure that the pane is not on the boundary
|
||||
if (isUpOrLeft) {
|
||||
if (ancestorIndex > 0) {
|
||||
closestHorizontalPane = pane;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (ancestorIndex < pane.children.length - 1) {
|
||||
closestHorizontalPane = pane;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There are no panes to the left
|
||||
if (!closestHorizontalPane) {
|
||||
public resizePane(direction: Direction): void {
|
||||
if (!this._splitPaneContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
let current: SplitPane;
|
||||
if (isUpOrLeft) {
|
||||
// Find the bottom/right-most instance
|
||||
current = closestHorizontalPane.children[ancestorIndex - 1];
|
||||
while (current.children && current.children.length > 0) {
|
||||
current = current.children[current.children.length - 1];
|
||||
}
|
||||
} else {
|
||||
// Find the top/left-most instance
|
||||
current = closestHorizontalPane.children[ancestorIndex + 1];
|
||||
while (current.children && current.children.length > 0) {
|
||||
current = current.children[0];
|
||||
}
|
||||
const isHorizontal = (direction === Direction.Left || direction === Direction.Right);
|
||||
const font = this._terminalService.configHelper.getFont();
|
||||
const amount = isHorizontal ? font.charWidth : font.charHeight;
|
||||
if (amount) {
|
||||
this._splitPaneContainer.resizePane(this._activeInstanceIndex, direction, amount);
|
||||
}
|
||||
|
||||
// Focus the instance to the left
|
||||
current.instance.focus();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue