Skip to content

Commit

Permalink
add option to dock terminal at top (microsoft#207721)
Browse files Browse the repository at this point in the history
* add option to dock terminal at top

* fixed formatting

* Update editorPart.ts

requested changes

* panel position fixes and cleanup

---------

Co-authored-by: BeniBenj <besimmonds@microsoft.com>
  • Loading branch information
2 people authored and aaronchucarroll committed Jul 10, 2024
1 parent bb9a149 commit 66461af
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 59 deletions.
75 changes: 42 additions & 33 deletions src/vs/workbench/browser/layout.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/vs/workbench/browser/parts/editor/editorPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,10 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
openVerticalPosition = Position.BOTTOM;
}

if (e.eventData.clientY < boundingRect.top + proximity) {
openVerticalPosition = Position.TOP;
}

if (horizontalOpenerTimeout && openHorizontalPosition !== lastOpenHorizontalPosition) {
clearTimeout(horizontalOpenerTimeout);
horizontalOpenerTimeout = undefined;
Expand Down
17 changes: 17 additions & 0 deletions src/vs/workbench/browser/parts/panel/media/panelpart.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@
border-top-width: 0; /* no border when main editor area is hiden */
}

.monaco-workbench .part.panel.top {
border-bottom-width: 1px;
border-bottom-style: solid;
}

.monaco-workbench.nomaineditorarea .part.panel.top {
border-bottom-width: 0; /* no border when main editor area is hiden */
}

.monaco-workbench .part.panel.right {
border-left-width: 1px;
border-left-style: solid;
Expand Down Expand Up @@ -81,3 +90,11 @@
display: inline-block;
transform: rotate(90deg);
}

