未验证 提交 600995bb 编写于 作者: S Sandeep Somavarapu 提交者: GitHub

Merge pull request #95721 from microsoft/sandy081/viewsModel

Unify view descriptor and view model into IViewContainerModel
......@@ -451,7 +451,8 @@ export class MainThreadComments extends Disposable implements MainThreadComments
const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry).registerViewContainer({
id: COMMENTS_VIEW_ID,
name: COMMENTS_VIEW_TITLE,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [COMMENTS_VIEW_ID, COMMENTS_VIEW_TITLE, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [COMMENTS_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
storageId: COMMENTS_VIEW_TITLE,
hideIfEmpty: true,
order: 10,
}, ViewContainerLocation.Panel);
......
......@@ -320,7 +320,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
name: title, extensionId,
ctorDescriptor: new SyncDescriptor(
ViewPaneContainer,
[id, `${id}.state`, { mergeViewWithContainerWhenSingleView: true }]
[id, { mergeViewWithContainerWhenSingleView: true }]
),
hideIfEmpty: true,
order,
......
......@@ -488,9 +488,9 @@ export class ResetViewLocationsAction extends Action {
async run(): Promise<void> {
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
viewContainerRegistry.all.forEach(viewContainer => {
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer);
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
viewDescriptors.allViewDescriptors.forEach(viewDescriptor => {
viewContainerModel.allViewDescriptors.forEach(viewDescriptor => {
const defaultContainer = this.viewDescriptorService.getDefaultContainer(viewDescriptor.id);
const currentContainer = this.viewDescriptorService.getViewContainer(viewDescriptor.id);
......@@ -583,7 +583,7 @@ export class MoveFocusedViewAction extends Action {
const currentContainer = this.viewDescriptorService.getViewContainer(focusedViewId)!;
const currentLocation = this.viewDescriptorService.getViewLocation(focusedViewId)!;
const isViewSolo = this.viewDescriptorService.getViewDescriptors(currentContainer).allViewDescriptors.length === 1;
const isViewSolo = this.viewDescriptorService.getViewContainerModel(currentContainer).allViewDescriptors.length === 1;
if (!(isViewSolo && currentLocation === ViewContainerLocation.Sidebar)) {
items.push({
......
......@@ -26,7 +26,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import { URI, UriComponents } from 'vs/base/common/uri';
import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { IViewDescriptorService, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewDescriptorCollection, ViewContainerLocation } from 'vs/workbench/common/views';
import { IViewDescriptorService, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewContainerModel, ViewContainerLocation } from 'vs/workbench/common/views';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IViewlet } from 'vs/workbench/common/viewlet';
import { isUndefinedOrNull, assertIsDefined, isString } from 'vs/base/common/types';
......@@ -216,8 +216,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
if (viewletDescriptor) {
const viewContainer = this.getViewContainer(viewletDescriptor.id);
if (viewContainer?.hideIfEmpty) {
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer);
if (viewDescriptors.activeViewDescriptors.length === 0) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
if (viewContainerModel.activeViewDescriptors.length === 0) {
this.hideComposite(viewletDescriptor.id); // Update the composite bar by hiding
}
}
......@@ -478,9 +478,14 @@ export class ActivitybarPart extends Part implements IActivityBarService {
for (const viewlet of viewlets) {
this.enableCompositeActions(viewlet);
const viewContainer = this.getViewContainer(viewlet.id)!;
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer);
this.onDidChangeActiveViews(viewlet, viewDescriptors, viewContainer.hideIfEmpty);
this.viewletDisposables.set(viewlet.id, viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(viewlet, viewDescriptors, viewContainer.hideIfEmpty)));
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
this.onDidChangeActiveViews(viewlet, viewContainerModel, viewContainer.hideIfEmpty);
const disposables = new DisposableStore();
disposables.add(viewContainerModel.onDidChangeActiveViewDescriptors(() => this.onDidChangeActiveViews(viewlet, viewContainerModel, viewContainer.hideIfEmpty)));
disposables.add(viewContainerModel.onDidChangeContainerInfo(() => this.updateActivity(viewlet, viewContainerModel)));
this.viewletDisposables.set(viewlet.id, disposables);
}
}
......@@ -494,17 +499,14 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.hideComposite(viewletId);
}
private updateActivity(viewlet: ViewletDescriptor, viewDescriptors: IViewDescriptorCollection): void {
const viewDescriptor = viewDescriptors.activeViewDescriptors[0];
// Use the viewlet icon if any view inside belongs to it statically
const shouldUseViewletIcon = viewDescriptors.allViewDescriptors.some(v => this.viewDescriptorService.getDefaultContainer(v.id)?.id === viewlet.id);
private updateActivity(viewlet: ViewletDescriptor, viewContainerModel: IViewContainerModel): void {
const icon = viewContainerModel.icon;
const activity: IActivity = {
id: viewlet.id,
name: shouldUseViewletIcon ? viewlet.name : viewDescriptor.name,
cssClass: shouldUseViewletIcon ? viewlet.cssClass : (isString(viewDescriptor.containerIcon) ? viewDescriptor.containerIcon : (viewDescriptor.containerIcon === undefined ? 'codicon-window' : undefined)),
iconUrl: shouldUseViewletIcon ? viewlet.iconUrl : (viewDescriptor.containerIcon instanceof URI ? viewDescriptor.containerIcon : undefined),
name: viewContainerModel.title,
cssClass: isString(icon) ? icon : undefined,
iconUrl: icon instanceof URI ? icon : undefined,
keybindingId: viewlet.keybindingId
};
......@@ -516,7 +518,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
private onDidChangeActiveViews(viewlet: ViewletDescriptor, viewDescriptors: IViewDescriptorCollection, hideIfEmpty?: boolean): void {
private onDidChangeActiveViews(viewlet: ViewletDescriptor, viewDescriptors: IViewContainerModel, hideIfEmpty?: boolean): void {
if (viewDescriptors.activeViewDescriptors.length) {
this.updateActivity(viewlet, viewDescriptors);
this.compositeBar.addComposite(viewlet);
......@@ -644,8 +646,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
if (viewlet) {
const views: { when: string | undefined }[] = [];
if (viewContainer) {
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer);
for (const { when } of viewDescriptors.allViewDescriptors) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
for (const { when } of viewContainerModel.allViewDescriptors) {
views.push({ when: when ? when.serialize() : undefined });
}
}
......
......@@ -56,7 +56,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
}
// ... on a different composite bar
else {
const viewsToMove = this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors;
const viewsToMove = this.viewDescriptorService.getViewContainerModel(currentContainer)!.allViewDescriptors;
if (viewsToMove.some(v => !v.canMoveView)) {
return;
}
......@@ -119,7 +119,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
}
// ... to another composite location
const draggedViews = this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors;
const draggedViews = this.viewDescriptorService.getViewContainerModel(currentContainer)!.allViewDescriptors;
// ... all views must be movable
return !draggedViews.some(v => !v.canMoveView);
......
......@@ -161,9 +161,11 @@ export class ActivityActionViewItem extends BaseActionViewItem {
if (this.activity.iconUrl) {
// Apply background color to activity bar item provided with iconUrls
this.label.style.backgroundColor = foreground ? foreground.toString() : '';
this.label.style.color = '';
} else {
// Apply foreground color to activity bar items provided with codicons
this.label.style.color = foreground ? foreground.toString() : '';
this.label.style.backgroundColor = '';
}
const dragColor = colors.activeBackgroundColor || colors.activeForegroundColor;
......@@ -691,9 +693,4 @@ export class ToggleCompositePinnedAction extends Action {
this.compositeBar.pin(id);
}
}
setActivity(activity: IActivity): void {
this.activity = activity;
this.label = activity.name;
}
}
......@@ -200,6 +200,10 @@ export class PlaceHolderToggleCompositePinnedAction extends ToggleCompositePinne
constructor(id: string, compositeBar: ICompositeBar) {
super({ id, name: id, cssClass: undefined }, compositeBar);
}
setActivity(activity: IActivity): void {
this.label = activity.name;
}
}
......
......@@ -33,12 +33,13 @@ import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/con
import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewDescriptorService, IViewDescriptorCollection, ViewContainerLocation } from 'vs/workbench/common/views';
import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewDescriptorService, IViewContainerModel, ViewContainerLocation } from 'vs/workbench/common/views';
import { MenuId } from 'vs/platform/actions/common/actions';
import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { Before2D } from 'vs/workbench/browser/dnd';
import { IActivity } from 'vs/workbench/common/activity';
interface ICachedPanel {
id: string;
......@@ -177,9 +178,9 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
const result: IAction[] = [];
const container = this.getViewContainer(compositeId);
if (container) {
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(container);
if (viewDescriptors.allViewDescriptors.length === 1) {
const viewMenuActions = this.instantiationService.createInstance(ViewMenuActions, viewDescriptors.allViewDescriptors[0].id, MenuId.ViewTitle, MenuId.ViewTitleContext);
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(container);
if (viewContainerModel.allViewDescriptors.length === 1) {
const viewMenuActions = this.instantiationService.createInstance(ViewMenuActions, viewContainerModel.allViewDescriptors[0].id, MenuId.ViewTitle, MenuId.ViewTitleContext);
result.push(...viewMenuActions.getContextMenuActions());
viewMenuActions.dispose();
}
......@@ -209,12 +210,16 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
for (const panel of panels) {
this.enableCompositeActions(panel);
const viewContainer = this.getViewContainer(panel.id);
if (viewContainer?.hideIfEmpty) {
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer);
this.onDidChangeActiveViews(panel, viewDescriptors);
this.panelDisposables.set(panel.id, viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(panel, viewDescriptors)));
}
const viewContainer = this.getViewContainer(panel.id)!;
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
this.onDidChangeActiveViews(panel, viewContainerModel, viewContainer.hideIfEmpty);
const disposables = new DisposableStore();
disposables.add(viewContainerModel.onDidChangeActiveViewDescriptors(() => this.onDidChangeActiveViews(panel, viewContainerModel, viewContainer.hideIfEmpty)));
disposables.add(viewContainerModel.onDidChangeAllViewDescriptors(() => this.onDidUpdateViews(panel, viewContainerModel)));
disposables.add(viewContainerModel.onDidMoveVisibleViewDescriptors(() => this.onDidUpdateViews(panel, viewContainerModel)));
this.panelDisposables.set(panel.id, disposables);
}
}
......@@ -230,19 +235,37 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
private enableCompositeActions(panel: PanelDescriptor): void {
const { activityAction, pinnedAction } = this.getCompositeActions(panel.id);
if (activityAction instanceof PlaceHolderPanelActivityAction) {
activityAction.setActivity(panel);
}
activityAction.setActivity(panel);
if (pinnedAction instanceof PlaceHolderToggleCompositePinnedAction) {
pinnedAction.setActivity(panel);
}
}
private onDidChangeActiveViews(panel: PanelDescriptor, viewDescriptors: IViewDescriptorCollection): void {
private updateActivity(panel: PanelDescriptor, viewContainerModel: IViewContainerModel): void {
const activity: IActivity = {
id: panel.id,
name: viewContainerModel.title,
keybindingId: panel.keybindingId
};
const { activityAction, pinnedAction } = this.getCompositeActions(panel.id);
activityAction.setActivity(activity);
if (pinnedAction instanceof PlaceHolderToggleCompositePinnedAction) {
pinnedAction.setActivity(activity);
}
}
private onDidUpdateViews(panel: PanelDescriptor, viewDescriptors: IViewContainerModel): void {
this.updateActivity(panel, viewDescriptors);
}
private onDidChangeActiveViews(panel: PanelDescriptor, viewDescriptors: IViewContainerModel, hideIfEmpty?: boolean): void {
if (viewDescriptors.activeViewDescriptors.length) {
this.updateActivity(panel, viewDescriptors);
this.compositeBar.addComposite(panel);
} else {
} else if (hideIfEmpty) {
this.hideComposite(panel.id);
}
}
......@@ -320,8 +343,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
if (panelDescriptor) {
const viewContainer = this.getViewContainer(panelDescriptor.id);
if (viewContainer?.hideIfEmpty) {
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer);
if (viewDescriptors.activeViewDescriptors.length === 0 && this.compositeBar.getPinnedComposites().length > 1) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
if (viewContainerModel.activeViewDescriptors.length === 0 && this.compositeBar.getPinnedComposites().length > 1) {
this.hideComposite(panelDescriptor.id); // Update the composite bar by hiding
}
}
......@@ -540,28 +563,6 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
return false;
}
protected onTitleAreaUpdate(compositeId: string): void {
super.onTitleAreaUpdate(compositeId);
const activePanel = this.getActivePanel();
const panel = this.createComposite(compositeId, activePanel?.getId() === compositeId);
if (panel) {
const compositeActions = this.compositeActions.get(compositeId);
if (compositeActions) {
compositeActions.activityAction.setActivity({
id: compositeActions.activityAction.id,
name: panel.getTitle() || compositeActions.activityAction.label
});
compositeActions.pinnedAction.setActivity({
id: compositeActions.activityAction.id,
name: panel.getTitle() || compositeActions.activityAction.label
});
}
}
}
private getToolbarWidth(): number {
const activePanel = this.getActivePanel();
if (!activePanel || !this.toolBar) {
......@@ -609,8 +610,11 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
const compositeItems = this.compositeBar.getCompositeBarItems();
for (const compositeItem of compositeItems) {
const activityAction = this.getCompositeActions(compositeItem.id).activityAction;
state.push({ id: compositeItem.id, name: activityAction.label, pinned: compositeItem.pinned, order: compositeItem.order, visible: compositeItem.visible });
const viewContainer = this.getViewContainer(compositeItem.id);
if (viewContainer) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
state.push({ id: compositeItem.id, name: viewContainerModel.title, pinned: compositeItem.pinned, order: compositeItem.order, visible: compositeItem.visible });
}
}
this.cachedPanelsValue = JSON.stringify(state);
......
......@@ -24,11 +24,10 @@ import { PaneView, IPaneViewOptions, IPaneOptions, Pane } from 'vs/base/browser/
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewContainersRegistry, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor } from 'vs/workbench/common/views';
import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewContainersRegistry, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel } from 'vs/workbench/common/views';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { assertIsDefined } from 'vs/base/common/types';
import { PersistentContributableViewsModel, IAddedViewDescriptorRef, IViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
......@@ -746,7 +745,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
private readonly visibleViewsCountFromCache: number | undefined;
private readonly visibleViewsStorageId: string;
protected readonly viewsModel: PersistentContributableViewsModel;
protected readonly viewContainerModel: IViewContainerModel;
private viewDisposables: IDisposable[] = [];
private readonly _onTitleAreaUpdate: Emitter<void> = this._register(new Emitter<void>());
......@@ -782,7 +781,6 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
constructor(
id: string,
viewPaneContainerStateStorageId: string,
private options: IViewPaneContainerOptions,
@IInstantiationService protected instantiationService: IInstantiationService,
@IConfigurationService protected configurationService: IConfigurationService,
......@@ -808,7 +806,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
this.visibleViewsStorageId = `${id}.numberOfVisibleViews`;
this.visibleViewsCountFromCache = this.storageService.getNumber(this.visibleViewsStorageId, StorageScope.WORKSPACE, undefined);
this._register(toDisposable(() => this.viewDisposables = dispose(this.viewDisposables)));
this.viewsModel = this._register(this.instantiationService.createInstance(PersistentContributableViewsModel, container, viewPaneContainerStateStorageId));
this.viewContainerModel = this.viewDescriptorService.getViewContainerModel(container);
}
create(parent: HTMLElement): void {
......@@ -839,7 +837,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
const container = viewContainerRegistry.get(dropData.id)!;
const viewsToMove = this.viewDescriptorService.getViewDescriptors(container).allViewDescriptors;
const viewsToMove = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
if (!viewsToMove.some(v => !v.canMoveView)) {
overlay = new ViewPaneDropOverlay(parent, undefined, this.themeService);
......@@ -861,7 +859,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
const container = viewContainerRegistry.get(dropData.id)!;
const allViews = this.viewDescriptorService.getViewDescriptors(container).allViewDescriptors;
const allViews = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
if (!allViews.some(v => !v.canMoveView)) {
viewsToMove.push(...allViews);
}
......@@ -884,11 +882,11 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}));
this._register(this.onDidSashChange(() => this.saveViewSizes()));
this.viewsModel.onDidAdd(added => this.onDidAddViewDescriptors(added));
this.viewsModel.onDidRemove(removed => this.onDidRemoveViewDescriptors(removed));
const addedViews: IAddedViewDescriptorRef[] = this.viewsModel.visibleViewDescriptors.map((viewDescriptor, index) => {
const size = this.viewsModel.getSize(viewDescriptor.id);
const collapsed = this.viewsModel.isCollapsed(viewDescriptor.id);
this.viewContainerModel.onDidAddVisibleViewDescriptors(added => this.onDidAddViewDescriptors(added));
this.viewContainerModel.onDidRemoveVisibleViewDescriptors(removed => this.onDidRemoveViewDescriptors(removed));
const addedViews: IAddedViewDescriptorRef[] = this.viewContainerModel.visibleViewDescriptors.map((viewDescriptor, index) => {
const size = this.viewContainerModel.getSize(viewDescriptor.id);
const collapsed = this.viewContainerModel.isCollapsed(viewDescriptor.id);
return ({ viewDescriptor, index, size, collapsed });
});
if (addedViews.length) {
......@@ -906,9 +904,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}
getTitle(): string {
// use registered title if any of our panes are statically registered to this container
const allViewDescriptors = this.viewDescriptorService.getViewDescriptors(this.viewContainer).allViewDescriptors;
const containerTitle = this.paneItems.length === 0 || allViewDescriptors.length === 0 || allViewDescriptors.some(v => this.viewDescriptorService.getDefaultContainer(v.id) === this.viewContainer) ? this.viewContainer.name : this.paneItems[0].pane.title;
const containerTitle = this.viewContainerModel.title;
if (this.isViewMergedWithContainer()) {
const paneItemTitle = this.paneItems[0].pane.title;
......@@ -959,10 +955,10 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}
}
const viewToggleActions = this.viewsModel.viewDescriptors.map(viewDescriptor => (<IAction>{
const viewToggleActions = this.viewContainerModel.activeViewDescriptors.map(viewDescriptor => (<IAction>{
id: `${viewDescriptor.id}.toggleVisibility`,
label: viewDescriptor.name,
checked: this.viewsModel.isVisible(viewDescriptor.id),
checked: this.viewContainerModel.isVisible(viewDescriptor.id),
enabled: viewDescriptor.canToggleVisibility,
run: () => this.toggleViewVisibility(viewDescriptor.id)
}));
......@@ -1091,7 +1087,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
// Save size only when the layout has happened
if (this.didLayout) {
for (const view of this.panes) {
this.viewsModel.setSize(view.id, this.getPaneSize(view));
this.viewContainerModel.setSize(view.id, this.getPaneSize(view));
}
}
}
......@@ -1100,10 +1096,10 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
// Restore sizes only when the layout has happened
if (this.didLayout) {
let initialSizes;
for (let i = 0; i < this.viewsModel.visibleViewDescriptors.length; i++) {
for (let i = 0; i < this.viewContainerModel.visibleViewDescriptors.length; i++) {
const pane = this.panes[i];
const viewDescriptor = this.viewsModel.visibleViewDescriptors[i];
const size = this.viewsModel.getSize(viewDescriptor.id);
const viewDescriptor = this.viewContainerModel.visibleViewDescriptors[i];
const size = this.viewContainerModel.getSize(viewDescriptor.id);
if (typeof size === 'number') {
this.resizePane(pane, size);
......@@ -1118,8 +1114,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
private computeInitialSizes(): Map<string, number> {
const sizes: Map<string, number> = new Map<string, number>();
if (this.dimension) {
const totalWeight = this.viewsModel.visibleViewDescriptors.reduce((totalWeight, { weight }) => totalWeight + (weight || 20), 0);
for (const viewDescriptor of this.viewsModel.visibleViewDescriptors) {
const totalWeight = this.viewContainerModel.visibleViewDescriptors.reduce((totalWeight, { weight }) => totalWeight + (weight || 20), 0);
for (const viewDescriptor of this.viewContainerModel.visibleViewDescriptors) {
if (this.orientation === Orientation.VERTICAL) {
sizes.set(viewDescriptor.id, this.dimension.height * (viewDescriptor.weight || 20) / totalWeight);
} else {
......@@ -1180,7 +1176,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
});
const collapseDisposable = Event.latch(Event.map(pane.onDidChange, () => !pane.isExpanded()))(collapsed => {
this.viewsModel.setCollapsed(viewDescriptor.id, collapsed);
this.viewContainerModel.setCollapsed(viewDescriptor.id, collapsed);
});
this.viewDisposables.splice(index, 0, combinedDisposable(contextMenuDisposable, collapseDisposable));
......@@ -1211,13 +1207,13 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}
protected toggleViewVisibility(viewId: string): void {
const visible = !this.viewsModel.isVisible(viewId);
const visible = !this.viewContainerModel.isVisible(viewId);
type ViewsToggleVisibilityClassification = {
viewId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
visible: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
};
this.telemetryService.publicLog2<{ viewId: String, visible: boolean }, ViewsToggleVisibilityClassification>('views.toggleVisibility', { viewId, visible });
this.viewsModel.setVisible(viewId, visible);
this.viewContainerModel.setVisible(viewId, visible);
}
private addPane(pane: ViewPane, size: number, index = this.paneItems.length - 1): void {
......@@ -1272,7 +1268,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
const container = viewContainerRegistry.get(dropData.id)!;
const viewsToMove = this.viewDescriptorService.getViewDescriptors(container).allViewDescriptors;
const viewsToMove = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
if (!viewsToMove.some(v => !v.canMoveView)) {
overlay = new ViewPaneDropOverlay(pane.dropTargetElement, this.orientation ?? Orientation.VERTICAL, this.themeService);
......@@ -1294,7 +1290,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
const container = viewContainerRegistry.get(dropData.id)!;
const allViews = this.viewDescriptorService.getViewDescriptors(container).allViewDescriptors;
const allViews = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
if (allViews.length > 0 && !allViews.some(v => !v.canMoveView)) {
viewsToMove.push(...allViews);
......@@ -1409,8 +1405,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
const fromIndex = firstIndex(this.paneItems, item => item.pane === from);
const toIndex = firstIndex(this.paneItems, item => item.pane === to);
const fromViewDescriptor = this.viewsModel.visibleViewDescriptors[fromIndex];
const toViewDescriptor = this.viewsModel.visibleViewDescriptors[toIndex];
const fromViewDescriptor = this.viewContainerModel.visibleViewDescriptors[fromIndex];
const toViewDescriptor = this.viewContainerModel.visibleViewDescriptors[toIndex];
if (fromIndex < 0 || fromIndex >= this.paneItems.length) {
return;
......@@ -1425,7 +1421,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
assertIsDefined(this.paneview).movePane(from, to);
this.viewsModel.move(fromViewDescriptor.id, toViewDescriptor.id);
this.viewContainerModel.move(fromViewDescriptor.id, toViewDescriptor.id);
this.updateTitleArea();
}
......
......@@ -6,7 +6,7 @@
import { IAction } from 'vs/base/common/actions';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IViewDescriptor, IViewDescriptorService } from 'vs/workbench/common/views';
import { IViewDescriptor, IViewDescriptorService, IAddedViewDescriptorRef } from 'vs/workbench/common/views';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -16,7 +16,6 @@ import { ViewPaneContainer, ViewPane, IViewPaneOptions } from 'vs/workbench/brow
import { Event } from 'vs/base/common/event';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
export interface IViewletViewOptions extends IViewPaneOptions {
}
......@@ -41,14 +40,14 @@ export abstract class FilterViewPaneContainer extends ViewPaneContainer {
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(viewletId, `${viewletId}.state`, { mergeViewWithContainerWhenSingleView: false }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
super(viewletId, { mergeViewWithContainerWhenSingleView: false }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
this._register(onDidChangeFilterValue(newFilterValue => {
this.filterValue = newFilterValue;
this.onFilterChanged(newFilterValue);
}));
this._register(this.viewsModel.onDidChangeActiveViews((viewDescriptors) => {
this.updateAllViews(viewDescriptors);
this._register(this.viewContainerModel.onDidChangeActiveViewDescriptors(() => {
this.updateAllViews(this.viewContainerModel.activeViewDescriptors);
}));
}
......@@ -63,7 +62,7 @@ export abstract class FilterViewPaneContainer extends ViewPaneContainer {
}
this.allViews.get(filterOnValue)!.set(descriptor.id, descriptor);
if (this.filterValue && !this.filterValue.includes(filterOnValue)) {
this.viewsModel.setVisible(descriptor.id, false);
this.viewContainerModel.setVisible(descriptor.id, false);
}
});
}
......@@ -76,17 +75,17 @@ export abstract class FilterViewPaneContainer extends ViewPaneContainer {
private onFilterChanged(newFilterValue: string[]) {
if (this.allViews.size === 0) {
this.updateAllViews(this.viewsModel.viewDescriptors);
this.updateAllViews(this.viewContainerModel.activeViewDescriptors);
}
this.getViewsNotForTarget(newFilterValue).forEach(item => this.viewsModel.setVisible(item.id, false));
this.getViewsForTarget(newFilterValue).forEach(item => this.viewsModel.setVisible(item.id, true));
this.getViewsNotForTarget(newFilterValue).forEach(item => this.viewContainerModel.setVisible(item.id, false));
this.getViewsForTarget(newFilterValue).forEach(item => this.viewContainerModel.setVisible(item.id, true));
}
getContextMenuActions(): IAction[] {
const result: IAction[] = Array.from(this.constantViewDescriptors.values()).map(viewDescriptor => (<IAction>{
id: `${viewDescriptor.id}.toggleVisibility`,
label: viewDescriptor.name,
checked: this.viewsModel.isVisible(viewDescriptor.id),
checked: this.viewContainerModel.isVisible(viewDescriptor.id),
enabled: viewDescriptor.canToggleVisibility,
run: () => this.toggleViewVisibility(viewDescriptor.id)
}));
......@@ -134,7 +133,7 @@ export abstract class FilterViewPaneContainer extends ViewPaneContainer {
}
// Check that allViews is ready
if (this.allViews.size === 0) {
this.updateAllViews(this.viewsModel.viewDescriptors);
this.updateAllViews(this.viewContainerModel.activeViewDescriptors);
}
return panes;
}
......
......@@ -43,6 +43,8 @@ export interface IViewContainerDescriptor {
readonly ctorDescriptor: SyncDescriptor<IViewPaneContainer>;
readonly storageId?: string;
readonly icon?: string | URI;
readonly order?: number;
......@@ -207,11 +209,43 @@ export interface IViewDescriptor {
readonly remoteAuthority?: string | string[];
}
export interface IViewDescriptorCollection extends IDisposable {
readonly onDidChangeViews: Event<{ added: IViewDescriptor[], removed: IViewDescriptor[] }>;
readonly onDidChangeActiveViews: Event<{ added: IViewDescriptor[], removed: IViewDescriptor[] }>;
readonly activeViewDescriptors: IViewDescriptor[];
readonly allViewDescriptors: IViewDescriptor[];
export interface IViewDescriptorRef {
viewDescriptor: IViewDescriptor;
index: number;
}
export interface IAddedViewDescriptorRef extends IViewDescriptorRef {
collapsed: boolean;
size?: number;
}
export interface IViewContainerModel {
readonly title: string;
readonly icon: string | URI | undefined;
readonly onDidChangeContainerInfo: Event<{ title?: boolean, icon?: boolean }>;
readonly allViewDescriptors: ReadonlyArray<IViewDescriptor>;
readonly onDidChangeAllViewDescriptors: Event<{ added: ReadonlyArray<IViewDescriptor>, removed: ReadonlyArray<IViewDescriptor> }>;
readonly activeViewDescriptors: ReadonlyArray<IViewDescriptor>;
readonly onDidChangeActiveViewDescriptors: Event<{ added: ReadonlyArray<IViewDescriptor>, removed: ReadonlyArray<IViewDescriptor> }>;
readonly visibleViewDescriptors: ReadonlyArray<IViewDescriptor>;
readonly onDidAddVisibleViewDescriptors: Event<IAddedViewDescriptorRef[]>;
readonly onDidRemoveVisibleViewDescriptors: Event<IViewDescriptorRef[]>
readonly onDidMoveVisibleViewDescriptors: Event<{ from: IViewDescriptorRef; to: IViewDescriptorRef; }>
isVisible(id: string): boolean;
setVisible(id: string, visible: boolean, size?: number): void;
isCollapsed(id: string): boolean;
setCollapsed(id: string, collapsed: boolean): void;
getSize(id: string): number | undefined;
setSize(id: string, size: number): void
move(from: string, to: string): void;
}
export enum ViewContentPriority {
......@@ -451,7 +485,7 @@ export interface IViewDescriptorService {
moveViewsToContainer(views: IViewDescriptor[], viewContainer: ViewContainer): void;
getViewDescriptors(container: ViewContainer): IViewDescriptorCollection;
getViewContainerModel(container: ViewContainer): IViewContainerModel;
getViewDescriptor(viewId: string): IViewDescriptor | null;
......
......@@ -352,8 +352,9 @@ const container = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.V
hideIfEmpty: true,
ctorDescriptor: new SyncDescriptor(
ViewPaneContainer,
[BulkEditPane.ID, BulkEditPane.ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]
)
[BulkEditPane.ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]
),
storageId: BulkEditPane.ID
}, ViewContainerLocation.Panel);
Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry).registerViews([{
......
......@@ -90,7 +90,8 @@ const openPanelKb: IKeybindings = {
const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry).registerViewContainer({
id: DEBUG_PANEL_ID,
name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
storageId: DEBUG_PANEL_ID,
focusCommand: {
id: OpenDebugConsoleAction.ID,
keybindings: openPanelKb
......
......@@ -62,7 +62,7 @@ export class DebugViewPaneContainer extends ViewPaneContainer {
@INotificationService private readonly notificationService: INotificationService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(VIEWLET_ID, `${VIEWLET_ID}.state`, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
this._register(this.debugService.onDidChangeState(state => this.onDebugServiceStateChange(state)));
this._register(this.debugService.onDidNewSession(() => this.updateToolBar()));
......
......@@ -34,7 +34,7 @@ import Severity from 'vs/base/common/severity';
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry, IViewDescriptorService } from 'vs/workbench/common/views';
import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry, IViewDescriptorService, IAddedViewDescriptorRef } from 'vs/workbench/common/views';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IContextKeyService, ContextKeyExpr, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
......@@ -44,7 +44,6 @@ import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
import { ViewPane, ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery';
import { SuggestEnabledInput, attachSuggestEnabledInputBoxStyler } from 'vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput';
......@@ -359,7 +358,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
@IPreferencesService private readonly preferencesService: IPreferencesService
) {
super(VIEWLET_ID, `${VIEWLET_ID}.state`, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
this.searchDelayer = new Delayer(500);
this.nonEmptyWorkspaceContextKey = NonEmptyWorkspaceContext.bindTo(contextKeyService);
......
......@@ -160,8 +160,6 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor
export class ExplorerViewPaneContainer extends ViewPaneContainer {
private static readonly EXPLORER_VIEWS_STATE = 'workbench.explorer.views.state';
private viewletVisibleContextKey: IContextKey<boolean>;
constructor(
......@@ -179,7 +177,7 @@ export class ExplorerViewPaneContainer extends ViewPaneContainer {
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(VIEWLET_ID, ExplorerViewPaneContainer.EXPLORER_VIEWS_STATE, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
this.viewletVisibleContextKey = ExplorerViewletVisibleContext.bindTo(contextKeyService);
......@@ -262,6 +260,7 @@ export const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry
id: VIEWLET_ID,
name: localize('explore', "Explorer"),
ctorDescriptor: new SyncDescriptor(ExplorerViewPaneContainer),
storageId: 'workbench.explorer.views.state',
icon: 'codicon-files',
order: 0
}, ViewContainerLocation.Sidebar);
......
......@@ -114,7 +114,8 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewC
name: Messages.MARKERS_PANEL_TITLE_PROBLEMS,
hideIfEmpty: true,
order: 0,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [Constants.MARKERS_CONTAINER_ID, Constants.MARKERS_VIEW_STORAGE_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [Constants.MARKERS_CONTAINER_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
storageId: Constants.MARKERS_VIEW_STORAGE_ID,
focusCommand: {
id: ToggleMarkersPanelAction.ID, keybindings: {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M
......
......@@ -62,7 +62,8 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewC
id: OUTPUT_VIEW_ID,
name: nls.localize('output', "Output"),
order: 1,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [OUTPUT_VIEW_ID, OUTPUT_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [OUTPUT_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
storageId: OUTPUT_VIEW_ID,
hideIfEmpty: true,
focusCommand: { id: toggleOutputAcitonId, keybindings: toggleOutputActionKeybindings }
}, ViewContainerLocation.Panel);
......
......@@ -96,9 +96,9 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
const viewEntries: Array<IViewQuickPickItem> = [];
const getViewEntriesForViewlet = (viewlet: ViewletDescriptor, viewContainer: ViewContainer): IViewQuickPickItem[] => {
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer);
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
const result: IViewQuickPickItem[] = [];
for (const view of viewDescriptors.allViewDescriptors) {
for (const view of viewContainerModel.allViewDescriptors) {
if (this.contextKeyService.contextMatchesRules(view.when)) {
result.push({
label: view.name,
......@@ -176,7 +176,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
private includeViewContainer(container: ViewletDescriptor | IPanelIdentifier): boolean {
const viewContainer = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry).get(container.id);
if (viewContainer?.hideIfEmpty) {
return this.viewDescriptorService.getViewDescriptors(viewContainer).activeViewDescriptors.length > 0;
return this.viewDescriptorService.getViewContainerModel(viewContainer).activeViewDescriptors.length > 0;
}
return true;
......
......@@ -19,7 +19,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import { FilterViewPaneContainer } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { VIEWLET_ID } from 'vs/workbench/contrib/remote/common/remote.contribution';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IViewDescriptor, IViewsRegistry, Extensions, ViewContainerLocation, IViewContainersRegistry, IViewDescriptorService } from 'vs/workbench/common/views';
import { IViewDescriptor, IViewsRegistry, Extensions, ViewContainerLocation, IViewContainersRegistry, IViewDescriptorService, IAddedViewDescriptorRef } from 'vs/workbench/common/views';
import { Registry } from 'vs/platform/registry/common/platform';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IOpenerService } from 'vs/platform/opener/common/opener';
......@@ -46,7 +46,6 @@ import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remo
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { startsWith } from 'vs/base/common/strings';
import { TunnelPanelDescriptor, TunnelViewModel, forwardedPortsViewEnabled } from 'vs/workbench/contrib/remote/browser/tunnelView';
import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { ITreeRenderer, ITreeNode, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
......
......@@ -51,6 +51,7 @@ Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegis
id: VIEWLET_ID,
name: localize('source control', "Source Control"),
ctorDescriptor: new SyncDescriptor(SCMViewPaneContainer),
storageId: 'workbench.scm.views.state',
icon: 'codicon-source-control',
order: 2
}, ViewContainerLocation.Sidebar);
......
......@@ -24,12 +24,11 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IViewsRegistry, Extensions, IViewDescriptorService, IViewDescriptor } from 'vs/workbench/common/views';
import { IViewsRegistry, Extensions, IViewDescriptorService, IViewDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef } from 'vs/workbench/common/views';
import { Registry } from 'vs/platform/registry/common/platform';
import { RepositoryPane, RepositoryViewDescriptor } from 'vs/workbench/contrib/scm/browser/repositoryPane';
import { MainPaneDescriptor, MainPane, IViewModel } from 'vs/workbench/contrib/scm/browser/mainPane';
import { ViewPaneContainer, IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import type { IAddedViewDescriptorRef, IViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
import { debounce } from 'vs/base/common/decorators';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IOpenerService } from 'vs/platform/opener/common/opener';
......@@ -80,8 +79,6 @@ export class EmptyPaneDescriptor implements IViewDescriptor {
export class SCMViewPaneContainer extends ViewPaneContainer implements IViewModel {
private static readonly STATE_KEY = 'workbench.scm.views.state';
private menus: SCMMenus;
private _repositories: ISCMRepository[] = [];
......@@ -104,7 +101,7 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode
}
get onDidChangeVisibleRepositories(): Event<ISCMRepository[]> {
const modificationEvent = Event.debounce(Event.any(this.viewsModel.onDidAdd, this.viewsModel.onDidRemove), () => null, 0);
const modificationEvent = Event.debounce(Event.any(this.viewContainerModel.onDidAddVisibleViewDescriptors, this.viewContainerModel.onDidRemoveVisibleViewDescriptors), () => null, 0);
return Event.map(modificationEvent, () => this.visibleRepositories);
}
......@@ -126,7 +123,7 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode
@IContextKeyService contextKeyService: IContextKeyService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(VIEWLET_ID, SCMViewPaneContainer.STATE_KEY, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
this.menus = instantiationService.createInstance(SCMMenus, undefined);
this._register(this.menus.onDidChangeTitle(this.updateTitleArea, this));
......@@ -143,14 +140,14 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode
this._register(configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('scm.alwaysShowProviders') && configurationService.getValue<boolean>('scm.alwaysShowProviders')) {
this.viewsModel.setVisible(MainPane.ID, true);
this.viewContainerModel.setVisible(MainPane.ID, true);
}
}));
this.repositoryCountKey = contextKeyService.createKey('scm.providerCount', 0);
this._register(this.viewsModel.onDidAdd(this.onDidShowView, this));
this._register(this.viewsModel.onDidRemove(this.onDidHideView, this));
this._register(this.viewContainerModel.onDidAddVisibleViewDescriptors(this.onDidShowView, this));
this._register(this.viewContainerModel.onDidRemoveVisibleViewDescriptors(this.onDidHideView, this));
}
create(parent: HTMLElement): void {
......@@ -217,8 +214,8 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode
@debounce(0)
private afterOnDidHideView(): void {
if (this.repositoryCountKey.get()! > 0 && this.viewDescriptors.every(d => !this.viewsModel.isVisible(d.id))) {
this.viewsModel.setVisible(this.viewDescriptors[0].id, true);
if (this.repositoryCountKey.get()! > 0 && this.viewDescriptors.every(d => !this.viewContainerModel.isVisible(d.id))) {
this.viewContainerModel.setVisible(this.viewDescriptors[0].id, true);
}
}
......@@ -285,9 +282,9 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode
}
setVisibleRepositories(repositories: ISCMRepository[]): void {
const visibleViewDescriptors = this.viewsModel.visibleViewDescriptors;
const visibleViewDescriptors = this.viewContainerModel.visibleViewDescriptors;
const toSetVisible = this.viewsModel.viewDescriptors
const toSetVisible = this.viewContainerModel.activeViewDescriptors
.filter((d): d is RepositoryViewDescriptor => d instanceof RepositoryViewDescriptor && repositories.indexOf(d.repository) > -1 && visibleViewDescriptors.indexOf(d) === -1);
const toSetInvisible = visibleViewDescriptors
......@@ -305,11 +302,11 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode
}
}
this.viewsModel.setVisible(viewDescriptor.id, false);
this.viewContainerModel.setVisible(viewDescriptor.id, false);
}
for (const viewDescriptor of toSetVisible) {
this.viewsModel.setVisible(viewDescriptor.id, true, size);
this.viewContainerModel.setVisible(viewDescriptor.id, true, size);
}
}
}
......@@ -504,7 +504,7 @@ class ShowAllSymbolsAction extends Action {
const viewContainer = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry).registerViewContainer({
id: VIEWLET_ID,
name: nls.localize('name', "Search"),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [VIEWLET_ID, `${VIEWLET_ID}.state`, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
hideIfEmpty: true,
icon: 'codicon-search',
order: 1
......
......@@ -68,7 +68,8 @@ if (platform.isWeb) {
const VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({
id: TERMINAL_VIEW_ID,
name: nls.localize('terminal', "Terminal"),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TERMINAL_VIEW_ID, TERMINAL_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TERMINAL_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
storageId: TERMINAL_VIEW_ID,
focusCommand: { id: TERMINAL_COMMAND_ID.FOCUS },
hideIfEmpty: true,
order: 3
......
......@@ -704,7 +704,7 @@ export class TerminalService implements ITerminalService {
const location = this._viewDescriptorService.getViewLocation(TERMINAL_VIEW_ID);
if (location === ViewContainerLocation.Panel) {
const panel = this._viewDescriptorService.getViewContainer(TERMINAL_VIEW_ID);
if (panel && this._viewDescriptorService.getViewDescriptors(panel).activeViewDescriptors.length === 1) {
if (panel && this._viewDescriptorService.getViewContainerModel(panel).activeViewDescriptors.length === 1) {
this._layoutService.setPanelHidden(true);
}
}
......
......@@ -39,7 +39,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
name: localize('sync preferences', "Preferences Sync"),
ctorDescriptor: new SyncDescriptor(
ViewPaneContainer,
['workbench.view.sync', `workbench.view.sync.state`, { mergeViewWithContainerWhenSingleView: true }]
['workbench.view.sync', { mergeViewWithContainerWhenSingleView: true }]
),
icon: 'codicon-sync',
hideIfEmpty: true,
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as sinon from 'sinon';
import { IViewsRegistry, IViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewContainerModel, IViewDescriptorService, ViewContainer } from 'vs/workbench/common/views';
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { move } from 'vs/base/common/arrays';
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService';
import { ViewDescriptorService } from 'vs/workbench/services/views/browser/viewDescriptorService';
import { Registry } from 'vs/platform/registry/common/platform';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
const ViewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
const ViewsRegistry = Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry);
class ViewDescriptorSequence {
readonly elements: IViewDescriptor[];
private disposables: IDisposable[] = [];
constructor(model: IViewContainerModel) {
this.elements = [...model.visibleViewDescriptors];
model.onDidAddVisibleViewDescriptors(added => added.forEach(({ viewDescriptor, index }) => this.elements.splice(index, 0, viewDescriptor)), null, this.disposables);
model.onDidRemoveVisibleViewDescriptors(removed => removed.sort((a, b) => b.index - a.index).forEach(({ index }) => this.elements.splice(index, 1)), null, this.disposables);
model.onDidMoveVisibleViewDescriptors(({ from, to }) => move(this.elements, from.index, to.index), null, this.disposables);
}
dispose() {
this.disposables = dispose(this.disposables);
}
}
suite('ViewContainerModel', () => {
let container: ViewContainer;
let disposableStore: DisposableStore;
let contextKeyService: IContextKeyService;
let viewDescriptorService: IViewDescriptorService;
let storageService: IStorageService;
setup(() => {
disposableStore = new DisposableStore();
const instantiationService: TestInstantiationService = <TestInstantiationService>workbenchInstantiationService();
contextKeyService = instantiationService.createInstance(ContextKeyService);
instantiationService.stub(IContextKeyService, contextKeyService);
storageService = instantiationService.get(IStorageService);
viewDescriptorService = instantiationService.createInstance(ViewDescriptorService);
});
teardown(() => {
disposableStore.dispose();
ViewsRegistry.deregisterViews(ViewsRegistry.getViews(container), container);
ViewContainerRegistry.deregisterViewContainer(container);
});
test('empty model', function () {
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
assert.equal(testObject.visibleViewDescriptors.length, 0);
});
test('register/unregister', () => {
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
assert.equal(testObject.visibleViewDescriptors.length, 0);
assert.equal(target.elements.length, 0);
const viewDescriptor: IViewDescriptor = {
id: 'view1',
ctorDescriptor: null!,
name: 'Test View 1'
};
ViewsRegistry.registerViews([viewDescriptor], container);
assert.equal(testObject.visibleViewDescriptors.length, 1);
assert.equal(target.elements.length, 1);
assert.deepEqual(testObject.visibleViewDescriptors[0], viewDescriptor);
assert.deepEqual(target.elements[0], viewDescriptor);
ViewsRegistry.deregisterViews([viewDescriptor], container);
assert.equal(testObject.visibleViewDescriptors.length, 0);
assert.equal(target.elements.length, 0);
});
test('when contexts', async function () {
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
assert.equal(testObject.visibleViewDescriptors.length, 0);
assert.equal(target.elements.length, 0);
const viewDescriptor: IViewDescriptor = {
id: 'view1',
ctorDescriptor: null!,
name: 'Test View 1',
when: ContextKeyExpr.equals('showview1', true)
};
ViewsRegistry.registerViews([viewDescriptor], container);
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should not appear since context isnt in');
assert.equal(target.elements.length, 0);
const key = contextKeyService.createKey('showview1', false);
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should still not appear since showview1 isnt true');
assert.equal(target.elements.length, 0);
key.set(true);
await new Promise(c => setTimeout(c, 30));
assert.equal(testObject.visibleViewDescriptors.length, 1, 'view should appear');
assert.equal(target.elements.length, 1);
assert.deepEqual(testObject.visibleViewDescriptors[0], viewDescriptor);
assert.equal(target.elements[0], viewDescriptor);
key.set(false);
await new Promise(c => setTimeout(c, 30));
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should disappear');
assert.equal(target.elements.length, 0);
ViewsRegistry.deregisterViews([viewDescriptor], container);
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should not be there anymore');
assert.equal(target.elements.length, 0);
key.set(true);
await new Promise(c => setTimeout(c, 30));
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should not be there anymore');
assert.equal(target.elements.length, 0);
});
test('when contexts - multiple', async function () {
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
const view1: IViewDescriptor = { id: 'view1', ctorDescriptor: null!, name: 'Test View 1' };
const view2: IViewDescriptor = { id: 'view2', ctorDescriptor: null!, name: 'Test View 2', when: ContextKeyExpr.equals('showview2', true) };
ViewsRegistry.registerViews([view1, view2], container);
assert.deepEqual(testObject.visibleViewDescriptors, [view1], 'only view1 should be visible');
assert.deepEqual(target.elements, [view1], 'only view1 should be visible');
const key = contextKeyService.createKey('showview2', false);
assert.deepEqual(testObject.visibleViewDescriptors, [view1], 'still only view1 should be visible');
assert.deepEqual(target.elements, [view1], 'still only view1 should be visible');
key.set(true);
await new Promise(c => setTimeout(c, 30));
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view2], 'both views should be visible');
assert.deepEqual(target.elements, [view1, view2], 'both views should be visible');
ViewsRegistry.deregisterViews([view1, view2], container);
});
test('when contexts - multiple 2', async function () {
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
const view1: IViewDescriptor = { id: 'view1', ctorDescriptor: null!, name: 'Test View 1', when: ContextKeyExpr.equals('showview1', true) };
const view2: IViewDescriptor = { id: 'view2', ctorDescriptor: null!, name: 'Test View 2' };
ViewsRegistry.registerViews([view1, view2], container);
assert.deepEqual(testObject.visibleViewDescriptors, [view2], 'only view2 should be visible');
assert.deepEqual(target.elements, [view2], 'only view2 should be visible');
const key = contextKeyService.createKey('showview1', false);
assert.deepEqual(testObject.visibleViewDescriptors, [view2], 'still only view2 should be visible');
assert.deepEqual(target.elements, [view2], 'still only view2 should be visible');
key.set(true);
await new Promise(c => setTimeout(c, 30));
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view2], 'both views should be visible');
assert.deepEqual(target.elements, [view1, view2], 'both views should be visible');
ViewsRegistry.deregisterViews([view1, view2], container);
});
test('setVisible', () => {
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
const view1: IViewDescriptor = { id: 'view1', ctorDescriptor: null!, name: 'Test View 1', canToggleVisibility: true };
const view2: IViewDescriptor = { id: 'view2', ctorDescriptor: null!, name: 'Test View 2', canToggleVisibility: true };
const view3: IViewDescriptor = { id: 'view3', ctorDescriptor: null!, name: 'Test View 3', canToggleVisibility: true };
ViewsRegistry.registerViews([view1, view2, view3], container);
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view2, view3]);
assert.deepEqual(target.elements, [view1, view2, view3]);
testObject.setVisible('view2', true);
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view2, view3], 'nothing should happen');
assert.deepEqual(target.elements, [view1, view2, view3]);
testObject.setVisible('view2', false);
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view3], 'view2 should hide');
assert.deepEqual(target.elements, [view1, view3]);
testObject.setVisible('view1', false);
assert.deepEqual(testObject.visibleViewDescriptors, [view3], 'view1 should hide');
assert.deepEqual(target.elements, [view3]);
testObject.setVisible('view3', false);
assert.deepEqual(testObject.visibleViewDescriptors, [], 'view3 shoud hide');
assert.deepEqual(target.elements, []);
testObject.setVisible('view1', true);
assert.deepEqual(testObject.visibleViewDescriptors, [view1], 'view1 should show');
assert.deepEqual(target.elements, [view1]);
testObject.setVisible('view3', true);
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view3], 'view3 should show');
assert.deepEqual(target.elements, [view1, view3]);
testObject.setVisible('view2', true);
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view2, view3], 'view2 should show');
assert.deepEqual(target.elements, [view1, view2, view3]);
ViewsRegistry.deregisterViews([view1, view2, view3], container);
assert.deepEqual(testObject.visibleViewDescriptors, []);
assert.deepEqual(target.elements, []);
});
test('move', () => {
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
const view1: IViewDescriptor = { id: 'view1', ctorDescriptor: null!, name: 'Test View 1' };
const view2: IViewDescriptor = { id: 'view2', ctorDescriptor: null!, name: 'Test View 2' };
const view3: IViewDescriptor = { id: 'view3', ctorDescriptor: null!, name: 'Test View 3' };
ViewsRegistry.registerViews([view1, view2, view3], container);
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view2, view3], 'model views should be OK');
assert.deepEqual(target.elements, [view1, view2, view3], 'sql views should be OK');
testObject.move('view3', 'view1');
assert.deepEqual(testObject.visibleViewDescriptors, [view3, view1, view2], 'view3 should go to the front');
assert.deepEqual(target.elements, [view3, view1, view2]);
testObject.move('view1', 'view2');
assert.deepEqual(testObject.visibleViewDescriptors, [view3, view2, view1], 'view1 should go to the end');
assert.deepEqual(target.elements, [view3, view2, view1]);
testObject.move('view1', 'view3');
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view3, view2], 'view1 should go to the front');
assert.deepEqual(target.elements, [view1, view3, view2]);
testObject.move('view2', 'view3');
assert.deepEqual(testObject.visibleViewDescriptors, [view1, view2, view3], 'view2 should go to the middle');
assert.deepEqual(target.elements, [view1, view2, view3]);
});
test('view states', async function () {
storageService.store(`${container.id}.state.hidden`, JSON.stringify([{ id: 'view1', isHidden: true }]), StorageScope.GLOBAL);
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
assert.equal(testObject.visibleViewDescriptors.length, 0);
assert.equal(target.elements.length, 0);
const viewDescriptor: IViewDescriptor = {
id: 'view1',
ctorDescriptor: null!,
name: 'Test View 1'
};
ViewsRegistry.registerViews([viewDescriptor], container);
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should not appear since it was set not visible in view state');
assert.equal(target.elements.length, 0);
});
test('view states and when contexts', async function () {
storageService.store(`${container.id}.state.hidden`, JSON.stringify([{ id: 'view1', isHidden: true }]), StorageScope.GLOBAL);
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
assert.equal(testObject.visibleViewDescriptors.length, 0);
assert.equal(target.elements.length, 0);
const viewDescriptor: IViewDescriptor = {
id: 'view1',
ctorDescriptor: null!,
name: 'Test View 1',
when: ContextKeyExpr.equals('showview1', true)
};
ViewsRegistry.registerViews([viewDescriptor], container);
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should not appear since context isnt in');
assert.equal(target.elements.length, 0);
const key = contextKeyService.createKey('showview1', false);
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should still not appear since showview1 isnt true');
assert.equal(target.elements.length, 0);
key.set(true);
await new Promise(c => setTimeout(c, 30));
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should still not appear since it was set not visible in view state');
assert.equal(target.elements.length, 0);
});
test('view states and when contexts multiple views', async function () {
storageService.store(`${container.id}.state.hidden`, JSON.stringify([{ id: 'view1', isHidden: true }]), StorageScope.GLOBAL);
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
assert.equal(testObject.visibleViewDescriptors.length, 0);
assert.equal(target.elements.length, 0);
const view1: IViewDescriptor = {
id: 'view1',
ctorDescriptor: null!,
name: 'Test View 1',
when: ContextKeyExpr.equals('showview', true)
};
const view2: IViewDescriptor = {
id: 'view2',
ctorDescriptor: null!,
name: 'Test View 2',
};
const view3: IViewDescriptor = {
id: 'view3',
ctorDescriptor: null!,
name: 'Test View 3',
when: ContextKeyExpr.equals('showview', true)
};
ViewsRegistry.registerViews([view1, view2, view3], container);
assert.deepEqual(testObject.visibleViewDescriptors, [view2], 'Only view2 should be visible');
assert.deepEqual(target.elements, [view2]);
const key = contextKeyService.createKey('showview', false);
assert.deepEqual(testObject.visibleViewDescriptors, [view2], 'Only view2 should be visible');
assert.deepEqual(target.elements, [view2]);
key.set(true);
await new Promise(c => setTimeout(c, 30));
assert.deepEqual(testObject.visibleViewDescriptors, [view2, view3], 'view3 should be visible');
assert.deepEqual(target.elements, [view2, view3]);
key.set(false);
await new Promise(c => setTimeout(c, 30));
assert.deepEqual(testObject.visibleViewDescriptors, [view2], 'Only view2 should be visible');
assert.deepEqual(target.elements, [view2]);
});
test('remove event is not triggered if view was hidden and removed', async function () {
container = ViewContainerRegistry.registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: new SyncDescriptor(<any>{}) }, ViewContainerLocation.Sidebar);
const testObject = viewDescriptorService.getViewContainerModel(container);
const target = disposableStore.add(new ViewDescriptorSequence(testObject));
const viewDescriptor: IViewDescriptor = {
id: 'view1',
ctorDescriptor: null!,
name: 'Test View 1',
when: ContextKeyExpr.equals('showview1', true),
canToggleVisibility: true
};
ViewsRegistry.registerViews([viewDescriptor], container);
const key = contextKeyService.createKey('showview1', true);
await new Promise(c => setTimeout(c, 30));
assert.equal(testObject.visibleViewDescriptors.length, 1, 'view should appear after context is set');
assert.equal(target.elements.length, 1);
testObject.setVisible('view1', false);
assert.equal(testObject.visibleViewDescriptors.length, 0, 'view should disappear after setting visibility to false');
assert.equal(target.elements.length, 0);
const targetEvent = sinon.spy(testObject.onDidRemoveVisibleViewDescriptors);
key.set(false);
await new Promise(c => setTimeout(c, 30));
assert.ok(!targetEvent.called, 'remove event should not be called since it is already hidden');
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册