Path: blob/main/src/vs/workbench/browser/parts/views/viewsViewlet.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { IExtensionService } from '../../../services/extensions/common/extensions.js';6import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';7import { IViewDescriptor, IViewDescriptorService, IAddedViewDescriptorRef, IView } from '../../../common/views.js';8import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';9import { IThemeService } from '../../../../platform/theme/common/themeService.js';10import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';11import { IStorageService } from '../../../../platform/storage/common/storage.js';12import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';13import { ViewPaneContainer } from './viewPaneContainer.js';14import { ViewPane, IViewPaneOptions } from './viewPane.js';15import { Event } from '../../../../base/common/event.js';16import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';17import { IWorkbenchLayoutService } from '../../../services/layout/browser/layoutService.js';18import { ExtensionIdentifier } from '../../../../platform/extensions/common/extensions.js';19import { ILogService } from '../../../../platform/log/common/log.js';2021export interface IViewletViewOptions extends IViewPaneOptions {22readonly fromExtensionId?: ExtensionIdentifier;23}2425export abstract class FilterViewPaneContainer extends ViewPaneContainer {26private constantViewDescriptors: Map<string, IViewDescriptor> = new Map();27private allViews: Map<string, Map<string, IViewDescriptor>> = new Map();28private filterValue: string[] | undefined;2930constructor(31viewletId: string,32onDidChangeFilterValue: Event<string[]>,33@IConfigurationService configurationService: IConfigurationService,34@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,35@ITelemetryService telemetryService: ITelemetryService,36@IStorageService storageService: IStorageService,37@IInstantiationService instantiationService: IInstantiationService,38@IThemeService themeService: IThemeService,39@IContextMenuService contextMenuService: IContextMenuService,40@IExtensionService extensionService: IExtensionService,41@IWorkspaceContextService contextService: IWorkspaceContextService,42@IViewDescriptorService viewDescriptorService: IViewDescriptorService,43@ILogService logService: ILogService,44) {4546super(viewletId, { mergeViewWithContainerWhenSingleView: false }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService, logService);47this._register(onDidChangeFilterValue(newFilterValue => {48this.filterValue = newFilterValue;49this.onFilterChanged(newFilterValue);50}));5152this._register(this.viewContainerModel.onDidChangeActiveViewDescriptors(() => {53this.updateAllViews(this.viewContainerModel.activeViewDescriptors);54}));55}5657private updateAllViews(viewDescriptors: ReadonlyArray<IViewDescriptor>) {58viewDescriptors.forEach(descriptor => {59const filterOnValue = this.getFilterOn(descriptor);60if (!filterOnValue) {61return;62}63if (!this.allViews.has(filterOnValue)) {64this.allViews.set(filterOnValue, new Map());65}66this.allViews.get(filterOnValue)!.set(descriptor.id, descriptor);67if (this.filterValue && !this.filterValue.includes(filterOnValue) && this.panes.find(pane => pane.id === descriptor.id)) {68this.viewContainerModel.setVisible(descriptor.id, false);69}70});71}7273protected addConstantViewDescriptors(constantViewDescriptors: IViewDescriptor[]) {74constantViewDescriptors.forEach(viewDescriptor => this.constantViewDescriptors.set(viewDescriptor.id, viewDescriptor));75}7677protected abstract getFilterOn(viewDescriptor: IViewDescriptor): string | undefined;7879protected abstract setFilter(viewDescriptor: IViewDescriptor): void;8081private onFilterChanged(newFilterValue: string[]) {82if (this.allViews.size === 0) {83this.updateAllViews(this.viewContainerModel.activeViewDescriptors);84}85this.getViewsNotForTarget(newFilterValue).forEach(item => this.viewContainerModel.setVisible(item.id, false));86this.getViewsForTarget(newFilterValue).forEach(item => this.viewContainerModel.setVisible(item.id, true));87}8889private getViewsForTarget(target: string[]): IViewDescriptor[] {90const views: IViewDescriptor[] = [];91for (let i = 0; i < target.length; i++) {92if (this.allViews.has(target[i])) {93views.push(...Array.from(this.allViews.get(target[i])!.values()));94}95}9697return views;98}99100private getViewsNotForTarget(target: string[]): IViewDescriptor[] {101const iterable = this.allViews.keys();102let key = iterable.next();103let views: IViewDescriptor[] = [];104while (!key.done) {105let isForTarget: boolean = false;106target.forEach(value => {107if (key.value === value) {108isForTarget = true;109}110});111if (!isForTarget) {112views = views.concat(this.getViewsForTarget([key.value]));113}114115key = iterable.next();116}117return views;118}119120protected override onDidAddViewDescriptors(added: IAddedViewDescriptorRef[]): ViewPane[] {121const panes: ViewPane[] = super.onDidAddViewDescriptors(added);122for (let i = 0; i < added.length; i++) {123if (this.constantViewDescriptors.has(added[i].viewDescriptor.id)) {124panes[i].setExpanded(false);125}126}127// Check that allViews is ready128if (this.allViews.size === 0) {129this.updateAllViews(this.viewContainerModel.activeViewDescriptors);130}131return panes;132}133134override openView(id: string, focus?: boolean): IView | undefined {135const result = super.openView(id, focus);136if (result) {137const descriptorMap = Array.from(this.allViews.entries()).find(entry => entry[1].has(id));138if (descriptorMap && !this.filterValue?.includes(descriptorMap[0])) {139this.setFilter(descriptorMap[1].get(id)!);140}141}142return result;143}144145abstract override getTitle(): string;146147}148149150