/* Rotate icons when panel is on left */
.monaco-workbench .part.basepanel.top .title-actions .codicon-split-horizontal::before,
.monaco-workbench .part.basepanel.top .global-actions .codicon-panel-maximize::before,
.monaco-workbench .part.basepanel.top .global-actions .codicon-panel-restore::before {
display: inline-block;
transform: rotate(180deg);
}
12 changes: 7 additions & 5 deletions src/vs/workbench/browser/parts/panel/panelActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { localize, localize2 } from 'vs/nls';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { MenuId, MenuRegistry, registerAction2, Action2, IAction2Options } from 'vs/platform/actions/common/actions';
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ActivityBarPosition, IWorkbenchLayoutService, LayoutSettings, PanelAlignment, Parts, Position, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
import { ActivityBarPosition, isHorizontal, IWorkbenchLayoutService, LayoutSettings, PanelAlignment, Parts, Position, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
import { AuxiliaryBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelPositionContext, PanelVisibleContext } from 'vs/workbench/common/contextkeys';
import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
import { Codicon } from 'vs/base/common/codicons';
Expand Down Expand Up @@ -99,6 +99,7 @@ const PositionPanelActionId = {
LEFT: 'workbench.action.positionPanelLeft',
RIGHT: 'workbench.action.positionPanelRight',
BOTTOM: 'workbench.action.positionPanelBottom',
TOP: 'workbench.action.positionPanelTop'
};

const AlignPanelActionId = {
Expand Down Expand Up @@ -136,6 +137,7 @@ function createAlignmentPanelActionConfig(id: string, title: ICommandActionTitle


const PositionPanelActionConfigs: PanelActionConfig<Position>[] = [
createPositionPanelActionConfig(PositionPanelActionId.TOP, localize2('positionPanelTop', "Move Panel To Top"), localize('positionPanelTopShort', "Top"), Position.TOP),
createPositionPanelActionConfig(PositionPanelActionId.LEFT, localize2('positionPanelLeft', "Move Panel Left"), localize('positionPanelLeftShort', "Left"), Position.LEFT),
createPositionPanelActionConfig(PositionPanelActionId.RIGHT, localize2('positionPanelRight', "Move Panel Right"), localize('positionPanelRightShort', "Right"), Position.RIGHT),
createPositionPanelActionConfig(PositionPanelActionId.BOTTOM, localize2('positionPanelBottom', "Move Panel To Bottom"), localize('positionPanelBottomShort', "Bottom"), Position.BOTTOM),
Expand All @@ -158,7 +160,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
order: 4
});

PositionPanelActionConfigs.forEach(positionPanelAction => {
PositionPanelActionConfigs.forEach((positionPanelAction, index) => {
const { id, title, shortLabel, value, when } = positionPanelAction;

registerAction2(class extends Action2 {
Expand All @@ -182,7 +184,7 @@ PositionPanelActionConfigs.forEach(positionPanelAction => {
title: shortLabel,
toggled: when.negate()
},
order: 5
order: 5 + index
});
});

Expand Down Expand Up @@ -280,7 +282,7 @@ registerAction2(class extends Action2 {
tooltip: localize('maximizePanel', "Maximize Panel Size"),
category: Categories.View,
f1: true,
icon: maximizeIcon,
icon: maximizeIcon, // This is being rotated in CSS depending on the panel position
// the workbench grid currently prevents us from supporting panel maximization with non-center panel alignment
precondition: ContextKeyExpr.or(PanelAlignmentContext.isEqualTo('center'), PanelPositionContext.notEqualsTo('bottom')),
toggled: { condition: PanelMaximizedContext, icon: restoreIcon, tooltip: localize('minimizePanel', "Restore Panel Size") },
Expand All @@ -296,7 +298,7 @@ registerAction2(class extends Action2 {
run(accessor: ServicesAccessor) {
const layoutService = accessor.get(IWorkbenchLayoutService);
const notificationService = accessor.get(INotificationService);
if (layoutService.getPanelAlignment() !== 'center' && layoutService.getPanelPosition() === Position.BOTTOM) {
if (layoutService.getPanelAlignment() !== 'center' && isHorizontal(layoutService.getPanelPosition())) {
notificationService.warn(localize('panelMaxNotSupported', "Maximizing the panel is only supported when it is center aligned."));
return;
}
Expand Down
15 changes: 11 additions & 4 deletions src/vs/workbench/browser/parts/panel/panelPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export class PanelPart extends AbstractPaneCompositePart {
const borderColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder) || '';
container.style.borderLeftColor = borderColor;
container.style.borderRightColor = borderColor;
container.style.borderBottomColor = borderColor;

const title = this.getTitleArea();
if (title) {
Expand Down Expand Up @@ -166,10 +167,16 @@ export class PanelPart extends AbstractPaneCompositePart {

override layout(width: number, height: number, top: number, left: number): void {
let dimensions: Dimension;
if (this.layoutService.getPanelPosition() === Position.RIGHT) {
dimensions = new Dimension(width - 1, height); // Take into account the 1px border when layouting
} else {
dimensions = new Dimension(width, height);
switch (this.layoutService.getPanelPosition()) {
case Position.RIGHT:
dimensions = new Dimension(width - 1, height); // Take into account the 1px border when layouting
break;
case Position.TOP:
dimensions = new Dimension(width, height - 1); // Take into account the 1px border when layouting
break;
default:
dimensions = new Dimension(width, height);
break;
}

// Layout contents
Expand Down
7 changes: 4 additions & 3 deletions src/vs/workbench/browser/parts/views/viewPaneContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { IAddedViewDescriptorRef, ICustomViewDescriptor, IView, IViewContainerMo
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
import { FocusedViewContext } from 'vs/workbench/common/contextkeys';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkbenchLayoutService, LayoutSettings, Position } from 'vs/workbench/services/layout/browser/layoutService';
import { isHorizontal, IWorkbenchLayoutService, LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
import { IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';

export const ViewsSubMenu = new MenuId('Views');
Expand Down Expand Up @@ -625,8 +625,9 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
case ViewContainerLocation.Sidebar:
case ViewContainerLocation.AuxiliaryBar:
return Orientation.VERTICAL;
case ViewContainerLocation.Panel:
return this.layoutService.getPanelPosition() === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL;
case ViewContainerLocation.Panel: {
return isHorizontal(this.layoutService.getPanelPosition()) ? Orientation.HORIZONTAL : Orientation.VERTICAL;
}
}

return Orientation.VERTICAL;
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/browser/workbench.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,9 +516,9 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
},
'workbench.panel.defaultLocation': {
'type': 'string',
'enum': ['left', 'bottom', 'right'],
'enum': ['left', 'bottom', 'top', 'right'],
'default': 'bottom',
'description': localize('panelDefaultLocation', "Controls the default location of the panel (Terminal, Debug Console, Output, Problems) in a new workspace. It can either show at the bottom, right, or left of the editor area."),
'description': localize('panelDefaultLocation', "Controls the default location of the panel (Terminal, Debug Console, Output, Problems) in a new workspace. It can either show at the bottom, top, right, or left of the editor area."),
},
'workbench.panel.opensMaximized': {
'type': 'string',
Expand Down
18 changes: 10 additions & 8 deletions src/vs/workbench/contrib/terminal/browser/terminalGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'
import { Event, Emitter } from 'vs/base/common/event';
import { IDisposable, Disposable, DisposableStore, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { SplitView, Orientation, IView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService';
import { isHorizontal, IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITerminalInstance, Direction, ITerminalGroup, ITerminalInstanceService, ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
Expand Down Expand Up @@ -285,7 +285,7 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
if (this._container) {
this.attachToElement(this._container);
}
this._onPanelOrientationChanged.fire(this._terminalLocation === ViewContainerLocation.Panel && this._panelPosition === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL);
this._onPanelOrientationChanged.fire(this._terminalLocation === ViewContainerLocation.Panel && isHorizontal(this._panelPosition) ? Orientation.HORIZONTAL : Orientation.VERTICAL);
this._register(toDisposable(() => {
if (this._container && this._groupElement) {
this._groupElement.remove();
Expand Down Expand Up @@ -466,7 +466,7 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
if (!this._splitPaneContainer) {
this._panelPosition = this._layoutService.getPanelPosition();
this._terminalLocation = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID)!;
const orientation = this._terminalLocation === ViewContainerLocation.Panel && this._panelPosition === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const orientation = this._terminalLocation === ViewContainerLocation.Panel && isHorizontal(this._panelPosition) ? Orientation.HORIZONTAL : Orientation.VERTICAL;
this._splitPaneContainer = this._instantiationService.createInstance(SplitPaneContainer, this._groupElement, orientation);
this.terminalInstances.forEach(instance => this._splitPaneContainer!.split(instance, this._activeInstanceIndex + 1));
}
Expand Down Expand Up @@ -527,7 +527,7 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
const newTerminalLocation = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID)!;
const terminalPositionChanged = newPanelPosition !== this._panelPosition || newTerminalLocation !== this._terminalLocation;
if (terminalPositionChanged) {
const newOrientation = newTerminalLocation === ViewContainerLocation.Panel && newPanelPosition === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const newOrientation = newTerminalLocation === ViewContainerLocation.Panel && isHorizontal(newPanelPosition) ? Orientation.HORIZONTAL : Orientation.VERTICAL;
this._splitPaneContainer.setOrientation(newOrientation);
this._panelPosition = newPanelPosition;
this._terminalLocation = newTerminalLocation;
Expand Down Expand Up @@ -563,7 +563,7 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
}

private _getOrientation(): Orientation {
return this._getPosition() === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL;
return isHorizontal(this._getPosition()) ? Orientation.HORIZONTAL : Orientation.VERTICAL;
}

resizePane(direction: Direction): void {
Expand All @@ -588,10 +588,12 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {

if (shouldResizePart) {

const position = this._getPosition();
const shouldShrink =
(this._getPosition() === Position.LEFT && direction === Direction.Left) ||
(this._getPosition() === Position.RIGHT && direction === Direction.Right) ||
(this._getPosition() === Position.BOTTOM && direction === Direction.Down);
(position === Position.LEFT && direction === Direction.Left) ||
(position === Position.RIGHT && direction === Direction.Right) ||
(position === Position.BOTTOM && direction === Direction.Down) ||
(position === Position.TOP && direction === Direction.Up);

if (shouldShrink) {
resizeAmount *= -1;
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ import { getWorkspaceForTerminal, preparePathForShell } from 'vs/workbench/contr
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService';
import { isHorizontal, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { importAMDNodeModule } from 'vs/amdX';
Expand Down Expand Up @@ -2413,7 +2413,7 @@ class TerminalInstanceDragAndDropController extends Disposable implements dom.ID
private _getViewOrientation(): Orientation {
const panelPosition = this._layoutService.getPanelPosition();
const terminalLocation = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID);
return terminalLocation === ViewContainerLocation.Panel && panelPosition === Position.BOTTOM
return terminalLocation === ViewContainerLocation.Panel && isHorizontal(panelPosition)
? Orientation.HORIZONTAL
: Orientation.VERTICAL;
}
Expand Down
11 changes: 9 additions & 2 deletions src/vs/workbench/services/layout/browser/layoutService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@ export const enum EditorActionsLocation {
export const enum Position {
LEFT,
RIGHT,
BOTTOM
BOTTOM,
TOP
}

export function isHorizontal(position: Position): boolean {
return position === Position.BOTTOM || position === Position.TOP;
}

export const enum PanelOpensMaximizedOptions {
Expand All @@ -86,14 +91,16 @@ export function positionToString(position: Position): string {
case Position.LEFT: return 'left';
case Position.RIGHT: return 'right';
case Position.BOTTOM: return 'bottom';
case Position.TOP: return 'top';
default: return 'bottom';
}
}

const positionsByString: { [key: string]: Position } = {
[positionToString(Position.LEFT)]: Position.LEFT,
[positionToString(Position.RIGHT)]: Position.RIGHT,
[positionToString(Position.BOTTOM)]: Position.BOTTOM
[positionToString(Position.BOTTOM)]: Position.BOTTOM,
[positionToString(Position.TOP)]: Position.TOP
};

export function positionFromString(str: string): Position {
Expand Down

0 comments on commit 66461af

Please sign in to comment.