diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index 70675aed006..6138e4961b9 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -40,7 +40,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { @IFileService private readonly _fileService: IFileService ) { this._proxy = extHostContext.get(ExtHostContext.ExtHostWorkspace); - this._contextService.onDidChangeWorkspaceFolders(this._onDidChangeWorkspace, this, this._toDispose); + this._contextService.onDidChangeWorkbenchState(this._onDidChangeWorkspaceState, this, this._toDispose); } dispose(): void { @@ -54,7 +54,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { // --- workspace --- - private _onDidChangeWorkspace(): void { + private _onDidChangeWorkspaceState(): void { this._proxy.$acceptWorkspaceData(this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : this._contextService.getWorkspace()); } diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index a83c9847408..1091ddda968 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -55,7 +55,7 @@ export class StatusbarPart extends Part implements IStatusbarService { } private registerListeners(): void { - this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateStyles())); + this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(() => this.updateStyles())); } public addEntry(entry: IStatusbarEntry, alignment: StatusbarAlignment, priority: number = 0): IDisposable { diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 3f7d2cee441..3f80f8c6a77 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -100,8 +100,9 @@ export class TitlebarPart extends Part implements ITitleService { this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.FOCUS, () => this.onFocus())); this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.onConfigurationChanged(true))); this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); - this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); - this.toUnbind.push(this.contextService.onDidChangeWorkspaceName(() => this.onDidChangeWorkspaceName())); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.setTitle(this.getWindowTitle()))); + this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(() => this.setTitle(this.getWindowTitle()))); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceName(() => this.setTitle(this.getWindowTitle()))); } private onBlur(): void { @@ -114,14 +115,6 @@ export class TitlebarPart extends Part implements ITitleService { this.updateStyles(); } - private onDidChangeWorkspaceFolders(): void { - this.setTitle(this.getWindowTitle()); - } - - private onDidChangeWorkspaceName(): void { - this.setTitle(this.getWindowTitle()); - } - private onConfigurationChanged(update?: boolean): void { const currentTitleTemplate = this.titleTemplate; this.titleTemplate = this.configurationService.lookup('window.title').value; diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index ee29aa9b7a2..34b7d02d846 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -90,16 +90,8 @@ export class ResourceGlobMatcher { } private registerListeners(): void { - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.onConfigurationChanged())); - this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); - } - - private onConfigurationChanged(): void { - this.updateExcludes(true); - } - - private onDidChangeWorkspaceFolders(): void { - this.updateExcludes(true); + this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.updateExcludes(true))); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateExcludes(true))); } private updateExcludes(fromEvent: boolean): void { diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index 4b53aa781f5..243f540d0bb 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -118,8 +118,10 @@ export class StartAction extends AbstractDebugAction { @IWorkspaceContextService private contextService: IWorkspaceContextService ) { super(id, label, 'debug-action start', debugService, keybindingService); - this.debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateEnablement()); - this.debugService.getModel().onDidChangeCallStack(() => this.updateEnablement()); + + this.toDispose.push(this.debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateEnablement())); + this.toDispose.push(this.debugService.getModel().onDidChangeCallStack(() => this.updateEnablement())); + this.toDispose.push(this.contextService.onDidChangeWorkbenchState(() => this.updateEnablement())); } public run(): TPromise { diff --git a/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts b/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts index b4ae967d067..979919f795a 100644 --- a/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts +++ b/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts @@ -49,7 +49,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri private registerListeners(): void { this.toUnbind.push(this.debugService.onDidChangeState(state => this.updateStyles())); - this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(state => this.updateStyles())); + this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(state => this.updateStyles())); } protected updateStyles(): void { diff --git a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts index 873ab35c441..0dd4994a388 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts @@ -63,7 +63,7 @@ export class FeedbackStatusbarItem extends Themable implements IStatusbarItem { } private registerListeners(): void { - this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateStyles())); + this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(() => this.updateStyles())); } protected updateStyles(): void { diff --git a/src/vs/workbench/parts/output/common/outputLinkProvider.ts b/src/vs/workbench/parts/output/common/outputLinkProvider.ts index 09c48178696..3964c0b2180 100644 --- a/src/vs/workbench/parts/output/common/outputLinkProvider.ts +++ b/src/vs/workbench/parts/output/common/outputLinkProvider.ts @@ -37,6 +37,7 @@ export class OutputLinkProvider { } private registerListeners(): void { + this.contextService.onDidChangeWorkbenchState(() => this.updateLinkProviderWorker()); this.contextService.onDidChangeWorkspaceFolders(() => this.updateLinkProviderWorker()); } diff --git a/src/vs/workbench/parts/search/browser/searchResultsView.ts b/src/vs/workbench/parts/search/browser/searchResultsView.ts index 752b44681bc..ec069ee2197 100644 --- a/src/vs/workbench/parts/search/browser/searchResultsView.ts +++ b/src/vs/workbench/parts/search/browser/searchResultsView.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import * as paths from 'vs/base/common/paths'; import * as DOM from 'vs/base/browser/dom'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; import { IAction, IActionRunner } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -14,7 +14,7 @@ import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; import { FileLabel } from 'vs/workbench/browser/labels'; import { ITree, IDataSource, ISorter, IAccessibilityProvider, IFilter, IRenderer } from 'vs/base/parts/tree/browser/tree'; import { Match, SearchResult, FileMatch, FileMatchOrMatch, SearchModel, FolderMatch } from 'vs/workbench/parts/search/common/searchModel'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { Range } from 'vs/editor/common/core/range'; import { SearchViewlet } from 'vs/workbench/parts/search/browser/searchViewlet'; import { RemoveAction, ReplaceAllAction, ReplaceAction } from 'vs/workbench/parts/search/browser/searchActions'; @@ -28,7 +28,17 @@ export class SearchDataSource implements IDataSource { private static AUTOEXPAND_CHILD_LIMIT = 10; - constructor(private includeFolderMatch: boolean = true) { } + private includeFolderMatch: boolean; + private listener: IDisposable; + + constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { + this.updateIncludeFolderMatch(); + this.listener = this.contextService.onDidChangeWorkbenchState(() => this.updateIncludeFolderMatch()); + } + + private updateIncludeFolderMatch(): void { + this.includeFolderMatch = (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE); + } public getId(tree: ITree, element: any): string { if (element instanceof FolderMatch) { @@ -90,6 +100,10 @@ export class SearchDataSource implements IDataSource { } return numChildren < SearchDataSource.AUTOEXPAND_CHILD_LIMIT || element instanceof FolderMatch; } + + public dispose(): void { + this.listener = dispose(this.listener); + } } export class SearchSorter implements ISorter { diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index a0b43cd4867..d7e68fd8658 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -103,6 +103,8 @@ export class SearchViewlet extends Viewlet { private selectCurrentMatchEmitter: Emitter; private delayedRefresh: Delayer; + private searchWithoutFolderMessageBuilder: Builder; + constructor( @ITelemetryService telemetryService: ITelemetryService, @IFileService private fileService: IFileService, @@ -141,6 +143,7 @@ export class SearchViewlet extends Viewlet { this.toUnbind.push(this.fileService.onFileChanges(e => this.onFilesChanged(e))); this.toUnbind.push(this.untitledEditorService.onDidChangeDirty(e => this.onUntitledDidChangeDirty(e))); + this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(() => this.onDidChangeWorkbenchState())); this.selectCurrentMatchEmitter = new Emitter(); debounceEvent(this.selectCurrentMatchEmitter.event, (l, e) => e, 100, /*leading=*/true) @@ -149,6 +152,12 @@ export class SearchViewlet extends Viewlet { this.delayedRefresh = new Delayer(250); } + private onDidChangeWorkbenchState(): void { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.searchWithoutFolderMessageBuilder) { + this.searchWithoutFolderMessageBuilder.hide(); + } + } + public create(parent: Builder): TPromise { super.create(parent); @@ -458,6 +467,8 @@ export class SearchViewlet extends Viewlet { } private clearMessage(): Builder { + this.searchWithoutFolderMessageBuilder = void 0; + return this.messages.empty().show() .asContainer().div({ 'class': 'message' }) .asContainer(); @@ -468,8 +479,12 @@ export class SearchViewlet extends Viewlet { this.results = div; this.results.addClass('show-file-icons'); - let dataSource = new SearchDataSource(this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE); + let dataSource = this.instantiationService.createInstance(SearchDataSource); + this.toUnbind.push(dataSource); + let renderer = this.instantiationService.createInstance(SearchRenderer, this.getActionRunner(), this); + this.toUnbind.push(renderer); + let dnd = new SimpleFileResourceDragAndDrop(obj => obj instanceof FileMatch ? obj.resource() : void 0); this.tree = new Tree(div.getHTMLElement(), { @@ -1271,7 +1286,9 @@ export class SearchViewlet extends Viewlet { } private searchWithoutFolderMessage(div: Builder): void { - $(div).p({ text: nls.localize('searchWithoutFolder', "You have not yet opened a folder. Only open files are currently searched - ") }) + this.searchWithoutFolderMessageBuilder = $(div); + + this.searchWithoutFolderMessageBuilder.p({ text: nls.localize('searchWithoutFolder', "You have not yet opened a folder. Only open files are currently searched - ") }) .asContainer().a({ 'class': ['pointer', 'prominent'], 'tabindex': '0', diff --git a/src/vs/workbench/parts/search/test/browser/searchViewlet.test.ts b/src/vs/workbench/parts/search/test/browser/searchViewlet.test.ts index 3ccd1cc1896..f30f81170d3 100644 --- a/src/vs/workbench/parts/search/test/browser/searchViewlet.test.ts +++ b/src/vs/workbench/parts/search/test/browser/searchViewlet.test.ts @@ -14,6 +14,9 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { IModelService } from 'vs/editor/common/services/modelService'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { TestContextService } from 'vs/workbench/test/workbenchTestServices'; +import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; suite('Search - Viewlet', () => { let instantiation: TestInstantiationService; @@ -21,10 +24,11 @@ suite('Search - Viewlet', () => { setup(() => { instantiation = new TestInstantiationService(); instantiation.stub(IModelService, stubModelService(instantiation)); + instantiation.set(IWorkspaceContextService, new TestContextService(TestWorkspace)); }); test('Data Source', function () { - let ds = new SearchDataSource(); + let ds = instantiation.createInstance(SearchDataSource); let result: SearchResult = instantiation.createInstance(SearchResult, null); result.query = { type: 1, folderQueries: [{ folder: uri.parse('file://c:/') }] }; result.add([{ diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index f7395cdbb27..f916baad3d1 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -301,7 +301,7 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { } private registerListeners(): void { - this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateStyles())); + this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(() => this.updateStyles())); } protected updateStyles(): void { diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index 96585270fa8..5420ab82b04 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -106,6 +106,7 @@ export class WatermarkContribution implements IWorkbenchContribution { private toDispose: IDisposable[] = []; private watermark: Builder; private enabled: boolean; + private workbenchState: WorkbenchState; constructor( @ILifecycleService lifecycleService: ILifecycleService, @@ -115,6 +116,8 @@ export class WatermarkContribution implements IWorkbenchContribution { @ITelemetryService private telemetryService: ITelemetryService, @IConfigurationService private configurationService: IConfigurationService ) { + this.workbenchState = contextService.getWorkbenchState(); + lifecycleService.onShutdown(this.dispose, this); this.partService.joinCreation().then(() => { this.enabled = this.configurationService.lookup('workbench.tips.enabled').value; @@ -122,7 +125,7 @@ export class WatermarkContribution implements IWorkbenchContribution { this.create(); } }); - this.configurationService.onDidUpdateConfiguration(e => { + this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { const enabled = this.configurationService.lookup('workbench.tips.enabled').value; if (enabled !== this.enabled) { this.enabled = enabled; @@ -132,7 +135,15 @@ export class WatermarkContribution implements IWorkbenchContribution { this.destroy(); } } - }); + })); + this.toDispose.push(this.contextService.onDidChangeWorkbenchState(e => { + const previousWorkbenchState = this.workbenchState; + this.workbenchState = this.contextService.getWorkbenchState(); + + if (this.enabled && this.workbenchState !== previousWorkbenchState) { + this.recreate(); + } + })); } public getId() { @@ -147,7 +158,7 @@ export class WatermarkContribution implements IWorkbenchContribution { .div({ 'class': 'watermark' }); const box = $(this.watermark) .div({ 'class': 'watermark-box' }); - const folder = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY; + const folder = this.workbenchState !== WorkbenchState.EMPTY; const selected = folder ? folderEntries : noFolderEntries .filter(entry => !('mac' in entry) || entry.mac === isMacintosh); const update = () => { @@ -189,6 +200,11 @@ export class WatermarkContribution implements IWorkbenchContribution { } } + private recreate(): void { + this.destroy(); + this.create(); + } + public dispose(): void { this.toDispose = dispose(this.toDispose); }