提交 7dec12f2 编写于 作者: I Isidor Nikolic 提交者: GitHub

Merge pull request #36827 from Microsoft/isidorn/vertical_panel

Isidorn/vertical panel
此差异已折叠。
......@@ -281,7 +281,7 @@ export class CompositeBar implements ICompositeBar {
}
// Add overflow action as needed
if (visibleCompositesChange && overflows) {
if ((visibleCompositesChange && overflows) || this.compositeSwitcherBar.length() === 0) {
this.compositeOverflowAction = this.instantiationService.createInstance(CompositeOverflowActivityAction, () => this.compositeOverflowActionItem.showMenu());
this.compositeOverflowActionItem = this.instantiationService.createInstance(
CompositeOverflowActivityActionItem,
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M.379 5.652l2.828-2.828 4.76 4.761 4.826-4.826 2.828 2.828-7.654 7.654L.379 5.652z" id="outline" style="display: none;"/><g id="iconBg"><path class="icon-vs-bg" d="M7.967 11.827L1.793 5.652l1.414-1.414 4.76 4.761 4.826-4.826 1.414 1.414-6.24 6.24z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M.379 5.652l2.828-2.828 4.76 4.761 4.826-4.826 2.828 2.828-7.654 7.654L.379 5.652z" id="outline" style="display: none;"/><g id="iconBg"><path class="icon-vs-bg" d="M7.967 11.827L1.793 5.652l1.414-1.414 4.76 4.761 4.826-4.826 1.414 1.414-6.24 6.24z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#2d2d30;}.icon-canvas-transparent{opacity:0;}.icon-vs-fg{fill:#2b282e;}.icon-vs-bg{fill:#c5c5c5;}</style></defs><title>BottomRowOfTwoRows_16x</title><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/><path class="icon-vs-out" d="M16,0V15H1V0Z" style="display: none;"/><path class="icon-vs-fg" d="M14,2V8H3V2Z" style="display: none;"/><path class="icon-vs-bg" d="M2,1V14H15V1ZM14,8H3V2H14Z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-fg{fill:#f0eff1;}.icon-vs-bg{fill:#424242;}</style></defs><title>BottomRowOfTwoRows_16x</title><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/><path class="icon-vs-out" d="M16,0V15H1V0Z" style="display: none;"/><path class="icon-vs-fg" d="M14,2V8H3V2Z" style="display: none;"/><path class="icon-vs-bg" d="M2,1V14H15V1ZM14,8H3V2H14Z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#2d2d30;}.icon-canvas-transparent{opacity:0;}.icon-vs-fg{fill:#2b282e;}.icon-vs-bg{fill:#c5c5c5;}</style></defs><title>RightColumnOfTwoColumns_16x</title><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/><path class="icon-vs-out" d="M16,0V15H1V0Z" style="display: none;"/><path class="icon-vs-fg" d="M9,2V13H3V2Z" style="display: none;"/><path class="icon-vs-bg" d="M2,1V14H15V1ZM9,13H3V2H9Z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-fg{fill:#f0eff1;}.icon-vs-bg{fill:#424242;}</style></defs><title>RightColumnOfTwoColumns_16x</title><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/><path class="icon-vs-out" d="M16,0V15H1V0Z" style="display: none;"/><path class="icon-vs-fg" d="M9,2V13H3V2Z" style="display: none;"/><path class="icon-vs-bg" d="M2,1V14H15V1ZM9,13H3V2H9Z"/></svg>
\ No newline at end of file
......@@ -13,8 +13,6 @@
}
.monaco-workbench > .part.panel .title {
border-top-width: 1px;
border-top-style: solid;
padding-right: 0px;
height: 35px;
display: flex;
......@@ -22,6 +20,16 @@
justify-content: space-between;
}
.monaco-workbench > .part.panel.bottom .title {
border-top-width: 1px;
border-top-style: solid;
}
.monaco-workbench > .part.panel.right {
border-left-width: 1px;
border-left-style: solid;
}
.monaco-workbench > .part.panel > .composite.title > .title-actions {
flex: 0;
}
......@@ -88,22 +96,22 @@
background: url('close.svg') center center no-repeat;
}
.monaco-workbench .maximize-panel-action {
background: url('up.svg') center center no-repeat;
.monaco-workbench .move-panel-to-right {
background: url('panel-right.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .maximize-panel-action,
.hc-black .monaco-workbench .maximize-panel-action {
background: url('up-inverse.svg') center center no-repeat;
.vs-dark .monaco-workbench .move-panel-to-right,
.hc-black .monaco-workbench .move-panel-to-right {
background: url('panel-right-inverse.svg') center center no-repeat;
}
.monaco-workbench .minimize-panel-action {
background: url('down.svg') center center no-repeat;
.monaco-workbench .move-panel-to-bottom {
background: url('panel-bottom.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .minimize-panel-action,
.hc-black .monaco-workbench .minimize-panel-action {
background: url('down-inverse.svg') center center no-repeat;
.vs-dark .monaco-workbench .move-panel-to-bottom,
.hc-black .monaco-workbench .move-panel-to-bottom {
background: url('panel-bottom-inverse.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .hide-panel-action,
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M7.967 2.759l7.654 7.654-2.828 2.828-4.826-4.826-4.76 4.761-2.828-2.828 7.588-7.589z" id="outline" style="display: none;"/><g id="iconBg"><path class="icon-vs-bg" d="M14.207 10.413l-1.414 1.414-4.826-4.826-4.76 4.761-1.414-1.414 6.174-6.175 6.24 6.24z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M7.967 2.759l7.654 7.654-2.828 2.828-4.826-4.826-4.76 4.761-2.828-2.828 7.588-7.589z" id="outline" style="display: none;"/><g id="iconBg"><path class="icon-vs-bg" d="M14.207 10.413l-1.414 1.414-4.826-4.826-4.76 4.761-1.414-1.414 6.174-6.175 6.24 6.24z"/></g></svg>
\ No newline at end of file
......@@ -13,10 +13,11 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/actions';
import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
import { IPartService, Parts, Position } from 'vs/workbench/services/part/common/partService';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ActivityAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions';
import { IActivity } from 'vs/workbench/common/activity';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
export class OpenPanelAction extends Action {
......@@ -117,32 +118,36 @@ class FocusPanelAction extends Action {
}
}
export class ToggleMaximizedPanelAction extends Action {
export class TogglePanelPositionAction extends Action {
public static ID = 'workbench.action.toggleMaximizedPanel';
public static LABEL = nls.localize('toggleMaximizedPanel', "Toggle Maximized Panel");
private static MAXIMIZE_LABEL = nls.localize('maximizePanel', "Maximize Panel Size");
private static RESTORE_LABEL = nls.localize('minimizePanel', "Restore Panel Size");
public static ID = 'workbench.action.togglePanelPosition';
public static LABEL = nls.localize('toggledPanelPosition', "Toggle Panel Position");
private static MOVE_TO_RIGHT_LABEL = nls.localize('moveToRight', "Move to Right");
private static MOVE_TO_BOTTOM_LABEL = nls.localize('moveToBottom', "Move to Bottom");
private static panelPositionConfigurationKey = 'workbench.panel.location';
private toDispose: IDisposable[];
constructor(
id: string,
label: string,
@IPartService private partService: IPartService
@IPartService private partService: IPartService,
@IConfigurationService private configurationService: IConfigurationService
) {
super(id, label, partService.isPanelMaximized() ? 'minimize-panel-action' : 'maximize-panel-action');
super(id, label, partService.getPanelPosition() === Position.RIGHT ? 'move-panel-to-bottom' : 'move-panel-to-right');
this.toDispose = [];
this.toDispose.push(partService.onEditorLayout(() => {
const maximized = this.partService.isPanelMaximized();
this.class = maximized ? 'minimize-panel-action' : 'maximize-panel-action';
this.label = maximized ? ToggleMaximizedPanelAction.RESTORE_LABEL : ToggleMaximizedPanelAction.MAXIMIZE_LABEL;
const positionRight = this.partService.getPanelPosition() === Position.RIGHT;
this.class = positionRight ? 'move-panel-to-bottom' : 'move-panel-to-right';
this.label = positionRight ? TogglePanelPositionAction.MOVE_TO_BOTTOM_LABEL : TogglePanelPositionAction.MOVE_TO_RIGHT_LABEL;
}));
}
public run(): TPromise<any> {
// Show panel
return this.partService.setPanelHidden(false)
.then(() => this.partService.toggleMaximizedPanel());
const position = this.partService.getPanelPosition();
const newPositionValue = (position === Position.BOTTOM) ? 'right' : 'bottom';
return this.configurationService.updateValue(TogglePanelPositionAction.panelPositionConfigurationKey, newPositionValue, ConfigurationTarget.USER);
}
public dispose(): void {
......@@ -168,5 +173,5 @@ export class PanelActivityAction extends ActivityAction {
const actionRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchExtensions.WorkbenchActions);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TogglePanelAction, TogglePanelAction.ID, TogglePanelAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_J }), 'View: Toggle Panel', nls.localize('view', "View"));
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPanelAction, FocusPanelAction.ID, FocusPanelAction.LABEL), 'View: Focus into Panel', nls.localize('view', "View"));
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, ToggleMaximizedPanelAction.LABEL), 'View: Toggle Maximized Panel', nls.localize('view', "View"));
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClosePanelAction, ClosePanelAction.ID, ClosePanelAction.LABEL), 'View: Close Panel', nls.localize('view', "View"));
\ No newline at end of file
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClosePanelAction, ClosePanelAction.ID, ClosePanelAction.LABEL), 'View: Close Panel', nls.localize('view', "View"));
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TogglePanelPositionAction, TogglePanelPositionAction.ID, TogglePanelPositionAction.LABEL), 'View: Toggle Panel Position', nls.localize('view', "View"));
......@@ -22,7 +22,7 @@ import { IMessageService } from 'vs/platform/message/common/message';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ClosePanelAction, ToggleMaximizedPanelAction, PanelActivityAction, OpenPanelAction } from 'vs/workbench/browser/parts/panel/panelActions';
import { ClosePanelAction, TogglePanelPositionAction, PanelActivityAction, OpenPanelAction } from 'vs/workbench/browser/parts/panel/panelActions';
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry';
......@@ -36,6 +36,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
public static activePanelSettingsKey = 'workbench.panelpart.activepanelid';
private static readonly PINNED_PANELS = 'workbench.panel.pinnedPanels';
private static readonly MIN_COMPOSITE_BAR_WIDTH = 50;
public _serviceBrand: any;
......@@ -120,11 +121,12 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
return this._onDidCompositeClose.event;
}
protected updateStyles(): void {
public updateStyles(): void {
super.updateStyles();
const container = this.getContainer();
container.style('background-color', this.getColor(PANEL_BACKGROUND));
container.style('border-left-color', this.getColor(PANEL_BORDER) || this.getColor(contrastBorder));
const title = this.getTitleArea();
title.style('border-top-color', this.getColor(PANEL_BORDER) || this.getColor(contrastBorder));
......@@ -175,7 +177,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
protected getActions(): IAction[] {
return [
this.instantiationService.createInstance(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, ToggleMaximizedPanelAction.LABEL),
this.instantiationService.createInstance(TogglePanelPositionAction, TogglePanelPositionAction.ID, TogglePanelPositionAction.LABEL),
this.instantiationService.createInstance(ClosePanelAction, ClosePanelAction.ID, ClosePanelAction.LABEL)
];
}
......@@ -224,7 +226,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
let availableWidth = this.dimension.width - 8; // take padding into account
if (this.toolBar) {
// adjust height for global actions showing
availableWidth -= this.toolBar.getContainer().getHTMLElement().offsetWidth;
availableWidth = Math.max(PanelPart.MIN_COMPOSITE_BAR_WIDTH, availableWidth - this.toolBar.getContainer().getHTMLElement().offsetWidth);
}
this.compositeBar.layout(new Dimension(availableWidth, this.dimension.height));
}
......
......@@ -222,6 +222,12 @@ let workbenchProperties: { [path: string]: IJSONSchema; } = {
'default': 'left',
'description': nls.localize('sideBarLocation', "Controls the location of the sidebar. It can either show on the left or right of the workbench.")
},
'workbench.panel.location': {
'type': 'string',
'enum': ['bottom', 'right'],
'default': 'bottom',
'description': nls.localize('panelLocation', "Controls the location of the panel. It can either show on the bottom or right of the workbench.")
},
'workbench.statusBar.visible': {
'type': 'boolean',
'default': true,
......
......@@ -38,7 +38,7 @@ import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbe
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController';
import { getServices } from 'vs/platform/instantiation/common/extensions';
import { Position, Parts, IPartService, ILayoutOptions } from 'vs/workbench/services/part/common/partService';
import { Position, Parts, IPartService } from 'vs/workbench/services/part/common/partService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService';
......@@ -152,6 +152,7 @@ export class Workbench implements IPartService {
private static zenModeActiveSettingKey = 'workbench.zenmode.active';
private static sidebarPositionConfigurationKey = 'workbench.sideBar.location';
private static panelPositionConfigurationKey = 'workbench.panel.location';
private static statusbarVisibleConfigurationKey = 'workbench.statusBar.visible';
private static activityBarVisibleConfigurationKey = 'workbench.activityBar.visible';
......@@ -194,6 +195,7 @@ export class Workbench implements IPartService {
private statusBarHidden: boolean;
private activityBarHidden: boolean;
private sideBarPosition: Position;
private panelPosition: Position;
private panelHidden: boolean;
private editorBackgroundDelayer: Delayer<void>;
private closeEmptyWindowScheduler: RunOnceScheduler;
......@@ -643,6 +645,10 @@ export class Workbench implements IPartService {
const sideBarPosition = this.configurationService.getValue<string>(Workbench.sidebarPositionConfigurationKey);
this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT;
// Panel position
const panelPosition = this.configurationService.getValue<string>(Workbench.panelPositionConfigurationKey);
this.panelPosition = (panelPosition === 'right') ? Position.RIGHT : Position.BOTTOM;
// Statusbar visibility
const statusBarVisible = this.configurationService.getValue<string>(Workbench.statusbarVisibleConfigurationKey);
this.statusBarHidden = !statusBarVisible;
......@@ -886,14 +892,6 @@ export class Workbench implements IPartService {
});
}
public toggleMaximizedPanel(): void {
this.workbenchLayout.layout({ toggleMaximizedPanel: true });
}
public isPanelMaximized(): boolean {
return this.workbenchLayout.isPanelMaximized();
}
public getSideBarPosition(): Position {
return this.sideBarPosition;
}
......@@ -921,6 +919,30 @@ export class Workbench implements IPartService {
this.workbenchLayout.layout();
}
public getPanelPosition(): Position {
return this.panelPosition;
}
private setPanelPosition(position: Position): void {
if (this.panelHidden) {
this.setPanelHidden(false, true /* Skip Layout */).done(undefined, errors.onUnexpectedError);
}
const newPositionValue = (position === Position.BOTTOM) ? 'bottom' : 'right';
const oldPositionValue = (this.panelPosition === Position.BOTTOM) ? 'bottom' : 'right';
this.panelPosition = position;
// Adjust CSS
this.panelPart.getContainer().removeClass(oldPositionValue);
this.panelPart.getContainer().addClass(newPositionValue);
// Update Styles
this.panelPart.updateStyles();
// Layout
this.workbenchLayout.layout();
}
private setFontAliasing(aliasing: string) {
this.fontAliasing = aliasing;
......@@ -940,9 +962,9 @@ export class Workbench implements IPartService {
* Asks the workbench and all its UI components inside to lay out according to
* the containers dimension the workbench is living in.
*/
public layout(options?: ILayoutOptions): void {
public layout(): void {
if (this.isStarted()) {
this.workbenchLayout.layout(options);
this.workbenchLayout.layout();
}
}
......@@ -1076,6 +1098,12 @@ export class Workbench implements IPartService {
this.setSideBarPosition(newSidebarPosition);
}
const newPanelPositionValue = this.configurationService.getValue<string>(Workbench.panelPositionConfigurationKey);
const newPanelPosition = (newPanelPositionValue === 'right') ? Position.RIGHT : Position.BOTTOM;
if (newPanelPosition !== this.getSideBarPosition()) {
this.setPanelPosition(newPanelPosition);
}
const fontAliasing = this.configurationService.getValue<string>(Workbench.fontAliasingConfigurationKey);
if (fontAliasing !== this.fontAliasing) {
this.setFontAliasing(fontAliasing);
......@@ -1190,7 +1218,7 @@ export class Workbench implements IPartService {
private createPanelPart(): void {
const panelPartContainer = $(this.workbench)
.div({
'class': ['part', 'panel'],
'class': ['part', 'panel', this.panelPosition === Position.BOTTOM ? 'bottom' : 'right'],
id: Identifiers.PANEL_PART,
role: 'complementary'
});
......
......@@ -19,11 +19,8 @@ export enum Parts {
export enum Position {
LEFT,
RIGHT
}
export interface ILayoutOptions {
toggleMaximizedPanel?: boolean;
RIGHT,
BOTTOM
}
export const IPartService = createDecorator<IPartService>('partService');
......@@ -44,7 +41,7 @@ export interface IPartService {
/**
* Asks the part service to layout all parts.
*/
layout(options?: ILayoutOptions): void;
layout(): void;
/**
* Asks the part service to if all parts have been created.
......@@ -92,20 +89,14 @@ export interface IPartService {
setPanelHidden(hidden: boolean): TPromise<void>;
/**
* Maximizes the panel height if the panel is not already maximized.
* Shrinks the panel to the default starting size if the panel is maximized.
*/
toggleMaximizedPanel(): void;
/**
* Returns true if the panel is maximized.
* Gets the current side bar position. Note that the sidebar can be hidden too.
*/
isPanelMaximized(): boolean;
getSideBarPosition(): Position;
/**
* Gets the current side bar position. Note that the sidebar can be hidden too.
* Gets the current panel position. Note that the panel can be hidden too.
*/
getSideBarPosition(): Position;
getPanelPosition(): Position;
/**
* Returns the identifier of the element that contains the workbench.
......
......@@ -418,6 +418,10 @@ export class TestPartService implements IPartService {
return 0;
}
public getPanelPosition() {
return 0;
}
public addClass(clazz: string): void { }
public removeClass(clazz: string): void { }
public getWorkbenchElementId(): string { return ''; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册