diff --git a/src/vs/test/utils/servicesTestUtils.ts b/src/vs/test/utils/servicesTestUtils.ts index c8e376329125b13c5b32f0cb3b992ed125bc14e5..ef2764d529dbeb6db856b2331a38ff1aa0ec015b 100644 --- a/src/vs/test/utils/servicesTestUtils.ts +++ b/src/vs/test/utils/servicesTestUtils.ts @@ -293,6 +293,8 @@ export class TestPartService implements IPartService { public setRestoreSidebar(): void { } + + public toggleZenMode(): void { } } export class TestEventService extends EventEmitter implements IEventService { diff --git a/src/vs/workbench/browser/actions/toggleZenMode.ts b/src/vs/workbench/browser/actions/toggleZenMode.ts new file mode 100644 index 0000000000000000000000000000000000000000..4e05fd7d2d30decbd58e0a07ae0546457fcfa9e2 --- /dev/null +++ b/src/vs/workbench/browser/actions/toggleZenMode.ts @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TPromise } from 'vs/base/common/winjs.base'; +import nls = require('vs/nls'); +import { Registry } from 'vs/platform/platform'; +import { Action } from 'vs/base/common/actions'; +import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actionRegistry'; +import { IPartService } from 'vs/workbench/services/part/common/partService'; + +class ToggleZenMode extends Action { + + public static ID = 'workbench.action.toggleZenMode'; + public static LABEL = nls.localize('toggleZenMode', "Toggle Zen Mode"); + + constructor( + id: string, + label: string, + @IPartService private partService: IPartService + ) { + super(id, label); + this.enabled = !!this.partService; + } + + public run(): TPromise { + this.partService.toggleZenMode(); + return TPromise.as(null); + } +} + +let registry = Registry.as(Extensions.WorkbenchActions); +registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleZenMode, ToggleZenMode.ID, ToggleZenMode.LABEL), 'View: Toggle Zen Mode', nls.localize('view', "View")); diff --git a/src/vs/workbench/electron-browser/workbench.main.ts b/src/vs/workbench/electron-browser/workbench.main.ts index efc06c1ca57428a42afcb30bc3c2c9cbce808185..2538ab88fce3ea363f94c8ab09a6797deb1c9e7b 100644 --- a/src/vs/workbench/electron-browser/workbench.main.ts +++ b/src/vs/workbench/electron-browser/workbench.main.ts @@ -25,6 +25,7 @@ import 'vs/workbench/browser/actions/toggleStatusbarVisibility'; import 'vs/workbench/browser/actions/toggleSidebarVisibility'; import 'vs/workbench/browser/actions/toggleSidebarPosition'; import 'vs/workbench/browser/actions/toggleEditorLayout'; +import 'vs/workbench/browser/actions/toggleZenMode'; import 'vs/workbench/parts/settings/browser/openSettings.contribution'; import 'vs/workbench/browser/actions/configureLocale'; diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 57970234e3ae15f7e60ca26c07a121e9f7a3a860..bb0d0a94e09aea32edf8aaae7b31736156a8367a 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -80,6 +80,7 @@ import { TextModelResolverService } from 'vs/workbench/services/textmodelResolve import { ITextModelResolverService } from 'vs/editor/common/services/resolverService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; +import { IWindowService } from 'vs/platform/windows/common/windows'; import { IMessageService } from 'vs/platform/message/common/message'; import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar'; import { IMenuService } from 'vs/platform/actions/common/actions'; @@ -166,6 +167,11 @@ export class Workbench implements IPartService { private messagesVisibleContext: IContextKey; private editorsVisibleContext: IContextKey; private hasFilesToCreateOpenOrDiff: boolean; + private zenMode: { + active: boolean; + transitionedToFullScreen: boolean; + isPartVisible: { [part: string]: boolean }; + }; constructor( parent: HTMLElement, @@ -181,7 +187,8 @@ export class Workbench implements IPartService { @IMessageService private messageService: IMessageService, @IConfigurationService private configurationService: IConfigurationService, @ITelemetryService private telemetryService: ITelemetryService, - @IEnvironmentService private environmentService: IEnvironmentService + @IEnvironmentService private environmentService: IEnvironmentService, + @IWindowService private windowService: IWindowService ) { this.parent = parent; this.container = container; @@ -528,6 +535,13 @@ export class Workbench implements IPartService { // Activity bar visibility const activityBarVisible = this.configurationService.lookup(Workbench.activityBarVisibleConfigurationKey).value; this.activityBarHidden = !activityBarVisible; + + // Zen mode + this.zenMode = { + active: false, + isPartVisible: {}, + transitionedToFullScreen: false + }; } /** @@ -584,17 +598,18 @@ export class Workbench implements IPartService { } public isVisible(part: Parts): boolean { + const checkZenMode = (part: Parts) => !this.zenMode.active || this.zenMode.isPartVisible[part.toString()]; switch (part) { case Parts.TITLEBAR_PART: - return !this.isTitleBarHidden(); + return !this.isTitleBarHidden() && checkZenMode(Parts.TITLEBAR_PART); case Parts.SIDEBAR_PART: - return !this.sideBarHidden; + return !this.sideBarHidden && checkZenMode(Parts.SIDEBAR_PART); case Parts.PANEL_PART: - return !this.panelHidden; + return !this.panelHidden && checkZenMode(Parts.PANEL_PART); case Parts.STATUSBAR_PART: - return !this.statusBarHidden; + return !this.statusBarHidden && checkZenMode(Parts.STATUSBAR_PART); case Parts.ACTIVITYBAR_PART: - return !this.activityBarHidden; + return !this.activityBarHidden && checkZenMode(Parts.ACTIVITYBAR_PART); } return true; // any other part cannot be hidden @@ -635,8 +650,12 @@ export class Workbench implements IPartService { } private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void { + if (this.zenMode.active) { + this.zenMode.isPartVisible[Parts.STATUSBAR_PART.toString()] = !hidden; + } this.statusBarHidden = hidden; + // Layout if (!skipLayout) { this.workbenchLayout.layout({ forceStyleRecompute: true }); @@ -644,8 +663,12 @@ export class Workbench implements IPartService { } public setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void { + if (this.zenMode.active) { + this.zenMode.isPartVisible[Parts.ACTIVITYBAR_PART.toString()] = !hidden; + } this.activityBarHidden = hidden; + // Layout if (!skipLayout) { this.workbenchLayout.layout({ forceStyleRecompute: true }); @@ -653,6 +676,10 @@ export class Workbench implements IPartService { } public setSideBarHidden(hidden: boolean, skipLayout?: boolean): void { + if (this.zenMode.active) { + this.zenMode.isPartVisible[Parts.SIDEBAR_PART.toString()] = !hidden; + } + this.sideBarHidden = hidden; // Adjust CSS @@ -696,6 +723,9 @@ export class Workbench implements IPartService { } public setPanelHidden(hidden: boolean, skipLayout?: boolean): void { + if (this.zenMode.active) { + this.zenMode.isPartVisible[Parts.PANEL_PART.toString()] = !hidden; + } this.panelHidden = hidden; // Adjust CSS @@ -812,16 +842,23 @@ export class Workbench implements IPartService { // Apply as CSS class const isFullscreen = browser.isFullscreen(); + let exitedZenMode = false; if (isFullscreen) { this.addClass('fullscreen'); } else { this.removeClass('fullscreen'); + if (this.zenMode.transitionedToFullScreen) { + this.zenMode.active = false; + exitedZenMode = true; + } } // Changing fullscreen state of the window has an impact on custom title bar visibility, so we need to update const hasCustomTitle = this.getCustomTitleBarStyle() === 'custom'; if (hasCustomTitle) { this._onTitleBarVisibilityChange.fire(); + } + if (hasCustomTitle || exitedZenMode) { this.layout(); // handle title bar when fullscreen changes } } @@ -1031,6 +1068,24 @@ export class Workbench implements IPartService { this.storageService.store(Workbench.sidebarRestoreSettingKey, 'true', StorageScope.WORKSPACE); } + public toggleZenMode(): void { + this.zenMode.active = !this.zenMode.active; + Object.keys(this.zenMode.isPartVisible).forEach(key => this.zenMode.isPartVisible[key] = false); + if (!this.zenMode.active && this.zenMode.transitionedToFullScreen && browser.isFullscreen()) { + // Zen mode transitioned to full screen, now that we are out of zen mode we need to go out of full screen + this.windowService.toggleFullScreen(); + } + + if (this.zenMode.active) { + this.zenMode.transitionedToFullScreen = !browser.isFullscreen(); + if (this.zenMode.transitionedToFullScreen) { + this.windowService.toggleFullScreen(); + } + } + + this.layout(); + } + private shouldRestoreLastOpenedViewlet(): boolean { if (!this.environmentService.isBuilt) { return true; // always restore sidebar when we are in development mode diff --git a/src/vs/workbench/services/part/common/partService.ts b/src/vs/workbench/services/part/common/partService.ts index d7423882c2af975e9c385cbbcf5a6c5aab44d905..85ae1cee79e5a2b7c3b7f7e961e62a4216b1f22d 100644 --- a/src/vs/workbench/services/part/common/partService.ts +++ b/src/vs/workbench/services/part/common/partService.ts @@ -117,4 +117,9 @@ export interface IPartService { * Enables to restore the contents of the sidebar after a restart. */ setRestoreSidebar(): void; + + /** + * Toggles the workbench in and out of zen mode - parts get hidden and window goes fullscreen. + */ + toggleZenMode(): void; } \ No newline at end of file