diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index abd11cd556af0e51b02c70a210420e99f42ccf8f..11c8359fdd26e96e083c06e477421903a704b5fd 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -588,6 +588,8 @@ export const HotExitConfiguration = { export const CONTENT_CHANGE_EVENT_BUFFER_DELAY = 1000; +export const FILES_ASSOCIATIONS_CONFIG = 'files.associations'; + export interface IFilesConfiguration { files: { associations: { [filepattern: string]: string }; diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index bf7bf9f97d64c6c27ab5697299c36d610422e5b1..5d2192810e887d572384f227891c2c8c8c026c5e 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -22,7 +22,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { IDecorationsService, IResourceDecorationChangeEvent } from 'vs/workbench/services/decorations/browser/decorations'; import { Schemas } from 'vs/base/common/network'; -import { FileKind } from 'vs/platform/files/common/files'; +import { FileKind, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IModel } from 'vs/editor/common/editorCommon'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -64,11 +64,25 @@ export class ResourceLabel extends IconLabel { } private registerListeners(): void { - this.extensionService.onReady().then(() => this.render(true /* clear cache */)); // update when extensions are loaded with potentially new languages - this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => this.render(true /* clear cache */))); // update when file.associations change - this.toDispose.push(this.modelService.onModelModeChanged(e => this.onModelModeChanged(e))); // react to model mode changes - this.toDispose.push(this.decorationsService.onDidChangeDecorations(this.onFileDecorationsChanges, this)); // react to file decoration changes + + // update when extensions are loaded with potentially new languages + this.extensionService.onReady().then(() => this.render(true /* clear cache */)); + + // react to model mode changes + this.toDispose.push(this.modelService.onModelModeChanged(e => this.onModelModeChanged(e))); + + // react to file decoration changes + this.toDispose.push(this.decorationsService.onDidChangeDecorations(this.onFileDecorationsChanges, this)); + + // react to theme changes this.toDispose.push(this.themeService.onThemeChange(() => this.render(false))); + + // react to files.associations changes + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(FILES_ASSOCIATIONS_CONFIG)) { + this.render(true /* clear cache */); + } + })); } private onModelModeChanged(e: { model: IModel; oldModeId: string; }): void { diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index fead4e1c3b3cb66b3b2782c79b02757f811d2a52..3e15e6118d34e6f3bdb62c2bf1eb35aa2164b922 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -218,7 +218,6 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService if (configuration && configuration.workbench && configuration.workbench.editor) { const editorConfig = configuration.workbench.editor; - // Pin all preview editors of the user chose to disable preview const newPreviewEditors = editorConfig.enablePreview; if (this.tabOptions.previewEditors !== newPreviewEditors && !newPreviewEditors) { diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index ee23ffe9df8e1c3732611a7b761d1f711f73be3a..2ffc03718df35e146eb22937c1b7eff7e9791cb3 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -33,7 +33,7 @@ import { IEditor as IBaseEditor, IEditorInput } from 'vs/platform/editor/common/ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { SUPPORTED_ENCODINGS, IFileService, IFilesConfiguration } from 'vs/platform/files/common/files'; +import { SUPPORTED_ENCODINGS, IFileService, IFilesConfiguration, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -785,8 +785,6 @@ export class ChangeModeAction extends Action { public static ID = 'workbench.action.editor.changeLanguageMode'; public static LABEL = nls.localize('changeMode', "Change Language Mode"); - private static FILE_ASSOCIATION_KEY = 'files.associations'; - constructor( actionId: string, actionLabel: string, @@ -964,7 +962,7 @@ export class ChangeModeAction extends Action { TPromise.timeout(50 /* quick open is sensitive to being opened so soon after another */).done(() => { this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickLanguageToConfigure', "Select Language Mode to Associate with '{0}'", extension || basename) }).done(language => { if (language) { - const fileAssociationsConfig = this.configurationService.inspect(ChangeModeAction.FILE_ASSOCIATION_KEY); + const fileAssociationsConfig = this.configurationService.inspect(FILES_ASSOCIATIONS_CONFIG); let associationKey: string; if (extension && basename[0] !== '.') { @@ -987,7 +985,7 @@ export class ChangeModeAction extends Action { currentAssociations[associationKey] = language.id; - this.configurationService.updateValue(ChangeModeAction.FILE_ASSOCIATION_KEY, currentAssociations, target); + this.configurationService.updateValue(FILES_ASSOCIATIONS_CONFIG, currentAssociations, target); } }); }); diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 3a666cfbc1cdb3e340f4573159d4718a93aa1d14..b9efab5784eea44a9147d548921cf6f51dbb3df2 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -36,7 +36,7 @@ import { Component } from 'vs/workbench/common/component'; import Event, { Emitter } from 'vs/base/common/event'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { KeyMod } from 'vs/base/common/keyCodes'; -import { QuickOpenHandler, QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions, EditorQuickOpenEntry, IWorkbenchQuickOpenConfiguration } from 'vs/workbench/browser/quickopen'; +import { QuickOpenHandler, QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions, EditorQuickOpenEntry, CLOSE_ON_FOCUS_LOST_CONFIG } from 'vs/workbench/browser/quickopen'; import errors = require('vs/base/common/errors'); import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPickOpenEntry, IFilePickOpenEntry, IInputOptions, IQuickOpenService, IPickOptions, IShowOptions, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen'; @@ -131,22 +131,22 @@ export class QuickOpenController extends Component implements IQuickOpenService this._onShow = new Emitter(); this._onHide = new Emitter(); - this.updateConfiguration(this.configurationService.getConfiguration()); + this.updateConfiguration(); this.registerListeners(); } private registerListeners(): void { - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.updateConfiguration(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.updateConfiguration())); this.toUnbind.push(this.partService.onTitleBarVisibilityChange(() => this.positionQuickOpenWidget())); this.toUnbind.push(browser.onDidChangeZoomLevel(() => this.positionQuickOpenWidget())); } - private updateConfiguration(settings: IWorkbenchQuickOpenConfiguration): void { + private updateConfiguration(): void { if (this.environmentService.args['sticky-quickopen']) { this.closeOnFocusLost = false; } else { - this.closeOnFocusLost = settings.workbench && settings.workbench.quickOpen && settings.workbench.quickOpen.closeOnFocusLost; + this.closeOnFocusLost = this.configurationService.getValue(CLOSE_ON_FOCUS_LOST_CONFIG); } } diff --git a/src/vs/workbench/browser/quickopen.ts b/src/vs/workbench/browser/quickopen.ts index 07d0289da9ead884392ca69d3f75d0a827f5ee51..8c7cf7bea1e4c607ddfbd3737ad9c287c26ab7dd 100644 --- a/src/vs/workbench/browser/quickopen.ts +++ b/src/vs/workbench/browser/quickopen.ts @@ -22,11 +22,10 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IConstructorSignature0, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +export const CLOSE_ON_FOCUS_LOST_CONFIG = 'workbench.quickOpen.closeOnFocusLost'; + export interface IWorkbenchQuickOpenConfiguration { workbench: { - quickOpen: { - closeOnFocusLost: boolean; - }, commandPalette: { history: number; preserveInput: boolean; diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 2df8fc14a2d425bb9e7c990bae6431e6260fabaa..6ec676c9306faec5c0799d8c2433129b6f6b026c 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -804,6 +804,8 @@ export const EditorOpenPositioning = { LAST: 'last' }; +export const OPEN_POSITIONING_CONFIG = 'workbench.editor.openPositioning'; + export interface IWorkbenchEditorConfiguration { /* __GDPR__FRAGMENT__ "IWorkbenchEditorConfiguration" : { diff --git a/src/vs/workbench/common/editor/editorStacksModel.ts b/src/vs/workbench/common/editor/editorStacksModel.ts index 148a01d2c41bca64c6b96caae8bb7f20b5c413a1..20f09e32702b1d94dec5752ac56a75daaacfa55a 100644 --- a/src/vs/workbench/common/editor/editorStacksModel.ts +++ b/src/vs/workbench/common/editor/editorStacksModel.ts @@ -6,11 +6,11 @@ 'use strict'; import Event, { Emitter, once } from 'vs/base/common/event'; -import { Extensions, IEditorInputFactoryRegistry, EditorInput, toResource, IEditorStacksModel, IEditorGroup, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, IStacksModelChangeEvent, IWorkbenchEditorConfiguration, EditorOpenPositioning, SideBySideEditorInput } from 'vs/workbench/common/editor'; +import { Extensions, IEditorInputFactoryRegistry, EditorInput, toResource, IEditorStacksModel, IEditorGroup, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, IStacksModelChangeEvent, EditorOpenPositioning, SideBySideEditorInput, OPEN_POSITIONING_CONFIG } from 'vs/workbench/common/editor'; import URI from 'vs/base/common/uri'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -84,7 +84,7 @@ export class EditorGroup implements IEditorGroup { this.mru = []; this.toDispose = []; this.mapResourceToEditorCount = new ResourceMap(); - this.onConfigurationUpdated(configurationService.getConfiguration()); + this.onConfigurationUpdated(); this._onEditorActivated = new Emitter(); this._onEditorOpened = new Emitter(); @@ -110,13 +110,11 @@ export class EditorGroup implements IEditorGroup { } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e))); } - private onConfigurationUpdated(config: IWorkbenchEditorConfiguration): void { - if (config && config.workbench && config.workbench.editor) { - this.editorOpenPositioning = config.workbench.editor.openPositioning; - } + private onConfigurationUpdated(event?: IConfigurationChangeEvent): void { + this.editorOpenPositioning = this.configurationService.getValue(OPEN_POSITIONING_CONFIG); } public get id(): GroupIdentifier { diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index aeefa814e9ff4b351f3662b01b989d490481ba93..e40bc555cb2d64381a452c66fe5abcdbe1d937fc 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -46,7 +46,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationTarget, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; const TextInputActions: IAction[] = [ new Action('undo', nls.localize('undo', "Undo"), null, true, () => document.execCommand('undo') && TPromise.as(true)), @@ -261,7 +261,11 @@ export class ElectronWindow extends Themable { } } - private onDidUpdateConfiguration(e): void { + private onDidUpdateConfiguration(event: IConfigurationChangeEvent): void { + if (!event.affectsConfiguration('window.zoomLevel')) { + return; + } + const windowConfig: IWindowsConfiguration = this.configurationService.getConfiguration(); let newZoomLevel = 0; diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 0ca26a15f24648b70d063dff79997edd11ed7a40..f2d871d7eb69c3294b51e42d780b2262a570391d 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -15,7 +15,6 @@ import DOM = require('vs/base/browser/dom'); import { Builder, $ } from 'vs/base/browser/builder'; import { Delayer, RunOnceScheduler } from 'vs/base/common/async'; import * as browser from 'vs/base/browser/browser'; -import assert = require('vs/base/common/assert'); import { StopWatch } from 'vs/base/common/stopwatch'; import { startTimer } from 'vs/base/node/startupTimers'; import errors = require('vs/base/common/errors'); @@ -267,9 +266,6 @@ export class Workbench implements IPartService { * once. Use the shutdown function to free up resources created by the workbench on startup. */ public startup(callbacks?: IWorkbenchCallbacks): void { - assert.ok(!this.workbenchStarted, 'Can not start a workbench that was already started'); - assert.ok(!this.workbenchShutdown, 'Can not start a workbench that was shutdown'); - try { this.workbenchStarted = true; this.callbacks = callbacks; @@ -1224,26 +1220,18 @@ export class Workbench implements IPartService { } public getEditorPart(): EditorPart { - assert.ok(this.workbenchStarted, 'Workbench is not started. Call startup() first.'); - return this.editorPart; } public getSidebarPart(): SidebarPart { - assert.ok(this.workbenchStarted, 'Workbench is not started. Call startup() first.'); - return this.sidebarPart; } public getPanelPart(): PanelPart { - assert.ok(this.workbenchStarted, 'Workbench is not started. Call startup() first.'); - return this.panelPart; } public getInstantiationService(): IInstantiationService { - assert.ok(this.workbenchStarted, 'Workbench is not started. Call startup() first.'); - return this.instantiationService; } @@ -1265,6 +1253,7 @@ export class Workbench implements IPartService { public toggleZenMode(skipLayout?: boolean): void { this.zenMode.active = !this.zenMode.active; + // Check if zen mode transitioned to full screen and if now we are out of zen mode -> we need to go out of full screen let toggleFullScreen = false; if (this.zenMode.active) { @@ -1279,9 +1268,11 @@ export class Workbench implements IPartService { if (config.hideActivityBar) { this.setActivityBarHidden(true, true); } + if (config.hideStatusBar) { this.setStatusBarHidden(true, true); } + if (config.hideTabs) { this.editorPart.hideTabs(true); } @@ -1289,9 +1280,11 @@ export class Workbench implements IPartService { if (this.zenMode.wasPanelVisible) { this.setPanelHidden(false, true).done(undefined, errors.onUnexpectedError); } + if (this.zenMode.wasSideBarVisible) { this.setSideBarHidden(false, true).done(undefined, errors.onUnexpectedError); } + // Status bar and activity bar visibility come from settings -> update their visibility. this.onDidUpdateConfiguration(true); this.editorPart.hideTabs(false); @@ -1299,13 +1292,16 @@ export class Workbench implements IPartService { if (activeEditor) { activeEditor.focus(); } + toggleFullScreen = this.zenMode.transitionedToFullScreen && browser.isFullscreen(); } + this.inZenMode.set(this.zenMode.active); if (!skipLayout) { this.layout(); } + if (toggleFullScreen) { this.windowService.toggleFullScreen().done(undefined, errors.onUnexpectedError); } diff --git a/src/vs/workbench/services/mode/common/workbenchModeService.ts b/src/vs/workbench/services/mode/common/workbenchModeService.ts index ad3c007b72c3d5f53b4ee88479c7ba32dd3e2f79..62023d035bbe3e7ad27cb22d8a9ef65188078b0c 100644 --- a/src/vs/workbench/services/mode/common/workbenchModeService.ts +++ b/src/vs/workbench/services/mode/common/workbenchModeService.ts @@ -9,7 +9,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; import mime = require('vs/base/common/mime'); -import { IFilesConfiguration } from 'vs/platform/files/common/files'; +import { IFilesConfiguration, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IExtensionPointUser, ExtensionMessageCollector, IExtensionPoint, ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry'; import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; @@ -124,7 +124,7 @@ export class WorkbenchModeServiceImpl extends ModeServiceImpl { }); this._configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration('files.associations')) { + if (e.affectsConfiguration(FILES_ASSOCIATIONS_CONFIG)) { this.updateMime(); } }); diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index 27a1924529696b02bf9194f89b1b98f2e440e688..21b9c241b60a9e65532e64c422d6bdc59e1243b3 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -85,7 +85,7 @@ export abstract class TextFileService implements ITextFileService { const configuration = this.configurationService.getConfiguration(); this.currentFilesAssociationConfig = configuration && configuration.files && configuration.files.associations; - this.onConfigurationChange(configuration); + this.onFilesConfigurationChange(configuration); /* __GDPR__ "autoSave" : { @@ -123,8 +123,12 @@ export abstract class TextFileService implements ITextFileService { this.lifecycleService.onWillShutdown(event => event.veto(this.beforeShutdown(event.reason))); this.lifecycleService.onShutdown(this.dispose, this); - // Configuration changes - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); + // Files configuration changes + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('files')) { + this.onFilesConfigurationChange(this.configurationService.getConfiguration()); + } + })); } private beforeShutdown(reason: ShutdownReason): boolean | TPromise { @@ -316,7 +320,7 @@ export abstract class TextFileService implements ITextFileService { return this.backupFileService.discardAllWorkspaceBackups(); } - protected onConfigurationChange(configuration: IFilesConfiguration): void { + protected onFilesConfigurationChange(configuration: IFilesConfiguration): void { const wasAutoSaveEnabled = (this.getAutoSaveMode() !== AutoSaveMode.OFF); const autoSaveMode = (configuration && configuration.files && configuration.files.autoSave) || AutoSaveConfiguration.OFF; diff --git a/src/vs/workbench/services/textfile/test/textFileService.test.ts b/src/vs/workbench/services/textfile/test/textFileService.test.ts index 38b5749c179c7cc503975f1f32e36a10e84c5d5b..6416edee36b348c29f5df65fd8d95963352ab2fe 100644 --- a/src/vs/workbench/services/textfile/test/textFileService.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileService.test.ts @@ -104,7 +104,7 @@ suite('Files - TextFileService', () => { const service = accessor.textFileService; service.setConfirmResult(ConfirmResult.DONT_SAVE); - service.onConfigurationChange({ files: { hotExit: 'off' } }); + service.onFilesConfigurationChange({ files: { hotExit: 'off' } }); model.load().done(() => { model.textEditorModel.setValue('foo'); @@ -137,7 +137,7 @@ suite('Files - TextFileService', () => { const service = accessor.textFileService; service.setConfirmResult(ConfirmResult.SAVE); - service.onConfigurationChange({ files: { hotExit: 'off' } }); + service.onFilesConfigurationChange({ files: { hotExit: 'off' } }); model.load().done(() => { model.textEditorModel.setValue('foo'); @@ -377,7 +377,7 @@ suite('Files - TextFileService', () => { const service = accessor.textFileService; // Set hot exit config - service.onConfigurationChange({ files: { hotExit: setting } }); + service.onFilesConfigurationChange({ files: { hotExit: setting } }); // Set empty workspace if required if (!workspace) { accessor.contextService.setWorkspace(new Workspace('empty:1508317022751')); diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index f371d3afeca318a3fd01ee7a15d87f796c587765..1fcdca0f09cc47be5ee8ce864ecc06811cd62211 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -233,8 +233,8 @@ export class TestTextFileService extends TextFileService { return this.confirmResult; } - public onConfigurationChange(configuration: any): void { - super.onConfigurationChange(configuration); + public onFilesConfigurationChange(configuration: any): void { + super.onFilesConfigurationChange(configuration); } protected cleanupBackupsBeforeShutdown(): TPromise {