diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index a0c81cc7e7e..bb7de4e4d14 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -299,24 +299,32 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { super.shutdown(); } - toggleViewVisibility(id: string, focus?: boolean): TPromise { - let viewState = this.viewsStates.get(id); - if (!viewState) { - const viewDescriptor = this.getViewDescriptorsFromRegistry().filter(v => v.id === id)[0]; - if (viewDescriptor && viewDescriptor.hideByDefault) { - viewState = { collapsed: viewDescriptor.collapsed, order: viewDescriptor.order, isHidden: void 0, size: void 0 }; - this.viewsStates.set(id, viewState); - } else { - return TPromise.as(null); - } + private toggleViewVisibility(id: string, focus?: boolean): TPromise { + const viewDescriptor = this.getViewDescriptorsFromRegistry().filter(v => v.id === id)[0]; + const viewState = this.viewsStates.get(id); + + if (!viewDescriptor || !viewState) { + return TPromise.as(null); } - viewState.isHidden = !!this.getView(id); + if (!viewDescriptor.canToggleVisibility) { + return TPromise.wrapError(new Error(localize('cannot toggle', "Visibility cannot be toggled for this view {0}", id))); + } + + if (viewState.isHidden && !this.contextKeyService.contextMatchesRules(viewDescriptor.when)) { + return TPromise.wrapError(new Error(localize('cannot show', "This view {0} cannot be shown because it is hidden by its 'when' condition", id))); + } + + viewState.isHidden = !viewState.isHidden; return this.updateViews() .then(() => { this._onDidChangeViewVisibilityState.fire(id); - if (!viewState.isHidden) { - this.openView(id, focus); + const view = this.getView(id); + if (view) { + view.setExpanded(true); + if (focus) { + view.focus(); + } } else if (focus) { this.focus(); } @@ -331,6 +339,13 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { this.viewsContextKeys.add(key); } } + + // Update view state + const viewState = this.viewsStates.get(viewDescriptor.id) || { collapsed: void 0, isHidden: void 0, order: void 0, size: void 0 }; + viewState.collapsed = isUndefined(viewState.collapsed) ? viewDescriptor.collapsed : viewState.collapsed; + viewState.isHidden = isUndefined(viewState.isHidden) ? !!viewDescriptor.hideByDefault : viewState.isHidden; + viewState.order = isUndefined(viewState.order) ? viewDescriptor.order : viewState.order; + this.viewsStates.set(viewDescriptor.id, viewState); } this.updateViews(); @@ -495,14 +510,12 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { if (!this.contextKeyService.contextMatchesRules(viewDescriptor.when)) { return false; } + const viewstate = this.viewsStates.get(viewDescriptor.id); - if (viewDescriptor.canToggleVisibility) { - if (viewstate && viewstate.isHidden !== void 0) { - return !viewstate.isHidden; - } else { - return !viewDescriptor.hideByDefault; - } + if (viewstate && viewDescriptor.canToggleVisibility) { + return !viewstate.isHidden; } + return true; } @@ -659,7 +672,7 @@ export class PersistentViewsViewlet extends ViewsViewlet { ) { super(id, location, showHeaderInTitleWhenSingleView, partService, telemetryService, storageService, instantiationService, themeService, contextKeyService, contextMenuService, extensionService); this.hiddenViewsStorageId = `${this.viewletStateStorageId}.hidden`; - this._register(this.onDidChangeViewVisibilityState(id => this.onViewVisibilityChanged(id))); + this._register(this.onDidChangeViewVisibilityState(id => this.saveViewsStates())); } create(parent: HTMLElement): TPromise { @@ -672,56 +685,49 @@ export class PersistentViewsViewlet extends ViewsViewlet { super.shutdown(); } - protected saveViewsStates(): void { - const viewsStates = {}; - const registeredViewDescriptors = this.getViewDescriptorsFromRegistry(); - this.viewsStates.forEach((viewState, id) => { - const view = this.getView(id); - - if (view) { - viewsStates[id] = { - collapsed: !view.isExpanded(), - size: this.getPanelSize(view), - isHidden: false, - order: viewState.order - }; - } else { - const viewDescriptor = registeredViewDescriptors.filter(v => v.id === id)[0]; - if (viewDescriptor) { - viewsStates[id] = viewState; + private saveViewsStates(): void { + const storedViewsStates: { [id: string]: { collapsed: boolean, size: number, order: number } } = {}; + const storedViewsVisibilityStates: { id: string, isHidden: boolean }[] = []; + for (const viewDescriptor of this.getViewDescriptorsFromRegistry()) { + const viewState = this.viewsStates.get(viewDescriptor.id); + if (viewState) { + const view = this.getView(viewDescriptor.id); + storedViewsVisibilityStates.push({ id: viewDescriptor.id, isHidden: viewState ? viewState.isHidden : void 0 }); + if (view) { + storedViewsStates[viewDescriptor.id] = { + collapsed: !view.isExpanded(), + size: this.getPanelSize(view), + order: viewState.order + }; + } else { + storedViewsStates[viewDescriptor.id] = { collapsed: viewState.collapsed, size: viewState.size, order: viewState.order }; } } - }); - - this.storageService.store(this.viewletStateStorageId, JSON.stringify(viewsStates), this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL); + } + this.storageService.store(this.viewletStateStorageId, JSON.stringify(storedViewsStates), this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL); + this.storageService.store(this.hiddenViewsStorageId, JSON.stringify(storedViewsVisibilityStates), StorageScope.GLOBAL); } protected loadViewsStates(): void { const viewsStates = JSON.parse(this.storageService.get(this.viewletStateStorageId, this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL, '{}')); - const globalViewsState = this.loadViewsGlobalState(); - Object.keys(viewsStates).forEach(id => { - const globalViewState = globalViewsState.filter(v => v.id === id)[0]; - this.viewsStates.set(id, { ...viewsStates[id], ...{ isHidden: globalViewState ? globalViewState.isHidden : void 0 } }); - }); - } - - private onViewVisibilityChanged(id: string) { - const views = this.loadViewsGlobalState(); - const view = views.filter(v => v.id === id)[0]; - const isHidden = !this.getView(id); - if (view) { - view.isHidden = isHidden; - } else { - views.push({ id, isHidden }); + const viewsVisibilityStates = this.loadViewsVisibilityStates(); + for (const { id, isHidden } of viewsVisibilityStates) { + const viewState = viewsStates[id]; + // View state should exist always. Add a check if in case does not exist. + if (viewState) { + this.viewsStates.set(id, { ...viewState, ...{ isHidden } }); + } + } + + // Migration: Update those not existing in visibility states + for (const id of Object.keys(viewsStates)) { + if (!this.viewsStates.has(id)) { + this.viewsStates.set(id, { ...viewsStates[id], ...{ isHidden: false } }); + } } - this.storeViewsGlobalState(views); } - private storeViewsGlobalState(hiddenViews: { id: string, isHidden: boolean }[]): void { - this.storageService.store(this.hiddenViewsStorageId, JSON.stringify(hiddenViews), StorageScope.GLOBAL); - } - - private loadViewsGlobalState(): { id: string, isHidden: boolean }[] { + private loadViewsVisibilityStates(): { id: string, isHidden: boolean }[] { const storedStates = >JSON.parse(this.storageService.get(this.hiddenViewsStorageId, StorageScope.GLOBAL, '[]')); return <{ id: string, isHidden: boolean }[]>storedStates.map(c => typeof c === 'string' /* migration */ ? { id: c, isHidden: true } : c);